1 // Copyright (c) 2011 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/http/http_network_transaction.h" 6 7 #include <math.h> // ceil 8 #include <vector> 9 10 #include "base/basictypes.h" 11 #include "base/compiler_specific.h" 12 #include "base/file_path.h" 13 #include "base/file_util.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/utf_string_conversions.h" 16 #include "net/base/auth.h" 17 #include "net/base/capturing_net_log.h" 18 #include "net/base/completion_callback.h" 19 #include "net/base/mock_host_resolver.h" 20 #include "net/base/net_log.h" 21 #include "net/base/net_log_unittest.h" 22 #include "net/base/request_priority.h" 23 #include "net/base/ssl_cert_request_info.h" 24 #include "net/base/ssl_config_service_defaults.h" 25 #include "net/base/ssl_info.h" 26 #include "net/base/test_completion_callback.h" 27 #include "net/base/upload_data.h" 28 #include "net/http/http_auth_handler_digest.h" 29 #include "net/http/http_auth_handler_mock.h" 30 #include "net/http/http_auth_handler_ntlm.h" 31 #include "net/http/http_basic_stream.h" 32 #include "net/http/http_net_log_params.h" 33 #include "net/http/http_network_session.h" 34 #include "net/http/http_network_session_peer.h" 35 #include "net/http/http_stream.h" 36 #include "net/http/http_stream_factory.h" 37 #include "net/http/http_transaction_unittest.h" 38 #include "net/proxy/proxy_config_service_fixed.h" 39 #include "net/proxy/proxy_resolver.h" 40 #include "net/proxy/proxy_service.h" 41 #include "net/socket/client_socket_factory.h" 42 #include "net/socket/socket_test_util.h" 43 #include "net/socket/ssl_client_socket.h" 44 #include "net/spdy/spdy_framer.h" 45 #include "net/spdy/spdy_session.h" 46 #include "net/spdy/spdy_session_pool.h" 47 #include "net/spdy/spdy_test_util.h" 48 #include "testing/gtest/include/gtest/gtest.h" 49 #include "testing/platform_test.h" 50 51 //----------------------------------------------------------------------------- 52 53 namespace { 54 55 const string16 kBar(ASCIIToUTF16("bar")); 56 const string16 kBar2(ASCIIToUTF16("bar2")); 57 const string16 kBar3(ASCIIToUTF16("bar3")); 58 const string16 kBaz(ASCIIToUTF16("baz")); 59 const string16 kFirst(ASCIIToUTF16("first")); 60 const string16 kFoo(ASCIIToUTF16("foo")); 61 const string16 kFoo2(ASCIIToUTF16("foo2")); 62 const string16 kFoo3(ASCIIToUTF16("foo3")); 63 const string16 kFou(ASCIIToUTF16("fou")); 64 const string16 kSecond(ASCIIToUTF16("second")); 65 const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm")); 66 const string16 kWrongPassword(ASCIIToUTF16("wrongpassword")); 67 68 } // namespace 69 70 namespace net { 71 72 // Helper to manage the lifetimes of the dependencies for a 73 // HttpNetworkTransaction. 74 struct SessionDependencies { 75 // Default set of dependencies -- "null" proxy service. 76 SessionDependencies() 77 : host_resolver(new MockHostResolver), 78 cert_verifier(new CertVerifier), 79 proxy_service(ProxyService::CreateDirect()), 80 ssl_config_service(new SSLConfigServiceDefaults), 81 http_auth_handler_factory( 82 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())), 83 net_log(NULL) {} 84 85 // Custom proxy service dependency. 86 explicit SessionDependencies(ProxyService* proxy_service) 87 : host_resolver(new MockHostResolver), 88 cert_verifier(new CertVerifier), 89 proxy_service(proxy_service), 90 ssl_config_service(new SSLConfigServiceDefaults), 91 http_auth_handler_factory( 92 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())), 93 net_log(NULL) {} 94 95 scoped_ptr<MockHostResolverBase> host_resolver; 96 scoped_ptr<CertVerifier> cert_verifier; 97 scoped_refptr<ProxyService> proxy_service; 98 scoped_refptr<SSLConfigService> ssl_config_service; 99 MockClientSocketFactory socket_factory; 100 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory; 101 NetLog* net_log; 102 }; 103 104 HttpNetworkSession* CreateSession(SessionDependencies* session_deps) { 105 net::HttpNetworkSession::Params params; 106 params.client_socket_factory = &session_deps->socket_factory; 107 params.host_resolver = session_deps->host_resolver.get(); 108 params.cert_verifier = session_deps->cert_verifier.get(); 109 params.proxy_service = session_deps->proxy_service; 110 params.ssl_config_service = session_deps->ssl_config_service; 111 params.http_auth_handler_factory = 112 session_deps->http_auth_handler_factory.get(); 113 params.net_log = session_deps->net_log; 114 return new HttpNetworkSession(params); 115 } 116 117 class HttpNetworkTransactionTest : public PlatformTest { 118 public: 119 virtual void SetUp() { 120 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 121 MessageLoop::current()->RunAllPending(); 122 spdy::SpdyFramer::set_enable_compression_default(false); 123 } 124 125 virtual void TearDown() { 126 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 127 MessageLoop::current()->RunAllPending(); 128 spdy::SpdyFramer::set_enable_compression_default(true); 129 // Empty the current queue. 130 MessageLoop::current()->RunAllPending(); 131 PlatformTest::TearDown(); 132 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 133 MessageLoop::current()->RunAllPending(); 134 } 135 136 protected: 137 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure); 138 139 struct SimpleGetHelperResult { 140 int rv; 141 std::string status_line; 142 std::string response_data; 143 }; 144 145 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[], 146 size_t reads_count) { 147 SimpleGetHelperResult out; 148 149 HttpRequestInfo request; 150 request.method = "GET"; 151 request.url = GURL("http://www.google.com/"); 152 request.load_flags = 0; 153 154 SessionDependencies session_deps; 155 scoped_ptr<HttpTransaction> trans( 156 new HttpNetworkTransaction(CreateSession(&session_deps))); 157 158 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0); 159 session_deps.socket_factory.AddSocketDataProvider(&data); 160 161 TestCompletionCallback callback; 162 163 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 164 EXPECT_TRUE(log.bound().IsLoggingAllEvents()); 165 int rv = trans->Start(&request, &callback, log.bound()); 166 EXPECT_EQ(ERR_IO_PENDING, rv); 167 168 out.rv = callback.WaitForResult(); 169 if (out.rv != OK) 170 return out; 171 172 const HttpResponseInfo* response = trans->GetResponseInfo(); 173 EXPECT_TRUE(response != NULL); 174 175 EXPECT_TRUE(response->headers != NULL); 176 out.status_line = response->headers->GetStatusLine(); 177 178 EXPECT_EQ("192.0.2.33", response->socket_address.host()); 179 EXPECT_EQ(0, response->socket_address.port()); 180 181 rv = ReadTransaction(trans.get(), &out.response_data); 182 EXPECT_EQ(OK, rv); 183 184 net::CapturingNetLog::EntryList entries; 185 log.GetEntries(&entries); 186 size_t pos = ExpectLogContainsSomewhere( 187 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 188 NetLog::PHASE_NONE); 189 ExpectLogContainsSomewhere( 190 entries, pos, 191 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS, 192 NetLog::PHASE_NONE); 193 194 CapturingNetLog::Entry entry = entries[pos]; 195 NetLogHttpRequestParameter* request_params = 196 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get()); 197 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine()); 198 EXPECT_EQ("Host: www.google.com\r\n" 199 "Connection: keep-alive\r\n\r\n", 200 request_params->GetHeaders().ToString()); 201 202 return out; 203 } 204 205 void ConnectStatusHelperWithExpectedStatus(const MockRead& status, 206 int expected_status); 207 208 void ConnectStatusHelper(const MockRead& status); 209 }; 210 211 // Fill |str| with a long header list that consumes >= |size| bytes. 212 void FillLargeHeadersString(std::string* str, int size) { 213 const char* row = 214 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"; 215 const int sizeof_row = strlen(row); 216 const int num_rows = static_cast<int>( 217 ceil(static_cast<float>(size) / sizeof_row)); 218 const int sizeof_data = num_rows * sizeof_row; 219 DCHECK(sizeof_data >= size); 220 str->reserve(sizeof_data); 221 222 for (int i = 0; i < num_rows; ++i) 223 str->append(row, sizeof_row); 224 } 225 226 // Alternative functions that eliminate randomness and dependency on the local 227 // host name so that the generated NTLM messages are reproducible. 228 void MockGenerateRandom1(uint8* output, size_t n) { 229 static const uint8 bytes[] = { 230 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54 231 }; 232 static size_t current_byte = 0; 233 for (size_t i = 0; i < n; ++i) { 234 output[i] = bytes[current_byte++]; 235 current_byte %= arraysize(bytes); 236 } 237 } 238 239 void MockGenerateRandom2(uint8* output, size_t n) { 240 static const uint8 bytes[] = { 241 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1, 242 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f 243 }; 244 static size_t current_byte = 0; 245 for (size_t i = 0; i < n; ++i) { 246 output[i] = bytes[current_byte++]; 247 current_byte %= arraysize(bytes); 248 } 249 } 250 251 std::string MockGetHostName() { 252 return "WTC-WIN7"; 253 } 254 255 template<typename ParentPool> 256 class CaptureGroupNameSocketPool : public ParentPool { 257 public: 258 CaptureGroupNameSocketPool(HostResolver* host_resolver, 259 CertVerifier* cert_verifier); 260 261 const std::string last_group_name_received() const { 262 return last_group_name_; 263 } 264 265 virtual int RequestSocket(const std::string& group_name, 266 const void* socket_params, 267 RequestPriority priority, 268 ClientSocketHandle* handle, 269 CompletionCallback* callback, 270 const BoundNetLog& net_log) { 271 last_group_name_ = group_name; 272 return ERR_IO_PENDING; 273 } 274 virtual void CancelRequest(const std::string& group_name, 275 ClientSocketHandle* handle) {} 276 virtual void ReleaseSocket(const std::string& group_name, 277 ClientSocket* socket, 278 int id) {} 279 virtual void CloseIdleSockets() {} 280 virtual int IdleSocketCount() const { 281 return 0; 282 } 283 virtual int IdleSocketCountInGroup(const std::string& group_name) const { 284 return 0; 285 } 286 virtual LoadState GetLoadState(const std::string& group_name, 287 const ClientSocketHandle* handle) const { 288 return LOAD_STATE_IDLE; 289 } 290 virtual base::TimeDelta ConnectionTimeout() const { 291 return base::TimeDelta(); 292 } 293 294 private: 295 std::string last_group_name_; 296 }; 297 298 typedef CaptureGroupNameSocketPool<TransportClientSocketPool> 299 CaptureGroupNameTransportSocketPool; 300 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool> 301 CaptureGroupNameHttpProxySocketPool; 302 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool> 303 CaptureGroupNameSOCKSSocketPool; 304 typedef CaptureGroupNameSocketPool<SSLClientSocketPool> 305 CaptureGroupNameSSLSocketPool; 306 307 template<typename ParentPool> 308 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( 309 HostResolver* host_resolver, 310 CertVerifier* /* cert_verifier */) 311 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {} 312 313 template<> 314 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( 315 HostResolver* host_resolver, 316 CertVerifier* /* cert_verifier */) 317 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {} 318 319 template<> 320 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( 321 HostResolver* host_resolver, 322 CertVerifier* cert_verifier) 323 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL, 324 NULL, NULL, NULL, NULL, NULL, NULL, NULL) {} 325 326 //----------------------------------------------------------------------------- 327 328 // This is the expected list of advertised protocols from the browser's NPN 329 // list. 330 static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2"; 331 332 // This is the expected return from a current server advertising SPDY. 333 static const char kAlternateProtocolHttpHeader[] = 334 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n"; 335 336 TEST_F(HttpNetworkTransactionTest, Basic) { 337 SessionDependencies session_deps; 338 scoped_ptr<HttpTransaction> trans( 339 new HttpNetworkTransaction(CreateSession(&session_deps))); 340 } 341 342 TEST_F(HttpNetworkTransactionTest, SimpleGET) { 343 MockRead data_reads[] = { 344 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 345 MockRead("hello world"), 346 MockRead(false, OK), 347 }; 348 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 349 arraysize(data_reads)); 350 EXPECT_EQ(OK, out.rv); 351 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 352 EXPECT_EQ("hello world", out.response_data); 353 } 354 355 // Response with no status line. 356 TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) { 357 MockRead data_reads[] = { 358 MockRead("hello world"), 359 MockRead(false, OK), 360 }; 361 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 362 arraysize(data_reads)); 363 EXPECT_EQ(OK, out.rv); 364 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 365 EXPECT_EQ("hello world", out.response_data); 366 } 367 368 // Allow up to 4 bytes of junk to precede status line. 369 TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) { 370 MockRead data_reads[] = { 371 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 372 MockRead(false, OK), 373 }; 374 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 375 arraysize(data_reads)); 376 EXPECT_EQ(OK, out.rv); 377 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 378 EXPECT_EQ("DATA", out.response_data); 379 } 380 381 // Allow up to 4 bytes of junk to precede status line. 382 TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) { 383 MockRead data_reads[] = { 384 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 385 MockRead(false, OK), 386 }; 387 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 388 arraysize(data_reads)); 389 EXPECT_EQ(OK, out.rv); 390 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 391 EXPECT_EQ("DATA", out.response_data); 392 } 393 394 // Beyond 4 bytes of slop and it should fail to find a status line. 395 TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) { 396 MockRead data_reads[] = { 397 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"), 398 MockRead(false, OK), 399 }; 400 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 401 arraysize(data_reads)); 402 EXPECT_EQ(OK, out.rv); 403 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 404 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data); 405 } 406 407 // Same as StatusLineJunk4Bytes, except the read chunks are smaller. 408 TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) { 409 MockRead data_reads[] = { 410 MockRead("\n"), 411 MockRead("\n"), 412 MockRead("Q"), 413 MockRead("J"), 414 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 415 MockRead(false, OK), 416 }; 417 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 418 arraysize(data_reads)); 419 EXPECT_EQ(OK, out.rv); 420 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 421 EXPECT_EQ("DATA", out.response_data); 422 } 423 424 // Close the connection before enough bytes to have a status line. 425 TEST_F(HttpNetworkTransactionTest, StatusLinePartial) { 426 MockRead data_reads[] = { 427 MockRead("HTT"), 428 MockRead(false, OK), 429 }; 430 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 431 arraysize(data_reads)); 432 EXPECT_EQ(OK, out.rv); 433 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 434 EXPECT_EQ("HTT", out.response_data); 435 } 436 437 // Simulate a 204 response, lacking a Content-Length header, sent over a 438 // persistent connection. The response should still terminate since a 204 439 // cannot have a response body. 440 TEST_F(HttpNetworkTransactionTest, StopsReading204) { 441 MockRead data_reads[] = { 442 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 443 MockRead("junk"), // Should not be read!! 444 MockRead(false, OK), 445 }; 446 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 447 arraysize(data_reads)); 448 EXPECT_EQ(OK, out.rv); 449 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line); 450 EXPECT_EQ("", out.response_data); 451 } 452 453 // A simple request using chunked encoding with some extra data after. 454 // (Like might be seen in a pipelined response.) 455 TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) { 456 MockRead data_reads[] = { 457 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"), 458 MockRead("5\r\nHello\r\n"), 459 MockRead("1\r\n"), 460 MockRead(" \r\n"), 461 MockRead("5\r\nworld\r\n"), 462 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), 463 MockRead(false, OK), 464 }; 465 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 466 arraysize(data_reads)); 467 EXPECT_EQ(OK, out.rv); 468 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 469 EXPECT_EQ("Hello world", out.response_data); 470 } 471 472 // Next tests deal with http://crbug.com/56344. 473 474 TEST_F(HttpNetworkTransactionTest, 475 MultipleContentLengthHeadersNoTransferEncoding) { 476 MockRead data_reads[] = { 477 MockRead("HTTP/1.1 200 OK\r\n"), 478 MockRead("Content-Length: 10\r\n"), 479 MockRead("Content-Length: 5\r\n\r\n"), 480 }; 481 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 482 arraysize(data_reads)); 483 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 484 } 485 486 TEST_F(HttpNetworkTransactionTest, 487 DuplicateContentLengthHeadersNoTransferEncoding) { 488 MockRead data_reads[] = { 489 MockRead("HTTP/1.1 200 OK\r\n"), 490 MockRead("Content-Length: 5\r\n"), 491 MockRead("Content-Length: 5\r\n\r\n"), 492 MockRead("Hello"), 493 }; 494 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 495 arraysize(data_reads)); 496 EXPECT_EQ(OK, out.rv); 497 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 498 EXPECT_EQ("Hello", out.response_data); 499 } 500 501 TEST_F(HttpNetworkTransactionTest, 502 ComplexContentLengthHeadersNoTransferEncoding) { 503 // More than 2 dupes. 504 { 505 MockRead data_reads[] = { 506 MockRead("HTTP/1.1 200 OK\r\n"), 507 MockRead("Content-Length: 5\r\n"), 508 MockRead("Content-Length: 5\r\n"), 509 MockRead("Content-Length: 5\r\n\r\n"), 510 MockRead("Hello"), 511 }; 512 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 513 arraysize(data_reads)); 514 EXPECT_EQ(OK, out.rv); 515 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 516 EXPECT_EQ("Hello", out.response_data); 517 } 518 // HTTP/1.0 519 { 520 MockRead data_reads[] = { 521 MockRead("HTTP/1.0 200 OK\r\n"), 522 MockRead("Content-Length: 5\r\n"), 523 MockRead("Content-Length: 5\r\n"), 524 MockRead("Content-Length: 5\r\n\r\n"), 525 MockRead("Hello"), 526 }; 527 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 528 arraysize(data_reads)); 529 EXPECT_EQ(OK, out.rv); 530 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 531 EXPECT_EQ("Hello", out.response_data); 532 } 533 // 2 dupes and one mismatched. 534 { 535 MockRead data_reads[] = { 536 MockRead("HTTP/1.1 200 OK\r\n"), 537 MockRead("Content-Length: 10\r\n"), 538 MockRead("Content-Length: 10\r\n"), 539 MockRead("Content-Length: 5\r\n\r\n"), 540 }; 541 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 542 arraysize(data_reads)); 543 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 544 } 545 } 546 547 TEST_F(HttpNetworkTransactionTest, 548 MultipleContentLengthHeadersTransferEncoding) { 549 MockRead data_reads[] = { 550 MockRead("HTTP/1.1 200 OK\r\n"), 551 MockRead("Content-Length: 666\r\n"), 552 MockRead("Content-Length: 1337\r\n"), 553 MockRead("Transfer-Encoding: chunked\r\n\r\n"), 554 MockRead("5\r\nHello\r\n"), 555 MockRead("1\r\n"), 556 MockRead(" \r\n"), 557 MockRead("5\r\nworld\r\n"), 558 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), 559 MockRead(false, OK), 560 }; 561 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 562 arraysize(data_reads)); 563 EXPECT_EQ(OK, out.rv); 564 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 565 EXPECT_EQ("Hello world", out.response_data); 566 } 567 568 // Do a request using the HEAD method. Verify that we don't try to read the 569 // message body (since HEAD has none). 570 TEST_F(HttpNetworkTransactionTest, Head) { 571 HttpRequestInfo request; 572 request.method = "HEAD"; 573 request.url = GURL("http://www.google.com/"); 574 request.load_flags = 0; 575 576 SessionDependencies session_deps; 577 scoped_ptr<HttpTransaction> trans( 578 new HttpNetworkTransaction(CreateSession(&session_deps))); 579 580 MockWrite data_writes1[] = { 581 MockWrite("HEAD / HTTP/1.1\r\n" 582 "Host: www.google.com\r\n" 583 "Connection: keep-alive\r\n" 584 "Content-Length: 0\r\n\r\n"), 585 }; 586 MockRead data_reads1[] = { 587 MockRead("HTTP/1.1 404 Not Found\r\n"), 588 MockRead("Server: Blah\r\n"), 589 MockRead("Content-Length: 1234\r\n\r\n"), 590 591 // No response body because the test stops reading here. 592 MockRead(false, ERR_UNEXPECTED), // Should not be reached. 593 }; 594 595 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 596 data_writes1, arraysize(data_writes1)); 597 session_deps.socket_factory.AddSocketDataProvider(&data1); 598 599 TestCompletionCallback callback1; 600 601 int rv = trans->Start(&request, &callback1, BoundNetLog()); 602 EXPECT_EQ(ERR_IO_PENDING, rv); 603 604 rv = callback1.WaitForResult(); 605 EXPECT_EQ(OK, rv); 606 607 const HttpResponseInfo* response = trans->GetResponseInfo(); 608 EXPECT_FALSE(response == NULL); 609 610 // Check that the headers got parsed. 611 EXPECT_TRUE(response->headers != NULL); 612 EXPECT_EQ(1234, response->headers->GetContentLength()); 613 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine()); 614 615 std::string server_header; 616 void* iter = NULL; 617 bool has_server_header = response->headers->EnumerateHeader( 618 &iter, "Server", &server_header); 619 EXPECT_TRUE(has_server_header); 620 EXPECT_EQ("Blah", server_header); 621 622 // Reading should give EOF right away, since there is no message body 623 // (despite non-zero content-length). 624 std::string response_data; 625 rv = ReadTransaction(trans.get(), &response_data); 626 EXPECT_EQ(OK, rv); 627 EXPECT_EQ("", response_data); 628 } 629 630 TEST_F(HttpNetworkTransactionTest, ReuseConnection) { 631 SessionDependencies session_deps; 632 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 633 634 MockRead data_reads[] = { 635 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 636 MockRead("hello"), 637 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 638 MockRead("world"), 639 MockRead(false, OK), 640 }; 641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 642 session_deps.socket_factory.AddSocketDataProvider(&data); 643 644 const char* const kExpectedResponseData[] = { 645 "hello", "world" 646 }; 647 648 for (int i = 0; i < 2; ++i) { 649 HttpRequestInfo request; 650 request.method = "GET"; 651 request.url = GURL("http://www.google.com/"); 652 request.load_flags = 0; 653 654 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 655 656 TestCompletionCallback callback; 657 658 int rv = trans->Start(&request, &callback, BoundNetLog()); 659 EXPECT_EQ(ERR_IO_PENDING, rv); 660 661 rv = callback.WaitForResult(); 662 EXPECT_EQ(OK, rv); 663 664 const HttpResponseInfo* response = trans->GetResponseInfo(); 665 EXPECT_TRUE(response != NULL); 666 667 EXPECT_TRUE(response->headers != NULL); 668 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 669 670 std::string response_data; 671 rv = ReadTransaction(trans.get(), &response_data); 672 EXPECT_EQ(OK, rv); 673 EXPECT_EQ(kExpectedResponseData[i], response_data); 674 } 675 } 676 677 TEST_F(HttpNetworkTransactionTest, Ignores100) { 678 HttpRequestInfo request; 679 request.method = "POST"; 680 request.url = GURL("http://www.foo.com/"); 681 request.upload_data = new UploadData; 682 request.upload_data->AppendBytes("foo", 3); 683 request.load_flags = 0; 684 685 SessionDependencies session_deps; 686 scoped_ptr<HttpTransaction> trans( 687 new HttpNetworkTransaction(CreateSession(&session_deps))); 688 689 MockRead data_reads[] = { 690 MockRead("HTTP/1.0 100 Continue\r\n\r\n"), 691 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 692 MockRead("hello world"), 693 MockRead(false, OK), 694 }; 695 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 696 session_deps.socket_factory.AddSocketDataProvider(&data); 697 698 TestCompletionCallback callback; 699 700 int rv = trans->Start(&request, &callback, BoundNetLog()); 701 EXPECT_EQ(ERR_IO_PENDING, rv); 702 703 rv = callback.WaitForResult(); 704 EXPECT_EQ(OK, rv); 705 706 const HttpResponseInfo* response = trans->GetResponseInfo(); 707 EXPECT_TRUE(response != NULL); 708 709 EXPECT_TRUE(response->headers != NULL); 710 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 711 712 std::string response_data; 713 rv = ReadTransaction(trans.get(), &response_data); 714 EXPECT_EQ(OK, rv); 715 EXPECT_EQ("hello world", response_data); 716 } 717 718 // This test is almost the same as Ignores100 above, but the response contains 719 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is 720 // HTTP/1.1 and the two status headers are read in one read. 721 TEST_F(HttpNetworkTransactionTest, Ignores1xx) { 722 HttpRequestInfo request; 723 request.method = "GET"; 724 request.url = GURL("http://www.foo.com/"); 725 request.load_flags = 0; 726 727 SessionDependencies session_deps; 728 scoped_ptr<HttpTransaction> trans( 729 new HttpNetworkTransaction(CreateSession(&session_deps))); 730 731 MockRead data_reads[] = { 732 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n" 733 "HTTP/1.1 200 OK\r\n\r\n"), 734 MockRead("hello world"), 735 MockRead(false, OK), 736 }; 737 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 738 session_deps.socket_factory.AddSocketDataProvider(&data); 739 740 TestCompletionCallback callback; 741 742 int rv = trans->Start(&request, &callback, BoundNetLog()); 743 EXPECT_EQ(ERR_IO_PENDING, rv); 744 745 rv = callback.WaitForResult(); 746 EXPECT_EQ(OK, rv); 747 748 const HttpResponseInfo* response = trans->GetResponseInfo(); 749 EXPECT_TRUE(response != NULL); 750 751 EXPECT_TRUE(response->headers != NULL); 752 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 753 754 std::string response_data; 755 rv = ReadTransaction(trans.get(), &response_data); 756 EXPECT_EQ(OK, rv); 757 EXPECT_EQ("hello world", response_data); 758 } 759 760 TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) { 761 HttpRequestInfo request; 762 request.method = "POST"; 763 request.url = GURL("http://www.foo.com/"); 764 request.load_flags = 0; 765 766 SessionDependencies session_deps; 767 scoped_ptr<HttpTransaction> trans( 768 new HttpNetworkTransaction(CreateSession(&session_deps))); 769 770 MockRead data_reads[] = { 771 MockRead(false, "HTTP/1.0 100 Continue\r\n"), 772 MockRead(true, 0), 773 }; 774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 775 session_deps.socket_factory.AddSocketDataProvider(&data); 776 777 TestCompletionCallback callback; 778 779 int rv = trans->Start(&request, &callback, BoundNetLog()); 780 EXPECT_EQ(ERR_IO_PENDING, rv); 781 782 rv = callback.WaitForResult(); 783 EXPECT_EQ(OK, rv); 784 785 std::string response_data; 786 rv = ReadTransaction(trans.get(), &response_data); 787 EXPECT_EQ(OK, rv); 788 EXPECT_EQ("", response_data); 789 } 790 791 TEST_F(HttpNetworkTransactionTest, EmptyResponse) { 792 HttpRequestInfo request; 793 request.method = "POST"; 794 request.url = GURL("http://www.foo.com/"); 795 request.load_flags = 0; 796 797 SessionDependencies session_deps; 798 scoped_ptr<HttpTransaction> trans( 799 new HttpNetworkTransaction(CreateSession(&session_deps))); 800 801 MockRead data_reads[] = { 802 MockRead(true, 0), 803 }; 804 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 805 session_deps.socket_factory.AddSocketDataProvider(&data); 806 807 TestCompletionCallback callback; 808 809 int rv = trans->Start(&request, &callback, BoundNetLog()); 810 EXPECT_EQ(ERR_IO_PENDING, rv); 811 812 rv = callback.WaitForResult(); 813 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 814 } 815 816 // read_failure specifies a read failure that should cause the network 817 // transaction to resend the request. 818 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest( 819 const MockRead& read_failure) { 820 HttpRequestInfo request; 821 request.method = "GET"; 822 request.url = GURL("http://www.foo.com/"); 823 request.load_flags = 0; 824 825 SessionDependencies session_deps; 826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 827 828 MockRead data1_reads[] = { 829 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 830 MockRead("hello"), 831 read_failure, // Now, we reuse the connection and fail the first read. 832 }; 833 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0); 834 session_deps.socket_factory.AddSocketDataProvider(&data1); 835 836 MockRead data2_reads[] = { 837 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 838 MockRead("world"), 839 MockRead(true, OK), 840 }; 841 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 842 session_deps.socket_factory.AddSocketDataProvider(&data2); 843 844 const char* kExpectedResponseData[] = { 845 "hello", "world" 846 }; 847 848 for (int i = 0; i < 2; ++i) { 849 TestCompletionCallback callback; 850 851 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 852 853 int rv = trans->Start(&request, &callback, BoundNetLog()); 854 EXPECT_EQ(ERR_IO_PENDING, rv); 855 856 rv = callback.WaitForResult(); 857 EXPECT_EQ(OK, rv); 858 859 const HttpResponseInfo* response = trans->GetResponseInfo(); 860 EXPECT_TRUE(response != NULL); 861 862 EXPECT_TRUE(response->headers != NULL); 863 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 864 865 std::string response_data; 866 rv = ReadTransaction(trans.get(), &response_data); 867 EXPECT_EQ(OK, rv); 868 EXPECT_EQ(kExpectedResponseData[i], response_data); 869 } 870 } 871 872 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) { 873 MockRead read_failure(true, ERR_CONNECTION_RESET); 874 KeepAliveConnectionResendRequestTest(read_failure); 875 } 876 877 TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) { 878 MockRead read_failure(false, OK); // EOF 879 KeepAliveConnectionResendRequestTest(read_failure); 880 } 881 882 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) { 883 HttpRequestInfo request; 884 request.method = "GET"; 885 request.url = GURL("http://www.google.com/"); 886 request.load_flags = 0; 887 888 SessionDependencies session_deps; 889 scoped_ptr<HttpTransaction> trans( 890 new HttpNetworkTransaction(CreateSession(&session_deps))); 891 892 MockRead data_reads[] = { 893 MockRead(true, ERR_CONNECTION_RESET), 894 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 895 MockRead("hello world"), 896 MockRead(false, OK), 897 }; 898 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 899 session_deps.socket_factory.AddSocketDataProvider(&data); 900 901 TestCompletionCallback callback; 902 903 int rv = trans->Start(&request, &callback, BoundNetLog()); 904 EXPECT_EQ(ERR_IO_PENDING, rv); 905 906 rv = callback.WaitForResult(); 907 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 908 909 const HttpResponseInfo* response = trans->GetResponseInfo(); 910 EXPECT_TRUE(response == NULL); 911 } 912 913 // What do various browsers do when the server closes a non-keepalive 914 // connection without sending any response header or body? 915 // 916 // IE7: error page 917 // Safari 3.1.2 (Windows): error page 918 // Firefox 3.0.1: blank page 919 // Opera 9.52: after five attempts, blank page 920 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE) 921 // Us: error page (EMPTY_RESPONSE) 922 TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) { 923 MockRead data_reads[] = { 924 MockRead(false, OK), // EOF 925 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 926 MockRead("hello world"), 927 MockRead(false, OK), 928 }; 929 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 930 arraysize(data_reads)); 931 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv); 932 } 933 934 // Test that we correctly reuse a keep-alive connection after not explicitly 935 // reading the body. 936 TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { 937 HttpRequestInfo request; 938 request.method = "GET"; 939 request.url = GURL("http://www.foo.com/"); 940 request.load_flags = 0; 941 942 SessionDependencies session_deps; 943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 944 945 // Note that because all these reads happen in the same 946 // StaticSocketDataProvider, it shows that the same socket is being reused for 947 // all transactions. 948 MockRead data1_reads[] = { 949 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 950 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"), 951 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"), 952 MockRead("HTTP/1.1 302 Found\r\n" 953 "Content-Length: 0\r\n\r\n"), 954 MockRead("HTTP/1.1 302 Found\r\n" 955 "Content-Length: 5\r\n\r\n" 956 "hello"), 957 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 958 "Content-Length: 0\r\n\r\n"), 959 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 960 "Content-Length: 5\r\n\r\n" 961 "hello"), 962 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 963 MockRead("hello"), 964 }; 965 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0); 966 session_deps.socket_factory.AddSocketDataProvider(&data1); 967 968 MockRead data2_reads[] = { 969 MockRead(false, ERR_UNEXPECTED), // Should not be reached. 970 }; 971 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 972 session_deps.socket_factory.AddSocketDataProvider(&data2); 973 974 const int kNumUnreadBodies = arraysize(data1_reads) - 2; 975 std::string response_lines[kNumUnreadBodies]; 976 977 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) { 978 TestCompletionCallback callback; 979 980 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 981 982 int rv = trans->Start(&request, &callback, BoundNetLog()); 983 EXPECT_EQ(ERR_IO_PENDING, rv); 984 985 rv = callback.WaitForResult(); 986 EXPECT_EQ(OK, rv); 987 988 const HttpResponseInfo* response = trans->GetResponseInfo(); 989 ASSERT_TRUE(response != NULL); 990 991 ASSERT_TRUE(response->headers != NULL); 992 response_lines[i] = response->headers->GetStatusLine(); 993 994 // We intentionally don't read the response bodies. 995 } 996 997 const char* const kStatusLines[] = { 998 "HTTP/1.1 204 No Content", 999 "HTTP/1.1 205 Reset Content", 1000 "HTTP/1.1 304 Not Modified", 1001 "HTTP/1.1 302 Found", 1002 "HTTP/1.1 302 Found", 1003 "HTTP/1.1 301 Moved Permanently", 1004 "HTTP/1.1 301 Moved Permanently", 1005 }; 1006 1007 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines), 1008 forgot_to_update_kStatusLines); 1009 1010 for (int i = 0; i < kNumUnreadBodies; ++i) 1011 EXPECT_EQ(kStatusLines[i], response_lines[i]); 1012 1013 TestCompletionCallback callback; 1014 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1015 int rv = trans->Start(&request, &callback, BoundNetLog()); 1016 EXPECT_EQ(ERR_IO_PENDING, rv); 1017 rv = callback.WaitForResult(); 1018 EXPECT_EQ(OK, rv); 1019 const HttpResponseInfo* response = trans->GetResponseInfo(); 1020 ASSERT_TRUE(response != NULL); 1021 ASSERT_TRUE(response->headers != NULL); 1022 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1023 std::string response_data; 1024 rv = ReadTransaction(trans.get(), &response_data); 1025 EXPECT_EQ(OK, rv); 1026 EXPECT_EQ("hello", response_data); 1027 } 1028 1029 // Test the request-challenge-retry sequence for basic auth. 1030 // (basic auth is the easiest to mock, because it has no randomness). 1031 TEST_F(HttpNetworkTransactionTest, BasicAuth) { 1032 HttpRequestInfo request; 1033 request.method = "GET"; 1034 request.url = GURL("http://www.google.com/"); 1035 request.load_flags = 0; 1036 1037 SessionDependencies session_deps; 1038 scoped_ptr<HttpTransaction> trans( 1039 new HttpNetworkTransaction(CreateSession(&session_deps))); 1040 1041 MockWrite data_writes1[] = { 1042 MockWrite("GET / HTTP/1.1\r\n" 1043 "Host: www.google.com\r\n" 1044 "Connection: keep-alive\r\n\r\n"), 1045 }; 1046 1047 MockRead data_reads1[] = { 1048 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1049 // Give a couple authenticate options (only the middle one is actually 1050 // supported). 1051 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed. 1052 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1053 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 1054 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1055 // Large content-length -- won't matter, as connection will be reset. 1056 MockRead("Content-Length: 10000\r\n\r\n"), 1057 MockRead(false, ERR_FAILED), 1058 }; 1059 1060 // After calling trans->RestartWithAuth(), this is the request we should 1061 // be issuing -- the final header line contains the credentials. 1062 MockWrite data_writes2[] = { 1063 MockWrite("GET / HTTP/1.1\r\n" 1064 "Host: www.google.com\r\n" 1065 "Connection: keep-alive\r\n" 1066 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1067 }; 1068 1069 // Lastly, the server responds with the actual content. 1070 MockRead data_reads2[] = { 1071 MockRead("HTTP/1.0 200 OK\r\n"), 1072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1073 MockRead("Content-Length: 100\r\n\r\n"), 1074 MockRead(false, OK), 1075 }; 1076 1077 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1078 data_writes1, arraysize(data_writes1)); 1079 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1080 data_writes2, arraysize(data_writes2)); 1081 session_deps.socket_factory.AddSocketDataProvider(&data1); 1082 session_deps.socket_factory.AddSocketDataProvider(&data2); 1083 1084 TestCompletionCallback callback1; 1085 1086 int rv = trans->Start(&request, &callback1, BoundNetLog()); 1087 EXPECT_EQ(ERR_IO_PENDING, rv); 1088 1089 rv = callback1.WaitForResult(); 1090 EXPECT_EQ(OK, rv); 1091 1092 const HttpResponseInfo* response = trans->GetResponseInfo(); 1093 EXPECT_FALSE(response == NULL); 1094 1095 // The password prompt info should have been set in response->auth_challenge. 1096 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1097 1098 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 1099 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1100 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1101 1102 TestCompletionCallback callback2; 1103 1104 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 1105 EXPECT_EQ(ERR_IO_PENDING, rv); 1106 1107 rv = callback2.WaitForResult(); 1108 EXPECT_EQ(OK, rv); 1109 1110 response = trans->GetResponseInfo(); 1111 EXPECT_FALSE(response == NULL); 1112 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1113 EXPECT_EQ(100, response->headers->GetContentLength()); 1114 } 1115 1116 TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) { 1117 HttpRequestInfo request; 1118 request.method = "GET"; 1119 request.url = GURL("http://www.google.com/"); 1120 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1121 1122 SessionDependencies session_deps; 1123 scoped_ptr<HttpTransaction> trans( 1124 new HttpNetworkTransaction(CreateSession(&session_deps))); 1125 1126 MockWrite data_writes[] = { 1127 MockWrite("GET / HTTP/1.1\r\n" 1128 "Host: www.google.com\r\n" 1129 "Connection: keep-alive\r\n\r\n"), 1130 }; 1131 1132 MockRead data_reads[] = { 1133 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1134 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1135 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1136 // Large content-length -- won't matter, as connection will be reset. 1137 MockRead("Content-Length: 10000\r\n\r\n"), 1138 MockRead(false, ERR_FAILED), 1139 }; 1140 1141 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 1142 data_writes, arraysize(data_writes)); 1143 session_deps.socket_factory.AddSocketDataProvider(&data); 1144 TestCompletionCallback callback; 1145 1146 int rv = trans->Start(&request, &callback, BoundNetLog()); 1147 EXPECT_EQ(ERR_IO_PENDING, rv); 1148 1149 rv = callback.WaitForResult(); 1150 EXPECT_EQ(0, rv); 1151 1152 const HttpResponseInfo* response = trans->GetResponseInfo(); 1153 ASSERT_FALSE(response == NULL); 1154 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1155 } 1156 1157 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 1158 // connection. 1159 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) { 1160 HttpRequestInfo request; 1161 request.method = "GET"; 1162 request.url = GURL("http://www.google.com/"); 1163 request.load_flags = 0; 1164 1165 SessionDependencies session_deps; 1166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1167 1168 MockWrite data_writes1[] = { 1169 MockWrite("GET / HTTP/1.1\r\n" 1170 "Host: www.google.com\r\n" 1171 "Connection: keep-alive\r\n\r\n"), 1172 1173 // After calling trans->RestartWithAuth(), this is the request we should 1174 // be issuing -- the final header line contains the credentials. 1175 MockWrite("GET / HTTP/1.1\r\n" 1176 "Host: www.google.com\r\n" 1177 "Connection: keep-alive\r\n" 1178 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1179 }; 1180 1181 MockRead data_reads1[] = { 1182 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1183 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1185 MockRead("Content-Length: 14\r\n\r\n"), 1186 MockRead("Unauthorized\r\n"), 1187 1188 // Lastly, the server responds with the actual content. 1189 MockRead("HTTP/1.1 200 OK\r\n"), 1190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1191 MockRead("Content-Length: 5\r\n\r\n"), 1192 MockRead("Hello"), 1193 }; 1194 1195 // If there is a regression where we disconnect a Keep-Alive 1196 // connection during an auth roundtrip, we'll end up reading this. 1197 MockRead data_reads2[] = { 1198 MockRead(false, ERR_FAILED), 1199 }; 1200 1201 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1202 data_writes1, arraysize(data_writes1)); 1203 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1204 NULL, 0); 1205 session_deps.socket_factory.AddSocketDataProvider(&data1); 1206 session_deps.socket_factory.AddSocketDataProvider(&data2); 1207 1208 TestCompletionCallback callback1; 1209 1210 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1211 int rv = trans->Start(&request, &callback1, BoundNetLog()); 1212 EXPECT_EQ(ERR_IO_PENDING, rv); 1213 1214 rv = callback1.WaitForResult(); 1215 EXPECT_EQ(OK, rv); 1216 1217 const HttpResponseInfo* response = trans->GetResponseInfo(); 1218 EXPECT_FALSE(response == NULL); 1219 1220 // The password prompt info should have been set in response->auth_challenge. 1221 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1222 1223 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 1224 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1225 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1226 1227 TestCompletionCallback callback2; 1228 1229 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 1230 EXPECT_EQ(ERR_IO_PENDING, rv); 1231 1232 rv = callback2.WaitForResult(); 1233 EXPECT_EQ(OK, rv); 1234 1235 response = trans->GetResponseInfo(); 1236 ASSERT_FALSE(response == NULL); 1237 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1238 EXPECT_EQ(5, response->headers->GetContentLength()); 1239 } 1240 1241 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 1242 // connection and with no response body to drain. 1243 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) { 1244 HttpRequestInfo request; 1245 request.method = "GET"; 1246 request.url = GURL("http://www.google.com/"); 1247 request.load_flags = 0; 1248 1249 SessionDependencies session_deps; 1250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1251 1252 MockWrite data_writes1[] = { 1253 MockWrite("GET / HTTP/1.1\r\n" 1254 "Host: www.google.com\r\n" 1255 "Connection: keep-alive\r\n\r\n"), 1256 1257 // After calling trans->RestartWithAuth(), this is the request we should 1258 // be issuing -- the final header line contains the credentials. 1259 MockWrite("GET / HTTP/1.1\r\n" 1260 "Host: www.google.com\r\n" 1261 "Connection: keep-alive\r\n" 1262 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1263 }; 1264 1265 MockRead data_reads1[] = { 1266 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1267 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1268 MockRead("Content-Length: 0\r\n\r\n"), // No response body. 1269 1270 // Lastly, the server responds with the actual content. 1271 MockRead("HTTP/1.1 200 OK\r\n"), 1272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1273 MockRead("Content-Length: 5\r\n\r\n"), 1274 MockRead("hello"), 1275 }; 1276 1277 // An incorrect reconnect would cause this to be read. 1278 MockRead data_reads2[] = { 1279 MockRead(false, ERR_FAILED), 1280 }; 1281 1282 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1283 data_writes1, arraysize(data_writes1)); 1284 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1285 NULL, 0); 1286 session_deps.socket_factory.AddSocketDataProvider(&data1); 1287 session_deps.socket_factory.AddSocketDataProvider(&data2); 1288 1289 TestCompletionCallback callback1; 1290 1291 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1292 int rv = trans->Start(&request, &callback1, BoundNetLog()); 1293 EXPECT_EQ(ERR_IO_PENDING, rv); 1294 1295 rv = callback1.WaitForResult(); 1296 EXPECT_EQ(OK, rv); 1297 1298 const HttpResponseInfo* response = trans->GetResponseInfo(); 1299 EXPECT_FALSE(response == NULL); 1300 1301 // The password prompt info should have been set in response->auth_challenge. 1302 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1303 1304 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 1305 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1306 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1307 1308 TestCompletionCallback callback2; 1309 1310 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 1311 EXPECT_EQ(ERR_IO_PENDING, rv); 1312 1313 rv = callback2.WaitForResult(); 1314 EXPECT_EQ(OK, rv); 1315 1316 response = trans->GetResponseInfo(); 1317 ASSERT_FALSE(response == NULL); 1318 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1319 EXPECT_EQ(5, response->headers->GetContentLength()); 1320 } 1321 1322 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 1323 // connection and with a large response body to drain. 1324 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) { 1325 HttpRequestInfo request; 1326 request.method = "GET"; 1327 request.url = GURL("http://www.google.com/"); 1328 request.load_flags = 0; 1329 1330 SessionDependencies session_deps; 1331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1332 1333 MockWrite data_writes1[] = { 1334 MockWrite("GET / HTTP/1.1\r\n" 1335 "Host: www.google.com\r\n" 1336 "Connection: keep-alive\r\n\r\n"), 1337 1338 // After calling trans->RestartWithAuth(), this is the request we should 1339 // be issuing -- the final header line contains the credentials. 1340 MockWrite("GET / HTTP/1.1\r\n" 1341 "Host: www.google.com\r\n" 1342 "Connection: keep-alive\r\n" 1343 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1344 }; 1345 1346 // Respond with 5 kb of response body. 1347 std::string large_body_string("Unauthorized"); 1348 large_body_string.append(5 * 1024, ' '); 1349 large_body_string.append("\r\n"); 1350 1351 MockRead data_reads1[] = { 1352 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1353 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1354 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1355 // 5134 = 12 + 5 * 1024 + 2 1356 MockRead("Content-Length: 5134\r\n\r\n"), 1357 MockRead(true, large_body_string.data(), large_body_string.size()), 1358 1359 // Lastly, the server responds with the actual content. 1360 MockRead("HTTP/1.1 200 OK\r\n"), 1361 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1362 MockRead("Content-Length: 5\r\n\r\n"), 1363 MockRead("hello"), 1364 }; 1365 1366 // An incorrect reconnect would cause this to be read. 1367 MockRead data_reads2[] = { 1368 MockRead(false, ERR_FAILED), 1369 }; 1370 1371 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1372 data_writes1, arraysize(data_writes1)); 1373 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1374 NULL, 0); 1375 session_deps.socket_factory.AddSocketDataProvider(&data1); 1376 session_deps.socket_factory.AddSocketDataProvider(&data2); 1377 1378 TestCompletionCallback callback1; 1379 1380 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1381 int rv = trans->Start(&request, &callback1, BoundNetLog()); 1382 EXPECT_EQ(ERR_IO_PENDING, rv); 1383 1384 rv = callback1.WaitForResult(); 1385 EXPECT_EQ(OK, rv); 1386 1387 const HttpResponseInfo* response = trans->GetResponseInfo(); 1388 EXPECT_FALSE(response == NULL); 1389 1390 // The password prompt info should have been set in response->auth_challenge. 1391 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1392 1393 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 1394 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1395 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1396 1397 TestCompletionCallback callback2; 1398 1399 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 1400 EXPECT_EQ(ERR_IO_PENDING, rv); 1401 1402 rv = callback2.WaitForResult(); 1403 EXPECT_EQ(OK, rv); 1404 1405 response = trans->GetResponseInfo(); 1406 ASSERT_FALSE(response == NULL); 1407 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1408 EXPECT_EQ(5, response->headers->GetContentLength()); 1409 } 1410 1411 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 1412 // connection, but the server gets impatient and closes the connection. 1413 TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) { 1414 HttpRequestInfo request; 1415 request.method = "GET"; 1416 request.url = GURL("http://www.google.com/"); 1417 request.load_flags = 0; 1418 1419 SessionDependencies session_deps; 1420 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1421 1422 MockWrite data_writes1[] = { 1423 MockWrite("GET / HTTP/1.1\r\n" 1424 "Host: www.google.com\r\n" 1425 "Connection: keep-alive\r\n\r\n"), 1426 // This simulates the seemingly successful write to a closed connection 1427 // if the bug is not fixed. 1428 MockWrite("GET / HTTP/1.1\r\n" 1429 "Host: www.google.com\r\n" 1430 "Connection: keep-alive\r\n" 1431 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1432 }; 1433 1434 MockRead data_reads1[] = { 1435 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1436 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1437 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1438 MockRead("Content-Length: 14\r\n\r\n"), 1439 // Tell MockTCPClientSocket to simulate the server closing the connection. 1440 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 1441 MockRead("Unauthorized\r\n"), 1442 MockRead(false, OK), // The server closes the connection. 1443 }; 1444 1445 // After calling trans->RestartWithAuth(), this is the request we should 1446 // be issuing -- the final header line contains the credentials. 1447 MockWrite data_writes2[] = { 1448 MockWrite("GET / HTTP/1.1\r\n" 1449 "Host: www.google.com\r\n" 1450 "Connection: keep-alive\r\n" 1451 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1452 }; 1453 1454 // Lastly, the server responds with the actual content. 1455 MockRead data_reads2[] = { 1456 MockRead("HTTP/1.1 200 OK\r\n"), 1457 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1458 MockRead("Content-Length: 5\r\n\r\n"), 1459 MockRead("hello"), 1460 }; 1461 1462 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1463 data_writes1, arraysize(data_writes1)); 1464 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1465 data_writes2, arraysize(data_writes2)); 1466 session_deps.socket_factory.AddSocketDataProvider(&data1); 1467 session_deps.socket_factory.AddSocketDataProvider(&data2); 1468 1469 TestCompletionCallback callback1; 1470 1471 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1472 int rv = trans->Start(&request, &callback1, BoundNetLog()); 1473 EXPECT_EQ(ERR_IO_PENDING, rv); 1474 1475 rv = callback1.WaitForResult(); 1476 EXPECT_EQ(OK, rv); 1477 1478 const HttpResponseInfo* response = trans->GetResponseInfo(); 1479 EXPECT_FALSE(response == NULL); 1480 1481 // The password prompt info should have been set in response->auth_challenge. 1482 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1483 1484 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 1485 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1486 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1487 1488 TestCompletionCallback callback2; 1489 1490 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 1491 EXPECT_EQ(ERR_IO_PENDING, rv); 1492 1493 rv = callback2.WaitForResult(); 1494 EXPECT_EQ(OK, rv); 1495 1496 response = trans->GetResponseInfo(); 1497 ASSERT_FALSE(response == NULL); 1498 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1499 EXPECT_EQ(5, response->headers->GetContentLength()); 1500 } 1501 1502 // Test the request-challenge-retry sequence for basic auth, over a connection 1503 // that requires a restart when setting up an SSL tunnel. 1504 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { 1505 HttpRequestInfo request; 1506 request.method = "GET"; 1507 request.url = GURL("https://www.google.com/"); 1508 // when the no authentication data flag is set. 1509 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1510 1511 // Configure against proxy server "myproxy:70". 1512 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 1513 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 1514 session_deps.net_log = log.bound().net_log(); 1515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1516 1517 // Since we have proxy, should try to establish tunnel. 1518 MockWrite data_writes1[] = { 1519 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1520 "Host: www.google.com\r\n" 1521 "Proxy-Connection: keep-alive\r\n\r\n"), 1522 1523 // After calling trans->RestartWithAuth(), this is the request we should 1524 // be issuing -- the final header line contains the credentials. 1525 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1526 "Host: www.google.com\r\n" 1527 "Proxy-Connection: keep-alive\r\n" 1528 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1529 1530 MockWrite("GET / HTTP/1.1\r\n" 1531 "Host: www.google.com\r\n" 1532 "Connection: keep-alive\r\n\r\n"), 1533 }; 1534 1535 // The proxy responds to the connect with a 407, using a persistent 1536 // connection. 1537 MockRead data_reads1[] = { 1538 // No credentials. 1539 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 1540 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1541 MockRead("Proxy-Connection: close\r\n\r\n"), 1542 1543 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 1544 1545 MockRead("HTTP/1.1 200 OK\r\n"), 1546 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1547 MockRead("Content-Length: 5\r\n\r\n"), 1548 MockRead(false, "hello"), 1549 }; 1550 1551 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1552 data_writes1, arraysize(data_writes1)); 1553 session_deps.socket_factory.AddSocketDataProvider(&data1); 1554 SSLSocketDataProvider ssl(true, OK); 1555 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 1556 1557 TestCompletionCallback callback1; 1558 1559 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1560 1561 int rv = trans->Start(&request, &callback1, log.bound()); 1562 EXPECT_EQ(ERR_IO_PENDING, rv); 1563 1564 rv = callback1.WaitForResult(); 1565 EXPECT_EQ(OK, rv); 1566 net::CapturingNetLog::EntryList entries; 1567 log.GetEntries(&entries); 1568 size_t pos = ExpectLogContainsSomewhere( 1569 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 1570 NetLog::PHASE_NONE); 1571 ExpectLogContainsSomewhere( 1572 entries, pos, 1573 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 1574 NetLog::PHASE_NONE); 1575 1576 const HttpResponseInfo* response = trans->GetResponseInfo(); 1577 ASSERT_FALSE(response == NULL); 1578 1579 EXPECT_EQ(407, response->headers->response_code()); 1580 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 1581 1582 // The password prompt info should have been set in response->auth_challenge. 1583 ASSERT_FALSE(response->auth_challenge.get() == NULL); 1584 1585 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port); 1586 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1587 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1588 1589 TestCompletionCallback callback2; 1590 1591 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 1592 EXPECT_EQ(ERR_IO_PENDING, rv); 1593 1594 rv = callback2.WaitForResult(); 1595 EXPECT_EQ(OK, rv); 1596 1597 response = trans->GetResponseInfo(); 1598 ASSERT_FALSE(response == NULL); 1599 1600 EXPECT_TRUE(response->headers->IsKeepAlive()); 1601 EXPECT_EQ(200, response->headers->response_code()); 1602 EXPECT_EQ(5, response->headers->GetContentLength()); 1603 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 1604 1605 // The password prompt info should not be set. 1606 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1607 1608 trans.reset(); 1609 session->CloseAllConnections(); 1610 } 1611 1612 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 1613 // proxy connection, when setting up an SSL tunnel. 1614 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { 1615 HttpRequestInfo request; 1616 request.method = "GET"; 1617 request.url = GURL("https://www.google.com/"); 1618 // Ensure that proxy authentication is attempted even 1619 // when the no authentication data flag is set. 1620 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1621 1622 // Configure against proxy server "myproxy:70". 1623 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 1624 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 1625 session_deps.net_log = log.bound().net_log(); 1626 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1627 1628 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1629 1630 // Since we have proxy, should try to establish tunnel. 1631 MockWrite data_writes1[] = { 1632 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1633 "Host: www.google.com\r\n" 1634 "Proxy-Connection: keep-alive\r\n\r\n"), 1635 1636 // After calling trans->RestartWithAuth(), this is the request we should 1637 // be issuing -- the final header line contains the credentials. 1638 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1639 "Host: www.google.com\r\n" 1640 "Proxy-Connection: keep-alive\r\n" 1641 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 1642 }; 1643 1644 // The proxy responds to the connect with a 407, using a persistent 1645 // connection. 1646 MockRead data_reads1[] = { 1647 // No credentials. 1648 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 1649 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1650 MockRead("Content-Length: 10\r\n\r\n"), 1651 MockRead("0123456789"), 1652 1653 // Wrong credentials (wrong password). 1654 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 1655 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1656 MockRead("Content-Length: 10\r\n\r\n"), 1657 // No response body because the test stops reading here. 1658 MockRead(false, ERR_UNEXPECTED), // Should not be reached. 1659 }; 1660 1661 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1662 data_writes1, arraysize(data_writes1)); 1663 session_deps.socket_factory.AddSocketDataProvider(&data1); 1664 1665 TestCompletionCallback callback1; 1666 1667 int rv = trans->Start(&request, &callback1, log.bound()); 1668 EXPECT_EQ(ERR_IO_PENDING, rv); 1669 1670 rv = callback1.WaitForResult(); 1671 EXPECT_EQ(OK, rv); 1672 net::CapturingNetLog::EntryList entries; 1673 log.GetEntries(&entries); 1674 size_t pos = ExpectLogContainsSomewhere( 1675 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 1676 NetLog::PHASE_NONE); 1677 ExpectLogContainsSomewhere( 1678 entries, pos, 1679 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 1680 NetLog::PHASE_NONE); 1681 1682 const HttpResponseInfo* response = trans->GetResponseInfo(); 1683 EXPECT_FALSE(response == NULL); 1684 1685 EXPECT_TRUE(response->headers->IsKeepAlive()); 1686 EXPECT_EQ(407, response->headers->response_code()); 1687 EXPECT_EQ(10, response->headers->GetContentLength()); 1688 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 1689 1690 // The password prompt info should have been set in response->auth_challenge. 1691 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1692 1693 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port); 1694 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1695 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1696 1697 TestCompletionCallback callback2; 1698 1699 // Wrong password (should be "bar"). 1700 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2); 1701 EXPECT_EQ(ERR_IO_PENDING, rv); 1702 1703 rv = callback2.WaitForResult(); 1704 EXPECT_EQ(OK, rv); 1705 1706 response = trans->GetResponseInfo(); 1707 EXPECT_FALSE(response == NULL); 1708 1709 EXPECT_TRUE(response->headers->IsKeepAlive()); 1710 EXPECT_EQ(407, response->headers->response_code()); 1711 EXPECT_EQ(10, response->headers->GetContentLength()); 1712 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 1713 1714 // The password prompt info should have been set in response->auth_challenge. 1715 EXPECT_FALSE(response->auth_challenge.get() == NULL); 1716 1717 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port); 1718 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 1719 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 1720 1721 // Flush the idle socket before the NetLog and HttpNetworkTransaction go 1722 // out of scope. 1723 session->CloseAllConnections(); 1724 } 1725 1726 // Test that we don't read the response body when we fail to establish a tunnel, 1727 // even if the user cancels the proxy's auth attempt. 1728 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) { 1729 HttpRequestInfo request; 1730 request.method = "GET"; 1731 request.url = GURL("https://www.google.com/"); 1732 request.load_flags = 0; 1733 1734 // Configure against proxy server "myproxy:70". 1735 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 1736 1737 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1738 1739 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1740 1741 // Since we have proxy, should try to establish tunnel. 1742 MockWrite data_writes[] = { 1743 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1744 "Host: www.google.com\r\n" 1745 "Proxy-Connection: keep-alive\r\n\r\n"), 1746 }; 1747 1748 // The proxy responds to the connect with a 407. 1749 MockRead data_reads[] = { 1750 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 1751 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1752 MockRead("Content-Length: 10\r\n\r\n"), 1753 MockRead(false, ERR_UNEXPECTED), // Should not be reached. 1754 }; 1755 1756 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 1757 data_writes, arraysize(data_writes)); 1758 session_deps.socket_factory.AddSocketDataProvider(&data); 1759 1760 TestCompletionCallback callback; 1761 1762 int rv = trans->Start(&request, &callback, BoundNetLog()); 1763 EXPECT_EQ(ERR_IO_PENDING, rv); 1764 1765 rv = callback.WaitForResult(); 1766 EXPECT_EQ(OK, rv); 1767 1768 const HttpResponseInfo* response = trans->GetResponseInfo(); 1769 EXPECT_FALSE(response == NULL); 1770 1771 EXPECT_TRUE(response->headers->IsKeepAlive()); 1772 EXPECT_EQ(407, response->headers->response_code()); 1773 EXPECT_EQ(10, response->headers->GetContentLength()); 1774 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 1775 1776 std::string response_data; 1777 rv = ReadTransaction(trans.get(), &response_data); 1778 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 1779 1780 // Flush the idle socket before the HttpNetworkTransaction goes out of scope. 1781 session->CloseAllConnections(); 1782 } 1783 1784 // Test when a server (non-proxy) returns a 407 (proxy-authenticate). 1785 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH. 1786 TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) { 1787 HttpRequestInfo request; 1788 request.method = "GET"; 1789 request.url = GURL("http://www.google.com/"); 1790 request.load_flags = 0; 1791 1792 // We are using a DIRECT connection (i.e. no proxy) for this session. 1793 SessionDependencies session_deps; 1794 scoped_ptr<HttpTransaction> trans( 1795 new HttpNetworkTransaction(CreateSession(&session_deps))); 1796 1797 MockWrite data_writes1[] = { 1798 MockWrite("GET / HTTP/1.1\r\n" 1799 "Host: www.google.com\r\n" 1800 "Connection: keep-alive\r\n\r\n"), 1801 }; 1802 1803 MockRead data_reads1[] = { 1804 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"), 1805 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1806 // Large content-length -- won't matter, as connection will be reset. 1807 MockRead("Content-Length: 10000\r\n\r\n"), 1808 MockRead(false, ERR_FAILED), 1809 }; 1810 1811 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1812 data_writes1, arraysize(data_writes1)); 1813 session_deps.socket_factory.AddSocketDataProvider(&data1); 1814 1815 TestCompletionCallback callback; 1816 1817 int rv = trans->Start(&request, &callback, BoundNetLog()); 1818 EXPECT_EQ(ERR_IO_PENDING, rv); 1819 1820 rv = callback.WaitForResult(); 1821 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 1822 } 1823 1824 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication) 1825 // through a non-authenticating proxy. The request should fail with 1826 // ERR_UNEXPECTED_PROXY_AUTH. 1827 // Note that it is impossible to detect if an HTTP server returns a 407 through 1828 // a non-authenticating proxy - there is nothing to indicate whether the 1829 // response came from the proxy or the server, so it is treated as if the proxy 1830 // issued the challenge. 1831 TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) { 1832 HttpRequestInfo request; 1833 request.method = "GET"; 1834 request.url = GURL("https://www.google.com/"); 1835 1836 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 1837 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 1838 session_deps.net_log = log.bound().net_log(); 1839 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1840 1841 // Since we have proxy, should try to establish tunnel. 1842 MockWrite data_writes1[] = { 1843 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1844 "Host: www.google.com\r\n" 1845 "Proxy-Connection: keep-alive\r\n\r\n"), 1846 1847 MockWrite("GET / HTTP/1.1\r\n" 1848 "Host: www.google.com\r\n" 1849 "Connection: keep-alive\r\n\r\n"), 1850 }; 1851 1852 MockRead data_reads1[] = { 1853 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 1854 1855 MockRead("HTTP/1.1 407 Unauthorized\r\n"), 1856 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1857 MockRead("\r\n"), 1858 MockRead(false, OK), 1859 }; 1860 1861 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1862 data_writes1, arraysize(data_writes1)); 1863 session_deps.socket_factory.AddSocketDataProvider(&data1); 1864 SSLSocketDataProvider ssl(true, OK); 1865 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 1866 1867 TestCompletionCallback callback1; 1868 1869 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1870 1871 int rv = trans->Start(&request, &callback1, log.bound()); 1872 EXPECT_EQ(ERR_IO_PENDING, rv); 1873 1874 rv = callback1.WaitForResult(); 1875 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 1876 net::CapturingNetLog::EntryList entries; 1877 log.GetEntries(&entries); 1878 size_t pos = ExpectLogContainsSomewhere( 1879 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 1880 NetLog::PHASE_NONE); 1881 ExpectLogContainsSomewhere( 1882 entries, pos, 1883 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 1884 NetLog::PHASE_NONE); 1885 } 1886 1887 // Test a simple get through an HTTPS Proxy. 1888 TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) { 1889 HttpRequestInfo request; 1890 request.method = "GET"; 1891 request.url = GURL("http://www.google.com/"); 1892 1893 // Configure against https proxy server "proxy:70". 1894 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 1895 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 1896 session_deps.net_log = log.bound().net_log(); 1897 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1898 1899 // Since we have proxy, should use full url 1900 MockWrite data_writes1[] = { 1901 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 1902 "Host: www.google.com\r\n" 1903 "Proxy-Connection: keep-alive\r\n\r\n"), 1904 }; 1905 1906 MockRead data_reads1[] = { 1907 MockRead("HTTP/1.1 200 OK\r\n"), 1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1909 MockRead("Content-Length: 100\r\n\r\n"), 1910 MockRead(false, OK), 1911 }; 1912 1913 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1914 data_writes1, arraysize(data_writes1)); 1915 session_deps.socket_factory.AddSocketDataProvider(&data1); 1916 SSLSocketDataProvider ssl(true, OK); 1917 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 1918 1919 TestCompletionCallback callback1; 1920 1921 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1922 1923 int rv = trans->Start(&request, &callback1, log.bound()); 1924 EXPECT_EQ(ERR_IO_PENDING, rv); 1925 1926 rv = callback1.WaitForResult(); 1927 EXPECT_EQ(OK, rv); 1928 1929 const HttpResponseInfo* response = trans->GetResponseInfo(); 1930 ASSERT_FALSE(response == NULL); 1931 1932 EXPECT_TRUE(response->headers->IsKeepAlive()); 1933 EXPECT_EQ(200, response->headers->response_code()); 1934 EXPECT_EQ(100, response->headers->GetContentLength()); 1935 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 1936 1937 // The password prompt info should not be set. 1938 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1939 } 1940 1941 // Test a SPDY get through an HTTPS Proxy. 1942 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) { 1943 HttpRequestInfo request; 1944 request.method = "GET"; 1945 request.url = GURL("http://www.google.com/"); 1946 request.load_flags = 0; 1947 1948 // Configure against https proxy server "proxy:70". 1949 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 1950 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 1951 session_deps.net_log = log.bound().net_log(); 1952 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 1953 1954 // fetch http://www.google.com/ via SPDY 1955 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST, 1956 false)); 1957 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 1958 1959 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 1960 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 1961 MockRead spdy_reads[] = { 1962 CreateMockRead(*resp), 1963 CreateMockRead(*data), 1964 MockRead(true, 0, 0), 1965 }; 1966 1967 scoped_refptr<DelayedSocketData> spdy_data( 1968 new DelayedSocketData( 1969 1, // wait for one write to finish before reading. 1970 spdy_reads, arraysize(spdy_reads), 1971 spdy_writes, arraysize(spdy_writes))); 1972 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 1973 1974 SSLSocketDataProvider ssl(true, OK); 1975 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 1976 ssl.next_proto = "spdy/2"; 1977 ssl.was_npn_negotiated = true; 1978 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 1979 1980 TestCompletionCallback callback1; 1981 1982 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 1983 1984 int rv = trans->Start(&request, &callback1, log.bound()); 1985 EXPECT_EQ(ERR_IO_PENDING, rv); 1986 1987 rv = callback1.WaitForResult(); 1988 EXPECT_EQ(OK, rv); 1989 1990 const HttpResponseInfo* response = trans->GetResponseInfo(); 1991 ASSERT_TRUE(response != NULL); 1992 ASSERT_TRUE(response->headers != NULL); 1993 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1994 1995 std::string response_data; 1996 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 1997 EXPECT_EQ(net::kUploadData, response_data); 1998 } 1999 2000 // Test a SPDY get through an HTTPS Proxy. 2001 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) { 2002 HttpRequestInfo request; 2003 request.method = "GET"; 2004 request.url = GURL("http://www.google.com/"); 2005 request.load_flags = 0; 2006 2007 // Configure against https proxy server "proxy:70". 2008 SessionDependencies session_deps( 2009 ProxyService::CreateFixed("https://proxy:70")); 2010 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 2011 session_deps.net_log = log.bound().net_log(); 2012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2013 2014 // The first request will be a bare GET, the second request will be a 2015 // GET with a Proxy-Authorization header. 2016 scoped_ptr<spdy::SpdyFrame> req_get( 2017 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 2018 const char* const kExtraAuthorizationHeaders[] = { 2019 "proxy-authorization", 2020 "Basic Zm9vOmJhcg==", 2021 }; 2022 scoped_ptr<spdy::SpdyFrame> req_get_authorization( 2023 ConstructSpdyGet( 2024 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2, 2025 false, 3, LOWEST, false)); 2026 MockWrite spdy_writes[] = { 2027 CreateMockWrite(*req_get, 1), 2028 CreateMockWrite(*req_get_authorization, 4), 2029 }; 2030 2031 // The first response is a 407 proxy authentication challenge, and the second 2032 // response will be a 200 response since the second request includes a valid 2033 // Authorization header. 2034 const char* const kExtraAuthenticationHeaders[] = { 2035 "Proxy-Authenticate", 2036 "Basic realm=\"MyRealm1\"" 2037 }; 2038 scoped_ptr<spdy::SpdyFrame> resp_authentication( 2039 ConstructSpdySynReplyError( 2040 "407 Proxy Authentication Required", 2041 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2, 2042 1)); 2043 scoped_ptr<spdy::SpdyFrame> body_authentication( 2044 ConstructSpdyBodyFrame(1, true)); 2045 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3)); 2046 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true)); 2047 MockRead spdy_reads[] = { 2048 CreateMockRead(*resp_authentication, 2), 2049 CreateMockRead(*body_authentication, 3), 2050 CreateMockRead(*resp_data, 5), 2051 CreateMockRead(*body_data, 6), 2052 MockRead(true, 0, 7), 2053 }; 2054 2055 scoped_refptr<OrderedSocketData> data( 2056 new OrderedSocketData(spdy_reads, arraysize(spdy_reads), 2057 spdy_writes, arraysize(spdy_writes))); 2058 session_deps.socket_factory.AddSocketDataProvider(data); 2059 2060 SSLSocketDataProvider ssl(true, OK); 2061 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 2062 ssl.next_proto = "spdy/2"; 2063 ssl.was_npn_negotiated = true; 2064 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 2065 2066 TestCompletionCallback callback1; 2067 2068 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2069 2070 int rv = trans->Start(&request, &callback1, log.bound()); 2071 EXPECT_EQ(ERR_IO_PENDING, rv); 2072 2073 rv = callback1.WaitForResult(); 2074 EXPECT_EQ(OK, rv); 2075 2076 const HttpResponseInfo* const response = trans->GetResponseInfo(); 2077 2078 ASSERT_TRUE(response != NULL); 2079 ASSERT_TRUE(response->headers != NULL); 2080 EXPECT_EQ(407, response->headers->response_code()); 2081 EXPECT_TRUE(response->was_fetched_via_spdy); 2082 2083 // The password prompt info should have been set in response->auth_challenge. 2084 ASSERT_TRUE(response->auth_challenge.get() != NULL); 2085 EXPECT_TRUE(response->auth_challenge->is_proxy); 2086 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port); 2087 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 2088 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 2089 2090 TestCompletionCallback callback2; 2091 2092 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 2093 EXPECT_EQ(ERR_IO_PENDING, rv); 2094 2095 rv = callback2.WaitForResult(); 2096 EXPECT_EQ(OK, rv); 2097 2098 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); 2099 2100 ASSERT_TRUE(response_restart != NULL); 2101 ASSERT_TRUE(response_restart->headers != NULL); 2102 EXPECT_EQ(200, response_restart->headers->response_code()); 2103 // The password prompt info should not be set. 2104 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); 2105 } 2106 2107 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server. 2108 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) { 2109 HttpRequestInfo request; 2110 request.method = "GET"; 2111 request.url = GURL("https://www.google.com/"); 2112 request.load_flags = 0; 2113 2114 // Configure against https proxy server "proxy:70". 2115 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 2116 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 2117 session_deps.net_log = log.bound().net_log(); 2118 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2119 2120 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2121 2122 // CONNECT to www.google.com:443 via SPDY 2123 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1)); 2124 // fetch https://www.google.com/ via HTTP 2125 2126 const char get[] = "GET / HTTP/1.1\r\n" 2127 "Host: www.google.com\r\n" 2128 "Connection: keep-alive\r\n\r\n"; 2129 scoped_ptr<spdy::SpdyFrame> wrapped_get( 2130 ConstructSpdyBodyFrame(1, get, strlen(get), false)); 2131 MockWrite spdy_writes[] = { 2132 CreateMockWrite(*connect, 1), 2133 CreateMockWrite(*wrapped_get, 3) 2134 }; 2135 2136 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 2137 const char resp[] = "HTTP/1.1 200 OK\r\n" 2138 "Content-Length: 10\r\n\r\n"; 2139 2140 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp( 2141 ConstructSpdyBodyFrame(1, resp, strlen(resp), false)); 2142 scoped_ptr<spdy::SpdyFrame> wrapped_body( 2143 ConstructSpdyBodyFrame(1, "1234567890", 10, false)); 2144 MockRead spdy_reads[] = { 2145 CreateMockRead(*conn_resp, 2, true), 2146 CreateMockRead(*wrapped_get_resp, 4, true), 2147 CreateMockRead(*wrapped_body, 5, true), 2148 CreateMockRead(*wrapped_body, 6, true), 2149 MockRead(true, 0, 7), 2150 }; 2151 2152 scoped_refptr<OrderedSocketData> spdy_data( 2153 new OrderedSocketData( 2154 spdy_reads, arraysize(spdy_reads), 2155 spdy_writes, arraysize(spdy_writes))); 2156 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 2157 2158 SSLSocketDataProvider ssl(true, OK); 2159 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 2160 ssl.next_proto = "spdy/2"; 2161 ssl.was_npn_negotiated = true; 2162 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 2163 SSLSocketDataProvider ssl2(true, OK); 2164 ssl2.was_npn_negotiated = false; 2165 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2); 2166 2167 TestCompletionCallback callback1; 2168 2169 int rv = trans->Start(&request, &callback1, log.bound()); 2170 EXPECT_EQ(ERR_IO_PENDING, rv); 2171 2172 rv = callback1.WaitForResult(); 2173 EXPECT_EQ(OK, rv); 2174 2175 const HttpResponseInfo* response = trans->GetResponseInfo(); 2176 ASSERT_TRUE(response != NULL); 2177 ASSERT_TRUE(response->headers != NULL); 2178 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 2179 2180 std::string response_data; 2181 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 2182 EXPECT_EQ("1234567890", response_data); 2183 } 2184 2185 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server. 2186 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) { 2187 HttpRequestInfo request; 2188 request.method = "GET"; 2189 request.url = GURL("https://www.google.com/"); 2190 request.load_flags = 0; 2191 2192 // Configure against https proxy server "proxy:70". 2193 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 2194 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 2195 session_deps.net_log = log.bound().net_log(); 2196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2197 2198 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2199 2200 // CONNECT to www.google.com:443 via SPDY 2201 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1)); 2202 // fetch https://www.google.com/ via SPDY 2203 const char* const kMyUrl = "https://www.google.com/"; 2204 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST)); 2205 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1)); 2206 MockWrite spdy_writes[] = { 2207 CreateMockWrite(*connect, 1), 2208 CreateMockWrite(*wrapped_get, 3) 2209 }; 2210 2211 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 2212 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 2213 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp( 2214 ConstructWrappedSpdyFrame(get_resp, 1)); 2215 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); 2216 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1)); 2217 MockRead spdy_reads[] = { 2218 CreateMockRead(*conn_resp, 2, true), 2219 CreateMockRead(*wrapped_get_resp, 4, true), 2220 CreateMockRead(*wrapped_body, 5, true), 2221 MockRead(true, 0, 1), 2222 }; 2223 2224 scoped_refptr<OrderedSocketData> spdy_data( 2225 new OrderedSocketData( 2226 spdy_reads, arraysize(spdy_reads), 2227 spdy_writes, arraysize(spdy_writes))); 2228 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 2229 2230 SSLSocketDataProvider ssl(true, OK); 2231 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 2232 ssl.next_proto = "spdy/2"; 2233 ssl.was_npn_negotiated = true; 2234 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 2235 SSLSocketDataProvider ssl2(true, OK); 2236 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 2237 ssl2.next_proto = "spdy/2"; 2238 ssl2.was_npn_negotiated = true; 2239 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2); 2240 2241 TestCompletionCallback callback1; 2242 2243 int rv = trans->Start(&request, &callback1, log.bound()); 2244 EXPECT_EQ(ERR_IO_PENDING, rv); 2245 2246 rv = callback1.WaitForResult(); 2247 EXPECT_EQ(OK, rv); 2248 2249 const HttpResponseInfo* response = trans->GetResponseInfo(); 2250 ASSERT_TRUE(response != NULL); 2251 ASSERT_TRUE(response->headers != NULL); 2252 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 2253 2254 std::string response_data; 2255 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 2256 EXPECT_EQ(net::kUploadData, response_data); 2257 } 2258 2259 // Test a SPDY CONNECT failure through an HTTPS Proxy. 2260 TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) { 2261 HttpRequestInfo request; 2262 request.method = "GET"; 2263 request.url = GURL("https://www.google.com/"); 2264 request.load_flags = 0; 2265 2266 // Configure against https proxy server "proxy:70". 2267 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 2268 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 2269 session_deps.net_log = log.bound().net_log(); 2270 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2271 2272 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2273 2274 // CONNECT to www.google.com:443 via SPDY 2275 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1)); 2276 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL)); 2277 2278 MockWrite spdy_writes[] = { 2279 CreateMockWrite(*connect, 1), 2280 CreateMockWrite(*get, 3), 2281 }; 2282 2283 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1)); 2284 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 2285 MockRead spdy_reads[] = { 2286 CreateMockRead(*resp, 2, true), 2287 MockRead(true, 0, 4), 2288 }; 2289 2290 scoped_refptr<OrderedSocketData> spdy_data( 2291 new OrderedSocketData( 2292 spdy_reads, arraysize(spdy_reads), 2293 spdy_writes, arraysize(spdy_writes))); 2294 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 2295 2296 SSLSocketDataProvider ssl(true, OK); 2297 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 2298 ssl.next_proto = "spdy/2"; 2299 ssl.was_npn_negotiated = true; 2300 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 2301 SSLSocketDataProvider ssl2(true, OK); 2302 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 2303 ssl2.next_proto = "spdy/2"; 2304 ssl2.was_npn_negotiated = true; 2305 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2); 2306 2307 TestCompletionCallback callback1; 2308 2309 int rv = trans->Start(&request, &callback1, log.bound()); 2310 EXPECT_EQ(ERR_IO_PENDING, rv); 2311 2312 rv = callback1.WaitForResult(); 2313 EXPECT_EQ(OK, rv); 2314 2315 const HttpResponseInfo* response = trans->GetResponseInfo(); 2316 ASSERT_FALSE(response == NULL); 2317 EXPECT_EQ(500, response->headers->response_code()); 2318 } 2319 2320 // Test the challenge-response-retry sequence through an HTTPS Proxy 2321 TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) { 2322 HttpRequestInfo request; 2323 request.method = "GET"; 2324 request.url = GURL("http://www.google.com/"); 2325 // when the no authentication data flag is set. 2326 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 2327 2328 // Configure against https proxy server "proxy:70". 2329 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 2330 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 2331 session_deps.net_log = log.bound().net_log(); 2332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2333 2334 // Since we have proxy, should use full url 2335 MockWrite data_writes1[] = { 2336 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2337 "Host: www.google.com\r\n" 2338 "Proxy-Connection: keep-alive\r\n\r\n"), 2339 2340 // After calling trans->RestartWithAuth(), this is the request we should 2341 // be issuing -- the final header line contains the credentials. 2342 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2343 "Host: www.google.com\r\n" 2344 "Proxy-Connection: keep-alive\r\n" 2345 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2346 }; 2347 2348 // The proxy responds to the GET with a 407, using a persistent 2349 // connection. 2350 MockRead data_reads1[] = { 2351 // No credentials. 2352 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2353 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2354 MockRead("Proxy-Connection: keep-alive\r\n"), 2355 MockRead("Content-Length: 0\r\n\r\n"), 2356 2357 MockRead("HTTP/1.1 200 OK\r\n"), 2358 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2359 MockRead("Content-Length: 100\r\n\r\n"), 2360 MockRead(false, OK), 2361 }; 2362 2363 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2364 data_writes1, arraysize(data_writes1)); 2365 session_deps.socket_factory.AddSocketDataProvider(&data1); 2366 SSLSocketDataProvider ssl(true, OK); 2367 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 2368 2369 TestCompletionCallback callback1; 2370 2371 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2372 2373 int rv = trans->Start(&request, &callback1, log.bound()); 2374 EXPECT_EQ(ERR_IO_PENDING, rv); 2375 2376 rv = callback1.WaitForResult(); 2377 EXPECT_EQ(OK, rv); 2378 2379 const HttpResponseInfo* response = trans->GetResponseInfo(); 2380 ASSERT_FALSE(response == NULL); 2381 2382 EXPECT_EQ(407, response->headers->response_code()); 2383 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2384 2385 // The password prompt info should have been set in response->auth_challenge. 2386 ASSERT_FALSE(response->auth_challenge.get() == NULL); 2387 2388 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port); 2389 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 2390 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 2391 2392 TestCompletionCallback callback2; 2393 2394 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 2395 EXPECT_EQ(ERR_IO_PENDING, rv); 2396 2397 rv = callback2.WaitForResult(); 2398 EXPECT_EQ(OK, rv); 2399 2400 response = trans->GetResponseInfo(); 2401 ASSERT_FALSE(response == NULL); 2402 2403 EXPECT_TRUE(response->headers->IsKeepAlive()); 2404 EXPECT_EQ(200, response->headers->response_code()); 2405 EXPECT_EQ(100, response->headers->GetContentLength()); 2406 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2407 2408 // The password prompt info should not be set. 2409 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2410 } 2411 2412 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( 2413 const MockRead& status, int expected_status) { 2414 HttpRequestInfo request; 2415 request.method = "GET"; 2416 request.url = GURL("https://www.google.com/"); 2417 request.load_flags = 0; 2418 2419 // Configure against proxy server "myproxy:70". 2420 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 2421 2422 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2423 2424 // Since we have proxy, should try to establish tunnel. 2425 MockWrite data_writes[] = { 2426 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2427 "Host: www.google.com\r\n" 2428 "Proxy-Connection: keep-alive\r\n\r\n"), 2429 }; 2430 2431 MockRead data_reads[] = { 2432 status, 2433 MockRead("Content-Length: 10\r\n\r\n"), 2434 // No response body because the test stops reading here. 2435 MockRead(false, ERR_UNEXPECTED), // Should not be reached. 2436 }; 2437 2438 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 2439 data_writes, arraysize(data_writes)); 2440 session_deps.socket_factory.AddSocketDataProvider(&data); 2441 2442 TestCompletionCallback callback; 2443 2444 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2445 2446 int rv = trans->Start(&request, &callback, BoundNetLog()); 2447 EXPECT_EQ(ERR_IO_PENDING, rv); 2448 2449 rv = callback.WaitForResult(); 2450 EXPECT_EQ(expected_status, rv); 2451 } 2452 2453 void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) { 2454 ConnectStatusHelperWithExpectedStatus( 2455 status, ERR_TUNNEL_CONNECTION_FAILED); 2456 } 2457 2458 TEST_F(HttpNetworkTransactionTest, ConnectStatus100) { 2459 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n")); 2460 } 2461 2462 TEST_F(HttpNetworkTransactionTest, ConnectStatus101) { 2463 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n")); 2464 } 2465 2466 TEST_F(HttpNetworkTransactionTest, ConnectStatus201) { 2467 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n")); 2468 } 2469 2470 TEST_F(HttpNetworkTransactionTest, ConnectStatus202) { 2471 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n")); 2472 } 2473 2474 TEST_F(HttpNetworkTransactionTest, ConnectStatus203) { 2475 ConnectStatusHelper( 2476 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n")); 2477 } 2478 2479 TEST_F(HttpNetworkTransactionTest, ConnectStatus204) { 2480 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n")); 2481 } 2482 2483 TEST_F(HttpNetworkTransactionTest, ConnectStatus205) { 2484 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n")); 2485 } 2486 2487 TEST_F(HttpNetworkTransactionTest, ConnectStatus206) { 2488 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n")); 2489 } 2490 2491 TEST_F(HttpNetworkTransactionTest, ConnectStatus300) { 2492 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n")); 2493 } 2494 2495 TEST_F(HttpNetworkTransactionTest, ConnectStatus301) { 2496 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n")); 2497 } 2498 2499 TEST_F(HttpNetworkTransactionTest, ConnectStatus302) { 2500 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n")); 2501 } 2502 2503 TEST_F(HttpNetworkTransactionTest, ConnectStatus303) { 2504 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n")); 2505 } 2506 2507 TEST_F(HttpNetworkTransactionTest, ConnectStatus304) { 2508 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n")); 2509 } 2510 2511 TEST_F(HttpNetworkTransactionTest, ConnectStatus305) { 2512 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n")); 2513 } 2514 2515 TEST_F(HttpNetworkTransactionTest, ConnectStatus306) { 2516 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n")); 2517 } 2518 2519 TEST_F(HttpNetworkTransactionTest, ConnectStatus307) { 2520 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n")); 2521 } 2522 2523 TEST_F(HttpNetworkTransactionTest, ConnectStatus400) { 2524 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n")); 2525 } 2526 2527 TEST_F(HttpNetworkTransactionTest, ConnectStatus401) { 2528 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n")); 2529 } 2530 2531 TEST_F(HttpNetworkTransactionTest, ConnectStatus402) { 2532 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n")); 2533 } 2534 2535 TEST_F(HttpNetworkTransactionTest, ConnectStatus403) { 2536 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n")); 2537 } 2538 2539 TEST_F(HttpNetworkTransactionTest, ConnectStatus404) { 2540 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n")); 2541 } 2542 2543 TEST_F(HttpNetworkTransactionTest, ConnectStatus405) { 2544 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n")); 2545 } 2546 2547 TEST_F(HttpNetworkTransactionTest, ConnectStatus406) { 2548 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n")); 2549 } 2550 2551 TEST_F(HttpNetworkTransactionTest, ConnectStatus407) { 2552 ConnectStatusHelperWithExpectedStatus( 2553 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2554 ERR_PROXY_AUTH_UNSUPPORTED); 2555 } 2556 2557 TEST_F(HttpNetworkTransactionTest, ConnectStatus408) { 2558 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n")); 2559 } 2560 2561 TEST_F(HttpNetworkTransactionTest, ConnectStatus409) { 2562 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n")); 2563 } 2564 2565 TEST_F(HttpNetworkTransactionTest, ConnectStatus410) { 2566 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n")); 2567 } 2568 2569 TEST_F(HttpNetworkTransactionTest, ConnectStatus411) { 2570 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n")); 2571 } 2572 2573 TEST_F(HttpNetworkTransactionTest, ConnectStatus412) { 2574 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n")); 2575 } 2576 2577 TEST_F(HttpNetworkTransactionTest, ConnectStatus413) { 2578 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n")); 2579 } 2580 2581 TEST_F(HttpNetworkTransactionTest, ConnectStatus414) { 2582 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n")); 2583 } 2584 2585 TEST_F(HttpNetworkTransactionTest, ConnectStatus415) { 2586 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n")); 2587 } 2588 2589 TEST_F(HttpNetworkTransactionTest, ConnectStatus416) { 2590 ConnectStatusHelper( 2591 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n")); 2592 } 2593 2594 TEST_F(HttpNetworkTransactionTest, ConnectStatus417) { 2595 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n")); 2596 } 2597 2598 TEST_F(HttpNetworkTransactionTest, ConnectStatus500) { 2599 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n")); 2600 } 2601 2602 TEST_F(HttpNetworkTransactionTest, ConnectStatus501) { 2603 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n")); 2604 } 2605 2606 TEST_F(HttpNetworkTransactionTest, ConnectStatus502) { 2607 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n")); 2608 } 2609 2610 TEST_F(HttpNetworkTransactionTest, ConnectStatus503) { 2611 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n")); 2612 } 2613 2614 TEST_F(HttpNetworkTransactionTest, ConnectStatus504) { 2615 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n")); 2616 } 2617 2618 TEST_F(HttpNetworkTransactionTest, ConnectStatus505) { 2619 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n")); 2620 } 2621 2622 // Test the flow when both the proxy server AND origin server require 2623 // authentication. Again, this uses basic auth for both since that is 2624 // the simplest to mock. 2625 TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { 2626 HttpRequestInfo request; 2627 request.method = "GET"; 2628 request.url = GURL("http://www.google.com/"); 2629 request.load_flags = 0; 2630 2631 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 2632 2633 // Configure against proxy server "myproxy:70". 2634 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction( 2635 CreateSession(&session_deps))); 2636 2637 MockWrite data_writes1[] = { 2638 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2639 "Host: www.google.com\r\n" 2640 "Proxy-Connection: keep-alive\r\n\r\n"), 2641 }; 2642 2643 MockRead data_reads1[] = { 2644 MockRead("HTTP/1.0 407 Unauthorized\r\n"), 2645 // Give a couple authenticate options (only the middle one is actually 2646 // supported). 2647 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed. 2648 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2649 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 2650 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2651 // Large content-length -- won't matter, as connection will be reset. 2652 MockRead("Content-Length: 10000\r\n\r\n"), 2653 MockRead(false, ERR_FAILED), 2654 }; 2655 2656 // After calling trans->RestartWithAuth() the first time, this is the 2657 // request we should be issuing -- the final header line contains the 2658 // proxy's credentials. 2659 MockWrite data_writes2[] = { 2660 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2661 "Host: www.google.com\r\n" 2662 "Proxy-Connection: keep-alive\r\n" 2663 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2664 }; 2665 2666 // Now the proxy server lets the request pass through to origin server. 2667 // The origin server responds with a 401. 2668 MockRead data_reads2[] = { 2669 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 2670 // Note: We are using the same realm-name as the proxy server. This is 2671 // completely valid, as realms are unique across hosts. 2672 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2673 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2674 MockRead("Content-Length: 2000\r\n\r\n"), 2675 MockRead(false, ERR_FAILED), // Won't be reached. 2676 }; 2677 2678 // After calling trans->RestartWithAuth() the second time, we should send 2679 // the credentials for both the proxy and origin server. 2680 MockWrite data_writes3[] = { 2681 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2682 "Host: www.google.com\r\n" 2683 "Proxy-Connection: keep-alive\r\n" 2684 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n" 2685 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 2686 }; 2687 2688 // Lastly we get the desired content. 2689 MockRead data_reads3[] = { 2690 MockRead("HTTP/1.0 200 OK\r\n"), 2691 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2692 MockRead("Content-Length: 100\r\n\r\n"), 2693 MockRead(false, OK), 2694 }; 2695 2696 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2697 data_writes1, arraysize(data_writes1)); 2698 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2699 data_writes2, arraysize(data_writes2)); 2700 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 2701 data_writes3, arraysize(data_writes3)); 2702 session_deps.socket_factory.AddSocketDataProvider(&data1); 2703 session_deps.socket_factory.AddSocketDataProvider(&data2); 2704 session_deps.socket_factory.AddSocketDataProvider(&data3); 2705 2706 TestCompletionCallback callback1; 2707 2708 int rv = trans->Start(&request, &callback1, BoundNetLog()); 2709 EXPECT_EQ(ERR_IO_PENDING, rv); 2710 2711 rv = callback1.WaitForResult(); 2712 EXPECT_EQ(OK, rv); 2713 2714 const HttpResponseInfo* response = trans->GetResponseInfo(); 2715 EXPECT_FALSE(response == NULL); 2716 2717 // The password prompt info should have been set in response->auth_challenge. 2718 EXPECT_FALSE(response->auth_challenge.get() == NULL); 2719 2720 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port); 2721 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 2722 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 2723 2724 TestCompletionCallback callback2; 2725 2726 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 2727 EXPECT_EQ(ERR_IO_PENDING, rv); 2728 2729 rv = callback2.WaitForResult(); 2730 EXPECT_EQ(OK, rv); 2731 2732 response = trans->GetResponseInfo(); 2733 EXPECT_FALSE(response == NULL); 2734 EXPECT_FALSE(response->auth_challenge.get() == NULL); 2735 2736 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 2737 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 2738 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 2739 2740 TestCompletionCallback callback3; 2741 2742 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3); 2743 EXPECT_EQ(ERR_IO_PENDING, rv); 2744 2745 rv = callback3.WaitForResult(); 2746 EXPECT_EQ(OK, rv); 2747 2748 response = trans->GetResponseInfo(); 2749 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2750 EXPECT_EQ(100, response->headers->GetContentLength()); 2751 } 2752 2753 // For the NTLM implementation using SSPI, we skip the NTLM tests since we 2754 // can't hook into its internals to cause it to generate predictable NTLM 2755 // authorization headers. 2756 #if defined(NTLM_PORTABLE) 2757 // The NTLM authentication unit tests were generated by capturing the HTTP 2758 // requests and responses using Fiddler 2 and inspecting the generated random 2759 // bytes in the debugger. 2760 2761 // Enter the correct password and authenticate successfully. 2762 TEST_F(HttpNetworkTransactionTest, NTLMAuth1) { 2763 HttpRequestInfo request; 2764 request.method = "GET"; 2765 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 2766 request.load_flags = 0; 2767 2768 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1, 2769 MockGetHostName); 2770 SessionDependencies session_deps; 2771 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2772 2773 MockWrite data_writes1[] = { 2774 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2775 "Host: 172.22.68.17\r\n" 2776 "Connection: keep-alive\r\n\r\n"), 2777 }; 2778 2779 MockRead data_reads1[] = { 2780 MockRead("HTTP/1.1 401 Access Denied\r\n"), 2781 // Negotiate and NTLM are often requested together. However, we only want 2782 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 2783 // the header that requests Negotiate for this test. 2784 MockRead("WWW-Authenticate: NTLM\r\n"), 2785 MockRead("Connection: close\r\n"), 2786 MockRead("Content-Length: 42\r\n"), 2787 MockRead("Content-Type: text/html\r\n\r\n"), 2788 // Missing content -- won't matter, as connection will be reset. 2789 MockRead(false, ERR_UNEXPECTED), 2790 }; 2791 2792 MockWrite data_writes2[] = { 2793 // After restarting with a null identity, this is the 2794 // request we should be issuing -- the final header line contains a Type 2795 // 1 message. 2796 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2797 "Host: 172.22.68.17\r\n" 2798 "Connection: keep-alive\r\n" 2799 "Authorization: NTLM " 2800 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 2801 2802 // After calling trans->RestartWithAuth(), we should send a Type 3 message 2803 // (the credentials for the origin server). The second request continues 2804 // on the same connection. 2805 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2806 "Host: 172.22.68.17\r\n" 2807 "Connection: keep-alive\r\n" 2808 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 2809 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 2810 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW" 2811 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX" 2812 "ahlhx5I=\r\n\r\n"), 2813 }; 2814 2815 MockRead data_reads2[] = { 2816 // The origin server responds with a Type 2 message. 2817 MockRead("HTTP/1.1 401 Access Denied\r\n"), 2818 MockRead("WWW-Authenticate: NTLM " 2819 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo" 2820 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 2821 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 2822 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 2823 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 2824 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 2825 "BtAAAAAAA=\r\n"), 2826 MockRead("Content-Length: 42\r\n"), 2827 MockRead("Content-Type: text/html\r\n\r\n"), 2828 MockRead("You are not authorized to view this page\r\n"), 2829 2830 // Lastly we get the desired content. 2831 MockRead("HTTP/1.1 200 OK\r\n"), 2832 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 2833 MockRead("Content-Length: 13\r\n\r\n"), 2834 MockRead("Please Login\r\n"), 2835 MockRead(false, OK), 2836 }; 2837 2838 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2839 data_writes1, arraysize(data_writes1)); 2840 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2841 data_writes2, arraysize(data_writes2)); 2842 session_deps.socket_factory.AddSocketDataProvider(&data1); 2843 session_deps.socket_factory.AddSocketDataProvider(&data2); 2844 2845 TestCompletionCallback callback1; 2846 2847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 2848 2849 int rv = trans->Start(&request, &callback1, BoundNetLog()); 2850 EXPECT_EQ(ERR_IO_PENDING, rv); 2851 2852 rv = callback1.WaitForResult(); 2853 EXPECT_EQ(OK, rv); 2854 2855 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 2856 2857 const HttpResponseInfo* response = trans->GetResponseInfo(); 2858 ASSERT_TRUE(response != NULL); 2859 2860 // The password prompt info should have been set in 2861 // response->auth_challenge. 2862 ASSERT_FALSE(response->auth_challenge.get() == NULL); 2863 2864 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port); 2865 EXPECT_EQ(L"", response->auth_challenge->realm); 2866 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme); 2867 2868 TestCompletionCallback callback2; 2869 2870 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2); 2871 EXPECT_EQ(ERR_IO_PENDING, rv); 2872 2873 rv = callback2.WaitForResult(); 2874 EXPECT_EQ(OK, rv); 2875 2876 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 2877 2878 response = trans->GetResponseInfo(); 2879 ASSERT_TRUE(response != NULL); 2880 2881 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2882 2883 TestCompletionCallback callback3; 2884 2885 rv = trans->RestartWithAuth(string16(), string16(), &callback3); 2886 EXPECT_EQ(ERR_IO_PENDING, rv); 2887 2888 rv = callback3.WaitForResult(); 2889 EXPECT_EQ(OK, rv); 2890 2891 response = trans->GetResponseInfo(); 2892 ASSERT_FALSE(response == NULL); 2893 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2894 EXPECT_EQ(13, response->headers->GetContentLength()); 2895 } 2896 2897 // Enter a wrong password, and then the correct one. 2898 TEST_F(HttpNetworkTransactionTest, NTLMAuth2) { 2899 HttpRequestInfo request; 2900 request.method = "GET"; 2901 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 2902 request.load_flags = 0; 2903 2904 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2, 2905 MockGetHostName); 2906 SessionDependencies session_deps; 2907 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 2908 2909 MockWrite data_writes1[] = { 2910 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2911 "Host: 172.22.68.17\r\n" 2912 "Connection: keep-alive\r\n\r\n"), 2913 }; 2914 2915 MockRead data_reads1[] = { 2916 MockRead("HTTP/1.1 401 Access Denied\r\n"), 2917 // Negotiate and NTLM are often requested together. However, we only want 2918 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 2919 // the header that requests Negotiate for this test. 2920 MockRead("WWW-Authenticate: NTLM\r\n"), 2921 MockRead("Connection: close\r\n"), 2922 MockRead("Content-Length: 42\r\n"), 2923 MockRead("Content-Type: text/html\r\n\r\n"), 2924 // Missing content -- won't matter, as connection will be reset. 2925 MockRead(false, ERR_UNEXPECTED), 2926 }; 2927 2928 MockWrite data_writes2[] = { 2929 // After restarting with a null identity, this is the 2930 // request we should be issuing -- the final header line contains a Type 2931 // 1 message. 2932 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2933 "Host: 172.22.68.17\r\n" 2934 "Connection: keep-alive\r\n" 2935 "Authorization: NTLM " 2936 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 2937 2938 // After calling trans->RestartWithAuth(), we should send a Type 3 message 2939 // (the credentials for the origin server). The second request continues 2940 // on the same connection. 2941 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2942 "Host: 172.22.68.17\r\n" 2943 "Connection: keep-alive\r\n" 2944 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 2945 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 2946 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY" 2947 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj" 2948 "4Ww7b7E=\r\n\r\n"), 2949 }; 2950 2951 MockRead data_reads2[] = { 2952 // The origin server responds with a Type 2 message. 2953 MockRead("HTTP/1.1 401 Access Denied\r\n"), 2954 MockRead("WWW-Authenticate: NTLM " 2955 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo" 2956 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 2957 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 2958 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 2959 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 2960 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 2961 "BtAAAAAAA=\r\n"), 2962 MockRead("Content-Length: 42\r\n"), 2963 MockRead("Content-Type: text/html\r\n\r\n"), 2964 MockRead("You are not authorized to view this page\r\n"), 2965 2966 // Wrong password. 2967 MockRead("HTTP/1.1 401 Access Denied\r\n"), 2968 MockRead("WWW-Authenticate: NTLM\r\n"), 2969 MockRead("Connection: close\r\n"), 2970 MockRead("Content-Length: 42\r\n"), 2971 MockRead("Content-Type: text/html\r\n\r\n"), 2972 // Missing content -- won't matter, as connection will be reset. 2973 MockRead(false, ERR_UNEXPECTED), 2974 }; 2975 2976 MockWrite data_writes3[] = { 2977 // After restarting with a null identity, this is the 2978 // request we should be issuing -- the final header line contains a Type 2979 // 1 message. 2980 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2981 "Host: 172.22.68.17\r\n" 2982 "Connection: keep-alive\r\n" 2983 "Authorization: NTLM " 2984 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 2985 2986 // After calling trans->RestartWithAuth(), we should send a Type 3 message 2987 // (the credentials for the origin server). The second request continues 2988 // on the same connection. 2989 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 2990 "Host: 172.22.68.17\r\n" 2991 "Connection: keep-alive\r\n" 2992 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 2993 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 2994 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54" 2995 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI" 2996 "+4MUm7c=\r\n\r\n"), 2997 }; 2998 2999 MockRead data_reads3[] = { 3000 // The origin server responds with a Type 2 message. 3001 MockRead("HTTP/1.1 401 Access Denied\r\n"), 3002 MockRead("WWW-Authenticate: NTLM " 3003 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo" 3004 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 3005 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 3006 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 3007 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 3008 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 3009 "BtAAAAAAA=\r\n"), 3010 MockRead("Content-Length: 42\r\n"), 3011 MockRead("Content-Type: text/html\r\n\r\n"), 3012 MockRead("You are not authorized to view this page\r\n"), 3013 3014 // Lastly we get the desired content. 3015 MockRead("HTTP/1.1 200 OK\r\n"), 3016 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 3017 MockRead("Content-Length: 13\r\n\r\n"), 3018 MockRead("Please Login\r\n"), 3019 MockRead(false, OK), 3020 }; 3021 3022 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3023 data_writes1, arraysize(data_writes1)); 3024 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3025 data_writes2, arraysize(data_writes2)); 3026 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 3027 data_writes3, arraysize(data_writes3)); 3028 session_deps.socket_factory.AddSocketDataProvider(&data1); 3029 session_deps.socket_factory.AddSocketDataProvider(&data2); 3030 session_deps.socket_factory.AddSocketDataProvider(&data3); 3031 3032 TestCompletionCallback callback1; 3033 3034 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3035 3036 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3037 EXPECT_EQ(ERR_IO_PENDING, rv); 3038 3039 rv = callback1.WaitForResult(); 3040 EXPECT_EQ(OK, rv); 3041 3042 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 3043 3044 const HttpResponseInfo* response = trans->GetResponseInfo(); 3045 EXPECT_FALSE(response == NULL); 3046 3047 // The password prompt info should have been set in response->auth_challenge. 3048 EXPECT_FALSE(response->auth_challenge.get() == NULL); 3049 3050 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port); 3051 EXPECT_EQ(L"", response->auth_challenge->realm); 3052 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme); 3053 3054 TestCompletionCallback callback2; 3055 3056 // Enter the wrong password. 3057 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2); 3058 EXPECT_EQ(ERR_IO_PENDING, rv); 3059 3060 rv = callback2.WaitForResult(); 3061 EXPECT_EQ(OK, rv); 3062 3063 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 3064 TestCompletionCallback callback3; 3065 rv = trans->RestartWithAuth(string16(), string16(), &callback3); 3066 EXPECT_EQ(ERR_IO_PENDING, rv); 3067 rv = callback3.WaitForResult(); 3068 EXPECT_EQ(OK, rv); 3069 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 3070 3071 response = trans->GetResponseInfo(); 3072 ASSERT_TRUE(response != NULL); 3073 3074 // The password prompt info should have been set in response->auth_challenge. 3075 EXPECT_FALSE(response->auth_challenge.get() == NULL); 3076 3077 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port); 3078 EXPECT_EQ(L"", response->auth_challenge->realm); 3079 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme); 3080 3081 TestCompletionCallback callback4; 3082 3083 // Now enter the right password. 3084 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4); 3085 EXPECT_EQ(ERR_IO_PENDING, rv); 3086 3087 rv = callback4.WaitForResult(); 3088 EXPECT_EQ(OK, rv); 3089 3090 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 3091 3092 TestCompletionCallback callback5; 3093 3094 // One more roundtrip 3095 rv = trans->RestartWithAuth(string16(), string16(), &callback5); 3096 EXPECT_EQ(ERR_IO_PENDING, rv); 3097 3098 rv = callback5.WaitForResult(); 3099 EXPECT_EQ(OK, rv); 3100 3101 response = trans->GetResponseInfo(); 3102 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3103 EXPECT_EQ(13, response->headers->GetContentLength()); 3104 } 3105 #endif // NTLM_PORTABLE 3106 3107 // Test reading a server response which has only headers, and no body. 3108 // After some maximum number of bytes is consumed, the transaction should 3109 // fail with ERR_RESPONSE_HEADERS_TOO_BIG. 3110 TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) { 3111 HttpRequestInfo request; 3112 request.method = "GET"; 3113 request.url = GURL("http://www.google.com/"); 3114 request.load_flags = 0; 3115 3116 SessionDependencies session_deps; 3117 scoped_ptr<HttpTransaction> trans( 3118 new HttpNetworkTransaction(CreateSession(&session_deps))); 3119 3120 // Respond with 300 kb of headers (we should fail after 256 kb). 3121 std::string large_headers_string; 3122 FillLargeHeadersString(&large_headers_string, 300 * 1024); 3123 3124 MockRead data_reads[] = { 3125 MockRead("HTTP/1.0 200 OK\r\n"), 3126 MockRead(true, large_headers_string.data(), large_headers_string.size()), 3127 MockRead("\r\nBODY"), 3128 MockRead(false, OK), 3129 }; 3130 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 3131 session_deps.socket_factory.AddSocketDataProvider(&data); 3132 3133 TestCompletionCallback callback; 3134 3135 int rv = trans->Start(&request, &callback, BoundNetLog()); 3136 EXPECT_EQ(ERR_IO_PENDING, rv); 3137 3138 rv = callback.WaitForResult(); 3139 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv); 3140 3141 const HttpResponseInfo* response = trans->GetResponseInfo(); 3142 EXPECT_TRUE(response == NULL); 3143 } 3144 3145 // Make sure that we don't try to reuse a TCPClientSocket when failing to 3146 // establish tunnel. 3147 // http://code.google.com/p/chromium/issues/detail?id=3772 3148 TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) { 3149 HttpRequestInfo request; 3150 request.method = "GET"; 3151 request.url = GURL("https://www.google.com/"); 3152 request.load_flags = 0; 3153 3154 // Configure against proxy server "myproxy:70". 3155 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 3156 3157 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3158 3159 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3160 3161 // Since we have proxy, should try to establish tunnel. 3162 MockWrite data_writes1[] = { 3163 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 3164 "Host: www.google.com\r\n" 3165 "Proxy-Connection: keep-alive\r\n\r\n"), 3166 }; 3167 3168 // The proxy responds to the connect with a 404, using a persistent 3169 // connection. Usually a proxy would return 501 (not implemented), 3170 // or 200 (tunnel established). 3171 MockRead data_reads1[] = { 3172 MockRead("HTTP/1.1 404 Not Found\r\n"), 3173 MockRead("Content-Length: 10\r\n\r\n"), 3174 MockRead(false, ERR_UNEXPECTED), // Should not be reached. 3175 }; 3176 3177 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3178 data_writes1, arraysize(data_writes1)); 3179 session_deps.socket_factory.AddSocketDataProvider(&data1); 3180 3181 TestCompletionCallback callback1; 3182 3183 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3184 EXPECT_EQ(ERR_IO_PENDING, rv); 3185 3186 rv = callback1.WaitForResult(); 3187 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 3188 3189 const HttpResponseInfo* response = trans->GetResponseInfo(); 3190 EXPECT_TRUE(response == NULL); 3191 3192 // Empty the current queue. This is necessary because idle sockets are 3193 // added to the connection pool asynchronously with a PostTask. 3194 MessageLoop::current()->RunAllPending(); 3195 3196 // We now check to make sure the TCPClientSocket was not added back to 3197 // the pool. 3198 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3199 trans.reset(); 3200 MessageLoop::current()->RunAllPending(); 3201 // Make sure that the socket didn't get recycled after calling the destructor. 3202 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3203 } 3204 3205 // Make sure that we recycle a socket after reading all of the response body. 3206 TEST_F(HttpNetworkTransactionTest, RecycleSocket) { 3207 HttpRequestInfo request; 3208 request.method = "GET"; 3209 request.url = GURL("http://www.google.com/"); 3210 request.load_flags = 0; 3211 3212 SessionDependencies session_deps; 3213 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3214 3215 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3216 3217 MockRead data_reads[] = { 3218 // A part of the response body is received with the response headers. 3219 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"), 3220 // The rest of the response body is received in two parts. 3221 MockRead("lo"), 3222 MockRead(" world"), 3223 MockRead("junk"), // Should not be read!! 3224 MockRead(false, OK), 3225 }; 3226 3227 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 3228 session_deps.socket_factory.AddSocketDataProvider(&data); 3229 3230 TestCompletionCallback callback; 3231 3232 int rv = trans->Start(&request, &callback, BoundNetLog()); 3233 EXPECT_EQ(ERR_IO_PENDING, rv); 3234 3235 rv = callback.WaitForResult(); 3236 EXPECT_EQ(OK, rv); 3237 3238 const HttpResponseInfo* response = trans->GetResponseInfo(); 3239 EXPECT_TRUE(response != NULL); 3240 3241 EXPECT_TRUE(response->headers != NULL); 3242 std::string status_line = response->headers->GetStatusLine(); 3243 EXPECT_EQ("HTTP/1.1 200 OK", status_line); 3244 3245 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3246 3247 std::string response_data; 3248 rv = ReadTransaction(trans.get(), &response_data); 3249 EXPECT_EQ(OK, rv); 3250 EXPECT_EQ("hello world", response_data); 3251 3252 // Empty the current queue. This is necessary because idle sockets are 3253 // added to the connection pool asynchronously with a PostTask. 3254 MessageLoop::current()->RunAllPending(); 3255 3256 // We now check to make sure the socket was added back to the pool. 3257 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount()); 3258 } 3259 3260 // Make sure that we recycle a SSL socket after reading all of the response 3261 // body. 3262 TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) { 3263 SessionDependencies session_deps; 3264 HttpRequestInfo request; 3265 request.method = "GET"; 3266 request.url = GURL("https://www.google.com/"); 3267 request.load_flags = 0; 3268 3269 MockWrite data_writes[] = { 3270 MockWrite("GET / HTTP/1.1\r\n" 3271 "Host: www.google.com\r\n" 3272 "Connection: keep-alive\r\n\r\n"), 3273 }; 3274 3275 MockRead data_reads[] = { 3276 MockRead("HTTP/1.1 200 OK\r\n"), 3277 MockRead("Content-Length: 11\r\n\r\n"), 3278 MockRead("hello world"), 3279 MockRead(false, OK), 3280 }; 3281 3282 SSLSocketDataProvider ssl(true, OK); 3283 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 3284 3285 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 3286 data_writes, arraysize(data_writes)); 3287 session_deps.socket_factory.AddSocketDataProvider(&data); 3288 3289 TestCompletionCallback callback; 3290 3291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3292 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3293 3294 int rv = trans->Start(&request, &callback, BoundNetLog()); 3295 3296 EXPECT_EQ(ERR_IO_PENDING, rv); 3297 EXPECT_EQ(OK, callback.WaitForResult()); 3298 3299 const HttpResponseInfo* response = trans->GetResponseInfo(); 3300 ASSERT_TRUE(response != NULL); 3301 ASSERT_TRUE(response->headers != NULL); 3302 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3303 3304 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3305 3306 std::string response_data; 3307 rv = ReadTransaction(trans.get(), &response_data); 3308 EXPECT_EQ(OK, rv); 3309 EXPECT_EQ("hello world", response_data); 3310 3311 // Empty the current queue. This is necessary because idle sockets are 3312 // added to the connection pool asynchronously with a PostTask. 3313 MessageLoop::current()->RunAllPending(); 3314 3315 // We now check to make sure the socket was added back to the pool. 3316 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount()); 3317 } 3318 3319 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it 3320 // from the pool and make sure that we recover okay. 3321 TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) { 3322 SessionDependencies session_deps; 3323 HttpRequestInfo request; 3324 request.method = "GET"; 3325 request.url = GURL("https://www.google.com/"); 3326 request.load_flags = 0; 3327 3328 MockWrite data_writes[] = { 3329 MockWrite("GET / HTTP/1.1\r\n" 3330 "Host: www.google.com\r\n" 3331 "Connection: keep-alive\r\n\r\n"), 3332 MockWrite("GET / HTTP/1.1\r\n" 3333 "Host: www.google.com\r\n" 3334 "Connection: keep-alive\r\n\r\n"), 3335 }; 3336 3337 MockRead data_reads[] = { 3338 MockRead("HTTP/1.1 200 OK\r\n"), 3339 MockRead("Content-Length: 11\r\n\r\n"), 3340 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 3341 MockRead("hello world"), 3342 MockRead(true, 0, 0) // EOF 3343 }; 3344 3345 SSLSocketDataProvider ssl(true, OK); 3346 SSLSocketDataProvider ssl2(true, OK); 3347 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 3348 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2); 3349 3350 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 3351 data_writes, arraysize(data_writes)); 3352 StaticSocketDataProvider data2(data_reads, arraysize(data_reads), 3353 data_writes, arraysize(data_writes)); 3354 session_deps.socket_factory.AddSocketDataProvider(&data); 3355 session_deps.socket_factory.AddSocketDataProvider(&data2); 3356 3357 TestCompletionCallback callback; 3358 3359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3360 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3361 3362 int rv = trans->Start(&request, &callback, BoundNetLog()); 3363 3364 EXPECT_EQ(ERR_IO_PENDING, rv); 3365 EXPECT_EQ(OK, callback.WaitForResult()); 3366 3367 const HttpResponseInfo* response = trans->GetResponseInfo(); 3368 ASSERT_TRUE(response != NULL); 3369 ASSERT_TRUE(response->headers != NULL); 3370 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3371 3372 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3373 3374 std::string response_data; 3375 rv = ReadTransaction(trans.get(), &response_data); 3376 EXPECT_EQ(OK, rv); 3377 EXPECT_EQ("hello world", response_data); 3378 3379 // Empty the current queue. This is necessary because idle sockets are 3380 // added to the connection pool asynchronously with a PostTask. 3381 MessageLoop::current()->RunAllPending(); 3382 3383 // We now check to make sure the socket was added back to the pool. 3384 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount()); 3385 3386 // Now start the second transaction, which should reuse the previous socket. 3387 3388 trans.reset(new HttpNetworkTransaction(session)); 3389 3390 rv = trans->Start(&request, &callback, BoundNetLog()); 3391 3392 EXPECT_EQ(ERR_IO_PENDING, rv); 3393 EXPECT_EQ(OK, callback.WaitForResult()); 3394 3395 response = trans->GetResponseInfo(); 3396 ASSERT_TRUE(response != NULL); 3397 ASSERT_TRUE(response->headers != NULL); 3398 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3399 3400 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3401 3402 rv = ReadTransaction(trans.get(), &response_data); 3403 EXPECT_EQ(OK, rv); 3404 EXPECT_EQ("hello world", response_data); 3405 3406 // Empty the current queue. This is necessary because idle sockets are 3407 // added to the connection pool asynchronously with a PostTask. 3408 MessageLoop::current()->RunAllPending(); 3409 3410 // We now check to make sure the socket was added back to the pool. 3411 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount()); 3412 } 3413 3414 // Make sure that we recycle a socket after a zero-length response. 3415 // http://crbug.com/9880 3416 TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { 3417 HttpRequestInfo request; 3418 request.method = "GET"; 3419 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&" 3420 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&" 3421 "e=17259,18167,19592,19773,19981,20133,20173,20233&" 3422 "rt=prt.2642,ol.2649,xjs.2951"); 3423 request.load_flags = 0; 3424 3425 SessionDependencies session_deps; 3426 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3427 3428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3429 3430 MockRead data_reads[] = { 3431 MockRead("HTTP/1.1 204 No Content\r\n" 3432 "Content-Length: 0\r\n" 3433 "Content-Type: text/html\r\n\r\n"), 3434 MockRead("junk"), // Should not be read!! 3435 MockRead(false, OK), 3436 }; 3437 3438 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 3439 session_deps.socket_factory.AddSocketDataProvider(&data); 3440 3441 TestCompletionCallback callback; 3442 3443 int rv = trans->Start(&request, &callback, BoundNetLog()); 3444 EXPECT_EQ(ERR_IO_PENDING, rv); 3445 3446 rv = callback.WaitForResult(); 3447 EXPECT_EQ(OK, rv); 3448 3449 const HttpResponseInfo* response = trans->GetResponseInfo(); 3450 EXPECT_TRUE(response != NULL); 3451 3452 EXPECT_TRUE(response->headers != NULL); 3453 std::string status_line = response->headers->GetStatusLine(); 3454 EXPECT_EQ("HTTP/1.1 204 No Content", status_line); 3455 3456 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount()); 3457 3458 std::string response_data; 3459 rv = ReadTransaction(trans.get(), &response_data); 3460 EXPECT_EQ(OK, rv); 3461 EXPECT_EQ("", response_data); 3462 3463 // Empty the current queue. This is necessary because idle sockets are 3464 // added to the connection pool asynchronously with a PostTask. 3465 MessageLoop::current()->RunAllPending(); 3466 3467 // We now check to make sure the socket was added back to the pool. 3468 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount()); 3469 } 3470 3471 TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { 3472 HttpRequestInfo request[2]; 3473 // Transaction 1: a GET request that succeeds. The socket is recycled 3474 // after use. 3475 request[0].method = "GET"; 3476 request[0].url = GURL("http://www.google.com/"); 3477 request[0].load_flags = 0; 3478 // Transaction 2: a POST request. Reuses the socket kept alive from 3479 // transaction 1. The first attempts fails when writing the POST data. 3480 // This causes the transaction to retry with a new socket. The second 3481 // attempt succeeds. 3482 request[1].method = "POST"; 3483 request[1].url = GURL("http://www.google.com/login.cgi"); 3484 request[1].upload_data = new UploadData; 3485 request[1].upload_data->AppendBytes("foo", 3); 3486 request[1].load_flags = 0; 3487 3488 SessionDependencies session_deps; 3489 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3490 3491 // The first socket is used for transaction 1 and the first attempt of 3492 // transaction 2. 3493 3494 // The response of transaction 1. 3495 MockRead data_reads1[] = { 3496 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"), 3497 MockRead("hello world"), 3498 MockRead(false, OK), 3499 }; 3500 // The mock write results of transaction 1 and the first attempt of 3501 // transaction 2. 3502 MockWrite data_writes1[] = { 3503 MockWrite(false, 64), // GET 3504 MockWrite(false, 93), // POST 3505 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data 3506 }; 3507 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3508 data_writes1, arraysize(data_writes1)); 3509 3510 // The second socket is used for the second attempt of transaction 2. 3511 3512 // The response of transaction 2. 3513 MockRead data_reads2[] = { 3514 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"), 3515 MockRead("welcome"), 3516 MockRead(false, OK), 3517 }; 3518 // The mock write results of the second attempt of transaction 2. 3519 MockWrite data_writes2[] = { 3520 MockWrite(false, 93), // POST 3521 MockWrite(false, 3), // POST data 3522 }; 3523 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3524 data_writes2, arraysize(data_writes2)); 3525 3526 session_deps.socket_factory.AddSocketDataProvider(&data1); 3527 session_deps.socket_factory.AddSocketDataProvider(&data2); 3528 3529 const char* kExpectedResponseData[] = { 3530 "hello world", "welcome" 3531 }; 3532 3533 for (int i = 0; i < 2; ++i) { 3534 scoped_ptr<HttpTransaction> trans( 3535 new HttpNetworkTransaction(session)); 3536 3537 TestCompletionCallback callback; 3538 3539 int rv = trans->Start(&request[i], &callback, BoundNetLog()); 3540 EXPECT_EQ(ERR_IO_PENDING, rv); 3541 3542 rv = callback.WaitForResult(); 3543 EXPECT_EQ(OK, rv); 3544 3545 const HttpResponseInfo* response = trans->GetResponseInfo(); 3546 EXPECT_TRUE(response != NULL); 3547 3548 EXPECT_TRUE(response->headers != NULL); 3549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3550 3551 std::string response_data; 3552 rv = ReadTransaction(trans.get(), &response_data); 3553 EXPECT_EQ(OK, rv); 3554 EXPECT_EQ(kExpectedResponseData[i], response_data); 3555 } 3556 } 3557 3558 // Test the request-challenge-retry sequence for basic auth when there is 3559 // an identity in the URL. The request should be sent as normal, but when 3560 // it fails the identity from the URL is used to answer the challenge. 3561 TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) { 3562 HttpRequestInfo request; 3563 request.method = "GET"; 3564 // Note: the URL has a username:password in it. 3565 request.url = GURL("http://foo:b@r@www.google.com/"); 3566 3567 SessionDependencies session_deps; 3568 scoped_ptr<HttpTransaction> trans( 3569 new HttpNetworkTransaction(CreateSession(&session_deps))); 3570 3571 // The password contains an escaped character -- for this test to pass it 3572 // will need to be unescaped by HttpNetworkTransaction. 3573 EXPECT_EQ("b%40r", request.url.password()); 3574 3575 request.load_flags = LOAD_NORMAL; 3576 3577 MockWrite data_writes1[] = { 3578 MockWrite("GET / HTTP/1.1\r\n" 3579 "Host: www.google.com\r\n" 3580 "Connection: keep-alive\r\n\r\n"), 3581 }; 3582 3583 MockRead data_reads1[] = { 3584 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3585 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3586 MockRead("Content-Length: 10\r\n\r\n"), 3587 MockRead(false, ERR_FAILED), 3588 }; 3589 3590 // After the challenge above, the transaction will be restarted using the 3591 // identity from the url (foo, b@r) to answer the challenge. 3592 MockWrite data_writes2[] = { 3593 MockWrite("GET / HTTP/1.1\r\n" 3594 "Host: www.google.com\r\n" 3595 "Connection: keep-alive\r\n" 3596 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"), 3597 }; 3598 3599 MockRead data_reads2[] = { 3600 MockRead("HTTP/1.0 200 OK\r\n"), 3601 MockRead("Content-Length: 100\r\n\r\n"), 3602 MockRead(false, OK), 3603 }; 3604 3605 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3606 data_writes1, arraysize(data_writes1)); 3607 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3608 data_writes2, arraysize(data_writes2)); 3609 session_deps.socket_factory.AddSocketDataProvider(&data1); 3610 session_deps.socket_factory.AddSocketDataProvider(&data2); 3611 3612 TestCompletionCallback callback1; 3613 3614 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3615 EXPECT_EQ(ERR_IO_PENDING, rv); 3616 3617 rv = callback1.WaitForResult(); 3618 EXPECT_EQ(OK, rv); 3619 3620 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 3621 TestCompletionCallback callback2; 3622 rv = trans->RestartWithAuth(string16(), string16(), &callback2); 3623 EXPECT_EQ(ERR_IO_PENDING, rv); 3624 rv = callback2.WaitForResult(); 3625 EXPECT_EQ(OK, rv); 3626 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 3627 3628 const HttpResponseInfo* response = trans->GetResponseInfo(); 3629 EXPECT_FALSE(response == NULL); 3630 3631 // There is no challenge info, since the identity in URL worked. 3632 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3633 3634 EXPECT_EQ(100, response->headers->GetContentLength()); 3635 3636 // Empty the current queue. 3637 MessageLoop::current()->RunAllPending(); 3638 } 3639 3640 // Test the request-challenge-retry sequence for basic auth when there is 3641 // an incorrect identity in the URL. The identity from the URL should be used 3642 // only once. 3643 TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) { 3644 HttpRequestInfo request; 3645 request.method = "GET"; 3646 // Note: the URL has a username:password in it. The password "baz" is 3647 // wrong (should be "bar"). 3648 request.url = GURL("http://foo:baz@www.google.com/"); 3649 3650 request.load_flags = LOAD_NORMAL; 3651 3652 SessionDependencies session_deps; 3653 scoped_ptr<HttpTransaction> trans( 3654 new HttpNetworkTransaction(CreateSession(&session_deps))); 3655 3656 MockWrite data_writes1[] = { 3657 MockWrite("GET / HTTP/1.1\r\n" 3658 "Host: www.google.com\r\n" 3659 "Connection: keep-alive\r\n\r\n"), 3660 }; 3661 3662 MockRead data_reads1[] = { 3663 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3664 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3665 MockRead("Content-Length: 10\r\n\r\n"), 3666 MockRead(false, ERR_FAILED), 3667 }; 3668 3669 // After the challenge above, the transaction will be restarted using the 3670 // identity from the url (foo, baz) to answer the challenge. 3671 MockWrite data_writes2[] = { 3672 MockWrite("GET / HTTP/1.1\r\n" 3673 "Host: www.google.com\r\n" 3674 "Connection: keep-alive\r\n" 3675 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 3676 }; 3677 3678 MockRead data_reads2[] = { 3679 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3680 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3681 MockRead("Content-Length: 10\r\n\r\n"), 3682 MockRead(false, ERR_FAILED), 3683 }; 3684 3685 // After the challenge above, the transaction will be restarted using the 3686 // identity supplied by the user (foo, bar) to answer the challenge. 3687 MockWrite data_writes3[] = { 3688 MockWrite("GET / HTTP/1.1\r\n" 3689 "Host: www.google.com\r\n" 3690 "Connection: keep-alive\r\n" 3691 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3692 }; 3693 3694 MockRead data_reads3[] = { 3695 MockRead("HTTP/1.0 200 OK\r\n"), 3696 MockRead("Content-Length: 100\r\n\r\n"), 3697 MockRead(false, OK), 3698 }; 3699 3700 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3701 data_writes1, arraysize(data_writes1)); 3702 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3703 data_writes2, arraysize(data_writes2)); 3704 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 3705 data_writes3, arraysize(data_writes3)); 3706 session_deps.socket_factory.AddSocketDataProvider(&data1); 3707 session_deps.socket_factory.AddSocketDataProvider(&data2); 3708 session_deps.socket_factory.AddSocketDataProvider(&data3); 3709 3710 TestCompletionCallback callback1; 3711 3712 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3713 EXPECT_EQ(ERR_IO_PENDING, rv); 3714 3715 rv = callback1.WaitForResult(); 3716 EXPECT_EQ(OK, rv); 3717 3718 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 3719 TestCompletionCallback callback2; 3720 rv = trans->RestartWithAuth(string16(), string16(), &callback2); 3721 EXPECT_EQ(ERR_IO_PENDING, rv); 3722 rv = callback2.WaitForResult(); 3723 EXPECT_EQ(OK, rv); 3724 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 3725 3726 const HttpResponseInfo* response = trans->GetResponseInfo(); 3727 EXPECT_FALSE(response == NULL); 3728 // The password prompt info should have been set in response->auth_challenge. 3729 EXPECT_FALSE(response->auth_challenge.get() == NULL); 3730 3731 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 3732 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 3733 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 3734 3735 TestCompletionCallback callback3; 3736 rv = trans->RestartWithAuth(kFoo, kBar, &callback3); 3737 EXPECT_EQ(ERR_IO_PENDING, rv); 3738 rv = callback3.WaitForResult(); 3739 EXPECT_EQ(OK, rv); 3740 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 3741 3742 response = trans->GetResponseInfo(); 3743 EXPECT_FALSE(response == NULL); 3744 3745 // There is no challenge info, since the identity worked. 3746 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3747 3748 EXPECT_EQ(100, response->headers->GetContentLength()); 3749 3750 // Empty the current queue. 3751 MessageLoop::current()->RunAllPending(); 3752 } 3753 3754 // Test that previously tried username/passwords for a realm get re-used. 3755 TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) { 3756 SessionDependencies session_deps; 3757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 3758 3759 // Transaction 1: authenticate (foo, bar) on MyRealm1 3760 { 3761 HttpRequestInfo request; 3762 request.method = "GET"; 3763 request.url = GURL("http://www.google.com/x/y/z"); 3764 request.load_flags = 0; 3765 3766 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3767 3768 MockWrite data_writes1[] = { 3769 MockWrite("GET /x/y/z HTTP/1.1\r\n" 3770 "Host: www.google.com\r\n" 3771 "Connection: keep-alive\r\n\r\n"), 3772 }; 3773 3774 MockRead data_reads1[] = { 3775 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3776 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3777 MockRead("Content-Length: 10000\r\n\r\n"), 3778 MockRead(false, ERR_FAILED), 3779 }; 3780 3781 // Resend with authorization (username=foo, password=bar) 3782 MockWrite data_writes2[] = { 3783 MockWrite("GET /x/y/z HTTP/1.1\r\n" 3784 "Host: www.google.com\r\n" 3785 "Connection: keep-alive\r\n" 3786 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3787 }; 3788 3789 // Sever accepts the authorization. 3790 MockRead data_reads2[] = { 3791 MockRead("HTTP/1.0 200 OK\r\n"), 3792 MockRead("Content-Length: 100\r\n\r\n"), 3793 MockRead(false, OK), 3794 }; 3795 3796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3797 data_writes1, arraysize(data_writes1)); 3798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3799 data_writes2, arraysize(data_writes2)); 3800 session_deps.socket_factory.AddSocketDataProvider(&data1); 3801 session_deps.socket_factory.AddSocketDataProvider(&data2); 3802 3803 TestCompletionCallback callback1; 3804 3805 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3806 EXPECT_EQ(ERR_IO_PENDING, rv); 3807 3808 rv = callback1.WaitForResult(); 3809 EXPECT_EQ(OK, rv); 3810 3811 const HttpResponseInfo* response = trans->GetResponseInfo(); 3812 EXPECT_FALSE(response == NULL); 3813 3814 // The password prompt info should have been set in 3815 // response->auth_challenge. 3816 EXPECT_FALSE(response->auth_challenge.get() == NULL); 3817 3818 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 3819 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 3820 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 3821 3822 TestCompletionCallback callback2; 3823 3824 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 3825 EXPECT_EQ(ERR_IO_PENDING, rv); 3826 3827 rv = callback2.WaitForResult(); 3828 EXPECT_EQ(OK, rv); 3829 3830 response = trans->GetResponseInfo(); 3831 EXPECT_FALSE(response == NULL); 3832 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3833 EXPECT_EQ(100, response->headers->GetContentLength()); 3834 } 3835 3836 // ------------------------------------------------------------------------ 3837 3838 // Transaction 2: authenticate (foo2, bar2) on MyRealm2 3839 { 3840 HttpRequestInfo request; 3841 request.method = "GET"; 3842 // Note that Transaction 1 was at /x/y/z, so this is in the same 3843 // protection space as MyRealm1. 3844 request.url = GURL("http://www.google.com/x/y/a/b"); 3845 request.load_flags = 0; 3846 3847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3848 3849 MockWrite data_writes1[] = { 3850 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 3851 "Host: www.google.com\r\n" 3852 "Connection: keep-alive\r\n" 3853 // Send preemptive authorization for MyRealm1 3854 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3855 }; 3856 3857 // The server didn't like the preemptive authorization, and 3858 // challenges us for a different realm (MyRealm2). 3859 MockRead data_reads1[] = { 3860 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3861 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"), 3862 MockRead("Content-Length: 10000\r\n\r\n"), 3863 MockRead(false, ERR_FAILED), 3864 }; 3865 3866 // Resend with authorization for MyRealm2 (username=foo2, password=bar2) 3867 MockWrite data_writes2[] = { 3868 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 3869 "Host: www.google.com\r\n" 3870 "Connection: keep-alive\r\n" 3871 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 3872 }; 3873 3874 // Sever accepts the authorization. 3875 MockRead data_reads2[] = { 3876 MockRead("HTTP/1.0 200 OK\r\n"), 3877 MockRead("Content-Length: 100\r\n\r\n"), 3878 MockRead(false, OK), 3879 }; 3880 3881 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3882 data_writes1, arraysize(data_writes1)); 3883 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3884 data_writes2, arraysize(data_writes2)); 3885 session_deps.socket_factory.AddSocketDataProvider(&data1); 3886 session_deps.socket_factory.AddSocketDataProvider(&data2); 3887 3888 TestCompletionCallback callback1; 3889 3890 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3891 EXPECT_EQ(ERR_IO_PENDING, rv); 3892 3893 rv = callback1.WaitForResult(); 3894 EXPECT_EQ(OK, rv); 3895 3896 const HttpResponseInfo* response = trans->GetResponseInfo(); 3897 EXPECT_FALSE(response == NULL); 3898 3899 // The password prompt info should have been set in 3900 // response->auth_challenge. 3901 EXPECT_FALSE(response->auth_challenge.get() == NULL); 3902 3903 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 3904 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm); 3905 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 3906 3907 TestCompletionCallback callback2; 3908 3909 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2); 3910 EXPECT_EQ(ERR_IO_PENDING, rv); 3911 3912 rv = callback2.WaitForResult(); 3913 EXPECT_EQ(OK, rv); 3914 3915 response = trans->GetResponseInfo(); 3916 EXPECT_FALSE(response == NULL); 3917 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3918 EXPECT_EQ(100, response->headers->GetContentLength()); 3919 } 3920 3921 // ------------------------------------------------------------------------ 3922 3923 // Transaction 3: Resend a request in MyRealm's protection space -- 3924 // succeed with preemptive authorization. 3925 { 3926 HttpRequestInfo request; 3927 request.method = "GET"; 3928 request.url = GURL("http://www.google.com/x/y/z2"); 3929 request.load_flags = 0; 3930 3931 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3932 3933 MockWrite data_writes1[] = { 3934 MockWrite("GET /x/y/z2 HTTP/1.1\r\n" 3935 "Host: www.google.com\r\n" 3936 "Connection: keep-alive\r\n" 3937 // The authorization for MyRealm1 gets sent preemptively 3938 // (since the url is in the same protection space) 3939 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3940 }; 3941 3942 // Sever accepts the preemptive authorization 3943 MockRead data_reads1[] = { 3944 MockRead("HTTP/1.0 200 OK\r\n"), 3945 MockRead("Content-Length: 100\r\n\r\n"), 3946 MockRead(false, OK), 3947 }; 3948 3949 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3950 data_writes1, arraysize(data_writes1)); 3951 session_deps.socket_factory.AddSocketDataProvider(&data1); 3952 3953 TestCompletionCallback callback1; 3954 3955 int rv = trans->Start(&request, &callback1, BoundNetLog()); 3956 EXPECT_EQ(ERR_IO_PENDING, rv); 3957 3958 rv = callback1.WaitForResult(); 3959 EXPECT_EQ(OK, rv); 3960 3961 const HttpResponseInfo* response = trans->GetResponseInfo(); 3962 EXPECT_FALSE(response == NULL); 3963 3964 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3965 EXPECT_EQ(100, response->headers->GetContentLength()); 3966 } 3967 3968 // ------------------------------------------------------------------------ 3969 3970 // Transaction 4: request another URL in MyRealm (however the 3971 // url is not known to belong to the protection space, so no pre-auth). 3972 { 3973 HttpRequestInfo request; 3974 request.method = "GET"; 3975 request.url = GURL("http://www.google.com/x/1"); 3976 request.load_flags = 0; 3977 3978 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 3979 3980 MockWrite data_writes1[] = { 3981 MockWrite("GET /x/1 HTTP/1.1\r\n" 3982 "Host: www.google.com\r\n" 3983 "Connection: keep-alive\r\n\r\n"), 3984 }; 3985 3986 MockRead data_reads1[] = { 3987 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3988 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3989 MockRead("Content-Length: 10000\r\n\r\n"), 3990 MockRead(false, ERR_FAILED), 3991 }; 3992 3993 // Resend with authorization from MyRealm's cache. 3994 MockWrite data_writes2[] = { 3995 MockWrite("GET /x/1 HTTP/1.1\r\n" 3996 "Host: www.google.com\r\n" 3997 "Connection: keep-alive\r\n" 3998 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3999 }; 4000 4001 // Sever accepts the authorization. 4002 MockRead data_reads2[] = { 4003 MockRead("HTTP/1.0 200 OK\r\n"), 4004 MockRead("Content-Length: 100\r\n\r\n"), 4005 MockRead(false, OK), 4006 }; 4007 4008 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4009 data_writes1, arraysize(data_writes1)); 4010 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4011 data_writes2, arraysize(data_writes2)); 4012 session_deps.socket_factory.AddSocketDataProvider(&data1); 4013 session_deps.socket_factory.AddSocketDataProvider(&data2); 4014 4015 TestCompletionCallback callback1; 4016 4017 int rv = trans->Start(&request, &callback1, BoundNetLog()); 4018 EXPECT_EQ(ERR_IO_PENDING, rv); 4019 4020 rv = callback1.WaitForResult(); 4021 EXPECT_EQ(OK, rv); 4022 4023 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4024 TestCompletionCallback callback2; 4025 rv = trans->RestartWithAuth(string16(), string16(), &callback2); 4026 EXPECT_EQ(ERR_IO_PENDING, rv); 4027 rv = callback2.WaitForResult(); 4028 EXPECT_EQ(OK, rv); 4029 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4030 4031 const HttpResponseInfo* response = trans->GetResponseInfo(); 4032 EXPECT_FALSE(response == NULL); 4033 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4034 EXPECT_EQ(100, response->headers->GetContentLength()); 4035 } 4036 4037 // ------------------------------------------------------------------------ 4038 4039 // Transaction 5: request a URL in MyRealm, but the server rejects the 4040 // cached identity. Should invalidate and re-prompt. 4041 { 4042 HttpRequestInfo request; 4043 request.method = "GET"; 4044 request.url = GURL("http://www.google.com/p/q/t"); 4045 request.load_flags = 0; 4046 4047 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 4048 4049 MockWrite data_writes1[] = { 4050 MockWrite("GET /p/q/t HTTP/1.1\r\n" 4051 "Host: www.google.com\r\n" 4052 "Connection: keep-alive\r\n\r\n"), 4053 }; 4054 4055 MockRead data_reads1[] = { 4056 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4057 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4058 MockRead("Content-Length: 10000\r\n\r\n"), 4059 MockRead(false, ERR_FAILED), 4060 }; 4061 4062 // Resend with authorization from cache for MyRealm. 4063 MockWrite data_writes2[] = { 4064 MockWrite("GET /p/q/t HTTP/1.1\r\n" 4065 "Host: www.google.com\r\n" 4066 "Connection: keep-alive\r\n" 4067 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 4068 }; 4069 4070 // Sever rejects the authorization. 4071 MockRead data_reads2[] = { 4072 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4073 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4074 MockRead("Content-Length: 10000\r\n\r\n"), 4075 MockRead(false, ERR_FAILED), 4076 }; 4077 4078 // At this point we should prompt for new credentials for MyRealm. 4079 // Restart with username=foo3, password=foo4. 4080 MockWrite data_writes3[] = { 4081 MockWrite("GET /p/q/t HTTP/1.1\r\n" 4082 "Host: www.google.com\r\n" 4083 "Connection: keep-alive\r\n" 4084 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"), 4085 }; 4086 4087 // Sever accepts the authorization. 4088 MockRead data_reads3[] = { 4089 MockRead("HTTP/1.0 200 OK\r\n"), 4090 MockRead("Content-Length: 100\r\n\r\n"), 4091 MockRead(false, OK), 4092 }; 4093 4094 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4095 data_writes1, arraysize(data_writes1)); 4096 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4097 data_writes2, arraysize(data_writes2)); 4098 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4099 data_writes3, arraysize(data_writes3)); 4100 session_deps.socket_factory.AddSocketDataProvider(&data1); 4101 session_deps.socket_factory.AddSocketDataProvider(&data2); 4102 session_deps.socket_factory.AddSocketDataProvider(&data3); 4103 4104 TestCompletionCallback callback1; 4105 4106 int rv = trans->Start(&request, &callback1, BoundNetLog()); 4107 EXPECT_EQ(ERR_IO_PENDING, rv); 4108 4109 rv = callback1.WaitForResult(); 4110 EXPECT_EQ(OK, rv); 4111 4112 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4113 TestCompletionCallback callback2; 4114 rv = trans->RestartWithAuth(string16(), string16(), &callback2); 4115 EXPECT_EQ(ERR_IO_PENDING, rv); 4116 rv = callback2.WaitForResult(); 4117 EXPECT_EQ(OK, rv); 4118 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4119 4120 const HttpResponseInfo* response = trans->GetResponseInfo(); 4121 EXPECT_FALSE(response == NULL); 4122 4123 // The password prompt info should have been set in 4124 // response->auth_challenge. 4125 EXPECT_FALSE(response->auth_challenge.get() == NULL); 4126 4127 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 4128 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 4129 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 4130 4131 TestCompletionCallback callback3; 4132 4133 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3); 4134 EXPECT_EQ(ERR_IO_PENDING, rv); 4135 4136 rv = callback3.WaitForResult(); 4137 EXPECT_EQ(OK, rv); 4138 4139 response = trans->GetResponseInfo(); 4140 EXPECT_FALSE(response == NULL); 4141 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4142 EXPECT_EQ(100, response->headers->GetContentLength()); 4143 } 4144 } 4145 4146 // Tests that nonce count increments when multiple auth attempts 4147 // are started with the same nonce. 4148 TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) { 4149 SessionDependencies session_deps; 4150 HttpAuthHandlerDigest::Factory* digest_factory = 4151 new HttpAuthHandlerDigest::Factory(); 4152 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator = 4153 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef"); 4154 digest_factory->set_nonce_generator(nonce_generator); 4155 session_deps.http_auth_handler_factory.reset(digest_factory); 4156 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 4157 4158 // Transaction 1: authenticate (foo, bar) on MyRealm1 4159 { 4160 HttpRequestInfo request; 4161 request.method = "GET"; 4162 request.url = GURL("http://www.google.com/x/y/z"); 4163 request.load_flags = 0; 4164 4165 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 4166 4167 MockWrite data_writes1[] = { 4168 MockWrite("GET /x/y/z HTTP/1.1\r\n" 4169 "Host: www.google.com\r\n" 4170 "Connection: keep-alive\r\n\r\n"), 4171 }; 4172 4173 MockRead data_reads1[] = { 4174 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4175 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", " 4176 "algorithm=MD5, qop=\"auth\"\r\n\r\n"), 4177 MockRead(false, OK), 4178 }; 4179 4180 // Resend with authorization (username=foo, password=bar) 4181 MockWrite data_writes2[] = { 4182 MockWrite("GET /x/y/z HTTP/1.1\r\n" 4183 "Host: www.google.com\r\n" 4184 "Connection: keep-alive\r\n" 4185 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 4186 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, " 4187 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, " 4188 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"), 4189 }; 4190 4191 // Sever accepts the authorization. 4192 MockRead data_reads2[] = { 4193 MockRead("HTTP/1.0 200 OK\r\n"), 4194 MockRead(false, OK), 4195 }; 4196 4197 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4198 data_writes1, arraysize(data_writes1)); 4199 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4200 data_writes2, arraysize(data_writes2)); 4201 session_deps.socket_factory.AddSocketDataProvider(&data1); 4202 session_deps.socket_factory.AddSocketDataProvider(&data2); 4203 4204 TestCompletionCallback callback1; 4205 4206 int rv = trans->Start(&request, &callback1, BoundNetLog()); 4207 EXPECT_EQ(ERR_IO_PENDING, rv); 4208 4209 rv = callback1.WaitForResult(); 4210 EXPECT_EQ(OK, rv); 4211 4212 const HttpResponseInfo* response = trans->GetResponseInfo(); 4213 ASSERT_FALSE(response == NULL); 4214 4215 // The password prompt info should have been set in 4216 // response->auth_challenge. 4217 ASSERT_FALSE(response->auth_challenge.get() == NULL); 4218 4219 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 4220 EXPECT_EQ(L"digestive", response->auth_challenge->realm); 4221 EXPECT_EQ(L"digest", response->auth_challenge->scheme); 4222 4223 TestCompletionCallback callback2; 4224 4225 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 4226 EXPECT_EQ(ERR_IO_PENDING, rv); 4227 4228 rv = callback2.WaitForResult(); 4229 EXPECT_EQ(OK, rv); 4230 4231 response = trans->GetResponseInfo(); 4232 ASSERT_FALSE(response == NULL); 4233 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4234 } 4235 4236 // ------------------------------------------------------------------------ 4237 4238 // Transaction 2: Request another resource in digestive's protection space. 4239 // This will preemptively add an Authorization header which should have an 4240 // "nc" value of 2 (as compared to 1 in the first use. 4241 { 4242 HttpRequestInfo request; 4243 request.method = "GET"; 4244 // Note that Transaction 1 was at /x/y/z, so this is in the same 4245 // protection space as digest. 4246 request.url = GURL("http://www.google.com/x/y/a/b"); 4247 request.load_flags = 0; 4248 4249 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 4250 4251 MockWrite data_writes1[] = { 4252 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 4253 "Host: www.google.com\r\n" 4254 "Connection: keep-alive\r\n" 4255 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 4256 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, " 4257 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, " 4258 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"), 4259 }; 4260 4261 // Sever accepts the authorization. 4262 MockRead data_reads1[] = { 4263 MockRead("HTTP/1.0 200 OK\r\n"), 4264 MockRead("Content-Length: 100\r\n\r\n"), 4265 MockRead(false, OK), 4266 }; 4267 4268 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4269 data_writes1, arraysize(data_writes1)); 4270 session_deps.socket_factory.AddSocketDataProvider(&data1); 4271 4272 TestCompletionCallback callback1; 4273 4274 int rv = trans->Start(&request, &callback1, BoundNetLog()); 4275 EXPECT_EQ(ERR_IO_PENDING, rv); 4276 4277 rv = callback1.WaitForResult(); 4278 EXPECT_EQ(OK, rv); 4279 4280 const HttpResponseInfo* response = trans->GetResponseInfo(); 4281 ASSERT_FALSE(response == NULL); 4282 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4283 } 4284 } 4285 4286 // Test the ResetStateForRestart() private method. 4287 TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) { 4288 // Create a transaction (the dependencies aren't important). 4289 SessionDependencies session_deps; 4290 scoped_ptr<HttpNetworkTransaction> trans( 4291 new HttpNetworkTransaction(CreateSession(&session_deps))); 4292 4293 // Setup some state (which we expect ResetStateForRestart() will clear). 4294 trans->read_buf_ = new IOBuffer(15); 4295 trans->read_buf_len_ = 15; 4296 trans->request_headers_.SetHeader("Authorization", "NTLM"); 4297 4298 // Setup state in response_ 4299 HttpResponseInfo* response = &trans->response_; 4300 response->auth_challenge = new AuthChallengeInfo(); 4301 response->ssl_info.cert_status = -15; 4302 response->response_time = base::Time::Now(); 4303 response->was_cached = true; // (Wouldn't ever actually be true...) 4304 4305 { // Setup state for response_.vary_data 4306 HttpRequestInfo request; 4307 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n"); 4308 std::replace(temp.begin(), temp.end(), '\n', '\0'); 4309 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp)); 4310 request.extra_headers.SetHeader("Foo", "1"); 4311 request.extra_headers.SetHeader("bar", "23"); 4312 EXPECT_TRUE(response->vary_data.Init(request, *headers)); 4313 } 4314 4315 // Cause the above state to be reset. 4316 trans->ResetStateForRestart(); 4317 4318 // Verify that the state that needed to be reset, has been reset. 4319 EXPECT_TRUE(trans->read_buf_.get() == NULL); 4320 EXPECT_EQ(0, trans->read_buf_len_); 4321 EXPECT_TRUE(trans->request_headers_.IsEmpty()); 4322 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4323 EXPECT_TRUE(response->headers.get() == NULL); 4324 EXPECT_FALSE(response->was_cached); 4325 EXPECT_EQ(0, response->ssl_info.cert_status); 4326 EXPECT_FALSE(response->vary_data.is_valid()); 4327 } 4328 4329 // Test HTTPS connections to a site with a bad certificate 4330 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) { 4331 HttpRequestInfo request; 4332 request.method = "GET"; 4333 request.url = GURL("https://www.google.com/"); 4334 request.load_flags = 0; 4335 4336 SessionDependencies session_deps; 4337 scoped_ptr<HttpTransaction> trans( 4338 new HttpNetworkTransaction(CreateSession(&session_deps))); 4339 4340 MockWrite data_writes[] = { 4341 MockWrite("GET / HTTP/1.1\r\n" 4342 "Host: www.google.com\r\n" 4343 "Connection: keep-alive\r\n\r\n"), 4344 }; 4345 4346 MockRead data_reads[] = { 4347 MockRead("HTTP/1.0 200 OK\r\n"), 4348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4349 MockRead("Content-Length: 100\r\n\r\n"), 4350 MockRead(false, OK), 4351 }; 4352 4353 StaticSocketDataProvider ssl_bad_certificate; 4354 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4355 data_writes, arraysize(data_writes)); 4356 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID); 4357 SSLSocketDataProvider ssl(true, OK); 4358 4359 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate); 4360 session_deps.socket_factory.AddSocketDataProvider(&data); 4361 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad); 4362 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 4363 4364 TestCompletionCallback callback; 4365 4366 int rv = trans->Start(&request, &callback, BoundNetLog()); 4367 EXPECT_EQ(ERR_IO_PENDING, rv); 4368 4369 rv = callback.WaitForResult(); 4370 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 4371 4372 rv = trans->RestartIgnoringLastError(&callback); 4373 EXPECT_EQ(ERR_IO_PENDING, rv); 4374 4375 rv = callback.WaitForResult(); 4376 EXPECT_EQ(OK, rv); 4377 4378 const HttpResponseInfo* response = trans->GetResponseInfo(); 4379 4380 EXPECT_FALSE(response == NULL); 4381 EXPECT_EQ(100, response->headers->GetContentLength()); 4382 } 4383 4384 // Test HTTPS connections to a site with a bad certificate, going through a 4385 // proxy 4386 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { 4387 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 4388 4389 HttpRequestInfo request; 4390 request.method = "GET"; 4391 request.url = GURL("https://www.google.com/"); 4392 request.load_flags = 0; 4393 4394 MockWrite proxy_writes[] = { 4395 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4396 "Host: www.google.com\r\n" 4397 "Proxy-Connection: keep-alive\r\n\r\n"), 4398 }; 4399 4400 MockRead proxy_reads[] = { 4401 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 4402 MockRead(false, OK) 4403 }; 4404 4405 MockWrite data_writes[] = { 4406 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4407 "Host: www.google.com\r\n" 4408 "Proxy-Connection: keep-alive\r\n\r\n"), 4409 MockWrite("GET / HTTP/1.1\r\n" 4410 "Host: www.google.com\r\n" 4411 "Connection: keep-alive\r\n\r\n"), 4412 }; 4413 4414 MockRead data_reads[] = { 4415 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 4416 MockRead("HTTP/1.0 200 OK\r\n"), 4417 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4418 MockRead("Content-Length: 100\r\n\r\n"), 4419 MockRead(false, OK), 4420 }; 4421 4422 StaticSocketDataProvider ssl_bad_certificate( 4423 proxy_reads, arraysize(proxy_reads), 4424 proxy_writes, arraysize(proxy_writes)); 4425 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4426 data_writes, arraysize(data_writes)); 4427 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID); 4428 SSLSocketDataProvider ssl(true, OK); 4429 4430 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate); 4431 session_deps.socket_factory.AddSocketDataProvider(&data); 4432 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad); 4433 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 4434 4435 TestCompletionCallback callback; 4436 4437 for (int i = 0; i < 2; i++) { 4438 session_deps.socket_factory.ResetNextMockIndexes(); 4439 4440 scoped_ptr<HttpTransaction> trans( 4441 new HttpNetworkTransaction(CreateSession(&session_deps))); 4442 4443 int rv = trans->Start(&request, &callback, BoundNetLog()); 4444 EXPECT_EQ(ERR_IO_PENDING, rv); 4445 4446 rv = callback.WaitForResult(); 4447 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 4448 4449 rv = trans->RestartIgnoringLastError(&callback); 4450 EXPECT_EQ(ERR_IO_PENDING, rv); 4451 4452 rv = callback.WaitForResult(); 4453 EXPECT_EQ(OK, rv); 4454 4455 const HttpResponseInfo* response = trans->GetResponseInfo(); 4456 4457 EXPECT_FALSE(response == NULL); 4458 EXPECT_EQ(100, response->headers->GetContentLength()); 4459 } 4460 } 4461 4462 4463 // Test HTTPS connections to a site, going through an HTTPS proxy 4464 TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { 4465 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 4466 4467 HttpRequestInfo request; 4468 request.method = "GET"; 4469 request.url = GURL("https://www.google.com/"); 4470 request.load_flags = 0; 4471 4472 MockWrite data_writes[] = { 4473 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4474 "Host: www.google.com\r\n" 4475 "Proxy-Connection: keep-alive\r\n\r\n"), 4476 MockWrite("GET / HTTP/1.1\r\n" 4477 "Host: www.google.com\r\n" 4478 "Connection: keep-alive\r\n\r\n"), 4479 }; 4480 4481 MockRead data_reads[] = { 4482 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 4483 MockRead("HTTP/1.1 200 OK\r\n"), 4484 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4485 MockRead("Content-Length: 100\r\n\r\n"), 4486 MockRead(false, OK), 4487 }; 4488 4489 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4490 data_writes, arraysize(data_writes)); 4491 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy 4492 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel 4493 4494 session_deps.socket_factory.AddSocketDataProvider(&data); 4495 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl); 4496 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl); 4497 4498 TestCompletionCallback callback; 4499 4500 scoped_ptr<HttpTransaction> trans( 4501 new HttpNetworkTransaction(CreateSession(&session_deps))); 4502 4503 int rv = trans->Start(&request, &callback, BoundNetLog()); 4504 EXPECT_EQ(ERR_IO_PENDING, rv); 4505 4506 rv = callback.WaitForResult(); 4507 EXPECT_EQ(OK, rv); 4508 const HttpResponseInfo* response = trans->GetResponseInfo(); 4509 4510 ASSERT_FALSE(response == NULL); 4511 4512 EXPECT_TRUE(response->headers->IsKeepAlive()); 4513 EXPECT_EQ(200, response->headers->response_code()); 4514 EXPECT_EQ(100, response->headers->GetContentLength()); 4515 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 4516 } 4517 4518 // Test an HTTPS Proxy's ability to redirect a CONNECT request 4519 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { 4520 SessionDependencies session_deps( 4521 ProxyService::CreateFixed("https://proxy:70")); 4522 4523 HttpRequestInfo request; 4524 request.method = "GET"; 4525 request.url = GURL("https://www.google.com/"); 4526 request.load_flags = 0; 4527 4528 MockWrite data_writes[] = { 4529 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4530 "Host: www.google.com\r\n" 4531 "Proxy-Connection: keep-alive\r\n\r\n"), 4532 }; 4533 4534 MockRead data_reads[] = { 4535 MockRead("HTTP/1.1 302 Redirect\r\n"), 4536 MockRead("Location: http://login.example.com/\r\n"), 4537 MockRead("Content-Length: 0\r\n\r\n"), 4538 MockRead(false, OK), 4539 }; 4540 4541 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4542 data_writes, arraysize(data_writes)); 4543 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy 4544 4545 session_deps.socket_factory.AddSocketDataProvider(&data); 4546 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl); 4547 4548 TestCompletionCallback callback; 4549 4550 scoped_ptr<HttpTransaction> trans( 4551 new HttpNetworkTransaction(CreateSession(&session_deps))); 4552 4553 int rv = trans->Start(&request, &callback, BoundNetLog()); 4554 EXPECT_EQ(ERR_IO_PENDING, rv); 4555 4556 rv = callback.WaitForResult(); 4557 EXPECT_EQ(OK, rv); 4558 const HttpResponseInfo* response = trans->GetResponseInfo(); 4559 4560 ASSERT_FALSE(response == NULL); 4561 4562 EXPECT_EQ(302, response->headers->response_code()); 4563 std::string url; 4564 EXPECT_TRUE(response->headers->IsRedirect(&url)); 4565 EXPECT_EQ("http://login.example.com/", url); 4566 } 4567 4568 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request 4569 TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { 4570 SessionDependencies session_deps( 4571 ProxyService::CreateFixed("https://proxy:70")); 4572 4573 HttpRequestInfo request; 4574 request.method = "GET"; 4575 request.url = GURL("https://www.google.com/"); 4576 request.load_flags = 0; 4577 4578 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1)); 4579 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL)); 4580 MockWrite data_writes[] = { 4581 CreateMockWrite(*conn.get(), 0, false), 4582 }; 4583 4584 static const char* const kExtraHeaders[] = { 4585 "location", 4586 "http://login.example.com/", 4587 }; 4588 scoped_ptr<spdy::SpdyFrame> resp( 4589 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders, 4590 arraysize(kExtraHeaders)/2, 1)); 4591 MockRead data_reads[] = { 4592 CreateMockRead(*resp.get(), 1, false), 4593 MockRead(true, 0, 2), // EOF 4594 }; 4595 4596 scoped_refptr<DelayedSocketData> data( 4597 new DelayedSocketData( 4598 1, // wait for one write to finish before reading. 4599 data_reads, arraysize(data_reads), 4600 data_writes, arraysize(data_writes))); 4601 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy 4602 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 4603 proxy_ssl.next_proto = "spdy/2"; 4604 proxy_ssl.was_npn_negotiated = true; 4605 4606 session_deps.socket_factory.AddSocketDataProvider(data.get()); 4607 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl); 4608 4609 TestCompletionCallback callback; 4610 4611 scoped_ptr<HttpTransaction> trans( 4612 new HttpNetworkTransaction(CreateSession(&session_deps))); 4613 4614 int rv = trans->Start(&request, &callback, BoundNetLog()); 4615 EXPECT_EQ(ERR_IO_PENDING, rv); 4616 4617 rv = callback.WaitForResult(); 4618 EXPECT_EQ(OK, rv); 4619 const HttpResponseInfo* response = trans->GetResponseInfo(); 4620 4621 ASSERT_FALSE(response == NULL); 4622 4623 EXPECT_EQ(302, response->headers->response_code()); 4624 std::string url; 4625 EXPECT_TRUE(response->headers->IsRedirect(&url)); 4626 EXPECT_EQ("http://login.example.com/", url); 4627 } 4628 4629 // Test an HTTPS Proxy's ability to provide a response to a CONNECT request 4630 TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) { 4631 SessionDependencies session_deps( 4632 ProxyService::CreateFixed("https://proxy:70")); 4633 4634 HttpRequestInfo request; 4635 request.method = "GET"; 4636 request.url = GURL("https://www.google.com/"); 4637 request.load_flags = 0; 4638 4639 MockWrite data_writes[] = { 4640 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4641 "Host: www.google.com\r\n" 4642 "Proxy-Connection: keep-alive\r\n\r\n"), 4643 }; 4644 4645 MockRead data_reads[] = { 4646 MockRead("HTTP/1.1 404 Not Found\r\n"), 4647 MockRead("Content-Length: 23\r\n\r\n"), 4648 MockRead("The host does not exist"), 4649 MockRead(false, OK), 4650 }; 4651 4652 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4653 data_writes, arraysize(data_writes)); 4654 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy 4655 4656 session_deps.socket_factory.AddSocketDataProvider(&data); 4657 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl); 4658 4659 TestCompletionCallback callback; 4660 4661 scoped_ptr<HttpTransaction> trans( 4662 new HttpNetworkTransaction(CreateSession(&session_deps))); 4663 4664 int rv = trans->Start(&request, &callback, BoundNetLog()); 4665 EXPECT_EQ(ERR_IO_PENDING, rv); 4666 4667 rv = callback.WaitForResult(); 4668 EXPECT_EQ(OK, rv); 4669 const HttpResponseInfo* response = trans->GetResponseInfo(); 4670 4671 ASSERT_FALSE(response == NULL); 4672 4673 EXPECT_EQ(404, response->headers->response_code()); 4674 EXPECT_EQ(23, response->headers->GetContentLength()); 4675 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 4676 EXPECT_FALSE(response->ssl_info.is_valid()); 4677 4678 std::string response_data; 4679 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 4680 EXPECT_EQ("The host does not exist", response_data); 4681 } 4682 4683 // Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT 4684 // request 4685 TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) { 4686 SessionDependencies session_deps( 4687 ProxyService::CreateFixed("https://proxy:70")); 4688 4689 HttpRequestInfo request; 4690 request.method = "GET"; 4691 request.url = GURL("https://www.google.com/"); 4692 request.load_flags = 0; 4693 4694 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1)); 4695 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL)); 4696 MockWrite data_writes[] = { 4697 CreateMockWrite(*conn.get(), 0, false), 4698 }; 4699 4700 static const char* const kExtraHeaders[] = { 4701 "location", 4702 "http://login.example.com/", 4703 }; 4704 scoped_ptr<spdy::SpdyFrame> resp( 4705 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders, 4706 arraysize(kExtraHeaders)/2, 1)); 4707 scoped_ptr<spdy::SpdyFrame> body( 4708 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true)); 4709 MockRead data_reads[] = { 4710 CreateMockRead(*resp.get(), 1, false), 4711 CreateMockRead(*body.get(), 2, false), 4712 MockRead(true, 0, 3), // EOF 4713 }; 4714 4715 scoped_refptr<DelayedSocketData> data( 4716 new DelayedSocketData( 4717 1, // wait for one write to finish before reading. 4718 data_reads, arraysize(data_reads), 4719 data_writes, arraysize(data_writes))); 4720 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy 4721 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 4722 proxy_ssl.next_proto = "spdy/2"; 4723 proxy_ssl.was_npn_negotiated = true; 4724 4725 session_deps.socket_factory.AddSocketDataProvider(data.get()); 4726 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl); 4727 4728 TestCompletionCallback callback; 4729 4730 scoped_ptr<HttpTransaction> trans( 4731 new HttpNetworkTransaction(CreateSession(&session_deps))); 4732 4733 int rv = trans->Start(&request, &callback, BoundNetLog()); 4734 EXPECT_EQ(ERR_IO_PENDING, rv); 4735 4736 rv = callback.WaitForResult(); 4737 EXPECT_EQ(OK, rv); 4738 const HttpResponseInfo* response = trans->GetResponseInfo(); 4739 4740 ASSERT_FALSE(response == NULL); 4741 4742 EXPECT_EQ(404, response->headers->response_code()); 4743 EXPECT_FALSE(response->ssl_info.is_valid()); 4744 4745 std::string response_data; 4746 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 4747 EXPECT_EQ("The host does not exist", response_data); 4748 } 4749 4750 // Test HTTPS connections to a site with a bad certificate, going through an 4751 // HTTPS proxy 4752 TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { 4753 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70")); 4754 4755 HttpRequestInfo request; 4756 request.method = "GET"; 4757 request.url = GURL("https://www.google.com/"); 4758 request.load_flags = 0; 4759 4760 // Attempt to fetch the URL from a server with a bad cert 4761 MockWrite bad_cert_writes[] = { 4762 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4763 "Host: www.google.com\r\n" 4764 "Proxy-Connection: keep-alive\r\n\r\n"), 4765 }; 4766 4767 MockRead bad_cert_reads[] = { 4768 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 4769 MockRead(false, OK) 4770 }; 4771 4772 // Attempt to fetch the URL with a good cert 4773 MockWrite good_data_writes[] = { 4774 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4775 "Host: www.google.com\r\n" 4776 "Proxy-Connection: keep-alive\r\n\r\n"), 4777 MockWrite("GET / HTTP/1.1\r\n" 4778 "Host: www.google.com\r\n" 4779 "Connection: keep-alive\r\n\r\n"), 4780 }; 4781 4782 MockRead good_cert_reads[] = { 4783 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 4784 MockRead("HTTP/1.0 200 OK\r\n"), 4785 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4786 MockRead("Content-Length: 100\r\n\r\n"), 4787 MockRead(false, OK), 4788 }; 4789 4790 StaticSocketDataProvider ssl_bad_certificate( 4791 bad_cert_reads, arraysize(bad_cert_reads), 4792 bad_cert_writes, arraysize(bad_cert_writes)); 4793 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads), 4794 good_data_writes, arraysize(good_data_writes)); 4795 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID); 4796 SSLSocketDataProvider ssl(true, OK); 4797 4798 // SSL to the proxy, then CONNECT request, then SSL with bad certificate 4799 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 4800 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate); 4801 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad); 4802 4803 // SSL to the proxy, then CONNECT request, then valid SSL certificate 4804 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 4805 session_deps.socket_factory.AddSocketDataProvider(&data); 4806 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 4807 4808 TestCompletionCallback callback; 4809 4810 scoped_ptr<HttpTransaction> trans( 4811 new HttpNetworkTransaction(CreateSession(&session_deps))); 4812 4813 int rv = trans->Start(&request, &callback, BoundNetLog()); 4814 EXPECT_EQ(ERR_IO_PENDING, rv); 4815 4816 rv = callback.WaitForResult(); 4817 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 4818 4819 rv = trans->RestartIgnoringLastError(&callback); 4820 EXPECT_EQ(ERR_IO_PENDING, rv); 4821 4822 rv = callback.WaitForResult(); 4823 EXPECT_EQ(OK, rv); 4824 4825 const HttpResponseInfo* response = trans->GetResponseInfo(); 4826 4827 EXPECT_FALSE(response == NULL); 4828 EXPECT_EQ(100, response->headers->GetContentLength()); 4829 } 4830 4831 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) { 4832 HttpRequestInfo request; 4833 request.method = "GET"; 4834 request.url = GURL("http://www.google.com/"); 4835 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 4836 "Chromium Ultra Awesome X Edition"); 4837 4838 SessionDependencies session_deps; 4839 scoped_ptr<HttpTransaction> trans( 4840 new HttpNetworkTransaction(CreateSession(&session_deps))); 4841 4842 MockWrite data_writes[] = { 4843 MockWrite("GET / HTTP/1.1\r\n" 4844 "Host: www.google.com\r\n" 4845 "Connection: keep-alive\r\n" 4846 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 4847 }; 4848 4849 // Lastly, the server responds with the actual content. 4850 MockRead data_reads[] = { 4851 MockRead("HTTP/1.0 200 OK\r\n"), 4852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4853 MockRead("Content-Length: 100\r\n\r\n"), 4854 MockRead(false, OK), 4855 }; 4856 4857 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4858 data_writes, arraysize(data_writes)); 4859 session_deps.socket_factory.AddSocketDataProvider(&data); 4860 4861 TestCompletionCallback callback; 4862 4863 int rv = trans->Start(&request, &callback, BoundNetLog()); 4864 EXPECT_EQ(ERR_IO_PENDING, rv); 4865 4866 rv = callback.WaitForResult(); 4867 EXPECT_EQ(OK, rv); 4868 } 4869 4870 TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) { 4871 HttpRequestInfo request; 4872 request.method = "GET"; 4873 request.url = GURL("https://www.google.com/"); 4874 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 4875 "Chromium Ultra Awesome X Edition"); 4876 4877 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 4878 scoped_ptr<HttpTransaction> trans( 4879 new HttpNetworkTransaction(CreateSession(&session_deps))); 4880 4881 MockWrite data_writes[] = { 4882 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4883 "Host: www.google.com\r\n" 4884 "Proxy-Connection: keep-alive\r\n" 4885 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 4886 }; 4887 MockRead data_reads[] = { 4888 // Return an error, so the transaction stops here (this test isn't 4889 // interested in the rest). 4890 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 4891 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4892 MockRead("Proxy-Connection: close\r\n\r\n"), 4893 }; 4894 4895 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4896 data_writes, arraysize(data_writes)); 4897 session_deps.socket_factory.AddSocketDataProvider(&data); 4898 4899 TestCompletionCallback callback; 4900 4901 int rv = trans->Start(&request, &callback, BoundNetLog()); 4902 EXPECT_EQ(ERR_IO_PENDING, rv); 4903 4904 rv = callback.WaitForResult(); 4905 EXPECT_EQ(OK, rv); 4906 } 4907 4908 TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) { 4909 HttpRequestInfo request; 4910 request.method = "GET"; 4911 request.url = GURL("http://www.google.com/"); 4912 request.load_flags = 0; 4913 request.referrer = GURL("http://the.previous.site.com/"); 4914 4915 SessionDependencies session_deps; 4916 scoped_ptr<HttpTransaction> trans( 4917 new HttpNetworkTransaction(CreateSession(&session_deps))); 4918 4919 MockWrite data_writes[] = { 4920 MockWrite("GET / HTTP/1.1\r\n" 4921 "Host: www.google.com\r\n" 4922 "Connection: keep-alive\r\n" 4923 "Referer: http://the.previous.site.com/\r\n\r\n"), 4924 }; 4925 4926 // Lastly, the server responds with the actual content. 4927 MockRead data_reads[] = { 4928 MockRead("HTTP/1.0 200 OK\r\n"), 4929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4930 MockRead("Content-Length: 100\r\n\r\n"), 4931 MockRead(false, OK), 4932 }; 4933 4934 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4935 data_writes, arraysize(data_writes)); 4936 session_deps.socket_factory.AddSocketDataProvider(&data); 4937 4938 TestCompletionCallback callback; 4939 4940 int rv = trans->Start(&request, &callback, BoundNetLog()); 4941 EXPECT_EQ(ERR_IO_PENDING, rv); 4942 4943 rv = callback.WaitForResult(); 4944 EXPECT_EQ(OK, rv); 4945 } 4946 4947 TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) { 4948 HttpRequestInfo request; 4949 request.method = "POST"; 4950 request.url = GURL("http://www.google.com/"); 4951 4952 SessionDependencies session_deps; 4953 scoped_ptr<HttpTransaction> trans( 4954 new HttpNetworkTransaction(CreateSession(&session_deps))); 4955 4956 MockWrite data_writes[] = { 4957 MockWrite("POST / HTTP/1.1\r\n" 4958 "Host: www.google.com\r\n" 4959 "Connection: keep-alive\r\n" 4960 "Content-Length: 0\r\n\r\n"), 4961 }; 4962 4963 // Lastly, the server responds with the actual content. 4964 MockRead data_reads[] = { 4965 MockRead("HTTP/1.0 200 OK\r\n"), 4966 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4967 MockRead("Content-Length: 100\r\n\r\n"), 4968 MockRead(false, OK), 4969 }; 4970 4971 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4972 data_writes, arraysize(data_writes)); 4973 session_deps.socket_factory.AddSocketDataProvider(&data); 4974 4975 TestCompletionCallback callback; 4976 4977 int rv = trans->Start(&request, &callback, BoundNetLog()); 4978 EXPECT_EQ(ERR_IO_PENDING, rv); 4979 4980 rv = callback.WaitForResult(); 4981 EXPECT_EQ(OK, rv); 4982 } 4983 4984 TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) { 4985 HttpRequestInfo request; 4986 request.method = "PUT"; 4987 request.url = GURL("http://www.google.com/"); 4988 4989 SessionDependencies session_deps; 4990 scoped_ptr<HttpTransaction> trans( 4991 new HttpNetworkTransaction(CreateSession(&session_deps))); 4992 4993 MockWrite data_writes[] = { 4994 MockWrite("PUT / HTTP/1.1\r\n" 4995 "Host: www.google.com\r\n" 4996 "Connection: keep-alive\r\n" 4997 "Content-Length: 0\r\n\r\n"), 4998 }; 4999 5000 // Lastly, the server responds with the actual content. 5001 MockRead data_reads[] = { 5002 MockRead("HTTP/1.0 200 OK\r\n"), 5003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5004 MockRead("Content-Length: 100\r\n\r\n"), 5005 MockRead(false, OK), 5006 }; 5007 5008 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5009 data_writes, arraysize(data_writes)); 5010 session_deps.socket_factory.AddSocketDataProvider(&data); 5011 5012 TestCompletionCallback callback; 5013 5014 int rv = trans->Start(&request, &callback, BoundNetLog()); 5015 EXPECT_EQ(ERR_IO_PENDING, rv); 5016 5017 rv = callback.WaitForResult(); 5018 EXPECT_EQ(OK, rv); 5019 } 5020 5021 TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) { 5022 HttpRequestInfo request; 5023 request.method = "HEAD"; 5024 request.url = GURL("http://www.google.com/"); 5025 5026 SessionDependencies session_deps; 5027 scoped_ptr<HttpTransaction> trans( 5028 new HttpNetworkTransaction(CreateSession(&session_deps))); 5029 5030 MockWrite data_writes[] = { 5031 MockWrite("HEAD / HTTP/1.1\r\n" 5032 "Host: www.google.com\r\n" 5033 "Connection: keep-alive\r\n" 5034 "Content-Length: 0\r\n\r\n"), 5035 }; 5036 5037 // Lastly, the server responds with the actual content. 5038 MockRead data_reads[] = { 5039 MockRead("HTTP/1.0 200 OK\r\n"), 5040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5041 MockRead("Content-Length: 100\r\n\r\n"), 5042 MockRead(false, OK), 5043 }; 5044 5045 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5046 data_writes, arraysize(data_writes)); 5047 session_deps.socket_factory.AddSocketDataProvider(&data); 5048 5049 TestCompletionCallback callback; 5050 5051 int rv = trans->Start(&request, &callback, BoundNetLog()); 5052 EXPECT_EQ(ERR_IO_PENDING, rv); 5053 5054 rv = callback.WaitForResult(); 5055 EXPECT_EQ(OK, rv); 5056 } 5057 5058 TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) { 5059 HttpRequestInfo request; 5060 request.method = "GET"; 5061 request.url = GURL("http://www.google.com/"); 5062 request.load_flags = LOAD_BYPASS_CACHE; 5063 5064 SessionDependencies session_deps; 5065 scoped_ptr<HttpTransaction> trans( 5066 new HttpNetworkTransaction(CreateSession(&session_deps))); 5067 5068 MockWrite data_writes[] = { 5069 MockWrite("GET / HTTP/1.1\r\n" 5070 "Host: www.google.com\r\n" 5071 "Connection: keep-alive\r\n" 5072 "Pragma: no-cache\r\n" 5073 "Cache-Control: no-cache\r\n\r\n"), 5074 }; 5075 5076 // Lastly, the server responds with the actual content. 5077 MockRead data_reads[] = { 5078 MockRead("HTTP/1.0 200 OK\r\n"), 5079 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5080 MockRead("Content-Length: 100\r\n\r\n"), 5081 MockRead(false, OK), 5082 }; 5083 5084 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5085 data_writes, arraysize(data_writes)); 5086 session_deps.socket_factory.AddSocketDataProvider(&data); 5087 5088 TestCompletionCallback callback; 5089 5090 int rv = trans->Start(&request, &callback, BoundNetLog()); 5091 EXPECT_EQ(ERR_IO_PENDING, rv); 5092 5093 rv = callback.WaitForResult(); 5094 EXPECT_EQ(OK, rv); 5095 } 5096 5097 TEST_F(HttpNetworkTransactionTest, 5098 BuildRequest_CacheControlValidateCache) { 5099 HttpRequestInfo request; 5100 request.method = "GET"; 5101 request.url = GURL("http://www.google.com/"); 5102 request.load_flags = LOAD_VALIDATE_CACHE; 5103 5104 SessionDependencies session_deps; 5105 scoped_ptr<HttpTransaction> trans( 5106 new HttpNetworkTransaction(CreateSession(&session_deps))); 5107 5108 MockWrite data_writes[] = { 5109 MockWrite("GET / HTTP/1.1\r\n" 5110 "Host: www.google.com\r\n" 5111 "Connection: keep-alive\r\n" 5112 "Cache-Control: max-age=0\r\n\r\n"), 5113 }; 5114 5115 // Lastly, the server responds with the actual content. 5116 MockRead data_reads[] = { 5117 MockRead("HTTP/1.0 200 OK\r\n"), 5118 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5119 MockRead("Content-Length: 100\r\n\r\n"), 5120 MockRead(false, OK), 5121 }; 5122 5123 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5124 data_writes, arraysize(data_writes)); 5125 session_deps.socket_factory.AddSocketDataProvider(&data); 5126 5127 TestCompletionCallback callback; 5128 5129 int rv = trans->Start(&request, &callback, BoundNetLog()); 5130 EXPECT_EQ(ERR_IO_PENDING, rv); 5131 5132 rv = callback.WaitForResult(); 5133 EXPECT_EQ(OK, rv); 5134 } 5135 5136 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) { 5137 HttpRequestInfo request; 5138 request.method = "GET"; 5139 request.url = GURL("http://www.google.com/"); 5140 request.extra_headers.SetHeader("FooHeader", "Bar"); 5141 5142 SessionDependencies session_deps; 5143 scoped_ptr<HttpTransaction> trans( 5144 new HttpNetworkTransaction(CreateSession(&session_deps))); 5145 5146 MockWrite data_writes[] = { 5147 MockWrite("GET / HTTP/1.1\r\n" 5148 "Host: www.google.com\r\n" 5149 "Connection: keep-alive\r\n" 5150 "FooHeader: Bar\r\n\r\n"), 5151 }; 5152 5153 // Lastly, the server responds with the actual content. 5154 MockRead data_reads[] = { 5155 MockRead("HTTP/1.0 200 OK\r\n"), 5156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5157 MockRead("Content-Length: 100\r\n\r\n"), 5158 MockRead(false, OK), 5159 }; 5160 5161 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5162 data_writes, arraysize(data_writes)); 5163 session_deps.socket_factory.AddSocketDataProvider(&data); 5164 5165 TestCompletionCallback callback; 5166 5167 int rv = trans->Start(&request, &callback, BoundNetLog()); 5168 EXPECT_EQ(ERR_IO_PENDING, rv); 5169 5170 rv = callback.WaitForResult(); 5171 EXPECT_EQ(OK, rv); 5172 } 5173 5174 TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) { 5175 HttpRequestInfo request; 5176 request.method = "GET"; 5177 request.url = GURL("http://www.google.com/"); 5178 request.extra_headers.SetHeader("referer", "www.foo.com"); 5179 request.extra_headers.SetHeader("hEllo", "Kitty"); 5180 request.extra_headers.SetHeader("FoO", "bar"); 5181 5182 SessionDependencies session_deps; 5183 scoped_ptr<HttpTransaction> trans( 5184 new HttpNetworkTransaction(CreateSession(&session_deps))); 5185 5186 MockWrite data_writes[] = { 5187 MockWrite("GET / HTTP/1.1\r\n" 5188 "Host: www.google.com\r\n" 5189 "Connection: keep-alive\r\n" 5190 "hEllo: Kitty\r\n" 5191 "FoO: bar\r\n\r\n"), 5192 }; 5193 5194 // Lastly, the server responds with the actual content. 5195 MockRead data_reads[] = { 5196 MockRead("HTTP/1.0 200 OK\r\n"), 5197 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5198 MockRead("Content-Length: 100\r\n\r\n"), 5199 MockRead(false, OK), 5200 }; 5201 5202 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5203 data_writes, arraysize(data_writes)); 5204 session_deps.socket_factory.AddSocketDataProvider(&data); 5205 5206 TestCompletionCallback callback; 5207 5208 int rv = trans->Start(&request, &callback, BoundNetLog()); 5209 EXPECT_EQ(ERR_IO_PENDING, rv); 5210 5211 rv = callback.WaitForResult(); 5212 EXPECT_EQ(OK, rv); 5213 } 5214 5215 TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) { 5216 HttpRequestInfo request; 5217 request.method = "GET"; 5218 request.url = GURL("http://www.google.com/"); 5219 request.load_flags = 0; 5220 5221 SessionDependencies session_deps( 5222 ProxyService::CreateFixed("socks4://myproxy:1080")); 5223 5224 scoped_ptr<HttpTransaction> trans( 5225 new HttpNetworkTransaction(CreateSession(&session_deps))); 5226 5227 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; 5228 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 5229 5230 MockWrite data_writes[] = { 5231 MockWrite(true, write_buffer, arraysize(write_buffer)), 5232 MockWrite("GET / HTTP/1.1\r\n" 5233 "Host: www.google.com\r\n" 5234 "Connection: keep-alive\r\n\r\n") 5235 }; 5236 5237 MockRead data_reads[] = { 5238 MockRead(true, read_buffer, arraysize(read_buffer)), 5239 MockRead("HTTP/1.0 200 OK\r\n"), 5240 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 5241 MockRead("Payload"), 5242 MockRead(false, OK) 5243 }; 5244 5245 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5246 data_writes, arraysize(data_writes)); 5247 session_deps.socket_factory.AddSocketDataProvider(&data); 5248 5249 TestCompletionCallback callback; 5250 5251 int rv = trans->Start(&request, &callback, BoundNetLog()); 5252 EXPECT_EQ(ERR_IO_PENDING, rv); 5253 5254 rv = callback.WaitForResult(); 5255 EXPECT_EQ(OK, rv); 5256 5257 const HttpResponseInfo* response = trans->GetResponseInfo(); 5258 EXPECT_FALSE(response == NULL); 5259 5260 std::string response_text; 5261 rv = ReadTransaction(trans.get(), &response_text); 5262 EXPECT_EQ(OK, rv); 5263 EXPECT_EQ("Payload", response_text); 5264 } 5265 5266 TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) { 5267 HttpRequestInfo request; 5268 request.method = "GET"; 5269 request.url = GURL("https://www.google.com/"); 5270 request.load_flags = 0; 5271 5272 SessionDependencies session_deps( 5273 ProxyService::CreateFixed("socks4://myproxy:1080")); 5274 5275 scoped_ptr<HttpTransaction> trans( 5276 new HttpNetworkTransaction(CreateSession(&session_deps))); 5277 5278 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 }; 5279 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 5280 5281 MockWrite data_writes[] = { 5282 MockWrite(true, reinterpret_cast<char*>(write_buffer), 5283 arraysize(write_buffer)), 5284 MockWrite("GET / HTTP/1.1\r\n" 5285 "Host: www.google.com\r\n" 5286 "Connection: keep-alive\r\n\r\n") 5287 }; 5288 5289 MockRead data_reads[] = { 5290 MockWrite(true, reinterpret_cast<char*>(read_buffer), 5291 arraysize(read_buffer)), 5292 MockRead("HTTP/1.0 200 OK\r\n"), 5293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 5294 MockRead("Payload"), 5295 MockRead(false, OK) 5296 }; 5297 5298 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5299 data_writes, arraysize(data_writes)); 5300 session_deps.socket_factory.AddSocketDataProvider(&data); 5301 5302 SSLSocketDataProvider ssl(true, OK); 5303 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 5304 5305 TestCompletionCallback callback; 5306 5307 int rv = trans->Start(&request, &callback, BoundNetLog()); 5308 EXPECT_EQ(ERR_IO_PENDING, rv); 5309 5310 rv = callback.WaitForResult(); 5311 EXPECT_EQ(OK, rv); 5312 5313 const HttpResponseInfo* response = trans->GetResponseInfo(); 5314 EXPECT_FALSE(response == NULL); 5315 5316 std::string response_text; 5317 rv = ReadTransaction(trans.get(), &response_text); 5318 EXPECT_EQ(OK, rv); 5319 EXPECT_EQ("Payload", response_text); 5320 } 5321 5322 TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) { 5323 HttpRequestInfo request; 5324 request.method = "GET"; 5325 request.url = GURL("http://www.google.com/"); 5326 request.load_flags = 0; 5327 5328 SessionDependencies session_deps( 5329 ProxyService::CreateFixed("socks5://myproxy:1080")); 5330 5331 scoped_ptr<HttpTransaction> trans( 5332 new HttpNetworkTransaction(CreateSession(&session_deps))); 5333 5334 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; 5335 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; 5336 const char kSOCKS5OkRequest[] = { 5337 0x05, // Version 5338 0x01, // Command (CONNECT) 5339 0x00, // Reserved. 5340 0x03, // Address type (DOMAINNAME). 5341 0x0E, // Length of domain (14) 5342 // Domain string: 5343 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', 5344 0x00, 0x50, // 16-bit port (80) 5345 }; 5346 const char kSOCKS5OkResponse[] = 5347 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 }; 5348 5349 MockWrite data_writes[] = { 5350 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), 5351 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)), 5352 MockWrite("GET / HTTP/1.1\r\n" 5353 "Host: www.google.com\r\n" 5354 "Connection: keep-alive\r\n\r\n") 5355 }; 5356 5357 MockRead data_reads[] = { 5358 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), 5359 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), 5360 MockRead("HTTP/1.0 200 OK\r\n"), 5361 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 5362 MockRead("Payload"), 5363 MockRead(false, OK) 5364 }; 5365 5366 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5367 data_writes, arraysize(data_writes)); 5368 session_deps.socket_factory.AddSocketDataProvider(&data); 5369 5370 TestCompletionCallback callback; 5371 5372 int rv = trans->Start(&request, &callback, BoundNetLog()); 5373 EXPECT_EQ(ERR_IO_PENDING, rv); 5374 5375 rv = callback.WaitForResult(); 5376 EXPECT_EQ(OK, rv); 5377 5378 const HttpResponseInfo* response = trans->GetResponseInfo(); 5379 EXPECT_FALSE(response == NULL); 5380 5381 std::string response_text; 5382 rv = ReadTransaction(trans.get(), &response_text); 5383 EXPECT_EQ(OK, rv); 5384 EXPECT_EQ("Payload", response_text); 5385 } 5386 5387 TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) { 5388 HttpRequestInfo request; 5389 request.method = "GET"; 5390 request.url = GURL("https://www.google.com/"); 5391 request.load_flags = 0; 5392 5393 SessionDependencies session_deps( 5394 ProxyService::CreateFixed("socks5://myproxy:1080")); 5395 5396 scoped_ptr<HttpTransaction> trans( 5397 new HttpNetworkTransaction(CreateSession(&session_deps))); 5398 5399 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; 5400 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; 5401 const unsigned char kSOCKS5OkRequest[] = { 5402 0x05, // Version 5403 0x01, // Command (CONNECT) 5404 0x00, // Reserved. 5405 0x03, // Address type (DOMAINNAME). 5406 0x0E, // Length of domain (14) 5407 // Domain string: 5408 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', 5409 0x01, 0xBB, // 16-bit port (443) 5410 }; 5411 5412 const char kSOCKS5OkResponse[] = 5413 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 }; 5414 5415 MockWrite data_writes[] = { 5416 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), 5417 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest), 5418 arraysize(kSOCKS5OkRequest)), 5419 MockWrite("GET / HTTP/1.1\r\n" 5420 "Host: www.google.com\r\n" 5421 "Connection: keep-alive\r\n\r\n") 5422 }; 5423 5424 MockRead data_reads[] = { 5425 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), 5426 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), 5427 MockRead("HTTP/1.0 200 OK\r\n"), 5428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 5429 MockRead("Payload"), 5430 MockRead(false, OK) 5431 }; 5432 5433 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5434 data_writes, arraysize(data_writes)); 5435 session_deps.socket_factory.AddSocketDataProvider(&data); 5436 5437 SSLSocketDataProvider ssl(true, OK); 5438 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 5439 5440 TestCompletionCallback callback; 5441 5442 int rv = trans->Start(&request, &callback, BoundNetLog()); 5443 EXPECT_EQ(ERR_IO_PENDING, rv); 5444 5445 rv = callback.WaitForResult(); 5446 EXPECT_EQ(OK, rv); 5447 5448 const HttpResponseInfo* response = trans->GetResponseInfo(); 5449 EXPECT_FALSE(response == NULL); 5450 5451 std::string response_text; 5452 rv = ReadTransaction(trans.get(), &response_text); 5453 EXPECT_EQ(OK, rv); 5454 EXPECT_EQ("Payload", response_text); 5455 } 5456 5457 // Tests that for connection endpoints the group names are correctly set. 5458 5459 struct GroupNameTest { 5460 std::string proxy_server; 5461 std::string url; 5462 std::string expected_group_name; 5463 bool ssl; 5464 }; 5465 5466 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests( 5467 SessionDependencies* session_deps) { 5468 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps)); 5469 5470 HttpAlternateProtocols* alternate_protocols = 5471 session->mutable_alternate_protocols(); 5472 alternate_protocols->SetAlternateProtocolFor( 5473 HostPortPair("host.with.alternate", 80), 443, 5474 HttpAlternateProtocols::NPN_SPDY_2); 5475 5476 return session; 5477 } 5478 5479 int GroupNameTransactionHelper( 5480 const std::string& url, 5481 const scoped_refptr<HttpNetworkSession>& session) { 5482 HttpRequestInfo request; 5483 request.method = "GET"; 5484 request.url = GURL(url); 5485 request.load_flags = 0; 5486 5487 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 5488 5489 TestCompletionCallback callback; 5490 5491 // We do not complete this request, the dtor will clean the transaction up. 5492 return trans->Start(&request, &callback, BoundNetLog()); 5493 } 5494 5495 TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) { 5496 const GroupNameTest tests[] = { 5497 { 5498 "", // unused 5499 "http://www.google.com/direct", 5500 "www.google.com:80", 5501 false, 5502 }, 5503 { 5504 "", // unused 5505 "http://[2001:1418:13:1::25]/direct", 5506 "[2001:1418:13:1::25]:80", 5507 false, 5508 }, 5509 5510 // SSL Tests 5511 { 5512 "", // unused 5513 "https://www.google.com/direct_ssl", 5514 "ssl/www.google.com:443", 5515 true, 5516 }, 5517 { 5518 "", // unused 5519 "https://[2001:1418:13:1::25]/direct", 5520 "ssl/[2001:1418:13:1::25]:443", 5521 true, 5522 }, 5523 { 5524 "", // unused 5525 "http://host.with.alternate/direct", 5526 "ssl/host.with.alternate:443", 5527 true, 5528 }, 5529 }; 5530 5531 HttpStreamFactory::set_use_alternate_protocols(true); 5532 5533 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 5534 SessionDependencies session_deps( 5535 ProxyService::CreateFixed(tests[i].proxy_server)); 5536 scoped_refptr<HttpNetworkSession> session( 5537 SetupSessionForGroupNameTests(&session_deps)); 5538 5539 HttpNetworkSessionPeer peer(session); 5540 CaptureGroupNameTransportSocketPool* transport_conn_pool = 5541 new CaptureGroupNameTransportSocketPool(NULL, NULL); 5542 peer.SetTransportSocketPool(transport_conn_pool); 5543 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 5544 new CaptureGroupNameSSLSocketPool(NULL, NULL); 5545 peer.SetSSLSocketPool(ssl_conn_pool); 5546 5547 EXPECT_EQ(ERR_IO_PENDING, 5548 GroupNameTransactionHelper(tests[i].url, session)); 5549 if (tests[i].ssl) 5550 EXPECT_EQ(tests[i].expected_group_name, 5551 ssl_conn_pool->last_group_name_received()); 5552 else 5553 EXPECT_EQ(tests[i].expected_group_name, 5554 transport_conn_pool->last_group_name_received()); 5555 } 5556 5557 HttpStreamFactory::set_use_alternate_protocols(false); 5558 } 5559 5560 TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) { 5561 const GroupNameTest tests[] = { 5562 { 5563 "http_proxy", 5564 "http://www.google.com/http_proxy_normal", 5565 "www.google.com:80", 5566 false, 5567 }, 5568 5569 // SSL Tests 5570 { 5571 "http_proxy", 5572 "https://www.google.com/http_connect_ssl", 5573 "ssl/www.google.com:443", 5574 true, 5575 }, 5576 5577 { 5578 "http_proxy", 5579 "http://host.with.alternate/direct", 5580 "ssl/host.with.alternate:443", 5581 true, 5582 }, 5583 }; 5584 5585 HttpStreamFactory::set_use_alternate_protocols(true); 5586 5587 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 5588 SessionDependencies session_deps( 5589 ProxyService::CreateFixed(tests[i].proxy_server)); 5590 scoped_refptr<HttpNetworkSession> session( 5591 SetupSessionForGroupNameTests(&session_deps)); 5592 5593 HttpNetworkSessionPeer peer(session); 5594 5595 HostPortPair proxy_host("http_proxy", 80); 5596 CaptureGroupNameHttpProxySocketPool* http_proxy_pool = 5597 new CaptureGroupNameHttpProxySocketPool(NULL, NULL); 5598 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool); 5599 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 5600 new CaptureGroupNameSSLSocketPool(NULL, NULL); 5601 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); 5602 5603 EXPECT_EQ(ERR_IO_PENDING, 5604 GroupNameTransactionHelper(tests[i].url, session)); 5605 if (tests[i].ssl) 5606 EXPECT_EQ(tests[i].expected_group_name, 5607 ssl_conn_pool->last_group_name_received()); 5608 else 5609 EXPECT_EQ(tests[i].expected_group_name, 5610 http_proxy_pool->last_group_name_received()); 5611 } 5612 5613 HttpStreamFactory::set_use_alternate_protocols(false); 5614 } 5615 5616 TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) { 5617 const GroupNameTest tests[] = { 5618 { 5619 "socks4://socks_proxy:1080", 5620 "http://www.google.com/socks4_direct", 5621 "socks4/www.google.com:80", 5622 false, 5623 }, 5624 { 5625 "socks5://socks_proxy:1080", 5626 "http://www.google.com/socks5_direct", 5627 "socks5/www.google.com:80", 5628 false, 5629 }, 5630 5631 // SSL Tests 5632 { 5633 "socks4://socks_proxy:1080", 5634 "https://www.google.com/socks4_ssl", 5635 "socks4/ssl/www.google.com:443", 5636 true, 5637 }, 5638 { 5639 "socks5://socks_proxy:1080", 5640 "https://www.google.com/socks5_ssl", 5641 "socks5/ssl/www.google.com:443", 5642 true, 5643 }, 5644 5645 { 5646 "socks4://socks_proxy:1080", 5647 "http://host.with.alternate/direct", 5648 "socks4/ssl/host.with.alternate:443", 5649 true, 5650 }, 5651 }; 5652 5653 HttpStreamFactory::set_use_alternate_protocols(true); 5654 5655 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 5656 SessionDependencies session_deps( 5657 ProxyService::CreateFixed(tests[i].proxy_server)); 5658 scoped_refptr<HttpNetworkSession> session( 5659 SetupSessionForGroupNameTests(&session_deps)); 5660 5661 HttpNetworkSessionPeer peer(session); 5662 5663 HostPortPair proxy_host("socks_proxy", 1080); 5664 CaptureGroupNameSOCKSSocketPool* socks_conn_pool = 5665 new CaptureGroupNameSOCKSSocketPool(NULL, NULL); 5666 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool); 5667 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 5668 new CaptureGroupNameSSLSocketPool(NULL, NULL); 5669 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); 5670 5671 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 5672 5673 EXPECT_EQ(ERR_IO_PENDING, 5674 GroupNameTransactionHelper(tests[i].url, session)); 5675 if (tests[i].ssl) 5676 EXPECT_EQ(tests[i].expected_group_name, 5677 ssl_conn_pool->last_group_name_received()); 5678 else 5679 EXPECT_EQ(tests[i].expected_group_name, 5680 socks_conn_pool->last_group_name_received()); 5681 } 5682 5683 HttpStreamFactory::set_use_alternate_protocols(false); 5684 } 5685 5686 TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) { 5687 HttpRequestInfo request; 5688 request.method = "GET"; 5689 request.url = GURL("http://www.google.com/"); 5690 5691 SessionDependencies session_deps( 5692 ProxyService::CreateFixed("myproxy:70;foobar:80")); 5693 5694 // This simulates failure resolving all hostnames; that means we will fail 5695 // connecting to both proxies (myproxy:70 and foobar:80). 5696 session_deps.host_resolver->rules()->AddSimulatedFailure("*"); 5697 5698 scoped_ptr<HttpTransaction> trans( 5699 new HttpNetworkTransaction(CreateSession(&session_deps))); 5700 5701 TestCompletionCallback callback; 5702 5703 int rv = trans->Start(&request, &callback, BoundNetLog()); 5704 EXPECT_EQ(ERR_IO_PENDING, rv); 5705 5706 rv = callback.WaitForResult(); 5707 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv); 5708 } 5709 5710 // Host resolution observer used by 5711 // HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host 5712 // resovle requests are issued with a referrer of |expected_referrer|. 5713 class ResolutionReferrerObserver : public HostResolver::Observer { 5714 public: 5715 explicit ResolutionReferrerObserver(const GURL& expected_referrer) 5716 : expected_referrer_(expected_referrer), 5717 called_start_with_referrer_(false), 5718 called_finish_with_referrer_(false) { 5719 } 5720 5721 virtual void OnStartResolution(int id, 5722 const HostResolver::RequestInfo& info) { 5723 if (info.referrer() == expected_referrer_) 5724 called_start_with_referrer_ = true; 5725 } 5726 5727 virtual void OnFinishResolutionWithStatus( 5728 int id, bool was_resolved, const HostResolver::RequestInfo& info ) { 5729 if (info.referrer() == expected_referrer_) 5730 called_finish_with_referrer_ = true; 5731 } 5732 5733 virtual void OnCancelResolution(int id, 5734 const HostResolver::RequestInfo& info ) { 5735 FAIL() << "Should not be cancelling any requests!"; 5736 } 5737 5738 bool did_complete_with_expected_referrer() const { 5739 return called_start_with_referrer_ && called_finish_with_referrer_; 5740 } 5741 5742 private: 5743 GURL expected_referrer_; 5744 bool called_start_with_referrer_; 5745 bool called_finish_with_referrer_; 5746 5747 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver); 5748 }; 5749 5750 // Make sure that when HostResolver::Resolve() is invoked, it passes through 5751 // the "referrer". This is depended on by the DNS prefetch observer. 5752 TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) { 5753 GURL referrer = GURL("http://expected-referrer/"); 5754 EXPECT_TRUE(referrer.is_valid()); 5755 ResolutionReferrerObserver resolution_observer(referrer); 5756 5757 // Issue a request, containing an HTTP referrer. 5758 HttpRequestInfo request; 5759 request.method = "GET"; 5760 request.referrer = referrer; 5761 request.url = GURL("http://www.google.com/"); 5762 5763 SessionDependencies session_deps; 5764 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction( 5765 CreateSession(&session_deps))); 5766 5767 // Attach an observer to watch the host resolutions being made. 5768 session_deps.host_resolver->AddObserver(&resolution_observer); 5769 5770 // Connect up a mock socket which will fail when reading. 5771 MockRead data_reads[] = { 5772 MockRead(false, ERR_FAILED), 5773 }; 5774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 5775 session_deps.socket_factory.AddSocketDataProvider(&data); 5776 5777 // Run the request until it fails reading from the socket. 5778 TestCompletionCallback callback; 5779 int rv = trans->Start(&request, &callback, BoundNetLog()); 5780 EXPECT_EQ(ERR_IO_PENDING, rv); 5781 rv = callback.WaitForResult(); 5782 EXPECT_EQ(ERR_FAILED, rv); 5783 5784 // Check that the host resolution observer saw |referrer|. 5785 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer()); 5786 } 5787 5788 // Base test to make sure that when the load flags for a request specify to 5789 // bypass the cache, the DNS cache is not used. 5790 void BypassHostCacheOnRefreshHelper(int load_flags) { 5791 // Issue a request, asking to bypass the cache(s). 5792 HttpRequestInfo request; 5793 request.method = "GET"; 5794 request.load_flags = load_flags; 5795 request.url = GURL("http://www.google.com/"); 5796 5797 SessionDependencies session_deps; 5798 5799 // Select a host resolver that does caching. 5800 session_deps.host_resolver.reset(new MockCachingHostResolver); 5801 5802 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction( 5803 CreateSession(&session_deps))); 5804 5805 // Warm up the host cache so it has an entry for "www.google.com" (by doing 5806 // a synchronous lookup.) 5807 AddressList addrlist; 5808 int rv = session_deps.host_resolver->Resolve( 5809 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist, 5810 NULL, NULL, BoundNetLog()); 5811 EXPECT_EQ(OK, rv); 5812 5813 // Verify that it was added to host cache, by doing a subsequent async lookup 5814 // and confirming it completes synchronously. 5815 TestCompletionCallback resolve_callback; 5816 rv = session_deps.host_resolver->Resolve( 5817 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist, 5818 &resolve_callback, NULL, BoundNetLog()); 5819 ASSERT_EQ(OK, rv); 5820 5821 // Inject a failure the next time that "www.google.com" is resolved. This way 5822 // we can tell if the next lookup hit the cache, or the "network". 5823 // (cache --> success, "network" --> failure). 5824 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com"); 5825 5826 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the 5827 // first read -- this won't be reached as the host resolution will fail first. 5828 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) }; 5829 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 5830 session_deps.socket_factory.AddSocketDataProvider(&data); 5831 5832 // Run the request. 5833 TestCompletionCallback callback; 5834 rv = trans->Start(&request, &callback, BoundNetLog()); 5835 ASSERT_EQ(ERR_IO_PENDING, rv); 5836 rv = callback.WaitForResult(); 5837 5838 // If we bypassed the cache, we would have gotten a failure while resolving 5839 // "www.google.com". 5840 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); 5841 } 5842 5843 // There are multiple load flags that should trigger the host cache bypass. 5844 // Test each in isolation: 5845 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) { 5846 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE); 5847 } 5848 5849 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) { 5850 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE); 5851 } 5852 5853 TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) { 5854 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE); 5855 } 5856 5857 // Make sure we can handle an error when writing the request. 5858 TEST_F(HttpNetworkTransactionTest, RequestWriteError) { 5859 SessionDependencies session_deps; 5860 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 5861 5862 HttpRequestInfo request; 5863 request.method = "GET"; 5864 request.url = GURL("http://www.foo.com/"); 5865 request.load_flags = 0; 5866 5867 MockWrite write_failure[] = { 5868 MockWrite(true, ERR_CONNECTION_RESET), 5869 }; 5870 StaticSocketDataProvider data(NULL, 0, 5871 write_failure, arraysize(write_failure)); 5872 session_deps.socket_factory.AddSocketDataProvider(&data); 5873 5874 TestCompletionCallback callback; 5875 5876 scoped_ptr<HttpTransaction> trans( 5877 new HttpNetworkTransaction(CreateSession(&session_deps))); 5878 5879 int rv = trans->Start(&request, &callback, BoundNetLog()); 5880 EXPECT_EQ(ERR_IO_PENDING, rv); 5881 5882 rv = callback.WaitForResult(); 5883 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 5884 } 5885 5886 // Check that a connection closed after the start of the headers finishes ok. 5887 TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { 5888 SessionDependencies session_deps; 5889 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 5890 5891 HttpRequestInfo request; 5892 request.method = "GET"; 5893 request.url = GURL("http://www.foo.com/"); 5894 request.load_flags = 0; 5895 5896 MockRead data_reads[] = { 5897 MockRead("HTTP/1."), 5898 MockRead(false, OK), 5899 }; 5900 5901 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 5902 session_deps.socket_factory.AddSocketDataProvider(&data); 5903 5904 TestCompletionCallback callback; 5905 5906 scoped_ptr<HttpTransaction> trans( 5907 new HttpNetworkTransaction(CreateSession(&session_deps))); 5908 5909 int rv = trans->Start(&request, &callback, BoundNetLog()); 5910 EXPECT_EQ(ERR_IO_PENDING, rv); 5911 5912 rv = callback.WaitForResult(); 5913 EXPECT_EQ(OK, rv); 5914 5915 const HttpResponseInfo* response = trans->GetResponseInfo(); 5916 EXPECT_TRUE(response != NULL); 5917 5918 EXPECT_TRUE(response->headers != NULL); 5919 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 5920 5921 std::string response_data; 5922 rv = ReadTransaction(trans.get(), &response_data); 5923 EXPECT_EQ(OK, rv); 5924 EXPECT_EQ("", response_data); 5925 } 5926 5927 // Make sure that a dropped connection while draining the body for auth 5928 // restart does the right thing. 5929 TEST_F(HttpNetworkTransactionTest, DrainResetOK) { 5930 SessionDependencies session_deps; 5931 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 5932 5933 HttpRequestInfo request; 5934 request.method = "GET"; 5935 request.url = GURL("http://www.google.com/"); 5936 request.load_flags = 0; 5937 5938 MockWrite data_writes1[] = { 5939 MockWrite("GET / HTTP/1.1\r\n" 5940 "Host: www.google.com\r\n" 5941 "Connection: keep-alive\r\n\r\n"), 5942 }; 5943 5944 MockRead data_reads1[] = { 5945 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 5946 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5947 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5948 MockRead("Content-Length: 14\r\n\r\n"), 5949 MockRead("Unauth"), 5950 MockRead(true, ERR_CONNECTION_RESET), 5951 }; 5952 5953 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5954 data_writes1, arraysize(data_writes1)); 5955 session_deps.socket_factory.AddSocketDataProvider(&data1); 5956 5957 // After calling trans->RestartWithAuth(), this is the request we should 5958 // be issuing -- the final header line contains the credentials. 5959 MockWrite data_writes2[] = { 5960 MockWrite("GET / HTTP/1.1\r\n" 5961 "Host: www.google.com\r\n" 5962 "Connection: keep-alive\r\n" 5963 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5964 }; 5965 5966 // Lastly, the server responds with the actual content. 5967 MockRead data_reads2[] = { 5968 MockRead("HTTP/1.1 200 OK\r\n"), 5969 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5970 MockRead("Content-Length: 100\r\n\r\n"), 5971 MockRead(false, OK), 5972 }; 5973 5974 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5975 data_writes2, arraysize(data_writes2)); 5976 session_deps.socket_factory.AddSocketDataProvider(&data2); 5977 5978 TestCompletionCallback callback1; 5979 5980 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 5981 5982 int rv = trans->Start(&request, &callback1, BoundNetLog()); 5983 EXPECT_EQ(ERR_IO_PENDING, rv); 5984 5985 rv = callback1.WaitForResult(); 5986 EXPECT_EQ(OK, rv); 5987 5988 const HttpResponseInfo* response = trans->GetResponseInfo(); 5989 EXPECT_FALSE(response == NULL); 5990 5991 // The password prompt info should have been set in response->auth_challenge. 5992 EXPECT_FALSE(response->auth_challenge.get() == NULL); 5993 5994 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 5995 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 5996 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 5997 5998 TestCompletionCallback callback2; 5999 6000 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 6001 EXPECT_EQ(ERR_IO_PENDING, rv); 6002 6003 rv = callback2.WaitForResult(); 6004 EXPECT_EQ(OK, rv); 6005 6006 response = trans->GetResponseInfo(); 6007 EXPECT_FALSE(response == NULL); 6008 EXPECT_TRUE(response->auth_challenge.get() == NULL); 6009 EXPECT_EQ(100, response->headers->GetContentLength()); 6010 } 6011 6012 // Test HTTPS connections going through a proxy that sends extra data. 6013 TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) { 6014 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 6015 6016 HttpRequestInfo request; 6017 request.method = "GET"; 6018 request.url = GURL("https://www.google.com/"); 6019 request.load_flags = 0; 6020 6021 MockRead proxy_reads[] = { 6022 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"), 6023 MockRead(false, OK) 6024 }; 6025 6026 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0); 6027 SSLSocketDataProvider ssl(true, OK); 6028 6029 session_deps.socket_factory.AddSocketDataProvider(&data); 6030 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 6031 6032 TestCompletionCallback callback; 6033 6034 session_deps.socket_factory.ResetNextMockIndexes(); 6035 6036 scoped_ptr<HttpTransaction> trans( 6037 new HttpNetworkTransaction(CreateSession(&session_deps))); 6038 6039 int rv = trans->Start(&request, &callback, BoundNetLog()); 6040 EXPECT_EQ(ERR_IO_PENDING, rv); 6041 6042 rv = callback.WaitForResult(); 6043 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 6044 } 6045 6046 TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) { 6047 HttpRequestInfo request; 6048 request.method = "GET"; 6049 request.url = GURL("http://www.google.com/"); 6050 request.load_flags = 0; 6051 6052 SessionDependencies session_deps; 6053 scoped_ptr<HttpTransaction> trans( 6054 new HttpNetworkTransaction(CreateSession(&session_deps))); 6055 6056 MockRead data_reads[] = { 6057 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"), 6058 MockRead(false, OK), 6059 }; 6060 6061 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 6062 session_deps.socket_factory.AddSocketDataProvider(&data); 6063 6064 TestCompletionCallback callback; 6065 6066 int rv = trans->Start(&request, &callback, BoundNetLog()); 6067 EXPECT_EQ(ERR_IO_PENDING, rv); 6068 6069 EXPECT_EQ(OK, callback.WaitForResult()); 6070 6071 const HttpResponseInfo* response = trans->GetResponseInfo(); 6072 EXPECT_TRUE(response != NULL); 6073 6074 EXPECT_TRUE(response->headers != NULL); 6075 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 6076 6077 std::string response_data; 6078 rv = ReadTransaction(trans.get(), &response_data); 6079 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); 6080 } 6081 6082 TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { 6083 HttpRequestInfo request; 6084 request.method = "POST"; 6085 request.url = GURL("http://www.google.com/upload"); 6086 request.upload_data = new UploadData; 6087 request.load_flags = 0; 6088 6089 SessionDependencies session_deps; 6090 scoped_ptr<HttpTransaction> trans( 6091 new HttpNetworkTransaction(CreateSession(&session_deps))); 6092 6093 FilePath temp_file_path; 6094 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path)); 6095 const uint64 kFakeSize = 100000; // file is actually blank 6096 6097 std::vector<UploadData::Element> elements; 6098 UploadData::Element element; 6099 element.SetToFilePath(temp_file_path); 6100 element.SetContentLength(kFakeSize); 6101 elements.push_back(element); 6102 request.upload_data->SetElements(elements); 6103 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength()); 6104 6105 MockRead data_reads[] = { 6106 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 6107 MockRead("hello world"), 6108 MockRead(false, OK), 6109 }; 6110 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 6111 session_deps.socket_factory.AddSocketDataProvider(&data); 6112 6113 TestCompletionCallback callback; 6114 6115 int rv = trans->Start(&request, &callback, BoundNetLog()); 6116 EXPECT_EQ(ERR_IO_PENDING, rv); 6117 6118 rv = callback.WaitForResult(); 6119 EXPECT_EQ(OK, rv); 6120 6121 const HttpResponseInfo* response = trans->GetResponseInfo(); 6122 EXPECT_TRUE(response != NULL); 6123 6124 EXPECT_TRUE(response->headers != NULL); 6125 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 6126 6127 std::string response_data; 6128 rv = ReadTransaction(trans.get(), &response_data); 6129 EXPECT_EQ(OK, rv); 6130 EXPECT_EQ("hello world", response_data); 6131 6132 file_util::Delete(temp_file_path, false); 6133 } 6134 6135 TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) { 6136 HttpRequestInfo request; 6137 request.method = "POST"; 6138 request.url = GURL("http://www.google.com/upload"); 6139 request.upload_data = new UploadData; 6140 request.load_flags = 0; 6141 6142 // If we try to upload an unreadable file, the network stack should report 6143 // the file size as zero and upload zero bytes for that file. 6144 SessionDependencies session_deps; 6145 scoped_ptr<HttpTransaction> trans( 6146 new HttpNetworkTransaction(CreateSession(&session_deps))); 6147 6148 FilePath temp_file; 6149 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file)); 6150 std::string temp_file_content("Unreadable file."); 6151 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(), 6152 temp_file_content.length())); 6153 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file)); 6154 6155 std::vector<UploadData::Element> elements; 6156 UploadData::Element element; 6157 element.SetToFilePath(temp_file); 6158 elements.push_back(element); 6159 request.upload_data->SetElements(elements); 6160 6161 MockRead data_reads[] = { 6162 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 6163 MockRead(false, OK), 6164 }; 6165 MockWrite data_writes[] = { 6166 MockWrite("POST /upload HTTP/1.1\r\n" 6167 "Host: www.google.com\r\n" 6168 "Connection: keep-alive\r\n" 6169 "Content-Length: 0\r\n\r\n"), 6170 MockWrite(false, OK), 6171 }; 6172 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, 6173 arraysize(data_writes)); 6174 session_deps.socket_factory.AddSocketDataProvider(&data); 6175 6176 TestCompletionCallback callback; 6177 6178 int rv = trans->Start(&request, &callback, BoundNetLog()); 6179 EXPECT_EQ(ERR_IO_PENDING, rv); 6180 6181 rv = callback.WaitForResult(); 6182 EXPECT_EQ(OK, rv); 6183 6184 const HttpResponseInfo* response = trans->GetResponseInfo(); 6185 EXPECT_TRUE(response != NULL); 6186 EXPECT_TRUE(response->headers != NULL); 6187 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 6188 6189 file_util::Delete(temp_file, false); 6190 } 6191 6192 TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) { 6193 HttpRequestInfo request; 6194 request.method = "POST"; 6195 request.url = GURL("http://www.google.com/upload"); 6196 request.upload_data = new UploadData; 6197 request.load_flags = 0; 6198 6199 SessionDependencies session_deps; 6200 scoped_ptr<HttpTransaction> trans( 6201 new HttpNetworkTransaction(CreateSession(&session_deps))); 6202 6203 FilePath temp_file; 6204 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file)); 6205 std::string temp_file_contents("Unreadable file."); 6206 std::string unreadable_contents(temp_file_contents.length(), '\0'); 6207 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(), 6208 temp_file_contents.length())); 6209 6210 std::vector<UploadData::Element> elements; 6211 UploadData::Element element; 6212 element.SetToFilePath(temp_file); 6213 elements.push_back(element); 6214 request.upload_data->SetElements(elements); 6215 6216 MockRead data_reads[] = { 6217 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 6218 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 6219 MockRead("Content-Length: 0\r\n\r\n"), // No response body. 6220 6221 MockRead("HTTP/1.1 200 OK\r\n"), 6222 MockRead("Content-Length: 0\r\n\r\n"), 6223 MockRead(false, OK), 6224 }; 6225 MockWrite data_writes[] = { 6226 MockWrite("POST /upload HTTP/1.1\r\n" 6227 "Host: www.google.com\r\n" 6228 "Connection: keep-alive\r\n" 6229 "Content-Length: 16\r\n\r\n"), 6230 MockWrite(false, temp_file_contents.c_str()), 6231 6232 MockWrite("POST /upload HTTP/1.1\r\n" 6233 "Host: www.google.com\r\n" 6234 "Connection: keep-alive\r\n" 6235 "Content-Length: 16\r\n" 6236 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 6237 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()), 6238 MockWrite(false, OK), 6239 }; 6240 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, 6241 arraysize(data_writes)); 6242 session_deps.socket_factory.AddSocketDataProvider(&data); 6243 6244 TestCompletionCallback callback1; 6245 6246 int rv = trans->Start(&request, &callback1, BoundNetLog()); 6247 EXPECT_EQ(ERR_IO_PENDING, rv); 6248 6249 rv = callback1.WaitForResult(); 6250 EXPECT_EQ(OK, rv); 6251 6252 const HttpResponseInfo* response = trans->GetResponseInfo(); 6253 EXPECT_TRUE(response != NULL); 6254 EXPECT_TRUE(response->headers != NULL); 6255 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine()); 6256 6257 // The password prompt info should have been set in response->auth_challenge. 6258 EXPECT_TRUE(response->auth_challenge.get() != NULL); 6259 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 6260 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm); 6261 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 6262 6263 // Now make the file unreadable and try again. 6264 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file)); 6265 6266 TestCompletionCallback callback2; 6267 6268 rv = trans->RestartWithAuth(kFoo, kBar, &callback2); 6269 EXPECT_EQ(ERR_IO_PENDING, rv); 6270 6271 rv = callback2.WaitForResult(); 6272 EXPECT_EQ(OK, rv); 6273 6274 response = trans->GetResponseInfo(); 6275 EXPECT_TRUE(response != NULL); 6276 EXPECT_TRUE(response->headers != NULL); 6277 EXPECT_TRUE(response->auth_challenge.get() == NULL); 6278 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6279 6280 file_util::Delete(temp_file, false); 6281 } 6282 6283 // Tests that changes to Auth realms are treated like auth rejections. 6284 TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) { 6285 SessionDependencies session_deps; 6286 6287 HttpRequestInfo request; 6288 request.method = "GET"; 6289 request.url = GURL("http://www.google.com/"); 6290 request.load_flags = 0; 6291 6292 // First transaction will request a resource and receive a Basic challenge 6293 // with realm="first_realm". 6294 MockWrite data_writes1[] = { 6295 MockWrite("GET / HTTP/1.1\r\n" 6296 "Host: www.google.com\r\n" 6297 "Connection: keep-alive\r\n" 6298 "\r\n"), 6299 }; 6300 MockRead data_reads1[] = { 6301 MockRead("HTTP/1.1 401 Unauthorized\r\n" 6302 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n" 6303 "\r\n"), 6304 }; 6305 6306 // After calling trans->RestartWithAuth(), provide an Authentication header 6307 // for first_realm. The server will reject and provide a challenge with 6308 // second_realm. 6309 MockWrite data_writes2[] = { 6310 MockWrite("GET / HTTP/1.1\r\n" 6311 "Host: www.google.com\r\n" 6312 "Connection: keep-alive\r\n" 6313 "Authorization: Basic Zmlyc3Q6YmF6\r\n" 6314 "\r\n"), 6315 }; 6316 MockRead data_reads2[] = { 6317 MockRead("HTTP/1.1 401 Unauthorized\r\n" 6318 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n" 6319 "\r\n"), 6320 }; 6321 6322 // This again fails, and goes back to first_realm. Make sure that the 6323 // entry is removed from cache. 6324 MockWrite data_writes3[] = { 6325 MockWrite("GET / HTTP/1.1\r\n" 6326 "Host: www.google.com\r\n" 6327 "Connection: keep-alive\r\n" 6328 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n" 6329 "\r\n"), 6330 }; 6331 MockRead data_reads3[] = { 6332 MockRead("HTTP/1.1 401 Unauthorized\r\n" 6333 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n" 6334 "\r\n"), 6335 }; 6336 6337 // Try one last time (with the correct password) and get the resource. 6338 MockWrite data_writes4[] = { 6339 MockWrite("GET / HTTP/1.1\r\n" 6340 "Host: www.google.com\r\n" 6341 "Connection: keep-alive\r\n" 6342 "Authorization: Basic Zmlyc3Q6YmFy\r\n" 6343 "\r\n"), 6344 }; 6345 MockRead data_reads4[] = { 6346 MockRead("HTTP/1.1 200 OK\r\n" 6347 "Content-Type: text/html; charset=iso-8859-1\r\n" 6348 "Content-Length: 5\r\n" 6349 "\r\n" 6350 "hello"), 6351 }; 6352 6353 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 6354 data_writes1, arraysize(data_writes1)); 6355 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 6356 data_writes2, arraysize(data_writes2)); 6357 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 6358 data_writes3, arraysize(data_writes3)); 6359 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4), 6360 data_writes4, arraysize(data_writes4)); 6361 session_deps.socket_factory.AddSocketDataProvider(&data1); 6362 session_deps.socket_factory.AddSocketDataProvider(&data2); 6363 session_deps.socket_factory.AddSocketDataProvider(&data3); 6364 session_deps.socket_factory.AddSocketDataProvider(&data4); 6365 6366 TestCompletionCallback callback1; 6367 6368 scoped_ptr<HttpTransaction> trans( 6369 new HttpNetworkTransaction(CreateSession(&session_deps))); 6370 6371 // Issue the first request with Authorize headers. There should be a 6372 // password prompt for first_realm waiting to be filled in after the 6373 // transaction completes. 6374 int rv = trans->Start(&request, &callback1, BoundNetLog()); 6375 EXPECT_EQ(ERR_IO_PENDING, rv); 6376 rv = callback1.WaitForResult(); 6377 EXPECT_EQ(OK, rv); 6378 const HttpResponseInfo* response = trans->GetResponseInfo(); 6379 ASSERT_FALSE(response == NULL); 6380 ASSERT_FALSE(response->auth_challenge.get() == NULL); 6381 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 6382 EXPECT_EQ(L"first_realm", response->auth_challenge->realm); 6383 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 6384 6385 // Issue the second request with an incorrect password. There should be a 6386 // password prompt for second_realm waiting to be filled in after the 6387 // transaction completes. 6388 TestCompletionCallback callback2; 6389 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2); 6390 EXPECT_EQ(ERR_IO_PENDING, rv); 6391 rv = callback2.WaitForResult(); 6392 EXPECT_EQ(OK, rv); 6393 response = trans->GetResponseInfo(); 6394 ASSERT_FALSE(response == NULL); 6395 ASSERT_FALSE(response->auth_challenge.get() == NULL); 6396 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 6397 EXPECT_EQ(L"second_realm", response->auth_challenge->realm); 6398 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 6399 6400 // Issue the third request with another incorrect password. There should be 6401 // a password prompt for first_realm waiting to be filled in. If the password 6402 // prompt is not present, it indicates that the HttpAuthCacheEntry for 6403 // first_realm was not correctly removed. 6404 TestCompletionCallback callback3; 6405 rv = trans->RestartWithAuth(kSecond, kFou, &callback3); 6406 EXPECT_EQ(ERR_IO_PENDING, rv); 6407 rv = callback3.WaitForResult(); 6408 EXPECT_EQ(OK, rv); 6409 response = trans->GetResponseInfo(); 6410 ASSERT_FALSE(response == NULL); 6411 ASSERT_FALSE(response->auth_challenge.get() == NULL); 6412 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port); 6413 EXPECT_EQ(L"first_realm", response->auth_challenge->realm); 6414 EXPECT_EQ(L"basic", response->auth_challenge->scheme); 6415 6416 // Issue the fourth request with the correct password and username. 6417 TestCompletionCallback callback4; 6418 rv = trans->RestartWithAuth(kFirst, kBar, &callback4); 6419 EXPECT_EQ(ERR_IO_PENDING, rv); 6420 rv = callback4.WaitForResult(); 6421 EXPECT_EQ(OK, rv); 6422 response = trans->GetResponseInfo(); 6423 ASSERT_FALSE(response == NULL); 6424 EXPECT_TRUE(response->auth_challenge.get() == NULL); 6425 } 6426 6427 TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) { 6428 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test"); 6429 HttpStreamFactory::set_use_alternate_protocols(true); 6430 6431 SessionDependencies session_deps; 6432 6433 MockRead data_reads[] = { 6434 MockRead("HTTP/1.1 200 OK\r\n"), 6435 MockRead(kAlternateProtocolHttpHeader), 6436 MockRead("hello world"), 6437 MockRead(false, OK), 6438 }; 6439 6440 HttpRequestInfo request; 6441 request.method = "GET"; 6442 request.url = GURL("http://www.google.com/"); 6443 request.load_flags = 0; 6444 6445 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 6446 6447 session_deps.socket_factory.AddSocketDataProvider(&data); 6448 6449 TestCompletionCallback callback; 6450 6451 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 6452 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 6453 6454 int rv = trans->Start(&request, &callback, BoundNetLog()); 6455 EXPECT_EQ(ERR_IO_PENDING, rv); 6456 6457 HostPortPair http_host_port_pair("www.google.com", 80); 6458 const HttpAlternateProtocols& alternate_protocols = 6459 session->alternate_protocols(); 6460 EXPECT_FALSE( 6461 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair)); 6462 6463 EXPECT_EQ(OK, callback.WaitForResult()); 6464 6465 const HttpResponseInfo* response = trans->GetResponseInfo(); 6466 ASSERT_TRUE(response != NULL); 6467 ASSERT_TRUE(response->headers != NULL); 6468 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6469 EXPECT_FALSE(response->was_fetched_via_spdy); 6470 EXPECT_FALSE(response->was_npn_negotiated); 6471 6472 std::string response_data; 6473 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6474 EXPECT_EQ("hello world", response_data); 6475 6476 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair)); 6477 const HttpAlternateProtocols::PortProtocolPair alternate = 6478 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair); 6479 HttpAlternateProtocols::PortProtocolPair expected_alternate; 6480 expected_alternate.port = 443; 6481 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2; 6482 EXPECT_TRUE(expected_alternate.Equals(alternate)); 6483 6484 HttpStreamFactory::set_use_alternate_protocols(false); 6485 HttpStreamFactory::set_next_protos(""); 6486 } 6487 6488 TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) { 6489 HttpStreamFactory::set_use_alternate_protocols(true); 6490 SessionDependencies session_deps; 6491 6492 HttpRequestInfo request; 6493 request.method = "GET"; 6494 request.url = GURL("http://www.google.com/"); 6495 request.load_flags = 0; 6496 6497 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED); 6498 StaticSocketDataProvider first_data; 6499 first_data.set_connect_data(mock_connect); 6500 session_deps.socket_factory.AddSocketDataProvider(&first_data); 6501 6502 MockRead data_reads[] = { 6503 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 6504 MockRead("hello world"), 6505 MockRead(true, OK), 6506 }; 6507 StaticSocketDataProvider second_data( 6508 data_reads, arraysize(data_reads), NULL, 0); 6509 session_deps.socket_factory.AddSocketDataProvider(&second_data); 6510 6511 TestCompletionCallback callback; 6512 6513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 6514 6515 HostPortPair http_host_port_pair("www.google.com", 80); 6516 HttpAlternateProtocols* alternate_protocols = 6517 session->mutable_alternate_protocols(); 6518 alternate_protocols->SetAlternateProtocolFor( 6519 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */, 6520 HttpAlternateProtocols::NPN_SPDY_2); 6521 6522 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 6523 6524 int rv = trans->Start(&request, &callback, BoundNetLog()); 6525 EXPECT_EQ(ERR_IO_PENDING, rv); 6526 EXPECT_EQ(OK, callback.WaitForResult()); 6527 6528 const HttpResponseInfo* response = trans->GetResponseInfo(); 6529 ASSERT_TRUE(response != NULL); 6530 ASSERT_TRUE(response->headers != NULL); 6531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6532 6533 std::string response_data; 6534 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6535 EXPECT_EQ("hello world", response_data); 6536 6537 ASSERT_TRUE( 6538 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair)); 6539 const HttpAlternateProtocols::PortProtocolPair alternate = 6540 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair); 6541 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol); 6542 HttpStreamFactory::set_use_alternate_protocols(false); 6543 } 6544 6545 TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { 6546 HttpStreamFactory::set_use_alternate_protocols(true); 6547 HttpStreamFactory::set_next_protos(kExpectedNPNString); 6548 SessionDependencies session_deps; 6549 6550 HttpRequestInfo request; 6551 request.method = "GET"; 6552 request.url = GURL("http://www.google.com/"); 6553 request.load_flags = 0; 6554 6555 MockRead data_reads[] = { 6556 MockRead("HTTP/1.1 200 OK\r\n"), 6557 MockRead(kAlternateProtocolHttpHeader), 6558 MockRead("hello world"), 6559 MockRead(true, OK), 6560 }; 6561 6562 StaticSocketDataProvider first_transaction( 6563 data_reads, arraysize(data_reads), NULL, 0); 6564 session_deps.socket_factory.AddSocketDataProvider(&first_transaction); 6565 6566 SSLSocketDataProvider ssl(true, OK); 6567 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 6568 ssl.next_proto = "spdy/2"; 6569 ssl.was_npn_negotiated = true; 6570 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 6571 6572 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 6573 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 6574 6575 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 6576 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 6577 MockRead spdy_reads[] = { 6578 CreateMockRead(*resp), 6579 CreateMockRead(*data), 6580 MockRead(true, 0, 0), 6581 }; 6582 6583 scoped_refptr<DelayedSocketData> spdy_data( 6584 new DelayedSocketData( 6585 1, // wait for one write to finish before reading. 6586 spdy_reads, arraysize(spdy_reads), 6587 spdy_writes, arraysize(spdy_writes))); 6588 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 6589 6590 MockConnect never_finishing_connect(false, ERR_IO_PENDING); 6591 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 6592 NULL, 0, NULL, 0); 6593 hanging_non_alternate_protocol_socket.set_connect_data( 6594 never_finishing_connect); 6595 session_deps.socket_factory.AddSocketDataProvider( 6596 &hanging_non_alternate_protocol_socket); 6597 6598 TestCompletionCallback callback; 6599 6600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 6601 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 6602 6603 int rv = trans->Start(&request, &callback, BoundNetLog()); 6604 EXPECT_EQ(ERR_IO_PENDING, rv); 6605 EXPECT_EQ(OK, callback.WaitForResult()); 6606 6607 const HttpResponseInfo* response = trans->GetResponseInfo(); 6608 ASSERT_TRUE(response != NULL); 6609 ASSERT_TRUE(response->headers != NULL); 6610 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6611 6612 std::string response_data; 6613 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6614 EXPECT_EQ("hello world", response_data); 6615 6616 trans.reset(new HttpNetworkTransaction(session)); 6617 6618 rv = trans->Start(&request, &callback, BoundNetLog()); 6619 EXPECT_EQ(ERR_IO_PENDING, rv); 6620 EXPECT_EQ(OK, callback.WaitForResult()); 6621 6622 response = trans->GetResponseInfo(); 6623 ASSERT_TRUE(response != NULL); 6624 ASSERT_TRUE(response->headers != NULL); 6625 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6626 EXPECT_TRUE(response->was_fetched_via_spdy); 6627 EXPECT_TRUE(response->was_npn_negotiated); 6628 6629 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6630 EXPECT_EQ("hello!", response_data); 6631 6632 HttpStreamFactory::set_next_protos(""); 6633 HttpStreamFactory::set_use_alternate_protocols(false); 6634 } 6635 6636 TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { 6637 HttpStreamFactory::set_use_alternate_protocols(true); 6638 HttpStreamFactory::set_next_protos(kExpectedNPNString); 6639 SessionDependencies session_deps; 6640 6641 HttpRequestInfo request; 6642 request.method = "GET"; 6643 request.url = GURL("http://www.google.com/"); 6644 request.load_flags = 0; 6645 6646 MockRead data_reads[] = { 6647 MockRead("HTTP/1.1 200 OK\r\n"), 6648 MockRead(kAlternateProtocolHttpHeader), 6649 MockRead("hello world"), 6650 MockRead(true, OK), 6651 }; 6652 6653 StaticSocketDataProvider first_transaction( 6654 data_reads, arraysize(data_reads), NULL, 0); 6655 // Socket 1 is the HTTP transaction with the Alternate-Protocol header. 6656 session_deps.socket_factory.AddSocketDataProvider(&first_transaction); 6657 6658 MockConnect never_finishing_connect(false, ERR_IO_PENDING); 6659 StaticSocketDataProvider hanging_socket( 6660 NULL, 0, NULL, 0); 6661 hanging_socket.set_connect_data(never_finishing_connect); 6662 // Socket 2 and 3 are the hanging Alternate-Protocol and 6663 // non-Alternate-Protocol jobs from the 2nd transaction. 6664 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket); 6665 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket); 6666 6667 SSLSocketDataProvider ssl(true, OK); 6668 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 6669 ssl.next_proto = "spdy/2"; 6670 ssl.was_npn_negotiated = true; 6671 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 6672 6673 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 6674 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST)); 6675 MockWrite spdy_writes[] = { 6676 CreateMockWrite(*req1), 6677 CreateMockWrite(*req2), 6678 }; 6679 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); 6680 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true)); 6681 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); 6682 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true)); 6683 MockRead spdy_reads[] = { 6684 CreateMockRead(*resp1), 6685 CreateMockRead(*data1), 6686 CreateMockRead(*resp2), 6687 CreateMockRead(*data2), 6688 MockRead(true, 0, 0), 6689 }; 6690 6691 scoped_refptr<DelayedSocketData> spdy_data( 6692 new DelayedSocketData( 6693 2, // wait for writes to finish before reading. 6694 spdy_reads, arraysize(spdy_reads), 6695 spdy_writes, arraysize(spdy_writes))); 6696 // Socket 4 is the successful Alternate-Protocol for transaction 3. 6697 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 6698 6699 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3. 6700 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket); 6701 6702 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 6703 TestCompletionCallback callback1; 6704 HttpNetworkTransaction trans1(session); 6705 6706 int rv = trans1.Start(&request, &callback1, BoundNetLog()); 6707 EXPECT_EQ(ERR_IO_PENDING, rv); 6708 EXPECT_EQ(OK, callback1.WaitForResult()); 6709 6710 const HttpResponseInfo* response = trans1.GetResponseInfo(); 6711 ASSERT_TRUE(response != NULL); 6712 ASSERT_TRUE(response->headers != NULL); 6713 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6714 6715 std::string response_data; 6716 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 6717 EXPECT_EQ("hello world", response_data); 6718 6719 TestCompletionCallback callback2; 6720 HttpNetworkTransaction trans2(session); 6721 rv = trans2.Start(&request, &callback2, BoundNetLog()); 6722 EXPECT_EQ(ERR_IO_PENDING, rv); 6723 6724 TestCompletionCallback callback3; 6725 HttpNetworkTransaction trans3(session); 6726 rv = trans3.Start(&request, &callback3, BoundNetLog()); 6727 EXPECT_EQ(ERR_IO_PENDING, rv); 6728 6729 EXPECT_EQ(OK, callback2.WaitForResult()); 6730 EXPECT_EQ(OK, callback3.WaitForResult()); 6731 6732 response = trans2.GetResponseInfo(); 6733 ASSERT_TRUE(response != NULL); 6734 ASSERT_TRUE(response->headers != NULL); 6735 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6736 EXPECT_TRUE(response->was_fetched_via_spdy); 6737 EXPECT_TRUE(response->was_npn_negotiated); 6738 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 6739 EXPECT_EQ("hello!", response_data); 6740 6741 response = trans3.GetResponseInfo(); 6742 ASSERT_TRUE(response != NULL); 6743 ASSERT_TRUE(response->headers != NULL); 6744 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6745 EXPECT_TRUE(response->was_fetched_via_spdy); 6746 EXPECT_TRUE(response->was_npn_negotiated); 6747 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data)); 6748 EXPECT_EQ("hello!", response_data); 6749 6750 HttpStreamFactory::set_next_protos(""); 6751 HttpStreamFactory::set_use_alternate_protocols(false); 6752 } 6753 6754 TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) { 6755 HttpStreamFactory::set_use_alternate_protocols(true); 6756 HttpStreamFactory::set_next_protos(kExpectedNPNString); 6757 SessionDependencies session_deps; 6758 6759 HttpRequestInfo request; 6760 request.method = "GET"; 6761 request.url = GURL("http://www.google.com/"); 6762 request.load_flags = 0; 6763 6764 MockRead data_reads[] = { 6765 MockRead("HTTP/1.1 200 OK\r\n"), 6766 MockRead(kAlternateProtocolHttpHeader), 6767 MockRead("hello world"), 6768 MockRead(true, OK), 6769 }; 6770 6771 StaticSocketDataProvider first_transaction( 6772 data_reads, arraysize(data_reads), NULL, 0); 6773 session_deps.socket_factory.AddSocketDataProvider(&first_transaction); 6774 6775 SSLSocketDataProvider ssl(true, OK); 6776 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 6777 ssl.next_proto = "spdy/2"; 6778 ssl.was_npn_negotiated = true; 6779 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 6780 6781 MockConnect never_finishing_connect(false, ERR_IO_PENDING); 6782 StaticSocketDataProvider hanging_alternate_protocol_socket( 6783 NULL, 0, NULL, 0); 6784 hanging_alternate_protocol_socket.set_connect_data( 6785 never_finishing_connect); 6786 session_deps.socket_factory.AddSocketDataProvider( 6787 &hanging_alternate_protocol_socket); 6788 6789 // 2nd request is just a copy of the first one, over HTTP again. 6790 session_deps.socket_factory.AddSocketDataProvider(&first_transaction); 6791 6792 TestCompletionCallback callback; 6793 6794 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 6795 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 6796 6797 int rv = trans->Start(&request, &callback, BoundNetLog()); 6798 EXPECT_EQ(ERR_IO_PENDING, rv); 6799 EXPECT_EQ(OK, callback.WaitForResult()); 6800 6801 const HttpResponseInfo* response = trans->GetResponseInfo(); 6802 ASSERT_TRUE(response != NULL); 6803 ASSERT_TRUE(response->headers != NULL); 6804 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6805 6806 std::string response_data; 6807 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6808 EXPECT_EQ("hello world", response_data); 6809 6810 trans.reset(new HttpNetworkTransaction(session)); 6811 6812 rv = trans->Start(&request, &callback, BoundNetLog()); 6813 EXPECT_EQ(ERR_IO_PENDING, rv); 6814 EXPECT_EQ(OK, callback.WaitForResult()); 6815 6816 response = trans->GetResponseInfo(); 6817 ASSERT_TRUE(response != NULL); 6818 ASSERT_TRUE(response->headers != NULL); 6819 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6820 EXPECT_FALSE(response->was_fetched_via_spdy); 6821 EXPECT_FALSE(response->was_npn_negotiated); 6822 6823 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6824 EXPECT_EQ("hello world", response_data); 6825 6826 HttpStreamFactory::set_next_protos(""); 6827 HttpStreamFactory::set_use_alternate_protocols(false); 6828 } 6829 6830 class CapturingProxyResolver : public ProxyResolver { 6831 public: 6832 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {} 6833 virtual ~CapturingProxyResolver() {} 6834 6835 virtual int GetProxyForURL(const GURL& url, 6836 ProxyInfo* results, 6837 CompletionCallback* callback, 6838 RequestHandle* request, 6839 const BoundNetLog& net_log) { 6840 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP, 6841 HostPortPair("myproxy", 80)); 6842 results->UseProxyServer(proxy_server); 6843 resolved_.push_back(url); 6844 return OK; 6845 } 6846 6847 virtual void CancelRequest(RequestHandle request) { 6848 NOTREACHED(); 6849 } 6850 6851 virtual void CancelSetPacScript() { 6852 NOTREACHED(); 6853 } 6854 6855 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&, 6856 CompletionCallback* /*callback*/) { 6857 return OK; 6858 } 6859 6860 const std::vector<GURL>& resolved() const { return resolved_; } 6861 6862 private: 6863 std::vector<GURL> resolved_; 6864 6865 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver); 6866 }; 6867 6868 TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) { 6869 HttpStreamFactory::set_use_alternate_protocols(true); 6870 HttpStreamFactory::set_next_protos(kExpectedNPNString); 6871 6872 ProxyConfig proxy_config; 6873 proxy_config.set_auto_detect(true); 6874 proxy_config.set_pac_url(GURL("http://fooproxyurl")); 6875 6876 CapturingProxyResolver* capturing_proxy_resolver = 6877 new CapturingProxyResolver(); 6878 SessionDependencies session_deps(new ProxyService( 6879 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver, 6880 NULL)); 6881 6882 HttpRequestInfo request; 6883 request.method = "GET"; 6884 request.url = GURL("http://www.google.com/"); 6885 request.load_flags = 0; 6886 6887 MockRead data_reads[] = { 6888 MockRead("HTTP/1.1 200 OK\r\n"), 6889 MockRead(kAlternateProtocolHttpHeader), 6890 MockRead("hello world"), 6891 MockRead(true, OK), 6892 }; 6893 6894 StaticSocketDataProvider first_transaction( 6895 data_reads, arraysize(data_reads), NULL, 0); 6896 session_deps.socket_factory.AddSocketDataProvider(&first_transaction); 6897 6898 SSLSocketDataProvider ssl(true, OK); 6899 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 6900 ssl.next_proto = "spdy/2"; 6901 ssl.was_npn_negotiated = true; 6902 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 6903 6904 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 6905 MockWrite spdy_writes[] = { 6906 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6907 "Host: www.google.com\r\n" 6908 "Proxy-Connection: keep-alive\r\n\r\n"), // 0 6909 CreateMockWrite(*req) // 3 6910 }; 6911 6912 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; 6913 6914 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 6915 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 6916 MockRead spdy_reads[] = { 6917 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1 6918 CreateMockRead(*resp.get(), 4), // 2, 4 6919 CreateMockRead(*data.get(), 4), // 5 6920 MockRead(true, 0, 0, 4), // 6 6921 }; 6922 6923 scoped_refptr<OrderedSocketData> spdy_data( 6924 new OrderedSocketData( 6925 spdy_reads, arraysize(spdy_reads), 6926 spdy_writes, arraysize(spdy_writes))); 6927 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 6928 6929 MockConnect never_finishing_connect(false, ERR_IO_PENDING); 6930 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 6931 NULL, 0, NULL, 0); 6932 hanging_non_alternate_protocol_socket.set_connect_data( 6933 never_finishing_connect); 6934 session_deps.socket_factory.AddSocketDataProvider( 6935 &hanging_non_alternate_protocol_socket); 6936 6937 TestCompletionCallback callback; 6938 6939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 6940 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 6941 6942 int rv = trans->Start(&request, &callback, BoundNetLog()); 6943 EXPECT_EQ(ERR_IO_PENDING, rv); 6944 EXPECT_EQ(OK, callback.WaitForResult()); 6945 6946 const HttpResponseInfo* response = trans->GetResponseInfo(); 6947 ASSERT_TRUE(response != NULL); 6948 ASSERT_TRUE(response->headers != NULL); 6949 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6950 EXPECT_FALSE(response->was_fetched_via_spdy); 6951 EXPECT_FALSE(response->was_npn_negotiated); 6952 6953 std::string response_data; 6954 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6955 EXPECT_EQ("hello world", response_data); 6956 6957 trans.reset(new HttpNetworkTransaction(session)); 6958 6959 rv = trans->Start(&request, &callback, BoundNetLog()); 6960 EXPECT_EQ(ERR_IO_PENDING, rv); 6961 EXPECT_EQ(OK, callback.WaitForResult()); 6962 6963 response = trans->GetResponseInfo(); 6964 ASSERT_TRUE(response != NULL); 6965 ASSERT_TRUE(response->headers != NULL); 6966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 6967 EXPECT_TRUE(response->was_fetched_via_spdy); 6968 EXPECT_TRUE(response->was_npn_negotiated); 6969 6970 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 6971 EXPECT_EQ("hello!", response_data); 6972 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size()); 6973 EXPECT_EQ("http://www.google.com/", 6974 capturing_proxy_resolver->resolved()[0].spec()); 6975 EXPECT_EQ("https://www.google.com/", 6976 capturing_proxy_resolver->resolved()[1].spec()); 6977 6978 HttpStreamFactory::set_next_protos(""); 6979 HttpStreamFactory::set_use_alternate_protocols(false); 6980 } 6981 6982 TEST_F(HttpNetworkTransactionTest, 6983 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) { 6984 HttpStreamFactory::set_use_alternate_protocols(true); 6985 HttpStreamFactory::set_next_protos(kExpectedNPNString); 6986 SessionDependencies session_deps; 6987 6988 HttpRequestInfo request; 6989 request.method = "GET"; 6990 request.url = GURL("http://www.google.com/"); 6991 request.load_flags = 0; 6992 6993 MockRead data_reads[] = { 6994 MockRead("HTTP/1.1 200 OK\r\n"), 6995 MockRead(kAlternateProtocolHttpHeader), 6996 MockRead("hello world"), 6997 MockRead(true, OK), 6998 }; 6999 7000 StaticSocketDataProvider first_transaction( 7001 data_reads, arraysize(data_reads), NULL, 0); 7002 session_deps.socket_factory.AddSocketDataProvider(&first_transaction); 7003 7004 SSLSocketDataProvider ssl(true, OK); 7005 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 7006 ssl.next_proto = "spdy/2"; 7007 ssl.was_npn_negotiated = true; 7008 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 7009 // Make sure we use ssl for spdy here. 7010 SpdySession::SetSSLMode(true); 7011 7012 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 7013 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 7014 7015 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 7016 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 7017 MockRead spdy_reads[] = { 7018 CreateMockRead(*resp), 7019 CreateMockRead(*data), 7020 MockRead(true, 0, 0), 7021 }; 7022 7023 scoped_refptr<DelayedSocketData> spdy_data( 7024 new DelayedSocketData( 7025 1, // wait for one write to finish before reading. 7026 spdy_reads, arraysize(spdy_reads), 7027 spdy_writes, arraysize(spdy_writes))); 7028 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 7029 7030 TestCompletionCallback callback; 7031 7032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7033 7034 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 7035 7036 int rv = trans->Start(&request, &callback, BoundNetLog()); 7037 EXPECT_EQ(ERR_IO_PENDING, rv); 7038 EXPECT_EQ(OK, callback.WaitForResult()); 7039 7040 const HttpResponseInfo* response = trans->GetResponseInfo(); 7041 ASSERT_TRUE(response != NULL); 7042 ASSERT_TRUE(response->headers != NULL); 7043 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7044 7045 std::string response_data; 7046 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 7047 EXPECT_EQ("hello world", response_data); 7048 7049 // Set up an initial SpdySession in the pool to reuse. 7050 HostPortPair host_port_pair("www.google.com", 443); 7051 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); 7052 scoped_refptr<SpdySession> spdy_session = 7053 session->spdy_session_pool()->Get(pair, BoundNetLog()); 7054 scoped_refptr<TransportSocketParams> transport_params( 7055 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false)); 7056 7057 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 7058 EXPECT_EQ(ERR_IO_PENDING, 7059 connection->Init(host_port_pair.ToString(), 7060 transport_params, 7061 LOWEST, 7062 &callback, 7063 session->transport_socket_pool(), 7064 BoundNetLog())); 7065 EXPECT_EQ(OK, callback.WaitForResult()); 7066 7067 SSLConfig ssl_config; 7068 session->ssl_config_service()->GetSSLConfig(&ssl_config); 7069 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle); 7070 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket( 7071 connection.release(), HostPortPair("" , 443), ssl_config, 7072 NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL)); 7073 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback)); 7074 EXPECT_EQ(OK, callback.WaitForResult()); 7075 7076 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(), 7077 true, OK)); 7078 7079 trans.reset(new HttpNetworkTransaction(session)); 7080 7081 rv = trans->Start(&request, &callback, BoundNetLog()); 7082 EXPECT_EQ(ERR_IO_PENDING, rv); 7083 EXPECT_EQ(OK, callback.WaitForResult()); 7084 7085 response = trans->GetResponseInfo(); 7086 ASSERT_TRUE(response != NULL); 7087 ASSERT_TRUE(response->headers != NULL); 7088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7089 EXPECT_TRUE(response->was_fetched_via_spdy); 7090 EXPECT_TRUE(response->was_npn_negotiated); 7091 7092 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 7093 EXPECT_EQ("hello!", response_data); 7094 7095 HttpStreamFactory::set_next_protos(""); 7096 HttpStreamFactory::set_use_alternate_protocols(false); 7097 } 7098 7099 // GenerateAuthToken is a mighty big test. 7100 // It tests all permutation of GenerateAuthToken behavior: 7101 // - Synchronous and Asynchronous completion. 7102 // - OK or error on completion. 7103 // - Direct connection, non-authenticating proxy, and authenticating proxy. 7104 // - HTTP or HTTPS backend (to include proxy tunneling). 7105 // - Non-authenticating and authenticating backend. 7106 // 7107 // In all, there are 44 reasonable permuations (for example, if there are 7108 // problems generating an auth token for an authenticating proxy, we don't 7109 // need to test all permutations of the backend server). 7110 // 7111 // The test proceeds by going over each of the configuration cases, and 7112 // potentially running up to three rounds in each of the tests. The TestConfig 7113 // specifies both the configuration for the test as well as the expectations 7114 // for the results. 7115 TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) { 7116 static const char kServer[] = "http://www.example.com"; 7117 static const char kSecureServer[] = "https://www.example.com"; 7118 static const char kProxy[] = "myproxy:70"; 7119 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS; 7120 7121 enum AuthTiming { 7122 AUTH_NONE, 7123 AUTH_SYNC, 7124 AUTH_ASYNC, 7125 }; 7126 7127 const MockWrite kGet( 7128 "GET / HTTP/1.1\r\n" 7129 "Host: www.example.com\r\n" 7130 "Connection: keep-alive\r\n\r\n"); 7131 const MockWrite kGetProxy( 7132 "GET http://www.example.com/ HTTP/1.1\r\n" 7133 "Host: www.example.com\r\n" 7134 "Proxy-Connection: keep-alive\r\n\r\n"); 7135 const MockWrite kGetAuth( 7136 "GET / HTTP/1.1\r\n" 7137 "Host: www.example.com\r\n" 7138 "Connection: keep-alive\r\n" 7139 "Authorization: auth_token\r\n\r\n"); 7140 const MockWrite kGetProxyAuth( 7141 "GET http://www.example.com/ HTTP/1.1\r\n" 7142 "Host: www.example.com\r\n" 7143 "Proxy-Connection: keep-alive\r\n" 7144 "Proxy-Authorization: auth_token\r\n\r\n"); 7145 const MockWrite kGetAuthThroughProxy( 7146 "GET http://www.example.com/ HTTP/1.1\r\n" 7147 "Host: www.example.com\r\n" 7148 "Proxy-Connection: keep-alive\r\n" 7149 "Authorization: auth_token\r\n\r\n"); 7150 const MockWrite kGetAuthWithProxyAuth( 7151 "GET http://www.example.com/ HTTP/1.1\r\n" 7152 "Host: www.example.com\r\n" 7153 "Proxy-Connection: keep-alive\r\n" 7154 "Proxy-Authorization: auth_token\r\n" 7155 "Authorization: auth_token\r\n\r\n"); 7156 const MockWrite kConnect( 7157 "CONNECT www.example.com:443 HTTP/1.1\r\n" 7158 "Host: www.example.com\r\n" 7159 "Proxy-Connection: keep-alive\r\n\r\n"); 7160 const MockWrite kConnectProxyAuth( 7161 "CONNECT www.example.com:443 HTTP/1.1\r\n" 7162 "Host: www.example.com\r\n" 7163 "Proxy-Connection: keep-alive\r\n" 7164 "Proxy-Authorization: auth_token\r\n\r\n"); 7165 7166 const MockRead kSuccess( 7167 "HTTP/1.1 200 OK\r\n" 7168 "Content-Type: text/html; charset=iso-8859-1\r\n" 7169 "Content-Length: 3\r\n\r\n" 7170 "Yes"); 7171 const MockRead kFailure( 7172 "Should not be called."); 7173 const MockRead kServerChallenge( 7174 "HTTP/1.1 401 Unauthorized\r\n" 7175 "WWW-Authenticate: Mock realm=server\r\n" 7176 "Content-Type: text/html; charset=iso-8859-1\r\n" 7177 "Content-Length: 14\r\n\r\n" 7178 "Unauthorized\r\n"); 7179 const MockRead kProxyChallenge( 7180 "HTTP/1.1 407 Unauthorized\r\n" 7181 "Proxy-Authenticate: Mock realm=proxy\r\n" 7182 "Proxy-Connection: close\r\n" 7183 "Content-Type: text/html; charset=iso-8859-1\r\n" 7184 "Content-Length: 14\r\n\r\n" 7185 "Unauthorized\r\n"); 7186 const MockRead kProxyConnected( 7187 "HTTP/1.1 200 Connection Established\r\n\r\n"); 7188 7189 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with 7190 // no constructors, but the C++ compiler on Windows warns about 7191 // unspecified data in compound literals. So, moved to using constructors, 7192 // and TestRound's created with the default constructor should not be used. 7193 struct TestRound { 7194 TestRound() 7195 : expected_rv(ERR_UNEXPECTED), 7196 extra_write(NULL), 7197 extra_read(NULL) { 7198 } 7199 TestRound(const MockWrite& write_arg, const MockRead& read_arg, 7200 int expected_rv_arg) 7201 : write(write_arg), 7202 read(read_arg), 7203 expected_rv(expected_rv_arg), 7204 extra_write(NULL), 7205 extra_read(NULL) { 7206 } 7207 TestRound(const MockWrite& write_arg, const MockRead& read_arg, 7208 int expected_rv_arg, const MockWrite* extra_write_arg, 7209 const MockWrite* extra_read_arg) 7210 : write(write_arg), 7211 read(read_arg), 7212 expected_rv(expected_rv_arg), 7213 extra_write(extra_write_arg), 7214 extra_read(extra_read_arg) { 7215 } 7216 MockWrite write; 7217 MockRead read; 7218 int expected_rv; 7219 const MockWrite* extra_write; 7220 const MockRead* extra_read; 7221 }; 7222 7223 static const int kNoSSL = 500; 7224 7225 struct TestConfig { 7226 const char* proxy_url; 7227 AuthTiming proxy_auth_timing; 7228 int proxy_auth_rv; 7229 const char* server_url; 7230 AuthTiming server_auth_timing; 7231 int server_auth_rv; 7232 int num_auth_rounds; 7233 int first_ssl_round; 7234 TestRound rounds[3]; 7235 } test_configs[] = { 7236 // Non-authenticating HTTP server with a direct connection. 7237 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL, 7238 { TestRound(kGet, kSuccess, OK)}}, 7239 // Authenticating HTTP server with a direct connection. 7240 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL, 7241 { TestRound(kGet, kServerChallenge, OK), 7242 TestRound(kGetAuth, kSuccess, OK)}}, 7243 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL, 7244 { TestRound(kGet, kServerChallenge, OK), 7245 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7246 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL, 7247 { TestRound(kGet, kServerChallenge, OK), 7248 TestRound(kGetAuth, kSuccess, OK)}}, 7249 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL, 7250 { TestRound(kGet, kServerChallenge, OK), 7251 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7252 // Non-authenticating HTTP server through a non-authenticating proxy. 7253 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL, 7254 { TestRound(kGetProxy, kSuccess, OK)}}, 7255 // Authenticating HTTP server through a non-authenticating proxy. 7256 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL, 7257 { TestRound(kGetProxy, kServerChallenge, OK), 7258 TestRound(kGetAuthThroughProxy, kSuccess, OK)}}, 7259 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL, 7260 { TestRound(kGetProxy, kServerChallenge, OK), 7261 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}}, 7262 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL, 7263 { TestRound(kGetProxy, kServerChallenge, OK), 7264 TestRound(kGetAuthThroughProxy, kSuccess, OK)}}, 7265 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL, 7266 { TestRound(kGetProxy, kServerChallenge, OK), 7267 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}}, 7268 // Non-authenticating HTTP server through an authenticating proxy. 7269 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL, 7270 { TestRound(kGetProxy, kProxyChallenge, OK), 7271 TestRound(kGetProxyAuth, kSuccess, OK)}}, 7272 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL, 7273 { TestRound(kGetProxy, kProxyChallenge, OK), 7274 TestRound(kGetProxyAuth, kFailure, kAuthErr)}}, 7275 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL, 7276 { TestRound(kGetProxy, kProxyChallenge, OK), 7277 TestRound(kGetProxyAuth, kSuccess, OK)}}, 7278 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL, 7279 { TestRound(kGetProxy, kProxyChallenge, OK), 7280 TestRound(kGetProxyAuth, kFailure, kAuthErr)}}, 7281 // Authenticating HTTP server through an authenticating proxy. 7282 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL, 7283 { TestRound(kGetProxy, kProxyChallenge, OK), 7284 TestRound(kGetProxyAuth, kServerChallenge, OK), 7285 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 7286 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL, 7287 { TestRound(kGetProxy, kProxyChallenge, OK), 7288 TestRound(kGetProxyAuth, kServerChallenge, OK), 7289 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 7290 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL, 7291 { TestRound(kGetProxy, kProxyChallenge, OK), 7292 TestRound(kGetProxyAuth, kServerChallenge, OK), 7293 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 7294 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL, 7295 { TestRound(kGetProxy, kProxyChallenge, OK), 7296 TestRound(kGetProxyAuth, kServerChallenge, OK), 7297 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 7298 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL, 7299 { TestRound(kGetProxy, kProxyChallenge, OK), 7300 TestRound(kGetProxyAuth, kServerChallenge, OK), 7301 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 7302 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL, 7303 { TestRound(kGetProxy, kProxyChallenge, OK), 7304 TestRound(kGetProxyAuth, kServerChallenge, OK), 7305 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 7306 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL, 7307 { TestRound(kGetProxy, kProxyChallenge, OK), 7308 TestRound(kGetProxyAuth, kServerChallenge, OK), 7309 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 7310 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL, 7311 { TestRound(kGetProxy, kProxyChallenge, OK), 7312 TestRound(kGetProxyAuth, kServerChallenge, OK), 7313 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 7314 // Non-authenticating HTTPS server with a direct connection. 7315 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0, 7316 { TestRound(kGet, kSuccess, OK)}}, 7317 // Authenticating HTTPS server with a direct connection. 7318 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0, 7319 { TestRound(kGet, kServerChallenge, OK), 7320 TestRound(kGetAuth, kSuccess, OK)}}, 7321 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0, 7322 { TestRound(kGet, kServerChallenge, OK), 7323 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7324 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0, 7325 { TestRound(kGet, kServerChallenge, OK), 7326 TestRound(kGetAuth, kSuccess, OK)}}, 7327 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0, 7328 { TestRound(kGet, kServerChallenge, OK), 7329 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7330 // Non-authenticating HTTPS server with a non-authenticating proxy. 7331 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0, 7332 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}}, 7333 // Authenticating HTTPS server through a non-authenticating proxy. 7334 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0, 7335 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 7336 TestRound(kGetAuth, kSuccess, OK)}}, 7337 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0, 7338 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 7339 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7340 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0, 7341 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 7342 TestRound(kGetAuth, kSuccess, OK)}}, 7343 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0, 7344 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 7345 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7346 // Non-Authenticating HTTPS server through an authenticating proxy. 7347 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1, 7348 { TestRound(kConnect, kProxyChallenge, OK), 7349 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}}, 7350 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL, 7351 { TestRound(kConnect, kProxyChallenge, OK), 7352 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}}, 7353 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1, 7354 { TestRound(kConnect, kProxyChallenge, OK), 7355 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}}, 7356 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL, 7357 { TestRound(kConnect, kProxyChallenge, OK), 7358 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}}, 7359 // Authenticating HTTPS server through an authenticating proxy. 7360 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1, 7361 { TestRound(kConnect, kProxyChallenge, OK), 7362 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7363 &kGet, &kServerChallenge), 7364 TestRound(kGetAuth, kSuccess, OK)}}, 7365 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1, 7366 { TestRound(kConnect, kProxyChallenge, OK), 7367 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7368 &kGet, &kServerChallenge), 7369 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7370 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1, 7371 { TestRound(kConnect, kProxyChallenge, OK), 7372 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7373 &kGet, &kServerChallenge), 7374 TestRound(kGetAuth, kSuccess, OK)}}, 7375 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1, 7376 { TestRound(kConnect, kProxyChallenge, OK), 7377 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7378 &kGet, &kServerChallenge), 7379 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7380 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1, 7381 { TestRound(kConnect, kProxyChallenge, OK), 7382 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7383 &kGet, &kServerChallenge), 7384 TestRound(kGetAuth, kSuccess, OK)}}, 7385 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1, 7386 { TestRound(kConnect, kProxyChallenge, OK), 7387 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7388 &kGet, &kServerChallenge), 7389 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7390 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1, 7391 { TestRound(kConnect, kProxyChallenge, OK), 7392 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7393 &kGet, &kServerChallenge), 7394 TestRound(kGetAuth, kSuccess, OK)}}, 7395 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1, 7396 { TestRound(kConnect, kProxyChallenge, OK), 7397 TestRound(kConnectProxyAuth, kProxyConnected, OK, 7398 &kGet, &kServerChallenge), 7399 TestRound(kGetAuth, kFailure, kAuthErr)}}, 7400 }; 7401 7402 SessionDependencies session_deps; 7403 HttpAuthHandlerMock::Factory* auth_factory( 7404 new HttpAuthHandlerMock::Factory()); 7405 session_deps.http_auth_handler_factory.reset(auth_factory); 7406 7407 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) { 7408 const TestConfig& test_config = test_configs[i]; 7409 7410 // Set up authentication handlers as necessary. 7411 if (test_config.proxy_auth_timing != AUTH_NONE) { 7412 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 7413 std::string auth_challenge = "Mock realm=proxy"; 7414 GURL origin(test_config.proxy_url); 7415 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 7416 auth_challenge.end()); 7417 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY, 7418 origin, BoundNetLog()); 7419 auth_handler->SetGenerateExpectation( 7420 test_config.proxy_auth_timing == AUTH_ASYNC, 7421 test_config.proxy_auth_rv); 7422 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY); 7423 } 7424 if (test_config.server_auth_timing != AUTH_NONE) { 7425 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 7426 std::string auth_challenge = "Mock realm=server"; 7427 GURL origin(test_config.server_url); 7428 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 7429 auth_challenge.end()); 7430 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, 7431 origin, BoundNetLog()); 7432 auth_handler->SetGenerateExpectation( 7433 test_config.server_auth_timing == AUTH_ASYNC, 7434 test_config.server_auth_rv); 7435 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER); 7436 } 7437 if (test_config.proxy_url) { 7438 session_deps.proxy_service = 7439 ProxyService::CreateFixed(test_config.proxy_url); 7440 } else { 7441 session_deps.proxy_service = ProxyService::CreateDirect(); 7442 } 7443 7444 HttpRequestInfo request; 7445 request.method = "GET"; 7446 request.url = GURL(test_config.server_url); 7447 request.load_flags = 0; 7448 7449 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7450 HttpNetworkTransaction trans(CreateSession(&session_deps)); 7451 7452 for (int round = 0; round < test_config.num_auth_rounds; ++round) { 7453 const TestRound& read_write_round = test_config.rounds[round]; 7454 7455 // Set up expected reads and writes. 7456 MockRead reads[2]; 7457 reads[0] = read_write_round.read; 7458 size_t length_reads = 1; 7459 if (read_write_round.extra_read) { 7460 reads[1] = *read_write_round.extra_read; 7461 length_reads = 2; 7462 } 7463 7464 MockWrite writes[2]; 7465 writes[0] = read_write_round.write; 7466 size_t length_writes = 1; 7467 if (read_write_round.extra_write) { 7468 writes[1] = *read_write_round.extra_write; 7469 length_writes = 2; 7470 } 7471 StaticSocketDataProvider data_provider( 7472 reads, length_reads, writes, length_writes); 7473 session_deps.socket_factory.AddSocketDataProvider(&data_provider); 7474 7475 // Add an SSL sequence if necessary. 7476 SSLSocketDataProvider ssl_socket_data_provider(false, OK); 7477 if (round >= test_config.first_ssl_round) 7478 session_deps.socket_factory.AddSSLSocketDataProvider( 7479 &ssl_socket_data_provider); 7480 7481 // Start or restart the transaction. 7482 TestCompletionCallback callback; 7483 int rv; 7484 if (round == 0) { 7485 rv = trans.Start(&request, &callback, BoundNetLog()); 7486 } else { 7487 rv = trans.RestartWithAuth(kFoo, kBar, &callback); 7488 } 7489 if (rv == ERR_IO_PENDING) 7490 rv = callback.WaitForResult(); 7491 7492 // Compare results with expected data. 7493 EXPECT_EQ(read_write_round.expected_rv, rv); 7494 const HttpResponseInfo* response = trans.GetResponseInfo(); 7495 if (read_write_round.expected_rv == OK) { 7496 EXPECT_FALSE(response == NULL); 7497 } else { 7498 EXPECT_TRUE(response == NULL); 7499 EXPECT_EQ(round + 1, test_config.num_auth_rounds); 7500 continue; 7501 } 7502 if (round + 1 < test_config.num_auth_rounds) { 7503 EXPECT_FALSE(response->auth_challenge.get() == NULL); 7504 } else { 7505 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7506 } 7507 } 7508 } 7509 } 7510 7511 TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) { 7512 // Do multi-round authentication and make sure it works correctly. 7513 SessionDependencies session_deps; 7514 HttpAuthHandlerMock::Factory* auth_factory( 7515 new HttpAuthHandlerMock::Factory()); 7516 session_deps.http_auth_handler_factory.reset(auth_factory); 7517 session_deps.proxy_service = ProxyService::CreateDirect(); 7518 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1"); 7519 session_deps.host_resolver->set_synchronous_mode(true); 7520 7521 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 7522 auth_handler->set_connection_based(true); 7523 std::string auth_challenge = "Mock realm=server"; 7524 GURL origin("http://www.example.com"); 7525 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 7526 auth_challenge.end()); 7527 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, 7528 origin, BoundNetLog()); 7529 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER); 7530 7531 int rv = OK; 7532 const HttpResponseInfo* response = NULL; 7533 HttpRequestInfo request; 7534 request.method = "GET"; 7535 request.url = origin; 7536 request.load_flags = 0; 7537 7538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7539 7540 // Use a TCP Socket Pool with only one connection per group. This is used 7541 // to validate that the TCP socket is not released to the pool between 7542 // each round of multi-round authentication. 7543 HttpNetworkSessionPeer session_peer(session); 7544 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP"); 7545 TransportClientSocketPool* transport_pool = new TransportClientSocketPool( 7546 50, // Max sockets for pool 7547 1, // Max sockets per group 7548 &transport_pool_histograms, 7549 session_deps.host_resolver.get(), 7550 &session_deps.socket_factory, 7551 session_deps.net_log); 7552 session_peer.SetTransportSocketPool(transport_pool); 7553 7554 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 7555 TestCompletionCallback callback; 7556 7557 const MockWrite kGet( 7558 "GET / HTTP/1.1\r\n" 7559 "Host: www.example.com\r\n" 7560 "Connection: keep-alive\r\n\r\n"); 7561 const MockWrite kGetAuth( 7562 "GET / HTTP/1.1\r\n" 7563 "Host: www.example.com\r\n" 7564 "Connection: keep-alive\r\n" 7565 "Authorization: auth_token\r\n\r\n"); 7566 7567 const MockRead kServerChallenge( 7568 "HTTP/1.1 401 Unauthorized\r\n" 7569 "WWW-Authenticate: Mock realm=server\r\n" 7570 "Content-Type: text/html; charset=iso-8859-1\r\n" 7571 "Content-Length: 14\r\n\r\n" 7572 "Unauthorized\r\n"); 7573 const MockRead kSuccess( 7574 "HTTP/1.1 200 OK\r\n" 7575 "Content-Type: text/html; charset=iso-8859-1\r\n" 7576 "Content-Length: 3\r\n\r\n" 7577 "Yes"); 7578 7579 MockWrite writes[] = { 7580 // First round 7581 kGet, 7582 // Second round 7583 kGetAuth, 7584 // Third round 7585 kGetAuth, 7586 // Fourth round 7587 kGetAuth, 7588 // Competing request 7589 kGet, 7590 }; 7591 MockRead reads[] = { 7592 // First round 7593 kServerChallenge, 7594 // Second round 7595 kServerChallenge, 7596 // Third round 7597 kServerChallenge, 7598 // Fourth round 7599 kSuccess, 7600 // Competing response 7601 kSuccess, 7602 }; 7603 StaticSocketDataProvider data_provider(reads, arraysize(reads), 7604 writes, arraysize(writes)); 7605 session_deps.socket_factory.AddSocketDataProvider(&data_provider); 7606 7607 const char* const kSocketGroup = "www.example.com:80"; 7608 7609 // First round of authentication. 7610 auth_handler->SetGenerateExpectation(false, OK); 7611 rv = trans->Start(&request, &callback, BoundNetLog()); 7612 if (rv == ERR_IO_PENDING) 7613 rv = callback.WaitForResult(); 7614 EXPECT_EQ(OK, rv); 7615 response = trans->GetResponseInfo(); 7616 ASSERT_FALSE(response == NULL); 7617 EXPECT_FALSE(response->auth_challenge.get() == NULL); 7618 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 7619 7620 // In between rounds, another request comes in for the same domain. 7621 // It should not be able to grab the TCP socket that trans has already 7622 // claimed. 7623 scoped_ptr<HttpTransaction> trans_compete( 7624 new HttpNetworkTransaction(session)); 7625 TestCompletionCallback callback_compete; 7626 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog()); 7627 EXPECT_EQ(ERR_IO_PENDING, rv); 7628 // callback_compete.WaitForResult at this point would stall forever, 7629 // since the HttpNetworkTransaction does not release the request back to 7630 // the pool until after authentication completes. 7631 7632 // Second round of authentication. 7633 auth_handler->SetGenerateExpectation(false, OK); 7634 rv = trans->RestartWithAuth(kFoo, kBar, &callback); 7635 if (rv == ERR_IO_PENDING) 7636 rv = callback.WaitForResult(); 7637 EXPECT_EQ(OK, rv); 7638 response = trans->GetResponseInfo(); 7639 ASSERT_FALSE(response == NULL); 7640 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7641 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 7642 7643 // Third round of authentication. 7644 auth_handler->SetGenerateExpectation(false, OK); 7645 rv = trans->RestartWithAuth(string16(), string16(), &callback); 7646 if (rv == ERR_IO_PENDING) 7647 rv = callback.WaitForResult(); 7648 EXPECT_EQ(OK, rv); 7649 response = trans->GetResponseInfo(); 7650 ASSERT_FALSE(response == NULL); 7651 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7652 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 7653 7654 // Fourth round of authentication, which completes successfully. 7655 auth_handler->SetGenerateExpectation(false, OK); 7656 rv = trans->RestartWithAuth(string16(), string16(), &callback); 7657 if (rv == ERR_IO_PENDING) 7658 rv = callback.WaitForResult(); 7659 EXPECT_EQ(OK, rv); 7660 response = trans->GetResponseInfo(); 7661 ASSERT_FALSE(response == NULL); 7662 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7663 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 7664 7665 // Read the body since the fourth round was successful. This will also 7666 // release the socket back to the pool. 7667 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50)); 7668 rv = trans->Read(io_buf, io_buf->size(), &callback); 7669 if (rv == ERR_IO_PENDING) 7670 rv = callback.WaitForResult(); 7671 EXPECT_EQ(3, rv); 7672 rv = trans->Read(io_buf, io_buf->size(), &callback); 7673 EXPECT_EQ(0, rv); 7674 // There are still 0 idle sockets, since the trans_compete transaction 7675 // will be handed it immediately after trans releases it to the group. 7676 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 7677 7678 // The competing request can now finish. Wait for the headers and then 7679 // read the body. 7680 rv = callback_compete.WaitForResult(); 7681 EXPECT_EQ(OK, rv); 7682 rv = trans_compete->Read(io_buf, io_buf->size(), &callback); 7683 if (rv == ERR_IO_PENDING) 7684 rv = callback.WaitForResult(); 7685 EXPECT_EQ(3, rv); 7686 rv = trans_compete->Read(io_buf, io_buf->size(), &callback); 7687 EXPECT_EQ(0, rv); 7688 7689 // Finally, the socket is released to the group. 7690 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 7691 } 7692 7693 class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider { 7694 public: 7695 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all) 7696 : fail_all_(fail_all) { 7697 } 7698 7699 virtual MockRead GetNextRead() { 7700 if (fail_all_) 7701 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT); 7702 7703 return MockRead(false /* async */, 7704 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n"); 7705 } 7706 7707 virtual MockWriteResult OnWrite(const std::string& data) { 7708 return MockWriteResult(false /* async */, data.size()); 7709 } 7710 7711 void Reset() { 7712 } 7713 7714 private: 7715 const bool fail_all_; 7716 }; 7717 7718 // Test that we restart a connection when we see a decompression failure from 7719 // the peer during the handshake. (In the real world we'll restart with SSLv3 7720 // and we won't offer DEFLATE in that case.) 7721 TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) { 7722 HttpRequestInfo request; 7723 request.method = "GET"; 7724 request.url = GURL("https://tlsdecompressionfailure.example.com/"); 7725 request.load_flags = 0; 7726 7727 SessionDependencies session_deps; 7728 TLSDecompressionFailureSocketDataProvider socket_data_provider1( 7729 false /* fail all reads */); 7730 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false); 7731 SSLSocketDataProvider ssl_socket_data_provider1( 7732 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT); 7733 SSLSocketDataProvider ssl_socket_data_provider2(false, OK); 7734 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1); 7735 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2); 7736 session_deps.socket_factory.AddSSLSocketDataProvider( 7737 &ssl_socket_data_provider1); 7738 session_deps.socket_factory.AddSSLSocketDataProvider( 7739 &ssl_socket_data_provider2); 7740 7741 // Work around http://crbug.com/37454 7742 StaticSocketDataProvider bug37454_connection; 7743 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED)); 7744 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection); 7745 7746 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7747 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 7748 TestCompletionCallback callback; 7749 7750 int rv = trans->Start(&request, &callback, BoundNetLog()); 7751 EXPECT_EQ(ERR_IO_PENDING, rv); 7752 EXPECT_EQ(OK, callback.WaitForResult()); 7753 7754 const HttpResponseInfo* response = trans->GetResponseInfo(); 7755 ASSERT_TRUE(response != NULL); 7756 ASSERT_TRUE(response->headers != NULL); 7757 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7758 7759 std::string response_data; 7760 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 7761 EXPECT_EQ("ok.", response_data); 7762 } 7763 7764 // Test that we restart a connection if we get a decompression failure from the 7765 // peer while reading the first bytes from the connection. This occurs when the 7766 // peer cannot handle DEFLATE but we're using False Start, so we don't notice 7767 // in the handshake. 7768 TEST_F(HttpNetworkTransactionTest, 7769 RestartAfterTLSDecompressionFailureWithFalseStart) { 7770 HttpRequestInfo request; 7771 request.method = "GET"; 7772 request.url = GURL("https://tlsdecompressionfailure2.example.com/"); 7773 request.load_flags = 0; 7774 7775 SessionDependencies session_deps; 7776 TLSDecompressionFailureSocketDataProvider socket_data_provider1( 7777 true /* fail all reads */); 7778 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false); 7779 SSLSocketDataProvider ssl_socket_data_provider1(false, OK); 7780 SSLSocketDataProvider ssl_socket_data_provider2(false, OK); 7781 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1); 7782 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2); 7783 session_deps.socket_factory.AddSSLSocketDataProvider( 7784 &ssl_socket_data_provider1); 7785 session_deps.socket_factory.AddSSLSocketDataProvider( 7786 &ssl_socket_data_provider2); 7787 7788 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7789 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 7790 TestCompletionCallback callback; 7791 7792 int rv = trans->Start(&request, &callback, BoundNetLog()); 7793 EXPECT_EQ(ERR_IO_PENDING, rv); 7794 EXPECT_EQ(OK, callback.WaitForResult()); 7795 7796 const HttpResponseInfo* response = trans->GetResponseInfo(); 7797 ASSERT_TRUE(response != NULL); 7798 ASSERT_TRUE(response->headers != NULL); 7799 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7800 7801 std::string response_data; 7802 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 7803 EXPECT_EQ("ok.", response_data); 7804 } 7805 7806 // This tests the case that a request is issued via http instead of spdy after 7807 // npn is negotiated. 7808 TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) { 7809 HttpStreamFactory::set_use_alternate_protocols(true); 7810 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1"); 7811 SessionDependencies session_deps; 7812 HttpRequestInfo request; 7813 request.method = "GET"; 7814 request.url = GURL("https://www.google.com/"); 7815 request.load_flags = 0; 7816 7817 MockWrite data_writes[] = { 7818 MockWrite("GET / HTTP/1.1\r\n" 7819 "Host: www.google.com\r\n" 7820 "Connection: keep-alive\r\n\r\n"), 7821 }; 7822 7823 MockRead data_reads[] = { 7824 MockRead("HTTP/1.1 200 OK\r\n"), 7825 MockRead(kAlternateProtocolHttpHeader), 7826 MockRead("hello world"), 7827 MockRead(false, OK), 7828 }; 7829 7830 SSLSocketDataProvider ssl(true, OK); 7831 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 7832 ssl.next_proto = "http/1.1"; 7833 7834 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 7835 7836 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7837 data_writes, arraysize(data_writes)); 7838 session_deps.socket_factory.AddSocketDataProvider(&data); 7839 7840 TestCompletionCallback callback; 7841 7842 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7843 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 7844 7845 int rv = trans->Start(&request, &callback, BoundNetLog()); 7846 7847 EXPECT_EQ(ERR_IO_PENDING, rv); 7848 EXPECT_EQ(OK, callback.WaitForResult()); 7849 7850 const HttpResponseInfo* response = trans->GetResponseInfo(); 7851 ASSERT_TRUE(response != NULL); 7852 ASSERT_TRUE(response->headers != NULL); 7853 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7854 7855 std::string response_data; 7856 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 7857 EXPECT_EQ("hello world", response_data); 7858 7859 EXPECT_FALSE(response->was_fetched_via_spdy); 7860 EXPECT_TRUE(response->was_npn_negotiated); 7861 7862 HttpStreamFactory::set_next_protos(""); 7863 HttpStreamFactory::set_use_alternate_protocols(false); 7864 } 7865 7866 TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) { 7867 // Simulate the SSL handshake completing with an NPN negotiation 7868 // followed by an immediate server closing of the socket. 7869 // Fix crash: http://crbug.com/46369 7870 HttpStreamFactory::set_use_alternate_protocols(true); 7871 HttpStreamFactory::set_next_protos(kExpectedNPNString); 7872 SessionDependencies session_deps; 7873 7874 HttpRequestInfo request; 7875 request.method = "GET"; 7876 request.url = GURL("https://www.google.com/"); 7877 request.load_flags = 0; 7878 7879 SSLSocketDataProvider ssl(true, OK); 7880 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 7881 ssl.next_proto = "spdy/2"; 7882 ssl.was_npn_negotiated = true; 7883 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 7884 7885 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 7886 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 7887 7888 MockRead spdy_reads[] = { 7889 MockRead(false, 0, 0) // Not async - return 0 immediately. 7890 }; 7891 7892 scoped_refptr<DelayedSocketData> spdy_data( 7893 new DelayedSocketData( 7894 0, // don't wait in this case, immediate hangup. 7895 spdy_reads, arraysize(spdy_reads), 7896 spdy_writes, arraysize(spdy_writes))); 7897 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 7898 7899 TestCompletionCallback callback; 7900 7901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 7902 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 7903 7904 int rv = trans->Start(&request, &callback, BoundNetLog()); 7905 EXPECT_EQ(ERR_IO_PENDING, rv); 7906 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult()); 7907 7908 HttpStreamFactory::set_next_protos(""); 7909 HttpStreamFactory::set_use_alternate_protocols(false); 7910 } 7911 7912 TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { 7913 // This test ensures that the URL passed into the proxy is upgraded 7914 // to https when doing an Alternate Protocol upgrade. 7915 HttpStreamFactory::set_use_alternate_protocols(true); 7916 HttpStreamFactory::set_next_protos( 7917 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy"); 7918 7919 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 7920 HttpAuthHandlerMock::Factory* auth_factory = 7921 new HttpAuthHandlerMock::Factory(); 7922 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock(); 7923 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY); 7924 auth_factory->set_do_init_from_challenge(true); 7925 session_deps.http_auth_handler_factory.reset(auth_factory); 7926 7927 HttpRequestInfo request; 7928 request.method = "GET"; 7929 request.url = GURL("http://www.google.com"); 7930 request.load_flags = 0; 7931 7932 // First round goes unauthenticated through the proxy. 7933 MockWrite data_writes_1[] = { 7934 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 7935 "Host: www.google.com\r\n" 7936 "Proxy-Connection: keep-alive\r\n" 7937 "\r\n"), 7938 }; 7939 MockRead data_reads_1[] = { 7940 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 7941 MockRead("HTTP/1.1 200 OK\r\n" 7942 "Alternate-Protocol: 443:npn-spdy/2\r\n" 7943 "Proxy-Connection: close\r\n" 7944 "\r\n"), 7945 }; 7946 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), 7947 data_writes_1, arraysize(data_writes_1)); 7948 7949 // Second round tries to tunnel to www.google.com due to the 7950 // Alternate-Protocol announcement in the first round. It fails due 7951 // to a proxy authentication challenge. 7952 // After the failure, a tunnel is established to www.google.com using 7953 // Proxy-Authorization headers. There is then a SPDY request round. 7954 // 7955 // NOTE: Despite the "Proxy-Connection: Close", these are done on the 7956 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket 7957 // does a Disconnect and Connect on the same socket, rather than trying 7958 // to obtain a new one. 7959 // 7960 // NOTE: Originally, the proxy response to the second CONNECT request 7961 // simply returned another 407 so the unit test could skip the SSL connection 7962 // establishment and SPDY framing issues. Alas, the 7963 // retry-http-when-alternate-protocol fails logic kicks in, which was more 7964 // complicated to set up expectations for than the SPDY session. 7965 7966 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); 7967 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 7968 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 7969 7970 MockWrite data_writes_2[] = { 7971 // First connection attempt without Proxy-Authorization. 7972 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 7973 "Host: www.google.com\r\n" 7974 "Proxy-Connection: keep-alive\r\n" 7975 "\r\n"), 7976 7977 // Second connection attempt with Proxy-Authorization. 7978 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 7979 "Host: www.google.com\r\n" 7980 "Proxy-Connection: keep-alive\r\n" 7981 "Proxy-Authorization: auth_token\r\n" 7982 "\r\n"), 7983 7984 // SPDY request 7985 CreateMockWrite(*req), 7986 }; 7987 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" 7988 "Proxy-Authenticate: Mock\r\n" 7989 "Proxy-Connection: close\r\n" 7990 "\r\n"); 7991 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; 7992 MockRead data_reads_2[] = { 7993 // First connection attempt fails 7994 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), 7995 MockRead(true, kRejectConnectResponse, 7996 arraysize(kRejectConnectResponse) - 1, 1), 7997 7998 // Second connection attempt passes 7999 MockRead(true, kAcceptConnectResponse, 8000 arraysize(kAcceptConnectResponse) -1, 4), 8001 8002 // SPDY response 8003 CreateMockRead(*resp.get(), 6), 8004 CreateMockRead(*data.get(), 6), 8005 MockRead(true, 0, 0, 6), 8006 }; 8007 scoped_refptr<OrderedSocketData> data_2( 8008 new OrderedSocketData(data_reads_2, arraysize(data_reads_2), 8009 data_writes_2, arraysize(data_writes_2))); 8010 8011 SSLSocketDataProvider ssl(true, OK); 8012 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 8013 ssl.next_proto = "spdy/2"; 8014 ssl.was_npn_negotiated = true; 8015 8016 MockConnect never_finishing_connect(false, ERR_IO_PENDING); 8017 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 8018 NULL, 0, NULL, 0); 8019 hanging_non_alternate_protocol_socket.set_connect_data( 8020 never_finishing_connect); 8021 8022 session_deps.socket_factory.AddSocketDataProvider(&data_1); 8023 session_deps.socket_factory.AddSocketDataProvider(data_2.get()); 8024 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 8025 session_deps.socket_factory.AddSocketDataProvider( 8026 &hanging_non_alternate_protocol_socket); 8027 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8028 8029 // First round should work and provide the Alternate-Protocol state. 8030 TestCompletionCallback callback_1; 8031 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session)); 8032 int rv = trans_1->Start(&request, &callback_1, BoundNetLog()); 8033 EXPECT_EQ(ERR_IO_PENDING, rv); 8034 EXPECT_EQ(OK, callback_1.WaitForResult()); 8035 8036 // Second round should attempt a tunnel connect and get an auth challenge. 8037 TestCompletionCallback callback_2; 8038 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session)); 8039 rv = trans_2->Start(&request, &callback_2, BoundNetLog()); 8040 EXPECT_EQ(ERR_IO_PENDING, rv); 8041 EXPECT_EQ(OK, callback_2.WaitForResult()); 8042 const HttpResponseInfo* response = trans_2->GetResponseInfo(); 8043 ASSERT_FALSE(response == NULL); 8044 ASSERT_FALSE(response->auth_challenge.get() == NULL); 8045 8046 // Restart with auth. Tunnel should work and response received. 8047 TestCompletionCallback callback_3; 8048 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3); 8049 EXPECT_EQ(ERR_IO_PENDING, rv); 8050 EXPECT_EQ(OK, callback_3.WaitForResult()); 8051 8052 // After all that work, these two lines (or actually, just the scheme) are 8053 // what this test is all about. Make sure it happens correctly. 8054 const GURL& request_url = auth_handler->request_url(); 8055 EXPECT_EQ("https", request_url.scheme()); 8056 EXPECT_EQ("www.google.com", request_url.host()); 8057 8058 HttpStreamFactory::set_next_protos(""); 8059 HttpStreamFactory::set_use_alternate_protocols(false); 8060 } 8061 8062 // Test that if we cancel the transaction as the connection is completing, that 8063 // everything tears down correctly. 8064 TEST_F(HttpNetworkTransactionTest, SimpleCancel) { 8065 // Setup everything about the connection to complete synchronously, so that 8066 // after calling HttpNetworkTransaction::Start, the only thing we're waiting 8067 // for is the callback from the HttpStreamRequest. 8068 // Then cancel the transaction. 8069 // Verify that we don't crash. 8070 MockConnect mock_connect(false, OK); 8071 MockRead data_reads[] = { 8072 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"), 8073 MockRead(false, "hello world"), 8074 MockRead(false, OK), 8075 }; 8076 8077 HttpRequestInfo request; 8078 request.method = "GET"; 8079 request.url = GURL("http://www.google.com/"); 8080 request.load_flags = 0; 8081 8082 SessionDependencies session_deps; 8083 session_deps.host_resolver->set_synchronous_mode(true); 8084 scoped_ptr<HttpTransaction> trans( 8085 new HttpNetworkTransaction(CreateSession(&session_deps))); 8086 8087 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 8088 data.set_connect_data(mock_connect); 8089 session_deps.socket_factory.AddSocketDataProvider(&data); 8090 8091 TestCompletionCallback callback; 8092 8093 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 8094 int rv = trans->Start(&request, &callback, log.bound()); 8095 EXPECT_EQ(ERR_IO_PENDING, rv); 8096 trans.reset(); // Cancel the transaction here. 8097 8098 MessageLoop::current()->RunAllPending(); 8099 } 8100 8101 // Test a basic GET request through a proxy. 8102 TEST_F(HttpNetworkTransactionTest, ProxyGet) { 8103 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 8104 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 8105 session_deps.net_log = log.bound().net_log(); 8106 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8107 8108 HttpRequestInfo request; 8109 request.method = "GET"; 8110 request.url = GURL("http://www.google.com/"); 8111 8112 MockWrite data_writes1[] = { 8113 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 8114 "Host: www.google.com\r\n" 8115 "Proxy-Connection: keep-alive\r\n\r\n"), 8116 }; 8117 8118 MockRead data_reads1[] = { 8119 MockRead("HTTP/1.1 200 OK\r\n"), 8120 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 8121 MockRead("Content-Length: 100\r\n\r\n"), 8122 MockRead(false, OK), 8123 }; 8124 8125 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 8126 data_writes1, arraysize(data_writes1)); 8127 session_deps.socket_factory.AddSocketDataProvider(&data1); 8128 8129 TestCompletionCallback callback1; 8130 8131 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 8132 8133 int rv = trans->Start(&request, &callback1, log.bound()); 8134 EXPECT_EQ(ERR_IO_PENDING, rv); 8135 8136 rv = callback1.WaitForResult(); 8137 EXPECT_EQ(OK, rv); 8138 8139 const HttpResponseInfo* response = trans->GetResponseInfo(); 8140 ASSERT_FALSE(response == NULL); 8141 8142 EXPECT_TRUE(response->headers->IsKeepAlive()); 8143 EXPECT_EQ(200, response->headers->response_code()); 8144 EXPECT_EQ(100, response->headers->GetContentLength()); 8145 EXPECT_TRUE(response->was_fetched_via_proxy); 8146 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 8147 } 8148 8149 // Test a basic HTTPS GET request through a proxy. 8150 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) { 8151 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 8152 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 8153 session_deps.net_log = log.bound().net_log(); 8154 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8155 8156 HttpRequestInfo request; 8157 request.method = "GET"; 8158 request.url = GURL("https://www.google.com/"); 8159 8160 // Since we have proxy, should try to establish tunnel. 8161 MockWrite data_writes1[] = { 8162 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 8163 "Host: www.google.com\r\n" 8164 "Proxy-Connection: keep-alive\r\n\r\n"), 8165 8166 MockWrite("GET / HTTP/1.1\r\n" 8167 "Host: www.google.com\r\n" 8168 "Connection: keep-alive\r\n\r\n"), 8169 }; 8170 8171 MockRead data_reads1[] = { 8172 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 8173 8174 MockRead("HTTP/1.1 200 OK\r\n"), 8175 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 8176 MockRead("Content-Length: 100\r\n\r\n"), 8177 MockRead(false, OK), 8178 }; 8179 8180 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 8181 data_writes1, arraysize(data_writes1)); 8182 session_deps.socket_factory.AddSocketDataProvider(&data1); 8183 SSLSocketDataProvider ssl(true, OK); 8184 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 8185 8186 TestCompletionCallback callback1; 8187 8188 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 8189 8190 int rv = trans->Start(&request, &callback1, log.bound()); 8191 EXPECT_EQ(ERR_IO_PENDING, rv); 8192 8193 rv = callback1.WaitForResult(); 8194 EXPECT_EQ(OK, rv); 8195 net::CapturingNetLog::EntryList entries; 8196 log.GetEntries(&entries); 8197 size_t pos = ExpectLogContainsSomewhere( 8198 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 8199 NetLog::PHASE_NONE); 8200 ExpectLogContainsSomewhere( 8201 entries, pos, 8202 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 8203 NetLog::PHASE_NONE); 8204 8205 const HttpResponseInfo* response = trans->GetResponseInfo(); 8206 ASSERT_FALSE(response == NULL); 8207 8208 EXPECT_TRUE(response->headers->IsKeepAlive()); 8209 EXPECT_EQ(200, response->headers->response_code()); 8210 EXPECT_EQ(100, response->headers->GetContentLength()); 8211 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 8212 EXPECT_TRUE(response->was_fetched_via_proxy); 8213 } 8214 8215 // Test a basic HTTPS GET request through a proxy, but the server hangs up 8216 // while establishing the tunnel. 8217 TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) { 8218 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70")); 8219 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 8220 session_deps.net_log = log.bound().net_log(); 8221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8222 8223 HttpRequestInfo request; 8224 request.method = "GET"; 8225 request.url = GURL("https://www.google.com/"); 8226 8227 // Since we have proxy, should try to establish tunnel. 8228 MockWrite data_writes1[] = { 8229 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 8230 "Host: www.google.com\r\n" 8231 "Proxy-Connection: keep-alive\r\n\r\n"), 8232 8233 MockWrite("GET / HTTP/1.1\r\n" 8234 "Host: www.google.com\r\n" 8235 "Connection: keep-alive\r\n\r\n"), 8236 }; 8237 8238 MockRead data_reads1[] = { 8239 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8240 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 8241 MockRead(true, 0, 0), // EOF 8242 }; 8243 8244 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 8245 data_writes1, arraysize(data_writes1)); 8246 session_deps.socket_factory.AddSocketDataProvider(&data1); 8247 SSLSocketDataProvider ssl(true, OK); 8248 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 8249 8250 TestCompletionCallback callback1; 8251 8252 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session)); 8253 8254 int rv = trans->Start(&request, &callback1, log.bound()); 8255 EXPECT_EQ(ERR_IO_PENDING, rv); 8256 8257 rv = callback1.WaitForResult(); 8258 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 8259 net::CapturingNetLog::EntryList entries; 8260 log.GetEntries(&entries); 8261 size_t pos = ExpectLogContainsSomewhere( 8262 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 8263 NetLog::PHASE_NONE); 8264 ExpectLogContainsSomewhere( 8265 entries, pos, 8266 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 8267 NetLog::PHASE_NONE); 8268 } 8269 8270 // Test for crbug.com/55424. 8271 TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { 8272 SessionDependencies session_deps; 8273 8274 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet( 8275 "https://www.google.com", false, 1, LOWEST)); 8276 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 8277 8278 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); 8279 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true)); 8280 MockRead spdy_reads[] = { 8281 CreateMockRead(*resp), 8282 CreateMockRead(*data), 8283 MockRead(true, 0, 0), 8284 }; 8285 8286 scoped_refptr<DelayedSocketData> spdy_data( 8287 new DelayedSocketData( 8288 1, // wait for one write to finish before reading. 8289 spdy_reads, arraysize(spdy_reads), 8290 spdy_writes, arraysize(spdy_writes))); 8291 session_deps.socket_factory.AddSocketDataProvider(spdy_data); 8292 8293 SSLSocketDataProvider ssl(true, OK); 8294 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 8295 ssl.next_proto = "spdy/2"; 8296 ssl.was_npn_negotiated = true; 8297 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); 8298 8299 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8300 8301 // Set up an initial SpdySession in the pool to reuse. 8302 HostPortPair host_port_pair("www.google.com", 443); 8303 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); 8304 scoped_refptr<SpdySession> spdy_session = 8305 session->spdy_session_pool()->Get(pair, BoundNetLog()); 8306 scoped_refptr<TransportSocketParams> transport_params( 8307 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false)); 8308 TestCompletionCallback callback; 8309 8310 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); 8311 EXPECT_EQ(ERR_IO_PENDING, 8312 connection->Init(host_port_pair.ToString(), transport_params, 8313 LOWEST, &callback, 8314 session->transport_socket_pool(), BoundNetLog())); 8315 EXPECT_EQ(OK, callback.WaitForResult()); 8316 spdy_session->InitializeWithSocket(connection.release(), false, OK); 8317 8318 HttpRequestInfo request; 8319 request.method = "GET"; 8320 request.url = GURL("https://www.google.com/"); 8321 request.load_flags = 0; 8322 8323 // This is the important line that marks this as a preconnect. 8324 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED; 8325 8326 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 8327 8328 int rv = trans->Start(&request, &callback, BoundNetLog()); 8329 EXPECT_EQ(ERR_IO_PENDING, rv); 8330 EXPECT_EQ(OK, callback.WaitForResult()); 8331 } 8332 8333 // Given a net error, cause that error to be returned from the first Write() 8334 // call and verify that the HttpTransaction fails with that error. 8335 static void CheckErrorIsPassedBack(int error, bool async) { 8336 net::HttpRequestInfo request_info; 8337 request_info.url = GURL("https://www.example.com/"); 8338 request_info.method = "GET"; 8339 request_info.load_flags = net::LOAD_NORMAL; 8340 8341 SessionDependencies session_deps; 8342 8343 SSLSocketDataProvider ssl_data(async, OK); 8344 net::MockWrite data_writes[] = { 8345 net::MockWrite(async, error), 8346 }; 8347 net::StaticSocketDataProvider data(NULL, 0, 8348 data_writes, arraysize(data_writes)); 8349 session_deps.socket_factory.AddSocketDataProvider(&data); 8350 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data); 8351 8352 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8353 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 8354 8355 TestCompletionCallback callback; 8356 int rv = trans->Start(&request_info, &callback, net::BoundNetLog()); 8357 if (rv == net::ERR_IO_PENDING) 8358 rv = callback.WaitForResult(); 8359 ASSERT_EQ(error, rv); 8360 } 8361 8362 TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) { 8363 // Just check a grab bag of cert errors. 8364 static const int kErrors[] = { 8365 ERR_CERT_COMMON_NAME_INVALID, 8366 ERR_CERT_AUTHORITY_INVALID, 8367 ERR_CERT_DATE_INVALID, 8368 }; 8369 for (size_t i = 0; i < arraysize(kErrors); i++) { 8370 CheckErrorIsPassedBack(kErrors[i], false /* not async */); 8371 CheckErrorIsPassedBack(kErrors[i], true /* async */); 8372 } 8373 } 8374 8375 // Ensure that a client certificate is removed from the SSL client auth 8376 // cache when: 8377 // 1) No proxy is involved. 8378 // 2) TLS False Start is disabled. 8379 // 3) The initial TLS handshake requests a client certificate. 8380 // 4) The client supplies an invalid/unacceptable certificate. 8381 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) { 8382 net::HttpRequestInfo request_info; 8383 request_info.url = GURL("https://www.example.com/"); 8384 request_info.method = "GET"; 8385 request_info.load_flags = net::LOAD_NORMAL; 8386 8387 SessionDependencies session_deps; 8388 8389 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 8390 cert_request->host_and_port = "www.example.com:443"; 8391 8392 // [ssl_]data1 contains the data for the first SSL handshake. When a 8393 // CertificateRequest is received for the first time, the handshake will 8394 // be aborted to allow the caller to provide a certificate. 8395 SSLSocketDataProvider ssl_data1(true /* async */, 8396 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 8397 ssl_data1.cert_request_info = cert_request.get(); 8398 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1); 8399 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 8400 session_deps.socket_factory.AddSocketDataProvider(&data1); 8401 8402 // [ssl_]data2 contains the data for the second SSL handshake. When TLS 8403 // False Start is not being used, the result of the SSL handshake will be 8404 // returned as part of the SSLClientSocket::Connect() call. This test 8405 // matches the result of a server sending a handshake_failure alert, 8406 // rather than a Finished message, because it requires a client 8407 // certificate and none was supplied. 8408 SSLSocketDataProvider ssl_data2(true /* async */, 8409 net::ERR_SSL_PROTOCOL_ERROR); 8410 ssl_data2.cert_request_info = cert_request.get(); 8411 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2); 8412 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); 8413 session_deps.socket_factory.AddSocketDataProvider(&data2); 8414 8415 // [ssl_]data3 contains the data for the third SSL handshake. When a 8416 // connection to a server fails during an SSL handshake, 8417 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial 8418 // connection was attempted with TLSv1. This is transparent to the caller 8419 // of the HttpNetworkTransaction. Because this test failure is due to 8420 // requiring a client certificate, this fallback handshake should also 8421 // fail. 8422 SSLSocketDataProvider ssl_data3(true /* async */, 8423 net::ERR_SSL_PROTOCOL_ERROR); 8424 ssl_data3.cert_request_info = cert_request.get(); 8425 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3); 8426 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); 8427 session_deps.socket_factory.AddSocketDataProvider(&data3); 8428 8429 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8430 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 8431 8432 // Begin the SSL handshake with the peer. This consumes ssl_data1. 8433 TestCompletionCallback callback; 8434 int rv = trans->Start(&request_info, &callback, net::BoundNetLog()); 8435 ASSERT_EQ(net::ERR_IO_PENDING, rv); 8436 8437 // Complete the SSL handshake, which should abort due to requiring a 8438 // client certificate. 8439 rv = callback.WaitForResult(); 8440 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 8441 8442 // Indicate that no certificate should be supplied. From the perspective 8443 // of SSLClientCertCache, NULL is just as meaningful as a real 8444 // certificate, so this is the same as supply a 8445 // legitimate-but-unacceptable certificate. 8446 rv = trans->RestartWithCertificate(NULL, &callback); 8447 ASSERT_EQ(net::ERR_IO_PENDING, rv); 8448 8449 // Ensure the certificate was added to the client auth cache before 8450 // allowing the connection to continue restarting. 8451 scoped_refptr<X509Certificate> client_cert; 8452 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 8453 &client_cert)); 8454 ASSERT_EQ(NULL, client_cert.get()); 8455 8456 // Restart the handshake. This will consume ssl_data2, which fails, and 8457 // then consume ssl_data3, which should also fail. The result code is 8458 // checked against what ssl_data3 should return. 8459 rv = callback.WaitForResult(); 8460 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 8461 8462 // Ensure that the client certificate is removed from the cache on a 8463 // handshake failure. 8464 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 8465 &client_cert)); 8466 } 8467 8468 // Ensure that a client certificate is removed from the SSL client auth 8469 // cache when: 8470 // 1) No proxy is involved. 8471 // 2) TLS False Start is enabled. 8472 // 3) The initial TLS handshake requests a client certificate. 8473 // 4) The client supplies an invalid/unacceptable certificate. 8474 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) { 8475 net::HttpRequestInfo request_info; 8476 request_info.url = GURL("https://www.example.com/"); 8477 request_info.method = "GET"; 8478 request_info.load_flags = net::LOAD_NORMAL; 8479 8480 SessionDependencies session_deps; 8481 8482 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 8483 cert_request->host_and_port = "www.example.com:443"; 8484 8485 // When TLS False Start is used, SSLClientSocket::Connect() calls will 8486 // return successfully after reading up to the peer's Certificate message. 8487 // This is to allow the caller to call SSLClientSocket::Write(), which can 8488 // enqueue application data to be sent in the same packet as the 8489 // ChangeCipherSpec and Finished messages. 8490 // The actual handshake will be finished when SSLClientSocket::Read() is 8491 // called, which expects to process the peer's ChangeCipherSpec and 8492 // Finished messages. If there was an error negotiating with the peer, 8493 // such as due to the peer requiring a client certificate when none was 8494 // supplied, the alert sent by the peer won't be processed until Read() is 8495 // called. 8496 8497 // Like the non-False Start case, when a client certificate is requested by 8498 // the peer, the handshake is aborted during the Connect() call. 8499 // [ssl_]data1 represents the initial SSL handshake with the peer. 8500 SSLSocketDataProvider ssl_data1(true /* async */, 8501 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 8502 ssl_data1.cert_request_info = cert_request.get(); 8503 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1); 8504 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 8505 session_deps.socket_factory.AddSocketDataProvider(&data1); 8506 8507 // When a client certificate is supplied, Connect() will not be aborted 8508 // when the peer requests the certificate. Instead, the handshake will 8509 // artificially succeed, allowing the caller to write the HTTP request to 8510 // the socket. The handshake messages are not processed until Read() is 8511 // called, which then detects that the handshake was aborted, due to the 8512 // peer sending a handshake_failure because it requires a client 8513 // certificate. 8514 SSLSocketDataProvider ssl_data2(true /* async */, net::OK); 8515 ssl_data2.cert_request_info = cert_request.get(); 8516 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2); 8517 net::MockRead data2_reads[] = { 8518 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR), 8519 }; 8520 net::StaticSocketDataProvider data2( 8521 data2_reads, arraysize(data2_reads), NULL, 0); 8522 session_deps.socket_factory.AddSocketDataProvider(&data2); 8523 8524 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is 8525 // the data for the SSL handshake once the TLSv1 connection falls back to 8526 // SSLv3. It has the same behaviour as [ssl_]data2. 8527 SSLSocketDataProvider ssl_data3(true /* async */, net::OK); 8528 ssl_data3.cert_request_info = cert_request.get(); 8529 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3); 8530 net::StaticSocketDataProvider data3( 8531 data2_reads, arraysize(data2_reads), NULL, 0); 8532 session_deps.socket_factory.AddSocketDataProvider(&data3); 8533 8534 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8535 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session)); 8536 8537 // Begin the initial SSL handshake. 8538 TestCompletionCallback callback; 8539 int rv = trans->Start(&request_info, &callback, net::BoundNetLog()); 8540 ASSERT_EQ(net::ERR_IO_PENDING, rv); 8541 8542 // Complete the SSL handshake, which should abort due to requiring a 8543 // client certificate. 8544 rv = callback.WaitForResult(); 8545 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 8546 8547 // Indicate that no certificate should be supplied. From the perspective 8548 // of SSLClientCertCache, NULL is just as meaningful as a real 8549 // certificate, so this is the same as supply a 8550 // legitimate-but-unacceptable certificate. 8551 rv = trans->RestartWithCertificate(NULL, &callback); 8552 ASSERT_EQ(net::ERR_IO_PENDING, rv); 8553 8554 // Ensure the certificate was added to the client auth cache before 8555 // allowing the connection to continue restarting. 8556 scoped_refptr<X509Certificate> client_cert; 8557 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 8558 &client_cert)); 8559 ASSERT_EQ(NULL, client_cert.get()); 8560 8561 8562 // Restart the handshake. This will consume ssl_data2, which fails, and 8563 // then consume ssl_data3, which should also fail. The result code is 8564 // checked against what ssl_data3 should return. 8565 rv = callback.WaitForResult(); 8566 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 8567 8568 // Ensure that the client certificate is removed from the cache on a 8569 // handshake failure. 8570 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 8571 &client_cert)); 8572 } 8573 8574 // Ensure that a client certificate is removed from the SSL client auth 8575 // cache when: 8576 // 1) An HTTPS proxy is involved. 8577 // 3) The HTTPS proxy requests a client certificate. 8578 // 4) The client supplies an invalid/unacceptable certificate for the 8579 // proxy. 8580 // The test is repeated twice, first for connecting to an HTTPS endpoint, 8581 // then for connecting to an HTTP endpoint. 8582 TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) { 8583 SessionDependencies session_deps( 8584 ProxyService::CreateFixed("https://proxy:70")); 8585 CapturingBoundNetLog log(CapturingNetLog::kUnbounded); 8586 session_deps.net_log = log.bound().net_log(); 8587 8588 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 8589 cert_request->host_and_port = "proxy:70"; 8590 8591 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of 8592 // [ssl_]data[1-3]. Rather than represending the endpoint 8593 // (www.example.com:443), they represent failures with the HTTPS proxy 8594 // (proxy:70). 8595 SSLSocketDataProvider ssl_data1(true /* async */, 8596 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 8597 ssl_data1.cert_request_info = cert_request.get(); 8598 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1); 8599 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 8600 session_deps.socket_factory.AddSocketDataProvider(&data1); 8601 8602 SSLSocketDataProvider ssl_data2(true /* async */, 8603 net::ERR_SSL_PROTOCOL_ERROR); 8604 ssl_data2.cert_request_info = cert_request.get(); 8605 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2); 8606 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); 8607 session_deps.socket_factory.AddSocketDataProvider(&data2); 8608 8609 SSLSocketDataProvider ssl_data3(true /* async */, 8610 net::ERR_SSL_PROTOCOL_ERROR); 8611 ssl_data3.cert_request_info = cert_request.get(); 8612 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3); 8613 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); 8614 session_deps.socket_factory.AddSocketDataProvider(&data3); 8615 8616 net::HttpRequestInfo requests[2]; 8617 requests[0].url = GURL("https://www.example.com/"); 8618 requests[0].method = "GET"; 8619 requests[0].load_flags = net::LOAD_NORMAL; 8620 8621 requests[1].url = GURL("http://www.example.com/"); 8622 requests[1].method = "GET"; 8623 requests[1].load_flags = net::LOAD_NORMAL; 8624 8625 for (size_t i = 0; i < arraysize(requests); ++i) { 8626 session_deps.socket_factory.ResetNextMockIndexes(); 8627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps)); 8628 scoped_ptr<HttpNetworkTransaction> trans( 8629 new HttpNetworkTransaction(session)); 8630 8631 // Begin the SSL handshake with the proxy. 8632 TestCompletionCallback callback; 8633 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog()); 8634 ASSERT_EQ(net::ERR_IO_PENDING, rv); 8635 8636 // Complete the SSL handshake, which should abort due to requiring a 8637 // client certificate. 8638 rv = callback.WaitForResult(); 8639 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 8640 8641 // Indicate that no certificate should be supplied. From the perspective 8642 // of SSLClientCertCache, NULL is just as meaningful as a real 8643 // certificate, so this is the same as supply a 8644 // legitimate-but-unacceptable certificate. 8645 rv = trans->RestartWithCertificate(NULL, &callback); 8646 ASSERT_EQ(net::ERR_IO_PENDING, rv); 8647 8648 // Ensure the certificate was added to the client auth cache before 8649 // allowing the connection to continue restarting. 8650 scoped_refptr<X509Certificate> client_cert; 8651 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70", 8652 &client_cert)); 8653 ASSERT_EQ(NULL, client_cert.get()); 8654 // Ensure the certificate was NOT cached for the endpoint. This only 8655 // applies to HTTPS requests, but is fine to check for HTTP requests. 8656 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 8657 &client_cert)); 8658 8659 // Restart the handshake. This will consume ssl_data2, which fails, and 8660 // then consume ssl_data3, which should also fail. The result code is 8661 // checked against what ssl_data3 should return. 8662 rv = callback.WaitForResult(); 8663 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv); 8664 8665 // Now that the new handshake has failed, ensure that the client 8666 // certificate was removed from the client auth cache. 8667 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70", 8668 &client_cert)); 8669 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 8670 &client_cert)); 8671 } 8672 } 8673 8674 } // namespace net 8675