http_network_transaction_unittest.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
1// Copyright 2013 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 <stdarg.h> 9#include <string> 10#include <vector> 11 12#include "base/basictypes.h" 13#include "base/compiler_specific.h" 14#include "base/file_util.h" 15#include "base/files/file_path.h" 16#include "base/json/json_writer.h" 17#include "base/memory/scoped_ptr.h" 18#include "base/strings/string_util.h" 19#include "base/strings/utf_string_conversions.h" 20#include "base/test/test_file_util.h" 21#include "net/base/auth.h" 22#include "net/base/capturing_net_log.h" 23#include "net/base/completion_callback.h" 24#include "net/base/load_timing_info.h" 25#include "net/base/load_timing_info_test_util.h" 26#include "net/base/net_log.h" 27#include "net/base/net_log_unittest.h" 28#include "net/base/request_priority.h" 29#include "net/base/test_completion_callback.h" 30#include "net/base/test_data_directory.h" 31#include "net/base/upload_bytes_element_reader.h" 32#include "net/base/upload_data_stream.h" 33#include "net/base/upload_file_element_reader.h" 34#include "net/cert/mock_cert_verifier.h" 35#include "net/dns/host_cache.h" 36#include "net/dns/mock_host_resolver.h" 37#include "net/http/http_auth_handler_digest.h" 38#include "net/http/http_auth_handler_mock.h" 39#include "net/http/http_auth_handler_ntlm.h" 40#include "net/http/http_basic_stream.h" 41#include "net/http/http_network_session.h" 42#include "net/http/http_network_session_peer.h" 43#include "net/http/http_server_properties_impl.h" 44#include "net/http/http_stream.h" 45#include "net/http/http_stream_factory.h" 46#include "net/http/http_transaction_unittest.h" 47#include "net/proxy/proxy_config_service_fixed.h" 48#include "net/proxy/proxy_resolver.h" 49#include "net/proxy/proxy_service.h" 50#include "net/socket/client_socket_factory.h" 51#include "net/socket/client_socket_pool_manager.h" 52#include "net/socket/mock_client_socket_pool_manager.h" 53#include "net/socket/next_proto.h" 54#include "net/socket/socket_test_util.h" 55#include "net/socket/ssl_client_socket.h" 56#include "net/spdy/spdy_framer.h" 57#include "net/spdy/spdy_session.h" 58#include "net/spdy/spdy_session_pool.h" 59#include "net/spdy/spdy_test_util_common.h" 60#include "net/ssl/ssl_cert_request_info.h" 61#include "net/ssl/ssl_config_service_defaults.h" 62#include "net/ssl/ssl_info.h" 63#include "net/test/cert_test_util.h" 64#include "testing/gtest/include/gtest/gtest.h" 65#include "testing/platform_test.h" 66#include "url/gurl.h" 67 68//----------------------------------------------------------------------------- 69 70namespace { 71 72const base::string16 kBar(ASCIIToUTF16("bar")); 73const base::string16 kBar2(ASCIIToUTF16("bar2")); 74const base::string16 kBar3(ASCIIToUTF16("bar3")); 75const base::string16 kBaz(ASCIIToUTF16("baz")); 76const base::string16 kFirst(ASCIIToUTF16("first")); 77const base::string16 kFoo(ASCIIToUTF16("foo")); 78const base::string16 kFoo2(ASCIIToUTF16("foo2")); 79const base::string16 kFoo3(ASCIIToUTF16("foo3")); 80const base::string16 kFou(ASCIIToUTF16("fou")); 81const base::string16 kSecond(ASCIIToUTF16("second")); 82const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm")); 83const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword")); 84 85int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) { 86 return session->GetTransportSocketPool( 87 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); 88} 89 90int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) { 91 return session->GetSSLSocketPool( 92 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); 93} 94 95// Takes in a Value created from a NetLogHttpResponseParameter, and returns 96// a JSONified list of headers as a single string. Uses single quotes instead 97// of double quotes for easier comparison. Returns false on failure. 98bool GetHeaders(base::DictionaryValue* params, std::string* headers) { 99 if (!params) 100 return false; 101 base::ListValue* header_list; 102 if (!params->GetList("headers", &header_list)) 103 return false; 104 std::string double_quote_headers; 105 base::JSONWriter::Write(header_list, &double_quote_headers); 106 ReplaceChars(double_quote_headers, "\"", "'", headers); 107 return true; 108} 109 110// Tests LoadTimingInfo in the case a socket is reused and no PAC script is 111// used. 112void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) { 113 EXPECT_TRUE(load_timing_info.socket_reused); 114 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 115 116 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); 117 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); 118 119 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 120 EXPECT_FALSE(load_timing_info.send_start.is_null()); 121 122 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 123 124 // Set at a higher level. 125 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 126 EXPECT_TRUE(load_timing_info.request_start.is_null()); 127 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 128} 129 130// Tests LoadTimingInfo in the case a new socket is used and no PAC script is 131// used. 132void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info, 133 int connect_timing_flags) { 134 EXPECT_FALSE(load_timing_info.socket_reused); 135 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 136 137 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); 138 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); 139 140 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 141 connect_timing_flags); 142 EXPECT_LE(load_timing_info.connect_timing.connect_end, 143 load_timing_info.send_start); 144 145 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 146 147 // Set at a higher level. 148 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 149 EXPECT_TRUE(load_timing_info.request_start.is_null()); 150 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 151} 152 153// Tests LoadTimingInfo in the case a socket is reused and a PAC script is 154// used. 155void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) { 156 EXPECT_TRUE(load_timing_info.socket_reused); 157 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 158 159 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 160 161 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 162 EXPECT_LE(load_timing_info.proxy_resolve_start, 163 load_timing_info.proxy_resolve_end); 164 EXPECT_LE(load_timing_info.proxy_resolve_end, 165 load_timing_info.send_start); 166 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 167 168 // Set at a higher level. 169 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 170 EXPECT_TRUE(load_timing_info.request_start.is_null()); 171 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 172} 173 174// Tests LoadTimingInfo in the case a new socket is used and a PAC script is 175// used. 176void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info, 177 int connect_timing_flags) { 178 EXPECT_FALSE(load_timing_info.socket_reused); 179 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 180 181 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 182 EXPECT_LE(load_timing_info.proxy_resolve_start, 183 load_timing_info.proxy_resolve_end); 184 EXPECT_LE(load_timing_info.proxy_resolve_end, 185 load_timing_info.connect_timing.connect_start); 186 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 187 connect_timing_flags); 188 EXPECT_LE(load_timing_info.connect_timing.connect_end, 189 load_timing_info.send_start); 190 191 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 192 193 // Set at a higher level. 194 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 195 EXPECT_TRUE(load_timing_info.request_start.is_null()); 196 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 197} 198 199} // namespace 200 201namespace net { 202 203namespace { 204 205HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) { 206 return SpdySessionDependencies::SpdyCreateSession(session_deps); 207} 208 209} // namespace 210 211class HttpNetworkTransactionTest 212 : public PlatformTest, 213 public ::testing::WithParamInterface<NextProto> { 214 public: 215 virtual ~HttpNetworkTransactionTest() { 216 // Important to restore the per-pool limit first, since the pool limit must 217 // always be greater than group limit, and the tests reduce both limits. 218 ClientSocketPoolManager::set_max_sockets_per_pool( 219 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_); 220 ClientSocketPoolManager::set_max_sockets_per_group( 221 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_); 222 } 223 224 protected: 225 HttpNetworkTransactionTest() 226 : spdy_util_(GetParam()), 227 session_deps_(GetParam()), 228 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( 229 HttpNetworkSession::NORMAL_SOCKET_POOL)), 230 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( 231 HttpNetworkSession::NORMAL_SOCKET_POOL)) { 232 } 233 234 struct SimpleGetHelperResult { 235 int rv; 236 std::string status_line; 237 std::string response_data; 238 LoadTimingInfo load_timing_info; 239 }; 240 241 virtual void SetUp() { 242 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 243 base::MessageLoop::current()->RunUntilIdle(); 244 } 245 246 virtual void TearDown() { 247 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 248 base::MessageLoop::current()->RunUntilIdle(); 249 // Empty the current queue. 250 base::MessageLoop::current()->RunUntilIdle(); 251 PlatformTest::TearDown(); 252 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 253 base::MessageLoop::current()->RunUntilIdle(); 254 HttpStreamFactory::set_use_alternate_protocols(false); 255 HttpStreamFactory::SetNextProtos(std::vector<NextProto>()); 256 } 257 258 // This is the expected return from a current server advertising SPDY. 259 std::string GetAlternateProtocolHttpHeader() { 260 return 261 std::string("Alternate-Protocol: 443:") + 262 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) + 263 "\r\n\r\n"; 264 } 265 266 // Either |write_failure| specifies a write failure or |read_failure| 267 // specifies a read failure when using a reused socket. In either case, the 268 // failure should cause the network transaction to resend the request, and the 269 // other argument should be NULL. 270 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure, 271 const MockRead* read_failure); 272 273 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[], 274 size_t data_count) { 275 SimpleGetHelperResult out; 276 277 HttpRequestInfo request; 278 request.method = "GET"; 279 request.url = GURL("http://www.google.com/"); 280 request.load_flags = 0; 281 282 CapturingBoundNetLog log; 283 session_deps_.net_log = log.bound().net_log(); 284 scoped_ptr<HttpTransaction> trans( 285 new HttpNetworkTransaction(DEFAULT_PRIORITY, 286 CreateSession(&session_deps_))); 287 288 for (size_t i = 0; i < data_count; ++i) { 289 session_deps_.socket_factory->AddSocketDataProvider(data[i]); 290 } 291 292 TestCompletionCallback callback; 293 294 EXPECT_TRUE(log.bound().IsLoggingAllEvents()); 295 int rv = trans->Start(&request, callback.callback(), log.bound()); 296 EXPECT_EQ(ERR_IO_PENDING, rv); 297 298 out.rv = callback.WaitForResult(); 299 300 // Even in the failure cases that use this function, connections are always 301 // successfully established before the error. 302 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info)); 303 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 304 305 if (out.rv != OK) 306 return out; 307 308 const HttpResponseInfo* response = trans->GetResponseInfo(); 309 // Can't use ASSERT_* inside helper functions like this, so 310 // return an error. 311 if (response == NULL || response->headers.get() == NULL) { 312 out.rv = ERR_UNEXPECTED; 313 return out; 314 } 315 out.status_line = response->headers->GetStatusLine(); 316 317 EXPECT_EQ("127.0.0.1", response->socket_address.host()); 318 EXPECT_EQ(80, response->socket_address.port()); 319 320 rv = ReadTransaction(trans.get(), &out.response_data); 321 EXPECT_EQ(OK, rv); 322 323 net::CapturingNetLog::CapturedEntryList entries; 324 log.GetEntries(&entries); 325 size_t pos = ExpectLogContainsSomewhere( 326 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 327 NetLog::PHASE_NONE); 328 ExpectLogContainsSomewhere( 329 entries, pos, 330 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS, 331 NetLog::PHASE_NONE); 332 333 std::string line; 334 EXPECT_TRUE(entries[pos].GetStringValue("line", &line)); 335 EXPECT_EQ("GET / HTTP/1.1\r\n", line); 336 337 HttpRequestHeaders request_headers; 338 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 339 std::string value; 340 EXPECT_TRUE(request_headers.GetHeader("Host", &value)); 341 EXPECT_EQ("www.google.com", value); 342 EXPECT_TRUE(request_headers.GetHeader("Connection", &value)); 343 EXPECT_EQ("keep-alive", value); 344 345 std::string response_headers; 346 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers)); 347 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']", 348 response_headers); 349 350 return out; 351 } 352 353 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[], 354 size_t reads_count) { 355 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0); 356 StaticSocketDataProvider* data[] = { &reads }; 357 return SimpleGetHelperForData(data, 1); 358 } 359 360 void ConnectStatusHelperWithExpectedStatus(const MockRead& status, 361 int expected_status); 362 363 void ConnectStatusHelper(const MockRead& status); 364 365 void BypassHostCacheOnRefreshHelper(int load_flags); 366 367 void CheckErrorIsPassedBack(int error, IoMode mode); 368 369 SpdyTestUtil spdy_util_; 370 SpdySessionDependencies session_deps_; 371 372 // Original socket limits. Some tests set these. Safest to always restore 373 // them once each test has been run. 374 int old_max_group_sockets_; 375 int old_max_pool_sockets_; 376}; 377 378INSTANTIATE_TEST_CASE_P( 379 NextProto, 380 HttpNetworkTransactionTest, 381 testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, 382 kProtoHTTP2Draft04)); 383 384namespace { 385 386// Fill |str| with a long header list that consumes >= |size| bytes. 387void FillLargeHeadersString(std::string* str, int size) { 388 const char* row = 389 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"; 390 const int sizeof_row = strlen(row); 391 const int num_rows = static_cast<int>( 392 ceil(static_cast<float>(size) / sizeof_row)); 393 const int sizeof_data = num_rows * sizeof_row; 394 DCHECK(sizeof_data >= size); 395 str->reserve(sizeof_data); 396 397 for (int i = 0; i < num_rows; ++i) 398 str->append(row, sizeof_row); 399} 400 401// Alternative functions that eliminate randomness and dependency on the local 402// host name so that the generated NTLM messages are reproducible. 403void MockGenerateRandom1(uint8* output, size_t n) { 404 static const uint8 bytes[] = { 405 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54 406 }; 407 static size_t current_byte = 0; 408 for (size_t i = 0; i < n; ++i) { 409 output[i] = bytes[current_byte++]; 410 current_byte %= arraysize(bytes); 411 } 412} 413 414void MockGenerateRandom2(uint8* output, size_t n) { 415 static const uint8 bytes[] = { 416 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1, 417 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f 418 }; 419 static size_t current_byte = 0; 420 for (size_t i = 0; i < n; ++i) { 421 output[i] = bytes[current_byte++]; 422 current_byte %= arraysize(bytes); 423 } 424} 425 426std::string MockGetHostName() { 427 return "WTC-WIN7"; 428} 429 430template<typename ParentPool> 431class CaptureGroupNameSocketPool : public ParentPool { 432 public: 433 CaptureGroupNameSocketPool(HostResolver* host_resolver, 434 CertVerifier* cert_verifier); 435 436 const std::string last_group_name_received() const { 437 return last_group_name_; 438 } 439 440 virtual int RequestSocket(const std::string& group_name, 441 const void* socket_params, 442 RequestPriority priority, 443 ClientSocketHandle* handle, 444 const CompletionCallback& callback, 445 const BoundNetLog& net_log) { 446 last_group_name_ = group_name; 447 return ERR_IO_PENDING; 448 } 449 virtual void CancelRequest(const std::string& group_name, 450 ClientSocketHandle* handle) {} 451 virtual void ReleaseSocket(const std::string& group_name, 452 StreamSocket* socket, 453 int id) {} 454 virtual void CloseIdleSockets() {} 455 virtual int IdleSocketCount() const { 456 return 0; 457 } 458 virtual int IdleSocketCountInGroup(const std::string& group_name) const { 459 return 0; 460 } 461 virtual LoadState GetLoadState(const std::string& group_name, 462 const ClientSocketHandle* handle) const { 463 return LOAD_STATE_IDLE; 464 } 465 virtual base::TimeDelta ConnectionTimeout() const { 466 return base::TimeDelta(); 467 } 468 469 private: 470 std::string last_group_name_; 471}; 472 473typedef CaptureGroupNameSocketPool<TransportClientSocketPool> 474CaptureGroupNameTransportSocketPool; 475typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool> 476CaptureGroupNameHttpProxySocketPool; 477typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool> 478CaptureGroupNameSOCKSSocketPool; 479typedef CaptureGroupNameSocketPool<SSLClientSocketPool> 480CaptureGroupNameSSLSocketPool; 481 482template<typename ParentPool> 483CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( 484 HostResolver* host_resolver, 485 CertVerifier* /* cert_verifier */) 486 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {} 487 488template<> 489CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( 490 HostResolver* host_resolver, 491 CertVerifier* /* cert_verifier */) 492 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {} 493 494template <> 495CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( 496 HostResolver* host_resolver, 497 CertVerifier* cert_verifier) 498 : SSLClientSocketPool(0, 499 0, 500 NULL, 501 host_resolver, 502 cert_verifier, 503 NULL, 504 NULL, 505 std::string(), 506 NULL, 507 NULL, 508 NULL, 509 NULL, 510 NULL, 511 NULL) {} 512 513//----------------------------------------------------------------------------- 514 515// Helper functions for validating that AuthChallengeInfo's are correctly 516// configured for common cases. 517bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) { 518 if (!auth_challenge) 519 return false; 520 EXPECT_FALSE(auth_challenge->is_proxy); 521 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString()); 522 EXPECT_EQ("MyRealm1", auth_challenge->realm); 523 EXPECT_EQ("basic", auth_challenge->scheme); 524 return true; 525} 526 527bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) { 528 if (!auth_challenge) 529 return false; 530 EXPECT_TRUE(auth_challenge->is_proxy); 531 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString()); 532 EXPECT_EQ("MyRealm1", auth_challenge->realm); 533 EXPECT_EQ("basic", auth_challenge->scheme); 534 return true; 535} 536 537bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) { 538 if (!auth_challenge) 539 return false; 540 EXPECT_FALSE(auth_challenge->is_proxy); 541 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString()); 542 EXPECT_EQ("digestive", auth_challenge->realm); 543 EXPECT_EQ("digest", auth_challenge->scheme); 544 return true; 545} 546 547bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) { 548 if (!auth_challenge) 549 return false; 550 EXPECT_FALSE(auth_challenge->is_proxy); 551 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString()); 552 EXPECT_EQ(std::string(), auth_challenge->realm); 553 EXPECT_EQ("ntlm", auth_challenge->scheme); 554 return true; 555} 556 557} // namespace 558 559TEST_P(HttpNetworkTransactionTest, Basic) { 560 scoped_ptr<HttpTransaction> trans( 561 new HttpNetworkTransaction(DEFAULT_PRIORITY, 562 CreateSession(&session_deps_))); 563} 564 565TEST_P(HttpNetworkTransactionTest, SimpleGET) { 566 MockRead data_reads[] = { 567 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 568 MockRead("hello world"), 569 MockRead(SYNCHRONOUS, OK), 570 }; 571 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 572 arraysize(data_reads)); 573 EXPECT_EQ(OK, out.rv); 574 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 575 EXPECT_EQ("hello world", out.response_data); 576} 577 578// Response with no status line. 579TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) { 580 MockRead data_reads[] = { 581 MockRead("hello world"), 582 MockRead(SYNCHRONOUS, OK), 583 }; 584 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 585 arraysize(data_reads)); 586 EXPECT_EQ(OK, out.rv); 587 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 588 EXPECT_EQ("hello world", out.response_data); 589} 590 591// Allow up to 4 bytes of junk to precede status line. 592TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) { 593 MockRead data_reads[] = { 594 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 595 MockRead(SYNCHRONOUS, OK), 596 }; 597 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 598 arraysize(data_reads)); 599 EXPECT_EQ(OK, out.rv); 600 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 601 EXPECT_EQ("DATA", out.response_data); 602} 603 604// Allow up to 4 bytes of junk to precede status line. 605TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) { 606 MockRead data_reads[] = { 607 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 608 MockRead(SYNCHRONOUS, OK), 609 }; 610 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 611 arraysize(data_reads)); 612 EXPECT_EQ(OK, out.rv); 613 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 614 EXPECT_EQ("DATA", out.response_data); 615} 616 617// Beyond 4 bytes of slop and it should fail to find a status line. 618TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) { 619 MockRead data_reads[] = { 620 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"), 621 MockRead(SYNCHRONOUS, OK), 622 }; 623 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 624 arraysize(data_reads)); 625 EXPECT_EQ(OK, out.rv); 626 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 627 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data); 628} 629 630// Same as StatusLineJunk4Bytes, except the read chunks are smaller. 631TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) { 632 MockRead data_reads[] = { 633 MockRead("\n"), 634 MockRead("\n"), 635 MockRead("Q"), 636 MockRead("J"), 637 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 638 MockRead(SYNCHRONOUS, OK), 639 }; 640 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 641 arraysize(data_reads)); 642 EXPECT_EQ(OK, out.rv); 643 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 644 EXPECT_EQ("DATA", out.response_data); 645} 646 647// Close the connection before enough bytes to have a status line. 648TEST_P(HttpNetworkTransactionTest, StatusLinePartial) { 649 MockRead data_reads[] = { 650 MockRead("HTT"), 651 MockRead(SYNCHRONOUS, OK), 652 }; 653 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 654 arraysize(data_reads)); 655 EXPECT_EQ(OK, out.rv); 656 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 657 EXPECT_EQ("HTT", out.response_data); 658} 659 660// Simulate a 204 response, lacking a Content-Length header, sent over a 661// persistent connection. The response should still terminate since a 204 662// cannot have a response body. 663TEST_P(HttpNetworkTransactionTest, StopsReading204) { 664 MockRead data_reads[] = { 665 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 666 MockRead("junk"), // Should not be read!! 667 MockRead(SYNCHRONOUS, OK), 668 }; 669 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 670 arraysize(data_reads)); 671 EXPECT_EQ(OK, out.rv); 672 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line); 673 EXPECT_EQ("", out.response_data); 674} 675 676// A simple request using chunked encoding with some extra data after. 677// (Like might be seen in a pipelined response.) 678TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) { 679 MockRead data_reads[] = { 680 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"), 681 MockRead("5\r\nHello\r\n"), 682 MockRead("1\r\n"), 683 MockRead(" \r\n"), 684 MockRead("5\r\nworld\r\n"), 685 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), 686 MockRead(SYNCHRONOUS, OK), 687 }; 688 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 689 arraysize(data_reads)); 690 EXPECT_EQ(OK, out.rv); 691 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 692 EXPECT_EQ("Hello world", out.response_data); 693} 694 695// Next tests deal with http://crbug.com/56344. 696 697TEST_P(HttpNetworkTransactionTest, 698 MultipleContentLengthHeadersNoTransferEncoding) { 699 MockRead data_reads[] = { 700 MockRead("HTTP/1.1 200 OK\r\n"), 701 MockRead("Content-Length: 10\r\n"), 702 MockRead("Content-Length: 5\r\n\r\n"), 703 }; 704 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 705 arraysize(data_reads)); 706 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 707} 708 709TEST_P(HttpNetworkTransactionTest, 710 DuplicateContentLengthHeadersNoTransferEncoding) { 711 MockRead data_reads[] = { 712 MockRead("HTTP/1.1 200 OK\r\n"), 713 MockRead("Content-Length: 5\r\n"), 714 MockRead("Content-Length: 5\r\n\r\n"), 715 MockRead("Hello"), 716 }; 717 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 718 arraysize(data_reads)); 719 EXPECT_EQ(OK, out.rv); 720 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 721 EXPECT_EQ("Hello", out.response_data); 722} 723 724TEST_P(HttpNetworkTransactionTest, 725 ComplexContentLengthHeadersNoTransferEncoding) { 726 // More than 2 dupes. 727 { 728 MockRead data_reads[] = { 729 MockRead("HTTP/1.1 200 OK\r\n"), 730 MockRead("Content-Length: 5\r\n"), 731 MockRead("Content-Length: 5\r\n"), 732 MockRead("Content-Length: 5\r\n\r\n"), 733 MockRead("Hello"), 734 }; 735 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 736 arraysize(data_reads)); 737 EXPECT_EQ(OK, out.rv); 738 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 739 EXPECT_EQ("Hello", out.response_data); 740 } 741 // HTTP/1.0 742 { 743 MockRead data_reads[] = { 744 MockRead("HTTP/1.0 200 OK\r\n"), 745 MockRead("Content-Length: 5\r\n"), 746 MockRead("Content-Length: 5\r\n"), 747 MockRead("Content-Length: 5\r\n\r\n"), 748 MockRead("Hello"), 749 }; 750 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 751 arraysize(data_reads)); 752 EXPECT_EQ(OK, out.rv); 753 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 754 EXPECT_EQ("Hello", out.response_data); 755 } 756 // 2 dupes and one mismatched. 757 { 758 MockRead data_reads[] = { 759 MockRead("HTTP/1.1 200 OK\r\n"), 760 MockRead("Content-Length: 10\r\n"), 761 MockRead("Content-Length: 10\r\n"), 762 MockRead("Content-Length: 5\r\n\r\n"), 763 }; 764 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 765 arraysize(data_reads)); 766 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 767 } 768} 769 770TEST_P(HttpNetworkTransactionTest, 771 MultipleContentLengthHeadersTransferEncoding) { 772 MockRead data_reads[] = { 773 MockRead("HTTP/1.1 200 OK\r\n"), 774 MockRead("Content-Length: 666\r\n"), 775 MockRead("Content-Length: 1337\r\n"), 776 MockRead("Transfer-Encoding: chunked\r\n\r\n"), 777 MockRead("5\r\nHello\r\n"), 778 MockRead("1\r\n"), 779 MockRead(" \r\n"), 780 MockRead("5\r\nworld\r\n"), 781 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), 782 MockRead(SYNCHRONOUS, OK), 783 }; 784 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 785 arraysize(data_reads)); 786 EXPECT_EQ(OK, out.rv); 787 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 788 EXPECT_EQ("Hello world", out.response_data); 789} 790 791// Next tests deal with http://crbug.com/98895. 792 793// Checks that a single Content-Disposition header results in no error. 794TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) { 795 MockRead data_reads[] = { 796 MockRead("HTTP/1.1 200 OK\r\n"), 797 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"), 798 MockRead("Content-Length: 5\r\n\r\n"), 799 MockRead("Hello"), 800 }; 801 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 802 arraysize(data_reads)); 803 EXPECT_EQ(OK, out.rv); 804 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 805 EXPECT_EQ("Hello", out.response_data); 806} 807 808// Checks that two identical Content-Disposition headers result in no error. 809TEST_P(HttpNetworkTransactionTest, 810 TwoIdenticalContentDispositionHeaders) { 811 MockRead data_reads[] = { 812 MockRead("HTTP/1.1 200 OK\r\n"), 813 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 814 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 815 MockRead("Content-Length: 5\r\n\r\n"), 816 MockRead("Hello"), 817 }; 818 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 819 arraysize(data_reads)); 820 EXPECT_EQ(OK, out.rv); 821 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 822 EXPECT_EQ("Hello", out.response_data); 823} 824 825// Checks that two distinct Content-Disposition headers result in an error. 826TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) { 827 MockRead data_reads[] = { 828 MockRead("HTTP/1.1 200 OK\r\n"), 829 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 830 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"), 831 MockRead("Content-Length: 5\r\n\r\n"), 832 MockRead("Hello"), 833 }; 834 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 835 arraysize(data_reads)); 836 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv); 837} 838 839// Checks that two identical Location headers result in no error. 840// Also tests Location header behavior. 841TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) { 842 MockRead data_reads[] = { 843 MockRead("HTTP/1.1 302 Redirect\r\n"), 844 MockRead("Location: http://good.com/\r\n"), 845 MockRead("Location: http://good.com/\r\n"), 846 MockRead("Content-Length: 0\r\n\r\n"), 847 MockRead(SYNCHRONOUS, OK), 848 }; 849 850 HttpRequestInfo request; 851 request.method = "GET"; 852 request.url = GURL("http://redirect.com/"); 853 request.load_flags = 0; 854 855 scoped_ptr<HttpTransaction> trans( 856 new HttpNetworkTransaction(DEFAULT_PRIORITY, 857 CreateSession(&session_deps_))); 858 859 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 860 session_deps_.socket_factory->AddSocketDataProvider(&data); 861 862 TestCompletionCallback callback; 863 864 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 865 EXPECT_EQ(ERR_IO_PENDING, rv); 866 867 EXPECT_EQ(OK, callback.WaitForResult()); 868 869 const HttpResponseInfo* response = trans->GetResponseInfo(); 870 ASSERT_TRUE(response != NULL && response->headers.get() != NULL); 871 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine()); 872 std::string url; 873 EXPECT_TRUE(response->headers->IsRedirect(&url)); 874 EXPECT_EQ("http://good.com/", url); 875} 876 877// Checks that two distinct Location headers result in an error. 878TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) { 879 MockRead data_reads[] = { 880 MockRead("HTTP/1.1 302 Redirect\r\n"), 881 MockRead("Location: http://good.com/\r\n"), 882 MockRead("Location: http://evil.com/\r\n"), 883 MockRead("Content-Length: 0\r\n\r\n"), 884 MockRead(SYNCHRONOUS, OK), 885 }; 886 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 887 arraysize(data_reads)); 888 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv); 889} 890 891// Do a request using the HEAD method. Verify that we don't try to read the 892// message body (since HEAD has none). 893TEST_P(HttpNetworkTransactionTest, Head) { 894 HttpRequestInfo request; 895 request.method = "HEAD"; 896 request.url = GURL("http://www.google.com/"); 897 request.load_flags = 0; 898 899 scoped_ptr<HttpTransaction> trans( 900 new HttpNetworkTransaction(DEFAULT_PRIORITY, 901 CreateSession(&session_deps_))); 902 903 MockWrite data_writes1[] = { 904 MockWrite("HEAD / HTTP/1.1\r\n" 905 "Host: www.google.com\r\n" 906 "Connection: keep-alive\r\n" 907 "Content-Length: 0\r\n\r\n"), 908 }; 909 MockRead data_reads1[] = { 910 MockRead("HTTP/1.1 404 Not Found\r\n"), 911 MockRead("Server: Blah\r\n"), 912 MockRead("Content-Length: 1234\r\n\r\n"), 913 914 // No response body because the test stops reading here. 915 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 916 }; 917 918 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 919 data_writes1, arraysize(data_writes1)); 920 session_deps_.socket_factory->AddSocketDataProvider(&data1); 921 922 TestCompletionCallback callback1; 923 924 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 925 EXPECT_EQ(ERR_IO_PENDING, rv); 926 927 rv = callback1.WaitForResult(); 928 EXPECT_EQ(OK, rv); 929 930 const HttpResponseInfo* response = trans->GetResponseInfo(); 931 ASSERT_TRUE(response != NULL); 932 933 // Check that the headers got parsed. 934 EXPECT_TRUE(response->headers.get() != NULL); 935 EXPECT_EQ(1234, response->headers->GetContentLength()); 936 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine()); 937 938 std::string server_header; 939 void* iter = NULL; 940 bool has_server_header = response->headers->EnumerateHeader( 941 &iter, "Server", &server_header); 942 EXPECT_TRUE(has_server_header); 943 EXPECT_EQ("Blah", server_header); 944 945 // Reading should give EOF right away, since there is no message body 946 // (despite non-zero content-length). 947 std::string response_data; 948 rv = ReadTransaction(trans.get(), &response_data); 949 EXPECT_EQ(OK, rv); 950 EXPECT_EQ("", response_data); 951} 952 953TEST_P(HttpNetworkTransactionTest, ReuseConnection) { 954 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 955 956 MockRead data_reads[] = { 957 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 958 MockRead("hello"), 959 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 960 MockRead("world"), 961 MockRead(SYNCHRONOUS, OK), 962 }; 963 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 964 session_deps_.socket_factory->AddSocketDataProvider(&data); 965 966 const char* const kExpectedResponseData[] = { 967 "hello", "world" 968 }; 969 970 for (int i = 0; i < 2; ++i) { 971 HttpRequestInfo request; 972 request.method = "GET"; 973 request.url = GURL("http://www.google.com/"); 974 request.load_flags = 0; 975 976 scoped_ptr<HttpTransaction> trans( 977 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 978 979 TestCompletionCallback callback; 980 981 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 982 EXPECT_EQ(ERR_IO_PENDING, rv); 983 984 rv = callback.WaitForResult(); 985 EXPECT_EQ(OK, rv); 986 987 const HttpResponseInfo* response = trans->GetResponseInfo(); 988 ASSERT_TRUE(response != NULL); 989 990 EXPECT_TRUE(response->headers.get() != NULL); 991 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 992 993 std::string response_data; 994 rv = ReadTransaction(trans.get(), &response_data); 995 EXPECT_EQ(OK, rv); 996 EXPECT_EQ(kExpectedResponseData[i], response_data); 997 } 998} 999 1000TEST_P(HttpNetworkTransactionTest, Ignores100) { 1001 ScopedVector<UploadElementReader> element_readers; 1002 element_readers.push_back(new UploadBytesElementReader("foo", 3)); 1003 UploadDataStream upload_data_stream(&element_readers, 0); 1004 1005 HttpRequestInfo request; 1006 request.method = "POST"; 1007 request.url = GURL("http://www.foo.com/"); 1008 request.upload_data_stream = &upload_data_stream; 1009 request.load_flags = 0; 1010 1011 scoped_ptr<HttpTransaction> trans( 1012 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1013 CreateSession(&session_deps_))); 1014 1015 MockRead data_reads[] = { 1016 MockRead("HTTP/1.0 100 Continue\r\n\r\n"), 1017 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 1018 MockRead("hello world"), 1019 MockRead(SYNCHRONOUS, OK), 1020 }; 1021 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1022 session_deps_.socket_factory->AddSocketDataProvider(&data); 1023 1024 TestCompletionCallback callback; 1025 1026 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1027 EXPECT_EQ(ERR_IO_PENDING, rv); 1028 1029 rv = callback.WaitForResult(); 1030 EXPECT_EQ(OK, rv); 1031 1032 const HttpResponseInfo* response = trans->GetResponseInfo(); 1033 ASSERT_TRUE(response != NULL); 1034 1035 EXPECT_TRUE(response->headers.get() != NULL); 1036 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 1037 1038 std::string response_data; 1039 rv = ReadTransaction(trans.get(), &response_data); 1040 EXPECT_EQ(OK, rv); 1041 EXPECT_EQ("hello world", response_data); 1042} 1043 1044// This test is almost the same as Ignores100 above, but the response contains 1045// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is 1046// HTTP/1.1 and the two status headers are read in one read. 1047TEST_P(HttpNetworkTransactionTest, Ignores1xx) { 1048 HttpRequestInfo request; 1049 request.method = "GET"; 1050 request.url = GURL("http://www.foo.com/"); 1051 request.load_flags = 0; 1052 1053 scoped_ptr<HttpTransaction> trans( 1054 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1055 CreateSession(&session_deps_))); 1056 1057 MockRead data_reads[] = { 1058 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n" 1059 "HTTP/1.1 200 OK\r\n\r\n"), 1060 MockRead("hello world"), 1061 MockRead(SYNCHRONOUS, OK), 1062 }; 1063 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1064 session_deps_.socket_factory->AddSocketDataProvider(&data); 1065 1066 TestCompletionCallback callback; 1067 1068 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1069 EXPECT_EQ(ERR_IO_PENDING, rv); 1070 1071 rv = callback.WaitForResult(); 1072 EXPECT_EQ(OK, rv); 1073 1074 const HttpResponseInfo* response = trans->GetResponseInfo(); 1075 ASSERT_TRUE(response != NULL); 1076 1077 EXPECT_TRUE(response->headers.get() != NULL); 1078 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1079 1080 std::string response_data; 1081 rv = ReadTransaction(trans.get(), &response_data); 1082 EXPECT_EQ(OK, rv); 1083 EXPECT_EQ("hello world", response_data); 1084} 1085 1086TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) { 1087 HttpRequestInfo request; 1088 request.method = "POST"; 1089 request.url = GURL("http://www.foo.com/"); 1090 request.load_flags = 0; 1091 1092 scoped_ptr<HttpTransaction> trans( 1093 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1094 CreateSession(&session_deps_))); 1095 1096 MockRead data_reads[] = { 1097 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"), 1098 MockRead(ASYNC, 0), 1099 }; 1100 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1101 session_deps_.socket_factory->AddSocketDataProvider(&data); 1102 1103 TestCompletionCallback callback; 1104 1105 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1106 EXPECT_EQ(ERR_IO_PENDING, rv); 1107 1108 rv = callback.WaitForResult(); 1109 EXPECT_EQ(OK, rv); 1110 1111 std::string response_data; 1112 rv = ReadTransaction(trans.get(), &response_data); 1113 EXPECT_EQ(OK, rv); 1114 EXPECT_EQ("", response_data); 1115} 1116 1117TEST_P(HttpNetworkTransactionTest, EmptyResponse) { 1118 HttpRequestInfo request; 1119 request.method = "POST"; 1120 request.url = GURL("http://www.foo.com/"); 1121 request.load_flags = 0; 1122 1123 scoped_ptr<HttpTransaction> trans( 1124 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1125 CreateSession(&session_deps_))); 1126 1127 MockRead data_reads[] = { 1128 MockRead(ASYNC, 0), 1129 }; 1130 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1131 session_deps_.socket_factory->AddSocketDataProvider(&data); 1132 1133 TestCompletionCallback callback; 1134 1135 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1136 EXPECT_EQ(ERR_IO_PENDING, rv); 1137 1138 rv = callback.WaitForResult(); 1139 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 1140} 1141 1142void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest( 1143 const MockWrite* write_failure, 1144 const MockRead* read_failure) { 1145 HttpRequestInfo request; 1146 request.method = "GET"; 1147 request.url = GURL("http://www.foo.com/"); 1148 request.load_flags = 0; 1149 1150 CapturingNetLog net_log; 1151 session_deps_.net_log = &net_log; 1152 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1153 1154 // Written data for successfully sending both requests. 1155 MockWrite data1_writes[] = { 1156 MockWrite("GET / HTTP/1.1\r\n" 1157 "Host: www.foo.com\r\n" 1158 "Connection: keep-alive\r\n\r\n"), 1159 MockWrite("GET / HTTP/1.1\r\n" 1160 "Host: www.foo.com\r\n" 1161 "Connection: keep-alive\r\n\r\n") 1162 }; 1163 1164 // Read results for the first request. 1165 MockRead data1_reads[] = { 1166 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1167 MockRead("hello"), 1168 MockRead(ASYNC, OK), 1169 }; 1170 1171 if (write_failure) { 1172 ASSERT_TRUE(!read_failure); 1173 data1_writes[1] = *write_failure; 1174 } else { 1175 ASSERT_TRUE(read_failure); 1176 data1_reads[2] = *read_failure; 1177 } 1178 1179 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), 1180 data1_writes, arraysize(data1_writes)); 1181 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1182 1183 MockRead data2_reads[] = { 1184 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1185 MockRead("world"), 1186 MockRead(ASYNC, OK), 1187 }; 1188 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 1189 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1190 1191 const char* kExpectedResponseData[] = { 1192 "hello", "world" 1193 }; 1194 1195 uint32 first_socket_log_id = NetLog::Source::kInvalidId; 1196 for (int i = 0; i < 2; ++i) { 1197 TestCompletionCallback callback; 1198 1199 scoped_ptr<HttpTransaction> trans( 1200 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1201 1202 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1203 EXPECT_EQ(ERR_IO_PENDING, rv); 1204 1205 rv = callback.WaitForResult(); 1206 EXPECT_EQ(OK, rv); 1207 1208 LoadTimingInfo load_timing_info; 1209 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1210 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 1211 if (i == 0) { 1212 first_socket_log_id = load_timing_info.socket_log_id; 1213 } else { 1214 // The second request should be using a new socket. 1215 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id); 1216 } 1217 1218 const HttpResponseInfo* response = trans->GetResponseInfo(); 1219 ASSERT_TRUE(response != NULL); 1220 1221 EXPECT_TRUE(response->headers.get() != NULL); 1222 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1223 1224 std::string response_data; 1225 rv = ReadTransaction(trans.get(), &response_data); 1226 EXPECT_EQ(OK, rv); 1227 EXPECT_EQ(kExpectedResponseData[i], response_data); 1228 } 1229} 1230 1231TEST_P(HttpNetworkTransactionTest, 1232 KeepAliveConnectionNotConnectedOnWrite) { 1233 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED); 1234 KeepAliveConnectionResendRequestTest(&write_failure, NULL); 1235} 1236 1237TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) { 1238 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET); 1239 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1240} 1241 1242TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) { 1243 MockRead read_failure(SYNCHRONOUS, OK); // EOF 1244 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1245} 1246 1247TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) { 1248 HttpRequestInfo request; 1249 request.method = "GET"; 1250 request.url = GURL("http://www.google.com/"); 1251 request.load_flags = 0; 1252 1253 scoped_ptr<HttpTransaction> trans( 1254 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1255 CreateSession(&session_deps_))); 1256 1257 MockRead data_reads[] = { 1258 MockRead(ASYNC, ERR_CONNECTION_RESET), 1259 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 1260 MockRead("hello world"), 1261 MockRead(SYNCHRONOUS, OK), 1262 }; 1263 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1264 session_deps_.socket_factory->AddSocketDataProvider(&data); 1265 1266 TestCompletionCallback callback; 1267 1268 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1269 EXPECT_EQ(ERR_IO_PENDING, rv); 1270 1271 rv = callback.WaitForResult(); 1272 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 1273 1274 const HttpResponseInfo* response = trans->GetResponseInfo(); 1275 EXPECT_TRUE(response == NULL); 1276} 1277 1278// What do various browsers do when the server closes a non-keepalive 1279// connection without sending any response header or body? 1280// 1281// IE7: error page 1282// Safari 3.1.2 (Windows): error page 1283// Firefox 3.0.1: blank page 1284// Opera 9.52: after five attempts, blank page 1285// Us with WinHTTP: error page (ERR_INVALID_RESPONSE) 1286// Us: error page (EMPTY_RESPONSE) 1287TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) { 1288 MockRead data_reads[] = { 1289 MockRead(SYNCHRONOUS, OK), // EOF 1290 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 1291 MockRead("hello world"), 1292 MockRead(SYNCHRONOUS, OK), 1293 }; 1294 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 1295 arraysize(data_reads)); 1296 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv); 1297} 1298 1299// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression 1300// tests. There was a bug causing HttpNetworkTransaction to hang in the 1301// destructor in such situations. 1302// See http://crbug.com/154712 and http://crbug.com/156609. 1303TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) { 1304 HttpRequestInfo request; 1305 request.method = "GET"; 1306 request.url = GURL("http://www.google.com/"); 1307 request.load_flags = 0; 1308 1309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1310 scoped_ptr<HttpTransaction> trans( 1311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1312 1313 MockRead data_reads[] = { 1314 MockRead("HTTP/1.0 200 OK\r\n"), 1315 MockRead("Connection: keep-alive\r\n"), 1316 MockRead("Content-Length: 100\r\n\r\n"), 1317 MockRead("hello"), 1318 MockRead(SYNCHRONOUS, 0), 1319 }; 1320 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1321 session_deps_.socket_factory->AddSocketDataProvider(&data); 1322 1323 TestCompletionCallback callback; 1324 1325 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1326 EXPECT_EQ(ERR_IO_PENDING, rv); 1327 1328 rv = callback.WaitForResult(); 1329 EXPECT_EQ(OK, rv); 1330 1331 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1332 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1333 if (rv == ERR_IO_PENDING) 1334 rv = callback.WaitForResult(); 1335 EXPECT_EQ(5, rv); 1336 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1337 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 1338 1339 trans.reset(); 1340 base::MessageLoop::current()->RunUntilIdle(); 1341 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 1342} 1343 1344TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) { 1345 HttpRequestInfo request; 1346 request.method = "GET"; 1347 request.url = GURL("http://www.google.com/"); 1348 request.load_flags = 0; 1349 1350 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1351 scoped_ptr<HttpTransaction> trans( 1352 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1353 1354 MockRead data_reads[] = { 1355 MockRead("HTTP/1.0 200 OK\r\n"), 1356 MockRead("Connection: keep-alive\r\n"), 1357 MockRead("Content-Length: 100\r\n\r\n"), 1358 MockRead(SYNCHRONOUS, 0), 1359 }; 1360 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1361 session_deps_.socket_factory->AddSocketDataProvider(&data); 1362 1363 TestCompletionCallback callback; 1364 1365 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1366 EXPECT_EQ(ERR_IO_PENDING, rv); 1367 1368 rv = callback.WaitForResult(); 1369 EXPECT_EQ(OK, rv); 1370 1371 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1372 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1373 if (rv == ERR_IO_PENDING) 1374 rv = callback.WaitForResult(); 1375 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 1376 1377 trans.reset(); 1378 base::MessageLoop::current()->RunUntilIdle(); 1379 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 1380} 1381 1382// Test that we correctly reuse a keep-alive connection after not explicitly 1383// reading the body. 1384TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { 1385 HttpRequestInfo request; 1386 request.method = "GET"; 1387 request.url = GURL("http://www.foo.com/"); 1388 request.load_flags = 0; 1389 1390 CapturingNetLog net_log; 1391 session_deps_.net_log = &net_log; 1392 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1393 1394 // Note that because all these reads happen in the same 1395 // StaticSocketDataProvider, it shows that the same socket is being reused for 1396 // all transactions. 1397 MockRead data1_reads[] = { 1398 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 1399 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"), 1400 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"), 1401 MockRead("HTTP/1.1 302 Found\r\n" 1402 "Content-Length: 0\r\n\r\n"), 1403 MockRead("HTTP/1.1 302 Found\r\n" 1404 "Content-Length: 5\r\n\r\n" 1405 "hello"), 1406 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 1407 "Content-Length: 0\r\n\r\n"), 1408 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 1409 "Content-Length: 5\r\n\r\n" 1410 "hello"), 1411 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1412 MockRead("hello"), 1413 }; 1414 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0); 1415 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1416 1417 MockRead data2_reads[] = { 1418 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 1419 }; 1420 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 1421 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1422 1423 const int kNumUnreadBodies = arraysize(data1_reads) - 2; 1424 std::string response_lines[kNumUnreadBodies]; 1425 1426 uint32 first_socket_log_id = NetLog::Source::kInvalidId; 1427 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) { 1428 TestCompletionCallback callback; 1429 1430 scoped_ptr<HttpTransaction> trans( 1431 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1432 1433 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1434 EXPECT_EQ(ERR_IO_PENDING, rv); 1435 1436 rv = callback.WaitForResult(); 1437 EXPECT_EQ(OK, rv); 1438 1439 LoadTimingInfo load_timing_info; 1440 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1441 if (i == 0) { 1442 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 1443 first_socket_log_id = load_timing_info.socket_log_id; 1444 } else { 1445 TestLoadTimingReused(load_timing_info); 1446 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id); 1447 } 1448 1449 const HttpResponseInfo* response = trans->GetResponseInfo(); 1450 ASSERT_TRUE(response != NULL); 1451 1452 ASSERT_TRUE(response->headers.get() != NULL); 1453 response_lines[i] = response->headers->GetStatusLine(); 1454 1455 // We intentionally don't read the response bodies. 1456 } 1457 1458 const char* const kStatusLines[] = { 1459 "HTTP/1.1 204 No Content", 1460 "HTTP/1.1 205 Reset Content", 1461 "HTTP/1.1 304 Not Modified", 1462 "HTTP/1.1 302 Found", 1463 "HTTP/1.1 302 Found", 1464 "HTTP/1.1 301 Moved Permanently", 1465 "HTTP/1.1 301 Moved Permanently", 1466 }; 1467 1468 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines), 1469 forgot_to_update_kStatusLines); 1470 1471 for (int i = 0; i < kNumUnreadBodies; ++i) 1472 EXPECT_EQ(kStatusLines[i], response_lines[i]); 1473 1474 TestCompletionCallback callback; 1475 scoped_ptr<HttpTransaction> trans( 1476 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1477 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1478 EXPECT_EQ(ERR_IO_PENDING, rv); 1479 rv = callback.WaitForResult(); 1480 EXPECT_EQ(OK, rv); 1481 const HttpResponseInfo* response = trans->GetResponseInfo(); 1482 ASSERT_TRUE(response != NULL); 1483 ASSERT_TRUE(response->headers.get() != NULL); 1484 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1485 std::string response_data; 1486 rv = ReadTransaction(trans.get(), &response_data); 1487 EXPECT_EQ(OK, rv); 1488 EXPECT_EQ("hello", response_data); 1489} 1490 1491// Test the request-challenge-retry sequence for basic auth. 1492// (basic auth is the easiest to mock, because it has no randomness). 1493TEST_P(HttpNetworkTransactionTest, BasicAuth) { 1494 HttpRequestInfo request; 1495 request.method = "GET"; 1496 request.url = GURL("http://www.google.com/"); 1497 request.load_flags = 0; 1498 1499 CapturingNetLog log; 1500 session_deps_.net_log = &log; 1501 scoped_ptr<HttpTransaction> trans( 1502 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1503 CreateSession(&session_deps_))); 1504 1505 MockWrite data_writes1[] = { 1506 MockWrite("GET / HTTP/1.1\r\n" 1507 "Host: www.google.com\r\n" 1508 "Connection: keep-alive\r\n\r\n"), 1509 }; 1510 1511 MockRead data_reads1[] = { 1512 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1513 // Give a couple authenticate options (only the middle one is actually 1514 // supported). 1515 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed. 1516 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1517 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 1518 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1519 // Large content-length -- won't matter, as connection will be reset. 1520 MockRead("Content-Length: 10000\r\n\r\n"), 1521 MockRead(SYNCHRONOUS, ERR_FAILED), 1522 }; 1523 1524 // After calling trans->RestartWithAuth(), this is the request we should 1525 // be issuing -- the final header line contains the credentials. 1526 MockWrite data_writes2[] = { 1527 MockWrite("GET / HTTP/1.1\r\n" 1528 "Host: www.google.com\r\n" 1529 "Connection: keep-alive\r\n" 1530 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1531 }; 1532 1533 // Lastly, the server responds with the actual content. 1534 MockRead data_reads2[] = { 1535 MockRead("HTTP/1.0 200 OK\r\n"), 1536 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1537 MockRead("Content-Length: 100\r\n\r\n"), 1538 MockRead(SYNCHRONOUS, OK), 1539 }; 1540 1541 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1542 data_writes1, arraysize(data_writes1)); 1543 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1544 data_writes2, arraysize(data_writes2)); 1545 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1546 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1547 1548 TestCompletionCallback callback1; 1549 1550 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1551 EXPECT_EQ(ERR_IO_PENDING, rv); 1552 1553 rv = callback1.WaitForResult(); 1554 EXPECT_EQ(OK, rv); 1555 1556 LoadTimingInfo load_timing_info1; 1557 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); 1558 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); 1559 1560 const HttpResponseInfo* response = trans->GetResponseInfo(); 1561 ASSERT_TRUE(response != NULL); 1562 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1563 1564 TestCompletionCallback callback2; 1565 1566 rv = trans->RestartWithAuth( 1567 AuthCredentials(kFoo, kBar), callback2.callback()); 1568 EXPECT_EQ(ERR_IO_PENDING, rv); 1569 1570 rv = callback2.WaitForResult(); 1571 EXPECT_EQ(OK, rv); 1572 1573 LoadTimingInfo load_timing_info2; 1574 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); 1575 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES); 1576 // The load timing after restart should have a new socket ID, and times after 1577 // those of the first load timing. 1578 EXPECT_LE(load_timing_info1.receive_headers_end, 1579 load_timing_info2.connect_timing.connect_start); 1580 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 1581 1582 response = trans->GetResponseInfo(); 1583 ASSERT_TRUE(response != NULL); 1584 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1585 EXPECT_EQ(100, response->headers->GetContentLength()); 1586} 1587 1588TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { 1589 HttpRequestInfo request; 1590 request.method = "GET"; 1591 request.url = GURL("http://www.google.com/"); 1592 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1593 1594 scoped_ptr<HttpTransaction> trans( 1595 new HttpNetworkTransaction(DEFAULT_PRIORITY, 1596 CreateSession(&session_deps_))); 1597 1598 MockWrite data_writes[] = { 1599 MockWrite("GET / HTTP/1.1\r\n" 1600 "Host: www.google.com\r\n" 1601 "Connection: keep-alive\r\n\r\n"), 1602 }; 1603 1604 MockRead data_reads[] = { 1605 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1606 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1607 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1608 // Large content-length -- won't matter, as connection will be reset. 1609 MockRead("Content-Length: 10000\r\n\r\n"), 1610 MockRead(SYNCHRONOUS, ERR_FAILED), 1611 }; 1612 1613 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 1614 data_writes, arraysize(data_writes)); 1615 session_deps_.socket_factory->AddSocketDataProvider(&data); 1616 TestCompletionCallback callback; 1617 1618 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1619 EXPECT_EQ(ERR_IO_PENDING, rv); 1620 1621 rv = callback.WaitForResult(); 1622 EXPECT_EQ(0, rv); 1623 1624 const HttpResponseInfo* response = trans->GetResponseInfo(); 1625 ASSERT_TRUE(response != NULL); 1626 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1627} 1628 1629// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1630// connection. 1631TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) { 1632 HttpRequestInfo request; 1633 request.method = "GET"; 1634 request.url = GURL("http://www.google.com/"); 1635 request.load_flags = 0; 1636 1637 CapturingNetLog log; 1638 session_deps_.net_log = &log; 1639 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1640 1641 MockWrite data_writes1[] = { 1642 MockWrite("GET / HTTP/1.1\r\n" 1643 "Host: www.google.com\r\n" 1644 "Connection: keep-alive\r\n\r\n"), 1645 1646 // After calling trans->RestartWithAuth(), this is the request we should 1647 // be issuing -- the final header line contains the credentials. 1648 MockWrite("GET / HTTP/1.1\r\n" 1649 "Host: www.google.com\r\n" 1650 "Connection: keep-alive\r\n" 1651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1652 }; 1653 1654 MockRead data_reads1[] = { 1655 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1656 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1657 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1658 MockRead("Content-Length: 14\r\n\r\n"), 1659 MockRead("Unauthorized\r\n"), 1660 1661 // Lastly, the server responds with the actual content. 1662 MockRead("HTTP/1.1 200 OK\r\n"), 1663 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1664 MockRead("Content-Length: 5\r\n\r\n"), 1665 MockRead("Hello"), 1666 }; 1667 1668 // If there is a regression where we disconnect a Keep-Alive 1669 // connection during an auth roundtrip, we'll end up reading this. 1670 MockRead data_reads2[] = { 1671 MockRead(SYNCHRONOUS, ERR_FAILED), 1672 }; 1673 1674 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1675 data_writes1, arraysize(data_writes1)); 1676 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1677 NULL, 0); 1678 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1679 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1680 1681 TestCompletionCallback callback1; 1682 1683 scoped_ptr<HttpTransaction> trans( 1684 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1685 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1686 EXPECT_EQ(ERR_IO_PENDING, rv); 1687 1688 rv = callback1.WaitForResult(); 1689 EXPECT_EQ(OK, rv); 1690 1691 LoadTimingInfo load_timing_info1; 1692 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); 1693 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); 1694 1695 const HttpResponseInfo* response = trans->GetResponseInfo(); 1696 ASSERT_TRUE(response != NULL); 1697 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1698 1699 TestCompletionCallback callback2; 1700 1701 rv = trans->RestartWithAuth( 1702 AuthCredentials(kFoo, kBar), callback2.callback()); 1703 EXPECT_EQ(ERR_IO_PENDING, rv); 1704 1705 rv = callback2.WaitForResult(); 1706 EXPECT_EQ(OK, rv); 1707 1708 LoadTimingInfo load_timing_info2; 1709 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); 1710 TestLoadTimingReused(load_timing_info2); 1711 // The load timing after restart should have the same socket ID, and times 1712 // those of the first load timing. 1713 EXPECT_LE(load_timing_info1.receive_headers_end, 1714 load_timing_info2.send_start); 1715 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 1716 1717 response = trans->GetResponseInfo(); 1718 ASSERT_TRUE(response != NULL); 1719 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1720 EXPECT_EQ(5, response->headers->GetContentLength()); 1721} 1722 1723// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1724// connection and with no response body to drain. 1725TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) { 1726 HttpRequestInfo request; 1727 request.method = "GET"; 1728 request.url = GURL("http://www.google.com/"); 1729 request.load_flags = 0; 1730 1731 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1732 1733 MockWrite data_writes1[] = { 1734 MockWrite("GET / HTTP/1.1\r\n" 1735 "Host: www.google.com\r\n" 1736 "Connection: keep-alive\r\n\r\n"), 1737 1738 // After calling trans->RestartWithAuth(), this is the request we should 1739 // be issuing -- the final header line contains the credentials. 1740 MockWrite("GET / HTTP/1.1\r\n" 1741 "Host: www.google.com\r\n" 1742 "Connection: keep-alive\r\n" 1743 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1744 }; 1745 1746 MockRead data_reads1[] = { 1747 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1748 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1749 MockRead("Content-Length: 0\r\n\r\n"), // No response body. 1750 1751 // Lastly, the server responds with the actual content. 1752 MockRead("HTTP/1.1 200 OK\r\n"), 1753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1754 MockRead("Content-Length: 5\r\n\r\n"), 1755 MockRead("hello"), 1756 }; 1757 1758 // An incorrect reconnect would cause this to be read. 1759 MockRead data_reads2[] = { 1760 MockRead(SYNCHRONOUS, ERR_FAILED), 1761 }; 1762 1763 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1764 data_writes1, arraysize(data_writes1)); 1765 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1766 NULL, 0); 1767 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1768 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1769 1770 TestCompletionCallback callback1; 1771 1772 scoped_ptr<HttpTransaction> trans( 1773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1774 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1775 EXPECT_EQ(ERR_IO_PENDING, rv); 1776 1777 rv = callback1.WaitForResult(); 1778 EXPECT_EQ(OK, rv); 1779 1780 const HttpResponseInfo* response = trans->GetResponseInfo(); 1781 ASSERT_TRUE(response != NULL); 1782 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1783 1784 TestCompletionCallback callback2; 1785 1786 rv = trans->RestartWithAuth( 1787 AuthCredentials(kFoo, kBar), callback2.callback()); 1788 EXPECT_EQ(ERR_IO_PENDING, rv); 1789 1790 rv = callback2.WaitForResult(); 1791 EXPECT_EQ(OK, rv); 1792 1793 response = trans->GetResponseInfo(); 1794 ASSERT_TRUE(response != NULL); 1795 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1796 EXPECT_EQ(5, response->headers->GetContentLength()); 1797} 1798 1799// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1800// connection and with a large response body to drain. 1801TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) { 1802 HttpRequestInfo request; 1803 request.method = "GET"; 1804 request.url = GURL("http://www.google.com/"); 1805 request.load_flags = 0; 1806 1807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1808 1809 MockWrite data_writes1[] = { 1810 MockWrite("GET / HTTP/1.1\r\n" 1811 "Host: www.google.com\r\n" 1812 "Connection: keep-alive\r\n\r\n"), 1813 1814 // After calling trans->RestartWithAuth(), this is the request we should 1815 // be issuing -- the final header line contains the credentials. 1816 MockWrite("GET / HTTP/1.1\r\n" 1817 "Host: www.google.com\r\n" 1818 "Connection: keep-alive\r\n" 1819 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1820 }; 1821 1822 // Respond with 5 kb of response body. 1823 std::string large_body_string("Unauthorized"); 1824 large_body_string.append(5 * 1024, ' '); 1825 large_body_string.append("\r\n"); 1826 1827 MockRead data_reads1[] = { 1828 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1829 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1830 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1831 // 5134 = 12 + 5 * 1024 + 2 1832 MockRead("Content-Length: 5134\r\n\r\n"), 1833 MockRead(ASYNC, large_body_string.data(), large_body_string.size()), 1834 1835 // Lastly, the server responds with the actual content. 1836 MockRead("HTTP/1.1 200 OK\r\n"), 1837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1838 MockRead("Content-Length: 5\r\n\r\n"), 1839 MockRead("hello"), 1840 }; 1841 1842 // An incorrect reconnect would cause this to be read. 1843 MockRead data_reads2[] = { 1844 MockRead(SYNCHRONOUS, ERR_FAILED), 1845 }; 1846 1847 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1848 data_writes1, arraysize(data_writes1)); 1849 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1850 NULL, 0); 1851 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1852 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1853 1854 TestCompletionCallback callback1; 1855 1856 scoped_ptr<HttpTransaction> trans( 1857 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1858 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1859 EXPECT_EQ(ERR_IO_PENDING, rv); 1860 1861 rv = callback1.WaitForResult(); 1862 EXPECT_EQ(OK, rv); 1863 1864 const HttpResponseInfo* response = trans->GetResponseInfo(); 1865 ASSERT_TRUE(response != NULL); 1866 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1867 1868 TestCompletionCallback callback2; 1869 1870 rv = trans->RestartWithAuth( 1871 AuthCredentials(kFoo, kBar), callback2.callback()); 1872 EXPECT_EQ(ERR_IO_PENDING, rv); 1873 1874 rv = callback2.WaitForResult(); 1875 EXPECT_EQ(OK, rv); 1876 1877 response = trans->GetResponseInfo(); 1878 ASSERT_TRUE(response != NULL); 1879 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1880 EXPECT_EQ(5, response->headers->GetContentLength()); 1881} 1882 1883// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1884// connection, but the server gets impatient and closes the connection. 1885TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) { 1886 HttpRequestInfo request; 1887 request.method = "GET"; 1888 request.url = GURL("http://www.google.com/"); 1889 request.load_flags = 0; 1890 1891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1892 1893 MockWrite data_writes1[] = { 1894 MockWrite("GET / HTTP/1.1\r\n" 1895 "Host: www.google.com\r\n" 1896 "Connection: keep-alive\r\n\r\n"), 1897 // This simulates the seemingly successful write to a closed connection 1898 // if the bug is not fixed. 1899 MockWrite("GET / HTTP/1.1\r\n" 1900 "Host: www.google.com\r\n" 1901 "Connection: keep-alive\r\n" 1902 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1903 }; 1904 1905 MockRead data_reads1[] = { 1906 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1907 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1909 MockRead("Content-Length: 14\r\n\r\n"), 1910 // Tell MockTCPClientSocket to simulate the server closing the connection. 1911 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 1912 MockRead("Unauthorized\r\n"), 1913 MockRead(SYNCHRONOUS, OK), // The server closes the connection. 1914 }; 1915 1916 // After calling trans->RestartWithAuth(), this is the request we should 1917 // be issuing -- the final header line contains the credentials. 1918 MockWrite data_writes2[] = { 1919 MockWrite("GET / HTTP/1.1\r\n" 1920 "Host: www.google.com\r\n" 1921 "Connection: keep-alive\r\n" 1922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1923 }; 1924 1925 // Lastly, the server responds with the actual content. 1926 MockRead data_reads2[] = { 1927 MockRead("HTTP/1.1 200 OK\r\n"), 1928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1929 MockRead("Content-Length: 5\r\n\r\n"), 1930 MockRead("hello"), 1931 }; 1932 1933 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1934 data_writes1, arraysize(data_writes1)); 1935 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1936 data_writes2, arraysize(data_writes2)); 1937 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1938 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1939 1940 TestCompletionCallback callback1; 1941 1942 scoped_ptr<HttpTransaction> trans( 1943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1944 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1945 EXPECT_EQ(ERR_IO_PENDING, rv); 1946 1947 rv = callback1.WaitForResult(); 1948 EXPECT_EQ(OK, rv); 1949 1950 const HttpResponseInfo* response = trans->GetResponseInfo(); 1951 ASSERT_TRUE(response != NULL); 1952 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1953 1954 TestCompletionCallback callback2; 1955 1956 rv = trans->RestartWithAuth( 1957 AuthCredentials(kFoo, kBar), callback2.callback()); 1958 EXPECT_EQ(ERR_IO_PENDING, rv); 1959 1960 rv = callback2.WaitForResult(); 1961 EXPECT_EQ(OK, rv); 1962 1963 response = trans->GetResponseInfo(); 1964 ASSERT_TRUE(response != NULL); 1965 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1966 EXPECT_EQ(5, response->headers->GetContentLength()); 1967} 1968 1969// Test the request-challenge-retry sequence for basic auth, over a connection 1970// that requires a restart when setting up an SSL tunnel. 1971TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { 1972 HttpRequestInfo request; 1973 request.method = "GET"; 1974 request.url = GURL("https://www.google.com/"); 1975 // when the no authentication data flag is set. 1976 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1977 1978 // Configure against proxy server "myproxy:70". 1979 session_deps_.proxy_service.reset( 1980 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 1981 CapturingBoundNetLog log; 1982 session_deps_.net_log = log.bound().net_log(); 1983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1984 1985 // Since we have proxy, should try to establish tunnel. 1986 MockWrite data_writes1[] = { 1987 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1988 "Host: www.google.com\r\n" 1989 "Proxy-Connection: keep-alive\r\n\r\n"), 1990 1991 // After calling trans->RestartWithAuth(), this is the request we should 1992 // be issuing -- the final header line contains the credentials. 1993 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 1994 "Host: www.google.com\r\n" 1995 "Proxy-Connection: keep-alive\r\n" 1996 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1997 1998 MockWrite("GET / HTTP/1.1\r\n" 1999 "Host: www.google.com\r\n" 2000 "Connection: keep-alive\r\n\r\n"), 2001 }; 2002 2003 // The proxy responds to the connect with a 407, using a persistent 2004 // connection. 2005 MockRead data_reads1[] = { 2006 // No credentials. 2007 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2008 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2009 MockRead("Proxy-Connection: close\r\n\r\n"), 2010 2011 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2012 2013 MockRead("HTTP/1.1 200 OK\r\n"), 2014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2015 MockRead("Content-Length: 5\r\n\r\n"), 2016 MockRead(SYNCHRONOUS, "hello"), 2017 }; 2018 2019 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2020 data_writes1, arraysize(data_writes1)); 2021 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2022 SSLSocketDataProvider ssl(ASYNC, OK); 2023 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2024 2025 TestCompletionCallback callback1; 2026 2027 scoped_ptr<HttpTransaction> trans( 2028 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2029 2030 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2031 EXPECT_EQ(ERR_IO_PENDING, rv); 2032 2033 rv = callback1.WaitForResult(); 2034 EXPECT_EQ(OK, rv); 2035 net::CapturingNetLog::CapturedEntryList entries; 2036 log.GetEntries(&entries); 2037 size_t pos = ExpectLogContainsSomewhere( 2038 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2039 NetLog::PHASE_NONE); 2040 ExpectLogContainsSomewhere( 2041 entries, pos, 2042 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2043 NetLog::PHASE_NONE); 2044 2045 const HttpResponseInfo* response = trans->GetResponseInfo(); 2046 ASSERT_TRUE(response != NULL); 2047 ASSERT_FALSE(response->headers.get() == NULL); 2048 EXPECT_EQ(407, response->headers->response_code()); 2049 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2050 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2051 2052 LoadTimingInfo load_timing_info; 2053 // CONNECT requests and responses are handled at the connect job level, so 2054 // the transaction does not yet have a connection. 2055 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info)); 2056 2057 TestCompletionCallback callback2; 2058 2059 rv = trans->RestartWithAuth( 2060 AuthCredentials(kFoo, kBar), callback2.callback()); 2061 EXPECT_EQ(ERR_IO_PENDING, rv); 2062 2063 rv = callback2.WaitForResult(); 2064 EXPECT_EQ(OK, rv); 2065 2066 response = trans->GetResponseInfo(); 2067 ASSERT_TRUE(response != NULL); 2068 2069 EXPECT_TRUE(response->headers->IsKeepAlive()); 2070 EXPECT_EQ(200, response->headers->response_code()); 2071 EXPECT_EQ(5, response->headers->GetContentLength()); 2072 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2073 2074 // The password prompt info should not be set. 2075 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2076 2077 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2078 TestLoadTimingNotReusedWithPac(load_timing_info, 2079 CONNECT_TIMING_HAS_SSL_TIMES); 2080 2081 trans.reset(); 2082 session->CloseAllConnections(); 2083} 2084 2085// Test the request-challenge-retry sequence for basic auth, over a keep-alive 2086// proxy connection, when setting up an SSL tunnel. 2087TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { 2088 HttpRequestInfo request; 2089 request.method = "GET"; 2090 request.url = GURL("https://www.google.com/"); 2091 // Ensure that proxy authentication is attempted even 2092 // when the no authentication data flag is set. 2093 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 2094 2095 // Configure against proxy server "myproxy:70". 2096 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2097 CapturingBoundNetLog log; 2098 session_deps_.net_log = log.bound().net_log(); 2099 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2100 2101 scoped_ptr<HttpTransaction> trans( 2102 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2103 2104 // Since we have proxy, should try to establish tunnel. 2105 MockWrite data_writes1[] = { 2106 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2107 "Host: www.google.com\r\n" 2108 "Proxy-Connection: keep-alive\r\n\r\n"), 2109 2110 // After calling trans->RestartWithAuth(), this is the request we should 2111 // be issuing -- the final header line contains the credentials. 2112 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2113 "Host: www.google.com\r\n" 2114 "Proxy-Connection: keep-alive\r\n" 2115 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 2116 }; 2117 2118 // The proxy responds to the connect with a 407, using a persistent 2119 // connection. 2120 MockRead data_reads1[] = { 2121 // No credentials. 2122 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2123 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2124 MockRead("Content-Length: 10\r\n\r\n"), 2125 MockRead("0123456789"), 2126 2127 // Wrong credentials (wrong password). 2128 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2129 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2130 MockRead("Content-Length: 10\r\n\r\n"), 2131 // No response body because the test stops reading here. 2132 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 2133 }; 2134 2135 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2136 data_writes1, arraysize(data_writes1)); 2137 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2138 2139 TestCompletionCallback callback1; 2140 2141 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2142 EXPECT_EQ(ERR_IO_PENDING, rv); 2143 2144 rv = callback1.WaitForResult(); 2145 EXPECT_EQ(OK, rv); 2146 net::CapturingNetLog::CapturedEntryList entries; 2147 log.GetEntries(&entries); 2148 size_t pos = ExpectLogContainsSomewhere( 2149 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2150 NetLog::PHASE_NONE); 2151 ExpectLogContainsSomewhere( 2152 entries, pos, 2153 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2154 NetLog::PHASE_NONE); 2155 2156 const HttpResponseInfo* response = trans->GetResponseInfo(); 2157 ASSERT_TRUE(response != NULL); 2158 ASSERT_FALSE(response->headers.get() == NULL); 2159 EXPECT_TRUE(response->headers->IsKeepAlive()); 2160 EXPECT_EQ(407, response->headers->response_code()); 2161 EXPECT_EQ(10, response->headers->GetContentLength()); 2162 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2163 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2164 2165 TestCompletionCallback callback2; 2166 2167 // Wrong password (should be "bar"). 2168 rv = trans->RestartWithAuth( 2169 AuthCredentials(kFoo, kBaz), callback2.callback()); 2170 EXPECT_EQ(ERR_IO_PENDING, rv); 2171 2172 rv = callback2.WaitForResult(); 2173 EXPECT_EQ(OK, rv); 2174 2175 response = trans->GetResponseInfo(); 2176 ASSERT_TRUE(response != NULL); 2177 ASSERT_FALSE(response->headers.get() == NULL); 2178 EXPECT_TRUE(response->headers->IsKeepAlive()); 2179 EXPECT_EQ(407, response->headers->response_code()); 2180 EXPECT_EQ(10, response->headers->GetContentLength()); 2181 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2182 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2183 2184 // Flush the idle socket before the NetLog and HttpNetworkTransaction go 2185 // out of scope. 2186 session->CloseAllConnections(); 2187} 2188 2189// Test that we don't read the response body when we fail to establish a tunnel, 2190// even if the user cancels the proxy's auth attempt. 2191TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) { 2192 HttpRequestInfo request; 2193 request.method = "GET"; 2194 request.url = GURL("https://www.google.com/"); 2195 request.load_flags = 0; 2196 2197 // Configure against proxy server "myproxy:70". 2198 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2199 2200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2201 2202 scoped_ptr<HttpTransaction> trans( 2203 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2204 2205 // Since we have proxy, should try to establish tunnel. 2206 MockWrite data_writes[] = { 2207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2208 "Host: www.google.com\r\n" 2209 "Proxy-Connection: keep-alive\r\n\r\n"), 2210 }; 2211 2212 // The proxy responds to the connect with a 407. 2213 MockRead data_reads[] = { 2214 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2215 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2216 MockRead("Content-Length: 10\r\n\r\n"), 2217 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 2218 }; 2219 2220 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 2221 data_writes, arraysize(data_writes)); 2222 session_deps_.socket_factory->AddSocketDataProvider(&data); 2223 2224 TestCompletionCallback callback; 2225 2226 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 2227 EXPECT_EQ(ERR_IO_PENDING, rv); 2228 2229 rv = callback.WaitForResult(); 2230 EXPECT_EQ(OK, rv); 2231 2232 const HttpResponseInfo* response = trans->GetResponseInfo(); 2233 ASSERT_TRUE(response != NULL); 2234 2235 EXPECT_TRUE(response->headers->IsKeepAlive()); 2236 EXPECT_EQ(407, response->headers->response_code()); 2237 EXPECT_EQ(10, response->headers->GetContentLength()); 2238 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2239 2240 std::string response_data; 2241 rv = ReadTransaction(trans.get(), &response_data); 2242 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 2243 2244 // Flush the idle socket before the HttpNetworkTransaction goes out of scope. 2245 session->CloseAllConnections(); 2246} 2247 2248// Test when a server (non-proxy) returns a 407 (proxy-authenticate). 2249// The request should fail with ERR_UNEXPECTED_PROXY_AUTH. 2250TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) { 2251 HttpRequestInfo request; 2252 request.method = "GET"; 2253 request.url = GURL("http://www.google.com/"); 2254 request.load_flags = 0; 2255 2256 // We are using a DIRECT connection (i.e. no proxy) for this session. 2257 scoped_ptr<HttpTransaction> trans( 2258 new HttpNetworkTransaction(DEFAULT_PRIORITY, 2259 CreateSession(&session_deps_))); 2260 2261 MockWrite data_writes1[] = { 2262 MockWrite("GET / HTTP/1.1\r\n" 2263 "Host: www.google.com\r\n" 2264 "Connection: keep-alive\r\n\r\n"), 2265 }; 2266 2267 MockRead data_reads1[] = { 2268 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"), 2269 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2270 // Large content-length -- won't matter, as connection will be reset. 2271 MockRead("Content-Length: 10000\r\n\r\n"), 2272 MockRead(SYNCHRONOUS, ERR_FAILED), 2273 }; 2274 2275 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2276 data_writes1, arraysize(data_writes1)); 2277 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2278 2279 TestCompletionCallback callback; 2280 2281 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 2282 EXPECT_EQ(ERR_IO_PENDING, rv); 2283 2284 rv = callback.WaitForResult(); 2285 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 2286} 2287 2288// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication) 2289// through a non-authenticating proxy. The request should fail with 2290// ERR_UNEXPECTED_PROXY_AUTH. 2291// Note that it is impossible to detect if an HTTP server returns a 407 through 2292// a non-authenticating proxy - there is nothing to indicate whether the 2293// response came from the proxy or the server, so it is treated as if the proxy 2294// issued the challenge. 2295TEST_P(HttpNetworkTransactionTest, 2296 HttpsServerRequestsProxyAuthThroughProxy) { 2297 HttpRequestInfo request; 2298 request.method = "GET"; 2299 request.url = GURL("https://www.google.com/"); 2300 2301 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2302 CapturingBoundNetLog log; 2303 session_deps_.net_log = log.bound().net_log(); 2304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2305 2306 // Since we have proxy, should try to establish tunnel. 2307 MockWrite data_writes1[] = { 2308 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2309 "Host: www.google.com\r\n" 2310 "Proxy-Connection: keep-alive\r\n\r\n"), 2311 2312 MockWrite("GET / HTTP/1.1\r\n" 2313 "Host: www.google.com\r\n" 2314 "Connection: keep-alive\r\n\r\n"), 2315 }; 2316 2317 MockRead data_reads1[] = { 2318 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2319 2320 MockRead("HTTP/1.1 407 Unauthorized\r\n"), 2321 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2322 MockRead("\r\n"), 2323 MockRead(SYNCHRONOUS, OK), 2324 }; 2325 2326 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2327 data_writes1, arraysize(data_writes1)); 2328 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2329 SSLSocketDataProvider ssl(ASYNC, OK); 2330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2331 2332 TestCompletionCallback callback1; 2333 2334 scoped_ptr<HttpTransaction> trans( 2335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2336 2337 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2338 EXPECT_EQ(ERR_IO_PENDING, rv); 2339 2340 rv = callback1.WaitForResult(); 2341 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 2342 net::CapturingNetLog::CapturedEntryList entries; 2343 log.GetEntries(&entries); 2344 size_t pos = ExpectLogContainsSomewhere( 2345 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2346 NetLog::PHASE_NONE); 2347 ExpectLogContainsSomewhere( 2348 entries, pos, 2349 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2350 NetLog::PHASE_NONE); 2351} 2352 2353// Test the load timing for HTTPS requests with an HTTP proxy. 2354TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) { 2355 HttpRequestInfo request1; 2356 request1.method = "GET"; 2357 request1.url = GURL("https://www.google.com/1"); 2358 2359 HttpRequestInfo request2; 2360 request2.method = "GET"; 2361 request2.url = GURL("https://www.google.com/2"); 2362 2363 // Configure against proxy server "myproxy:70". 2364 session_deps_.proxy_service.reset( 2365 ProxyService::CreateFixed("PROXY myproxy:70")); 2366 CapturingBoundNetLog log; 2367 session_deps_.net_log = log.bound().net_log(); 2368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2369 2370 // Since we have proxy, should try to establish tunnel. 2371 MockWrite data_writes1[] = { 2372 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2373 "Host: www.google.com\r\n" 2374 "Proxy-Connection: keep-alive\r\n\r\n"), 2375 2376 MockWrite("GET /1 HTTP/1.1\r\n" 2377 "Host: www.google.com\r\n" 2378 "Connection: keep-alive\r\n\r\n"), 2379 2380 MockWrite("GET /2 HTTP/1.1\r\n" 2381 "Host: www.google.com\r\n" 2382 "Connection: keep-alive\r\n\r\n"), 2383 }; 2384 2385 // The proxy responds to the connect with a 407, using a persistent 2386 // connection. 2387 MockRead data_reads1[] = { 2388 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2389 2390 MockRead("HTTP/1.1 200 OK\r\n"), 2391 MockRead("Content-Length: 1\r\n\r\n"), 2392 MockRead(SYNCHRONOUS, "1"), 2393 2394 MockRead("HTTP/1.1 200 OK\r\n"), 2395 MockRead("Content-Length: 2\r\n\r\n"), 2396 MockRead(SYNCHRONOUS, "22"), 2397 }; 2398 2399 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2400 data_writes1, arraysize(data_writes1)); 2401 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2402 SSLSocketDataProvider ssl(ASYNC, OK); 2403 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2404 2405 TestCompletionCallback callback1; 2406 scoped_ptr<HttpTransaction> trans1( 2407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2408 2409 int rv = trans1->Start(&request1, callback1.callback(), log.bound()); 2410 EXPECT_EQ(ERR_IO_PENDING, rv); 2411 2412 rv = callback1.WaitForResult(); 2413 EXPECT_EQ(OK, rv); 2414 2415 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 2416 ASSERT_TRUE(response1 != NULL); 2417 ASSERT_TRUE(response1->headers.get() != NULL); 2418 EXPECT_EQ(1, response1->headers->GetContentLength()); 2419 2420 LoadTimingInfo load_timing_info1; 2421 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1)); 2422 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES); 2423 2424 trans1.reset(); 2425 2426 TestCompletionCallback callback2; 2427 scoped_ptr<HttpTransaction> trans2( 2428 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2429 2430 rv = trans2->Start(&request2, callback2.callback(), log.bound()); 2431 EXPECT_EQ(ERR_IO_PENDING, rv); 2432 2433 rv = callback2.WaitForResult(); 2434 EXPECT_EQ(OK, rv); 2435 2436 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 2437 ASSERT_TRUE(response2 != NULL); 2438 ASSERT_TRUE(response2->headers.get() != NULL); 2439 EXPECT_EQ(2, response2->headers->GetContentLength()); 2440 2441 LoadTimingInfo load_timing_info2; 2442 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 2443 TestLoadTimingReused(load_timing_info2); 2444 2445 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2446 2447 trans2.reset(); 2448 session->CloseAllConnections(); 2449} 2450 2451// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script. 2452TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) { 2453 HttpRequestInfo request1; 2454 request1.method = "GET"; 2455 request1.url = GURL("https://www.google.com/1"); 2456 2457 HttpRequestInfo request2; 2458 request2.method = "GET"; 2459 request2.url = GURL("https://www.google.com/2"); 2460 2461 // Configure against proxy server "myproxy:70". 2462 session_deps_.proxy_service.reset( 2463 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 2464 CapturingBoundNetLog log; 2465 session_deps_.net_log = log.bound().net_log(); 2466 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2467 2468 // Since we have proxy, should try to establish tunnel. 2469 MockWrite data_writes1[] = { 2470 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2471 "Host: www.google.com\r\n" 2472 "Proxy-Connection: keep-alive\r\n\r\n"), 2473 2474 MockWrite("GET /1 HTTP/1.1\r\n" 2475 "Host: www.google.com\r\n" 2476 "Connection: keep-alive\r\n\r\n"), 2477 2478 MockWrite("GET /2 HTTP/1.1\r\n" 2479 "Host: www.google.com\r\n" 2480 "Connection: keep-alive\r\n\r\n"), 2481 }; 2482 2483 // The proxy responds to the connect with a 407, using a persistent 2484 // connection. 2485 MockRead data_reads1[] = { 2486 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2487 2488 MockRead("HTTP/1.1 200 OK\r\n"), 2489 MockRead("Content-Length: 1\r\n\r\n"), 2490 MockRead(SYNCHRONOUS, "1"), 2491 2492 MockRead("HTTP/1.1 200 OK\r\n"), 2493 MockRead("Content-Length: 2\r\n\r\n"), 2494 MockRead(SYNCHRONOUS, "22"), 2495 }; 2496 2497 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2498 data_writes1, arraysize(data_writes1)); 2499 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2500 SSLSocketDataProvider ssl(ASYNC, OK); 2501 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2502 2503 TestCompletionCallback callback1; 2504 scoped_ptr<HttpTransaction> trans1( 2505 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2506 2507 int rv = trans1->Start(&request1, callback1.callback(), log.bound()); 2508 EXPECT_EQ(ERR_IO_PENDING, rv); 2509 2510 rv = callback1.WaitForResult(); 2511 EXPECT_EQ(OK, rv); 2512 2513 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 2514 ASSERT_TRUE(response1 != NULL); 2515 ASSERT_TRUE(response1->headers.get() != NULL); 2516 EXPECT_EQ(1, response1->headers->GetContentLength()); 2517 2518 LoadTimingInfo load_timing_info1; 2519 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1)); 2520 TestLoadTimingNotReusedWithPac(load_timing_info1, 2521 CONNECT_TIMING_HAS_SSL_TIMES); 2522 2523 trans1.reset(); 2524 2525 TestCompletionCallback callback2; 2526 scoped_ptr<HttpTransaction> trans2( 2527 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2528 2529 rv = trans2->Start(&request2, callback2.callback(), log.bound()); 2530 EXPECT_EQ(ERR_IO_PENDING, rv); 2531 2532 rv = callback2.WaitForResult(); 2533 EXPECT_EQ(OK, rv); 2534 2535 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 2536 ASSERT_TRUE(response2 != NULL); 2537 ASSERT_TRUE(response2->headers.get() != NULL); 2538 EXPECT_EQ(2, response2->headers->GetContentLength()); 2539 2540 LoadTimingInfo load_timing_info2; 2541 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 2542 TestLoadTimingReusedWithPac(load_timing_info2); 2543 2544 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2545 2546 trans2.reset(); 2547 session->CloseAllConnections(); 2548} 2549 2550// Test a simple get through an HTTPS Proxy. 2551TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) { 2552 HttpRequestInfo request; 2553 request.method = "GET"; 2554 request.url = GURL("http://www.google.com/"); 2555 2556 // Configure against https proxy server "proxy:70". 2557 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2558 "https://proxy:70")); 2559 CapturingBoundNetLog log; 2560 session_deps_.net_log = log.bound().net_log(); 2561 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2562 2563 // Since we have proxy, should use full url 2564 MockWrite data_writes1[] = { 2565 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2566 "Host: www.google.com\r\n" 2567 "Proxy-Connection: keep-alive\r\n\r\n"), 2568 }; 2569 2570 MockRead data_reads1[] = { 2571 MockRead("HTTP/1.1 200 OK\r\n"), 2572 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2573 MockRead("Content-Length: 100\r\n\r\n"), 2574 MockRead(SYNCHRONOUS, OK), 2575 }; 2576 2577 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2578 data_writes1, arraysize(data_writes1)); 2579 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2580 SSLSocketDataProvider ssl(ASYNC, OK); 2581 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2582 2583 TestCompletionCallback callback1; 2584 2585 scoped_ptr<HttpTransaction> trans( 2586 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2587 2588 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2589 EXPECT_EQ(ERR_IO_PENDING, rv); 2590 2591 rv = callback1.WaitForResult(); 2592 EXPECT_EQ(OK, rv); 2593 2594 LoadTimingInfo load_timing_info; 2595 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2596 TestLoadTimingNotReused(load_timing_info, 2597 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 2598 2599 const HttpResponseInfo* response = trans->GetResponseInfo(); 2600 ASSERT_TRUE(response != NULL); 2601 2602 EXPECT_TRUE(response->headers->IsKeepAlive()); 2603 EXPECT_EQ(200, response->headers->response_code()); 2604 EXPECT_EQ(100, response->headers->GetContentLength()); 2605 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2606 2607 // The password prompt info should not be set. 2608 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2609} 2610 2611// Test a SPDY get through an HTTPS Proxy. 2612TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) { 2613 HttpRequestInfo request; 2614 request.method = "GET"; 2615 request.url = GURL("http://www.google.com/"); 2616 request.load_flags = 0; 2617 2618 // Configure against https proxy server "proxy:70". 2619 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2620 "https://proxy:70")); 2621 CapturingBoundNetLog log; 2622 session_deps_.net_log = log.bound().net_log(); 2623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2624 2625 // fetch http://www.google.com/ via SPDY 2626 scoped_ptr<SpdyFrame> req( 2627 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 2628 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 2629 2630 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2631 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2632 MockRead spdy_reads[] = { 2633 CreateMockRead(*resp), 2634 CreateMockRead(*data), 2635 MockRead(ASYNC, 0, 0), 2636 }; 2637 2638 DelayedSocketData spdy_data( 2639 1, // wait for one write to finish before reading. 2640 spdy_reads, arraysize(spdy_reads), 2641 spdy_writes, arraysize(spdy_writes)); 2642 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 2643 2644 SSLSocketDataProvider ssl(ASYNC, OK); 2645 ssl.SetNextProto(GetParam()); 2646 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2647 2648 TestCompletionCallback callback1; 2649 2650 scoped_ptr<HttpTransaction> trans( 2651 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2652 2653 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2654 EXPECT_EQ(ERR_IO_PENDING, rv); 2655 2656 rv = callback1.WaitForResult(); 2657 EXPECT_EQ(OK, rv); 2658 2659 LoadTimingInfo load_timing_info; 2660 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2661 TestLoadTimingNotReused(load_timing_info, 2662 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 2663 2664 const HttpResponseInfo* response = trans->GetResponseInfo(); 2665 ASSERT_TRUE(response != NULL); 2666 ASSERT_TRUE(response->headers.get() != NULL); 2667 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 2668 2669 std::string response_data; 2670 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 2671 EXPECT_EQ(kUploadData, response_data); 2672} 2673 2674// Test a SPDY get through an HTTPS Proxy. 2675TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) { 2676 HttpRequestInfo request; 2677 request.method = "GET"; 2678 request.url = GURL("http://www.google.com/"); 2679 request.load_flags = 0; 2680 2681 // Configure against https proxy server "myproxy:70". 2682 session_deps_.proxy_service.reset( 2683 ProxyService::CreateFixed("https://myproxy:70")); 2684 CapturingBoundNetLog log; 2685 session_deps_.net_log = log.bound().net_log(); 2686 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2687 2688 // The first request will be a bare GET, the second request will be a 2689 // GET with a Proxy-Authorization header. 2690 scoped_ptr<SpdyFrame> req_get( 2691 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 2692 const char* const kExtraAuthorizationHeaders[] = { 2693 "proxy-authorization", "Basic Zm9vOmJhcg==" 2694 }; 2695 scoped_ptr<SpdyFrame> req_get_authorization( 2696 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 2697 arraysize(kExtraAuthorizationHeaders) / 2, 2698 false, 2699 3, 2700 LOWEST, 2701 false)); 2702 MockWrite spdy_writes[] = { 2703 CreateMockWrite(*req_get, 1), 2704 CreateMockWrite(*req_get_authorization, 4), 2705 }; 2706 2707 // The first response is a 407 proxy authentication challenge, and the second 2708 // response will be a 200 response since the second request includes a valid 2709 // Authorization header. 2710 const char* const kExtraAuthenticationHeaders[] = { 2711 "proxy-authenticate", "Basic realm=\"MyRealm1\"" 2712 }; 2713 scoped_ptr<SpdyFrame> resp_authentication( 2714 spdy_util_.ConstructSpdySynReplyError( 2715 "407 Proxy Authentication Required", 2716 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2, 2717 1)); 2718 scoped_ptr<SpdyFrame> body_authentication( 2719 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2720 scoped_ptr<SpdyFrame> resp_data( 2721 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 2722 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true)); 2723 MockRead spdy_reads[] = { 2724 CreateMockRead(*resp_authentication, 2), 2725 CreateMockRead(*body_authentication, 3), 2726 CreateMockRead(*resp_data, 5), 2727 CreateMockRead(*body_data, 6), 2728 MockRead(ASYNC, 0, 7), 2729 }; 2730 2731 OrderedSocketData data( 2732 spdy_reads, arraysize(spdy_reads), 2733 spdy_writes, arraysize(spdy_writes)); 2734 session_deps_.socket_factory->AddSocketDataProvider(&data); 2735 2736 SSLSocketDataProvider ssl(ASYNC, OK); 2737 ssl.SetNextProto(GetParam()); 2738 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2739 2740 TestCompletionCallback callback1; 2741 2742 scoped_ptr<HttpTransaction> trans( 2743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2744 2745 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2746 EXPECT_EQ(ERR_IO_PENDING, rv); 2747 2748 rv = callback1.WaitForResult(); 2749 EXPECT_EQ(OK, rv); 2750 2751 const HttpResponseInfo* const response = trans->GetResponseInfo(); 2752 2753 ASSERT_TRUE(response != NULL); 2754 ASSERT_TRUE(response->headers.get() != NULL); 2755 EXPECT_EQ(407, response->headers->response_code()); 2756 EXPECT_TRUE(response->was_fetched_via_spdy); 2757 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2758 2759 TestCompletionCallback callback2; 2760 2761 rv = trans->RestartWithAuth( 2762 AuthCredentials(kFoo, kBar), callback2.callback()); 2763 EXPECT_EQ(ERR_IO_PENDING, rv); 2764 2765 rv = callback2.WaitForResult(); 2766 EXPECT_EQ(OK, rv); 2767 2768 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); 2769 2770 ASSERT_TRUE(response_restart != NULL); 2771 ASSERT_TRUE(response_restart->headers.get() != NULL); 2772 EXPECT_EQ(200, response_restart->headers->response_code()); 2773 // The password prompt info should not be set. 2774 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); 2775} 2776 2777// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server. 2778TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) { 2779 HttpRequestInfo request; 2780 request.method = "GET"; 2781 request.url = GURL("https://www.google.com/"); 2782 request.load_flags = 0; 2783 2784 // Configure against https proxy server "proxy:70". 2785 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2786 "https://proxy:70")); 2787 CapturingBoundNetLog log; 2788 session_deps_.net_log = log.bound().net_log(); 2789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2790 2791 scoped_ptr<HttpTransaction> trans( 2792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2793 2794 // CONNECT to www.google.com:443 via SPDY 2795 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 2796 // fetch https://www.google.com/ via HTTP 2797 2798 const char get[] = "GET / HTTP/1.1\r\n" 2799 "Host: www.google.com\r\n" 2800 "Connection: keep-alive\r\n\r\n"; 2801 scoped_ptr<SpdyFrame> wrapped_get( 2802 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false)); 2803 scoped_ptr<SpdyFrame> conn_resp( 2804 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2805 const char resp[] = "HTTP/1.1 200 OK\r\n" 2806 "Content-Length: 10\r\n\r\n"; 2807 scoped_ptr<SpdyFrame> wrapped_get_resp( 2808 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false)); 2809 scoped_ptr<SpdyFrame> wrapped_body( 2810 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false)); 2811 scoped_ptr<SpdyFrame> window_update( 2812 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size())); 2813 2814 MockWrite spdy_writes[] = { 2815 CreateMockWrite(*connect, 1), 2816 CreateMockWrite(*wrapped_get, 3), 2817 CreateMockWrite(*window_update, 5), 2818 }; 2819 2820 MockRead spdy_reads[] = { 2821 CreateMockRead(*conn_resp, 2, ASYNC), 2822 CreateMockRead(*wrapped_get_resp, 4, ASYNC), 2823 CreateMockRead(*wrapped_body, 6, ASYNC), 2824 CreateMockRead(*wrapped_body, 7, ASYNC), 2825 MockRead(ASYNC, 0, 8), 2826 }; 2827 2828 OrderedSocketData spdy_data( 2829 spdy_reads, arraysize(spdy_reads), 2830 spdy_writes, arraysize(spdy_writes)); 2831 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 2832 2833 SSLSocketDataProvider ssl(ASYNC, OK); 2834 ssl.SetNextProto(GetParam()); 2835 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2836 SSLSocketDataProvider ssl2(ASYNC, OK); 2837 ssl2.was_npn_negotiated = false; 2838 ssl2.protocol_negotiated = kProtoUnknown; 2839 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 2840 2841 TestCompletionCallback callback1; 2842 2843 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2844 EXPECT_EQ(ERR_IO_PENDING, rv); 2845 2846 rv = callback1.WaitForResult(); 2847 EXPECT_EQ(OK, rv); 2848 2849 LoadTimingInfo load_timing_info; 2850 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2851 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 2852 2853 const HttpResponseInfo* response = trans->GetResponseInfo(); 2854 ASSERT_TRUE(response != NULL); 2855 ASSERT_TRUE(response->headers.get() != NULL); 2856 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 2857 2858 std::string response_data; 2859 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 2860 EXPECT_EQ("1234567890", response_data); 2861} 2862 2863// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server. 2864TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) { 2865 HttpRequestInfo request; 2866 request.method = "GET"; 2867 request.url = GURL("https://www.google.com/"); 2868 request.load_flags = 0; 2869 2870 // Configure against https proxy server "proxy:70". 2871 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2872 "https://proxy:70")); 2873 CapturingBoundNetLog log; 2874 session_deps_.net_log = log.bound().net_log(); 2875 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2876 2877 scoped_ptr<HttpTransaction> trans( 2878 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2879 2880 // CONNECT to www.google.com:443 via SPDY 2881 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 2882 // fetch https://www.google.com/ via SPDY 2883 const char* const kMyUrl = "https://www.google.com/"; 2884 scoped_ptr<SpdyFrame> get( 2885 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST)); 2886 scoped_ptr<SpdyFrame> wrapped_get( 2887 spdy_util_.ConstructWrappedSpdyFrame(get, 1)); 2888 scoped_ptr<SpdyFrame> conn_resp( 2889 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2890 scoped_ptr<SpdyFrame> get_resp( 2891 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2892 scoped_ptr<SpdyFrame> wrapped_get_resp( 2893 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1)); 2894 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2895 scoped_ptr<SpdyFrame> wrapped_body( 2896 spdy_util_.ConstructWrappedSpdyFrame(body, 1)); 2897 scoped_ptr<SpdyFrame> window_update_get_resp( 2898 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size())); 2899 scoped_ptr<SpdyFrame> window_update_body( 2900 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size())); 2901 2902 MockWrite spdy_writes[] = { 2903 CreateMockWrite(*connect, 1), 2904 CreateMockWrite(*wrapped_get, 3), 2905 CreateMockWrite(*window_update_get_resp, 5), 2906 CreateMockWrite(*window_update_body, 7), 2907 }; 2908 2909 MockRead spdy_reads[] = { 2910 CreateMockRead(*conn_resp, 2, ASYNC), 2911 CreateMockRead(*wrapped_get_resp, 4, ASYNC), 2912 CreateMockRead(*wrapped_body, 6, ASYNC), 2913 MockRead(ASYNC, 0, 8), 2914 }; 2915 2916 OrderedSocketData spdy_data( 2917 spdy_reads, arraysize(spdy_reads), 2918 spdy_writes, arraysize(spdy_writes)); 2919 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 2920 2921 SSLSocketDataProvider ssl(ASYNC, OK); 2922 ssl.SetNextProto(GetParam()); 2923 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2924 SSLSocketDataProvider ssl2(ASYNC, OK); 2925 ssl2.SetNextProto(GetParam()); 2926 ssl2.protocol_negotiated = GetParam(); 2927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 2928 2929 TestCompletionCallback callback1; 2930 2931 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2932 EXPECT_EQ(ERR_IO_PENDING, rv); 2933 2934 rv = callback1.WaitForResult(); 2935 EXPECT_EQ(OK, rv); 2936 2937 LoadTimingInfo load_timing_info; 2938 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2939 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 2940 2941 const HttpResponseInfo* response = trans->GetResponseInfo(); 2942 ASSERT_TRUE(response != NULL); 2943 ASSERT_TRUE(response->headers.get() != NULL); 2944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 2945 2946 std::string response_data; 2947 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 2948 EXPECT_EQ(kUploadData, response_data); 2949} 2950 2951// Test a SPDY CONNECT failure through an HTTPS Proxy. 2952TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) { 2953 HttpRequestInfo request; 2954 request.method = "GET"; 2955 request.url = GURL("https://www.google.com/"); 2956 request.load_flags = 0; 2957 2958 // Configure against https proxy server "proxy:70". 2959 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2960 "https://proxy:70")); 2961 CapturingBoundNetLog log; 2962 session_deps_.net_log = log.bound().net_log(); 2963 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2964 2965 scoped_ptr<HttpTransaction> trans( 2966 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2967 2968 // CONNECT to www.google.com:443 via SPDY 2969 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 2970 scoped_ptr<SpdyFrame> get( 2971 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 2972 2973 MockWrite spdy_writes[] = { 2974 CreateMockWrite(*connect, 1), 2975 CreateMockWrite(*get, 3), 2976 }; 2977 2978 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1)); 2979 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2980 MockRead spdy_reads[] = { 2981 CreateMockRead(*resp, 2, ASYNC), 2982 MockRead(ASYNC, 0, 4), 2983 }; 2984 2985 OrderedSocketData spdy_data( 2986 spdy_reads, arraysize(spdy_reads), 2987 spdy_writes, arraysize(spdy_writes)); 2988 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 2989 2990 SSLSocketDataProvider ssl(ASYNC, OK); 2991 ssl.SetNextProto(GetParam()); 2992 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2993 SSLSocketDataProvider ssl2(ASYNC, OK); 2994 ssl2.SetNextProto(GetParam()); 2995 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 2996 2997 TestCompletionCallback callback1; 2998 2999 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3000 EXPECT_EQ(ERR_IO_PENDING, rv); 3001 3002 rv = callback1.WaitForResult(); 3003 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 3004 3005 // TODO(ttuttle): Anything else to check here? 3006} 3007 3008// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY 3009// HTTPS Proxy to different servers. 3010TEST_P(HttpNetworkTransactionTest, 3011 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) { 3012 // Configure against https proxy server "proxy:70". 3013 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3014 "https://proxy:70")); 3015 CapturingBoundNetLog log; 3016 session_deps_.net_log = log.bound().net_log(); 3017 scoped_refptr<HttpNetworkSession> session( 3018 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3019 3020 HttpRequestInfo request1; 3021 request1.method = "GET"; 3022 request1.url = GURL("https://www.google.com/"); 3023 request1.load_flags = 0; 3024 3025 HttpRequestInfo request2; 3026 request2.method = "GET"; 3027 request2.url = GURL("https://news.google.com/"); 3028 request2.load_flags = 0; 3029 3030 // CONNECT to www.google.com:443 via SPDY. 3031 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 3032 scoped_ptr<SpdyFrame> conn_resp1( 3033 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3034 3035 // Fetch https://www.google.com/ via HTTP. 3036 const char get1[] = "GET / HTTP/1.1\r\n" 3037 "Host: www.google.com\r\n" 3038 "Connection: keep-alive\r\n\r\n"; 3039 scoped_ptr<SpdyFrame> wrapped_get1( 3040 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false)); 3041 const char resp1[] = "HTTP/1.1 200 OK\r\n" 3042 "Content-Length: 1\r\n\r\n"; 3043 scoped_ptr<SpdyFrame> wrapped_get_resp1( 3044 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false)); 3045 scoped_ptr<SpdyFrame> wrapped_body1( 3046 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false)); 3047 scoped_ptr<SpdyFrame> window_update( 3048 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size())); 3049 3050 // CONNECT to news.google.com:443 via SPDY. 3051 const char* const kConnectHeaders2[] = { 3052 spdy_util_.GetMethodKey(), "CONNECT", 3053 spdy_util_.GetPathKey(), "news.google.com:443", 3054 spdy_util_.GetHostKey(), "news.google.com", 3055 spdy_util_.GetVersionKey(), "HTTP/1.1", 3056 }; 3057 scoped_ptr<SpdyFrame> connect2( 3058 spdy_util_.ConstructSpdyControlFrame(NULL, 3059 0, 3060 /*compressed*/ false, 3061 3, 3062 LOWEST, 3063 SYN_STREAM, 3064 CONTROL_FLAG_NONE, 3065 kConnectHeaders2, 3066 arraysize(kConnectHeaders2), 3067 0)); 3068 scoped_ptr<SpdyFrame> conn_resp2( 3069 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3070 3071 // Fetch https://news.google.com/ via HTTP. 3072 const char get2[] = "GET / HTTP/1.1\r\n" 3073 "Host: news.google.com\r\n" 3074 "Connection: keep-alive\r\n\r\n"; 3075 scoped_ptr<SpdyFrame> wrapped_get2( 3076 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false)); 3077 const char resp2[] = "HTTP/1.1 200 OK\r\n" 3078 "Content-Length: 2\r\n\r\n"; 3079 scoped_ptr<SpdyFrame> wrapped_get_resp2( 3080 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false)); 3081 scoped_ptr<SpdyFrame> wrapped_body2( 3082 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false)); 3083 3084 MockWrite spdy_writes[] = { 3085 CreateMockWrite(*connect1, 0), 3086 CreateMockWrite(*wrapped_get1, 2), 3087 CreateMockWrite(*connect2, 5), 3088 CreateMockWrite(*wrapped_get2, 7), 3089 }; 3090 3091 MockRead spdy_reads[] = { 3092 CreateMockRead(*conn_resp1, 1, ASYNC), 3093 CreateMockRead(*wrapped_get_resp1, 3, ASYNC), 3094 CreateMockRead(*wrapped_body1, 4, ASYNC), 3095 CreateMockRead(*conn_resp2, 6, ASYNC), 3096 CreateMockRead(*wrapped_get_resp2, 8, ASYNC), 3097 CreateMockRead(*wrapped_body2, 9, ASYNC), 3098 MockRead(ASYNC, 0, 10), 3099 }; 3100 3101 DeterministicSocketData spdy_data( 3102 spdy_reads, arraysize(spdy_reads), 3103 spdy_writes, arraysize(spdy_writes)); 3104 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3105 3106 SSLSocketDataProvider ssl(ASYNC, OK); 3107 ssl.SetNextProto(GetParam()); 3108 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3109 SSLSocketDataProvider ssl2(ASYNC, OK); 3110 ssl2.was_npn_negotiated = false; 3111 ssl2.protocol_negotiated = kProtoUnknown; 3112 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 3113 SSLSocketDataProvider ssl3(ASYNC, OK); 3114 ssl3.was_npn_negotiated = false; 3115 ssl3.protocol_negotiated = kProtoUnknown; 3116 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3); 3117 3118 TestCompletionCallback callback; 3119 3120 scoped_ptr<HttpTransaction> trans( 3121 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3122 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3123 EXPECT_EQ(ERR_IO_PENDING, rv); 3124 // The first connect and request, each of their responses, and the body. 3125 spdy_data.RunFor(5); 3126 3127 rv = callback.WaitForResult(); 3128 EXPECT_EQ(OK, rv); 3129 3130 LoadTimingInfo load_timing_info; 3131 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3132 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3133 3134 const HttpResponseInfo* response = trans->GetResponseInfo(); 3135 ASSERT_TRUE(response != NULL); 3136 ASSERT_TRUE(response->headers.get() != NULL); 3137 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3138 3139 std::string response_data; 3140 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3141 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); 3142 3143 scoped_ptr<HttpTransaction> trans2( 3144 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3145 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3146 EXPECT_EQ(ERR_IO_PENDING, rv); 3147 3148 // The second connect and request, each of their responses, and the body. 3149 spdy_data.RunFor(5); 3150 rv = callback.WaitForResult(); 3151 EXPECT_EQ(OK, rv); 3152 3153 LoadTimingInfo load_timing_info2; 3154 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3155 // Even though the SPDY connection is reused, a new tunnelled connection has 3156 // to be created, so the socket's load timing looks like a fresh connection. 3157 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES); 3158 3159 // The requests should have different IDs, since they each are using their own 3160 // separate stream. 3161 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3162 3163 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback())); 3164} 3165 3166// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY 3167// HTTPS Proxy to the same server. 3168TEST_P(HttpNetworkTransactionTest, 3169 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) { 3170 // Configure against https proxy server "proxy:70". 3171 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3172 "https://proxy:70")); 3173 CapturingBoundNetLog log; 3174 session_deps_.net_log = log.bound().net_log(); 3175 scoped_refptr<HttpNetworkSession> session( 3176 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3177 3178 HttpRequestInfo request1; 3179 request1.method = "GET"; 3180 request1.url = GURL("https://www.google.com/"); 3181 request1.load_flags = 0; 3182 3183 HttpRequestInfo request2; 3184 request2.method = "GET"; 3185 request2.url = GURL("https://www.google.com/2"); 3186 request2.load_flags = 0; 3187 3188 // CONNECT to www.google.com:443 via SPDY. 3189 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 3190 scoped_ptr<SpdyFrame> conn_resp1( 3191 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3192 3193 // Fetch https://www.google.com/ via HTTP. 3194 const char get1[] = "GET / HTTP/1.1\r\n" 3195 "Host: www.google.com\r\n" 3196 "Connection: keep-alive\r\n\r\n"; 3197 scoped_ptr<SpdyFrame> wrapped_get1( 3198 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false)); 3199 const char resp1[] = "HTTP/1.1 200 OK\r\n" 3200 "Content-Length: 1\r\n\r\n"; 3201 scoped_ptr<SpdyFrame> wrapped_get_resp1( 3202 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false)); 3203 scoped_ptr<SpdyFrame> wrapped_body1( 3204 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false)); 3205 scoped_ptr<SpdyFrame> window_update( 3206 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size())); 3207 3208 // Fetch https://www.google.com/2 via HTTP. 3209 const char get2[] = "GET /2 HTTP/1.1\r\n" 3210 "Host: www.google.com\r\n" 3211 "Connection: keep-alive\r\n\r\n"; 3212 scoped_ptr<SpdyFrame> wrapped_get2( 3213 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false)); 3214 const char resp2[] = "HTTP/1.1 200 OK\r\n" 3215 "Content-Length: 2\r\n\r\n"; 3216 scoped_ptr<SpdyFrame> wrapped_get_resp2( 3217 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false)); 3218 scoped_ptr<SpdyFrame> wrapped_body2( 3219 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false)); 3220 3221 MockWrite spdy_writes[] = { 3222 CreateMockWrite(*connect1, 0), 3223 CreateMockWrite(*wrapped_get1, 2), 3224 CreateMockWrite(*wrapped_get2, 5), 3225 }; 3226 3227 MockRead spdy_reads[] = { 3228 CreateMockRead(*conn_resp1, 1, ASYNC), 3229 CreateMockRead(*wrapped_get_resp1, 3, ASYNC), 3230 CreateMockRead(*wrapped_body1, 4, ASYNC), 3231 CreateMockRead(*wrapped_get_resp2, 6, ASYNC), 3232 CreateMockRead(*wrapped_body2, 7, ASYNC), 3233 MockRead(ASYNC, 0, 8), 3234 }; 3235 3236 DeterministicSocketData spdy_data( 3237 spdy_reads, arraysize(spdy_reads), 3238 spdy_writes, arraysize(spdy_writes)); 3239 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3240 3241 SSLSocketDataProvider ssl(ASYNC, OK); 3242 ssl.SetNextProto(GetParam()); 3243 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3244 SSLSocketDataProvider ssl2(ASYNC, OK); 3245 ssl2.was_npn_negotiated = false; 3246 ssl2.protocol_negotiated = kProtoUnknown; 3247 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 3248 3249 TestCompletionCallback callback; 3250 3251 scoped_ptr<HttpTransaction> trans( 3252 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3253 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3254 EXPECT_EQ(ERR_IO_PENDING, rv); 3255 // The first connect and request, each of their responses, and the body. 3256 spdy_data.RunFor(5); 3257 3258 rv = callback.WaitForResult(); 3259 EXPECT_EQ(OK, rv); 3260 3261 LoadTimingInfo load_timing_info; 3262 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3263 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3264 3265 const HttpResponseInfo* response = trans->GetResponseInfo(); 3266 ASSERT_TRUE(response != NULL); 3267 ASSERT_TRUE(response->headers.get() != NULL); 3268 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3269 3270 std::string response_data; 3271 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3272 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); 3273 trans.reset(); 3274 3275 scoped_ptr<HttpTransaction> trans2( 3276 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3277 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3278 EXPECT_EQ(ERR_IO_PENDING, rv); 3279 3280 // The second request, response, and body. There should not be a second 3281 // connect. 3282 spdy_data.RunFor(3); 3283 rv = callback.WaitForResult(); 3284 EXPECT_EQ(OK, rv); 3285 3286 LoadTimingInfo load_timing_info2; 3287 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3288 TestLoadTimingReused(load_timing_info2); 3289 3290 // The requests should have the same ID. 3291 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3292 3293 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback())); 3294} 3295 3296// Test load timing in the case of of two HTTP requests through a SPDY HTTPS 3297// Proxy to different servers. 3298TEST_P(HttpNetworkTransactionTest, 3299 HttpsProxySpdyLoadTimingTwoHttpRequests) { 3300 // Configure against https proxy server "proxy:70". 3301 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3302 "https://proxy:70")); 3303 CapturingBoundNetLog log; 3304 session_deps_.net_log = log.bound().net_log(); 3305 scoped_refptr<HttpNetworkSession> session( 3306 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3307 3308 HttpRequestInfo request1; 3309 request1.method = "GET"; 3310 request1.url = GURL("http://www.google.com/"); 3311 request1.load_flags = 0; 3312 3313 HttpRequestInfo request2; 3314 request2.method = "GET"; 3315 request2.url = GURL("http://news.google.com/"); 3316 request2.load_flags = 0; 3317 3318 // http://www.google.com/ 3319 scoped_ptr<SpdyHeaderBlock> headers( 3320 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/")); 3321 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame( 3322 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 3323 scoped_ptr<SpdyFrame> get_resp1( 3324 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3325 scoped_ptr<SpdyFrame> body1( 3326 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true)); 3327 3328 // http://news.google.com/ 3329 scoped_ptr<SpdyHeaderBlock> headers2( 3330 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/")); 3331 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame( 3332 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 3333 scoped_ptr<SpdyFrame> get_resp2( 3334 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3335 scoped_ptr<SpdyFrame> body2( 3336 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true)); 3337 3338 MockWrite spdy_writes[] = { 3339 CreateMockWrite(*get1, 0), 3340 CreateMockWrite(*get2, 3), 3341 }; 3342 3343 MockRead spdy_reads[] = { 3344 CreateMockRead(*get_resp1, 1, ASYNC), 3345 CreateMockRead(*body1, 2, ASYNC), 3346 CreateMockRead(*get_resp2, 4, ASYNC), 3347 CreateMockRead(*body2, 5, ASYNC), 3348 MockRead(ASYNC, 0, 6), 3349 }; 3350 3351 DeterministicSocketData spdy_data( 3352 spdy_reads, arraysize(spdy_reads), 3353 spdy_writes, arraysize(spdy_writes)); 3354 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3355 3356 SSLSocketDataProvider ssl(ASYNC, OK); 3357 ssl.SetNextProto(GetParam()); 3358 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3359 3360 TestCompletionCallback callback; 3361 3362 scoped_ptr<HttpTransaction> trans( 3363 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3364 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3365 EXPECT_EQ(ERR_IO_PENDING, rv); 3366 spdy_data.RunFor(2); 3367 3368 rv = callback.WaitForResult(); 3369 EXPECT_EQ(OK, rv); 3370 3371 LoadTimingInfo load_timing_info; 3372 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3373 TestLoadTimingNotReused(load_timing_info, 3374 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3375 3376 const HttpResponseInfo* response = trans->GetResponseInfo(); 3377 ASSERT_TRUE(response != NULL); 3378 ASSERT_TRUE(response->headers.get() != NULL); 3379 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3380 3381 std::string response_data; 3382 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3383 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback())); 3384 spdy_data.RunFor(1); 3385 EXPECT_EQ(1, callback.WaitForResult()); 3386 // Delete the first request, so the second one can reuse the socket. 3387 trans.reset(); 3388 3389 scoped_ptr<HttpTransaction> trans2( 3390 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3391 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3392 EXPECT_EQ(ERR_IO_PENDING, rv); 3393 3394 spdy_data.RunFor(2); 3395 rv = callback.WaitForResult(); 3396 EXPECT_EQ(OK, rv); 3397 3398 LoadTimingInfo load_timing_info2; 3399 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3400 TestLoadTimingReused(load_timing_info2); 3401 3402 // The requests should have the same ID. 3403 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3404 3405 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback())); 3406 spdy_data.RunFor(1); 3407 EXPECT_EQ(2, callback.WaitForResult()); 3408} 3409 3410// Test the challenge-response-retry sequence through an HTTPS Proxy 3411TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) { 3412 HttpRequestInfo request; 3413 request.method = "GET"; 3414 request.url = GURL("http://www.google.com/"); 3415 // when the no authentication data flag is set. 3416 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 3417 3418 // Configure against https proxy server "myproxy:70". 3419 session_deps_.proxy_service.reset( 3420 ProxyService::CreateFixed("https://myproxy:70")); 3421 CapturingBoundNetLog log; 3422 session_deps_.net_log = log.bound().net_log(); 3423 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3424 3425 // Since we have proxy, should use full url 3426 MockWrite data_writes1[] = { 3427 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3428 "Host: www.google.com\r\n" 3429 "Proxy-Connection: keep-alive\r\n\r\n"), 3430 3431 // After calling trans->RestartWithAuth(), this is the request we should 3432 // be issuing -- the final header line contains the credentials. 3433 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3434 "Host: www.google.com\r\n" 3435 "Proxy-Connection: keep-alive\r\n" 3436 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3437 }; 3438 3439 // The proxy responds to the GET with a 407, using a persistent 3440 // connection. 3441 MockRead data_reads1[] = { 3442 // No credentials. 3443 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 3444 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3445 MockRead("Proxy-Connection: keep-alive\r\n"), 3446 MockRead("Content-Length: 0\r\n\r\n"), 3447 3448 MockRead("HTTP/1.1 200 OK\r\n"), 3449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3450 MockRead("Content-Length: 100\r\n\r\n"), 3451 MockRead(SYNCHRONOUS, OK), 3452 }; 3453 3454 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3455 data_writes1, arraysize(data_writes1)); 3456 session_deps_.socket_factory->AddSocketDataProvider(&data1); 3457 SSLSocketDataProvider ssl(ASYNC, OK); 3458 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3459 3460 TestCompletionCallback callback1; 3461 3462 scoped_ptr<HttpTransaction> trans( 3463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3464 3465 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3466 EXPECT_EQ(ERR_IO_PENDING, rv); 3467 3468 rv = callback1.WaitForResult(); 3469 EXPECT_EQ(OK, rv); 3470 3471 LoadTimingInfo load_timing_info; 3472 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3473 TestLoadTimingNotReused(load_timing_info, 3474 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3475 3476 const HttpResponseInfo* response = trans->GetResponseInfo(); 3477 ASSERT_TRUE(response != NULL); 3478 ASSERT_FALSE(response->headers.get() == NULL); 3479 EXPECT_EQ(407, response->headers->response_code()); 3480 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 3481 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 3482 3483 TestCompletionCallback callback2; 3484 3485 rv = trans->RestartWithAuth( 3486 AuthCredentials(kFoo, kBar), callback2.callback()); 3487 EXPECT_EQ(ERR_IO_PENDING, rv); 3488 3489 rv = callback2.WaitForResult(); 3490 EXPECT_EQ(OK, rv); 3491 3492 load_timing_info = LoadTimingInfo(); 3493 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3494 // Retrying with HTTP AUTH is considered to be reusing a socket. 3495 TestLoadTimingReused(load_timing_info); 3496 3497 response = trans->GetResponseInfo(); 3498 ASSERT_TRUE(response != NULL); 3499 3500 EXPECT_TRUE(response->headers->IsKeepAlive()); 3501 EXPECT_EQ(200, response->headers->response_code()); 3502 EXPECT_EQ(100, response->headers->GetContentLength()); 3503 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 3504 3505 // The password prompt info should not be set. 3506 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3507} 3508 3509void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( 3510 const MockRead& status, int expected_status) { 3511 HttpRequestInfo request; 3512 request.method = "GET"; 3513 request.url = GURL("https://www.google.com/"); 3514 request.load_flags = 0; 3515 3516 // Configure against proxy server "myproxy:70". 3517 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 3518 3519 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3520 3521 // Since we have proxy, should try to establish tunnel. 3522 MockWrite data_writes[] = { 3523 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 3524 "Host: www.google.com\r\n" 3525 "Proxy-Connection: keep-alive\r\n\r\n"), 3526 }; 3527 3528 MockRead data_reads[] = { 3529 status, 3530 MockRead("Content-Length: 10\r\n\r\n"), 3531 // No response body because the test stops reading here. 3532 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 3533 }; 3534 3535 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 3536 data_writes, arraysize(data_writes)); 3537 session_deps_.socket_factory->AddSocketDataProvider(&data); 3538 3539 TestCompletionCallback callback; 3540 3541 scoped_ptr<HttpTransaction> trans( 3542 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3543 3544 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 3545 EXPECT_EQ(ERR_IO_PENDING, rv); 3546 3547 rv = callback.WaitForResult(); 3548 EXPECT_EQ(expected_status, rv); 3549} 3550 3551void HttpNetworkTransactionTest::ConnectStatusHelper( 3552 const MockRead& status) { 3553 ConnectStatusHelperWithExpectedStatus( 3554 status, ERR_TUNNEL_CONNECTION_FAILED); 3555} 3556 3557TEST_P(HttpNetworkTransactionTest, ConnectStatus100) { 3558 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n")); 3559} 3560 3561TEST_P(HttpNetworkTransactionTest, ConnectStatus101) { 3562 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n")); 3563} 3564 3565TEST_P(HttpNetworkTransactionTest, ConnectStatus201) { 3566 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n")); 3567} 3568 3569TEST_P(HttpNetworkTransactionTest, ConnectStatus202) { 3570 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n")); 3571} 3572 3573TEST_P(HttpNetworkTransactionTest, ConnectStatus203) { 3574 ConnectStatusHelper( 3575 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n")); 3576} 3577 3578TEST_P(HttpNetworkTransactionTest, ConnectStatus204) { 3579 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n")); 3580} 3581 3582TEST_P(HttpNetworkTransactionTest, ConnectStatus205) { 3583 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n")); 3584} 3585 3586TEST_P(HttpNetworkTransactionTest, ConnectStatus206) { 3587 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n")); 3588} 3589 3590TEST_P(HttpNetworkTransactionTest, ConnectStatus300) { 3591 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n")); 3592} 3593 3594TEST_P(HttpNetworkTransactionTest, ConnectStatus301) { 3595 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n")); 3596} 3597 3598TEST_P(HttpNetworkTransactionTest, ConnectStatus302) { 3599 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n")); 3600} 3601 3602TEST_P(HttpNetworkTransactionTest, ConnectStatus303) { 3603 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n")); 3604} 3605 3606TEST_P(HttpNetworkTransactionTest, ConnectStatus304) { 3607 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n")); 3608} 3609 3610TEST_P(HttpNetworkTransactionTest, ConnectStatus305) { 3611 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n")); 3612} 3613 3614TEST_P(HttpNetworkTransactionTest, ConnectStatus306) { 3615 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n")); 3616} 3617 3618TEST_P(HttpNetworkTransactionTest, ConnectStatus307) { 3619 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n")); 3620} 3621 3622TEST_P(HttpNetworkTransactionTest, ConnectStatus400) { 3623 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n")); 3624} 3625 3626TEST_P(HttpNetworkTransactionTest, ConnectStatus401) { 3627 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n")); 3628} 3629 3630TEST_P(HttpNetworkTransactionTest, ConnectStatus402) { 3631 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n")); 3632} 3633 3634TEST_P(HttpNetworkTransactionTest, ConnectStatus403) { 3635 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n")); 3636} 3637 3638TEST_P(HttpNetworkTransactionTest, ConnectStatus404) { 3639 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n")); 3640} 3641 3642TEST_P(HttpNetworkTransactionTest, ConnectStatus405) { 3643 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n")); 3644} 3645 3646TEST_P(HttpNetworkTransactionTest, ConnectStatus406) { 3647 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n")); 3648} 3649 3650TEST_P(HttpNetworkTransactionTest, ConnectStatus407) { 3651 ConnectStatusHelperWithExpectedStatus( 3652 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 3653 ERR_PROXY_AUTH_UNSUPPORTED); 3654} 3655 3656TEST_P(HttpNetworkTransactionTest, ConnectStatus408) { 3657 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n")); 3658} 3659 3660TEST_P(HttpNetworkTransactionTest, ConnectStatus409) { 3661 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n")); 3662} 3663 3664TEST_P(HttpNetworkTransactionTest, ConnectStatus410) { 3665 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n")); 3666} 3667 3668TEST_P(HttpNetworkTransactionTest, ConnectStatus411) { 3669 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n")); 3670} 3671 3672TEST_P(HttpNetworkTransactionTest, ConnectStatus412) { 3673 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n")); 3674} 3675 3676TEST_P(HttpNetworkTransactionTest, ConnectStatus413) { 3677 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n")); 3678} 3679 3680TEST_P(HttpNetworkTransactionTest, ConnectStatus414) { 3681 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n")); 3682} 3683 3684TEST_P(HttpNetworkTransactionTest, ConnectStatus415) { 3685 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n")); 3686} 3687 3688TEST_P(HttpNetworkTransactionTest, ConnectStatus416) { 3689 ConnectStatusHelper( 3690 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n")); 3691} 3692 3693TEST_P(HttpNetworkTransactionTest, ConnectStatus417) { 3694 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n")); 3695} 3696 3697TEST_P(HttpNetworkTransactionTest, ConnectStatus500) { 3698 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n")); 3699} 3700 3701TEST_P(HttpNetworkTransactionTest, ConnectStatus501) { 3702 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n")); 3703} 3704 3705TEST_P(HttpNetworkTransactionTest, ConnectStatus502) { 3706 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n")); 3707} 3708 3709TEST_P(HttpNetworkTransactionTest, ConnectStatus503) { 3710 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n")); 3711} 3712 3713TEST_P(HttpNetworkTransactionTest, ConnectStatus504) { 3714 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n")); 3715} 3716 3717TEST_P(HttpNetworkTransactionTest, ConnectStatus505) { 3718 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n")); 3719} 3720 3721// Test the flow when both the proxy server AND origin server require 3722// authentication. Again, this uses basic auth for both since that is 3723// the simplest to mock. 3724TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { 3725 HttpRequestInfo request; 3726 request.method = "GET"; 3727 request.url = GURL("http://www.google.com/"); 3728 request.load_flags = 0; 3729 3730 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 3731 3732 // Configure against proxy server "myproxy:70". 3733 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY, 3734 CreateSession(&session_deps_))); 3735 3736 MockWrite data_writes1[] = { 3737 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3738 "Host: www.google.com\r\n" 3739 "Proxy-Connection: keep-alive\r\n\r\n"), 3740 }; 3741 3742 MockRead data_reads1[] = { 3743 MockRead("HTTP/1.0 407 Unauthorized\r\n"), 3744 // Give a couple authenticate options (only the middle one is actually 3745 // supported). 3746 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed. 3747 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3748 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 3749 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3750 // Large content-length -- won't matter, as connection will be reset. 3751 MockRead("Content-Length: 10000\r\n\r\n"), 3752 MockRead(SYNCHRONOUS, ERR_FAILED), 3753 }; 3754 3755 // After calling trans->RestartWithAuth() the first time, this is the 3756 // request we should be issuing -- the final header line contains the 3757 // proxy's credentials. 3758 MockWrite data_writes2[] = { 3759 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3760 "Host: www.google.com\r\n" 3761 "Proxy-Connection: keep-alive\r\n" 3762 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3763 }; 3764 3765 // Now the proxy server lets the request pass through to origin server. 3766 // The origin server responds with a 401. 3767 MockRead data_reads2[] = { 3768 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3769 // Note: We are using the same realm-name as the proxy server. This is 3770 // completely valid, as realms are unique across hosts. 3771 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3772 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3773 MockRead("Content-Length: 2000\r\n\r\n"), 3774 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached. 3775 }; 3776 3777 // After calling trans->RestartWithAuth() the second time, we should send 3778 // the credentials for both the proxy and origin server. 3779 MockWrite data_writes3[] = { 3780 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3781 "Host: www.google.com\r\n" 3782 "Proxy-Connection: keep-alive\r\n" 3783 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n" 3784 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 3785 }; 3786 3787 // Lastly we get the desired content. 3788 MockRead data_reads3[] = { 3789 MockRead("HTTP/1.0 200 OK\r\n"), 3790 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3791 MockRead("Content-Length: 100\r\n\r\n"), 3792 MockRead(SYNCHRONOUS, OK), 3793 }; 3794 3795 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3796 data_writes1, arraysize(data_writes1)); 3797 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3798 data_writes2, arraysize(data_writes2)); 3799 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 3800 data_writes3, arraysize(data_writes3)); 3801 session_deps_.socket_factory->AddSocketDataProvider(&data1); 3802 session_deps_.socket_factory->AddSocketDataProvider(&data2); 3803 session_deps_.socket_factory->AddSocketDataProvider(&data3); 3804 3805 TestCompletionCallback callback1; 3806 3807 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 3808 EXPECT_EQ(ERR_IO_PENDING, rv); 3809 3810 rv = callback1.WaitForResult(); 3811 EXPECT_EQ(OK, rv); 3812 3813 const HttpResponseInfo* response = trans->GetResponseInfo(); 3814 ASSERT_TRUE(response != NULL); 3815 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 3816 3817 TestCompletionCallback callback2; 3818 3819 rv = trans->RestartWithAuth( 3820 AuthCredentials(kFoo, kBar), callback2.callback()); 3821 EXPECT_EQ(ERR_IO_PENDING, rv); 3822 3823 rv = callback2.WaitForResult(); 3824 EXPECT_EQ(OK, rv); 3825 3826 response = trans->GetResponseInfo(); 3827 ASSERT_TRUE(response != NULL); 3828 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 3829 3830 TestCompletionCallback callback3; 3831 3832 rv = trans->RestartWithAuth( 3833 AuthCredentials(kFoo2, kBar2), callback3.callback()); 3834 EXPECT_EQ(ERR_IO_PENDING, rv); 3835 3836 rv = callback3.WaitForResult(); 3837 EXPECT_EQ(OK, rv); 3838 3839 response = trans->GetResponseInfo(); 3840 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3841 EXPECT_EQ(100, response->headers->GetContentLength()); 3842} 3843 3844// For the NTLM implementation using SSPI, we skip the NTLM tests since we 3845// can't hook into its internals to cause it to generate predictable NTLM 3846// authorization headers. 3847#if defined(NTLM_PORTABLE) 3848// The NTLM authentication unit tests were generated by capturing the HTTP 3849// requests and responses using Fiddler 2 and inspecting the generated random 3850// bytes in the debugger. 3851 3852// Enter the correct password and authenticate successfully. 3853TEST_P(HttpNetworkTransactionTest, NTLMAuth1) { 3854 HttpRequestInfo request; 3855 request.method = "GET"; 3856 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 3857 request.load_flags = 0; 3858 3859 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1, 3860 MockGetHostName); 3861 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3862 3863 MockWrite data_writes1[] = { 3864 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 3865 "Host: 172.22.68.17\r\n" 3866 "Connection: keep-alive\r\n\r\n"), 3867 }; 3868 3869 MockRead data_reads1[] = { 3870 MockRead("HTTP/1.1 401 Access Denied\r\n"), 3871 // Negotiate and NTLM are often requested together. However, we only want 3872 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 3873 // the header that requests Negotiate for this test. 3874 MockRead("WWW-Authenticate: NTLM\r\n"), 3875 MockRead("Connection: close\r\n"), 3876 MockRead("Content-Length: 42\r\n"), 3877 MockRead("Content-Type: text/html\r\n\r\n"), 3878 // Missing content -- won't matter, as connection will be reset. 3879 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 3880 }; 3881 3882 MockWrite data_writes2[] = { 3883 // After restarting with a null identity, this is the 3884 // request we should be issuing -- the final header line contains a Type 3885 // 1 message. 3886 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 3887 "Host: 172.22.68.17\r\n" 3888 "Connection: keep-alive\r\n" 3889 "Authorization: NTLM " 3890 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 3891 3892 // After calling trans->RestartWithAuth(), we should send a Type 3 message 3893 // (the credentials for the origin server). The second request continues 3894 // on the same connection. 3895 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 3896 "Host: 172.22.68.17\r\n" 3897 "Connection: keep-alive\r\n" 3898 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 3899 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 3900 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW" 3901 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX" 3902 "ahlhx5I=\r\n\r\n"), 3903 }; 3904 3905 MockRead data_reads2[] = { 3906 // The origin server responds with a Type 2 message. 3907 MockRead("HTTP/1.1 401 Access Denied\r\n"), 3908 MockRead("WWW-Authenticate: NTLM " 3909 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo" 3910 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 3911 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 3912 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 3913 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 3914 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 3915 "BtAAAAAAA=\r\n"), 3916 MockRead("Content-Length: 42\r\n"), 3917 MockRead("Content-Type: text/html\r\n\r\n"), 3918 MockRead("You are not authorized to view this page\r\n"), 3919 3920 // Lastly we get the desired content. 3921 MockRead("HTTP/1.1 200 OK\r\n"), 3922 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 3923 MockRead("Content-Length: 13\r\n\r\n"), 3924 MockRead("Please Login\r\n"), 3925 MockRead(SYNCHRONOUS, OK), 3926 }; 3927 3928 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3929 data_writes1, arraysize(data_writes1)); 3930 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3931 data_writes2, arraysize(data_writes2)); 3932 session_deps_.socket_factory->AddSocketDataProvider(&data1); 3933 session_deps_.socket_factory->AddSocketDataProvider(&data2); 3934 3935 TestCompletionCallback callback1; 3936 3937 scoped_ptr<HttpTransaction> trans( 3938 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3939 3940 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 3941 EXPECT_EQ(ERR_IO_PENDING, rv); 3942 3943 rv = callback1.WaitForResult(); 3944 EXPECT_EQ(OK, rv); 3945 3946 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 3947 3948 const HttpResponseInfo* response = trans->GetResponseInfo(); 3949 ASSERT_FALSE(response == NULL); 3950 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 3951 3952 TestCompletionCallback callback2; 3953 3954 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM), 3955 callback2.callback()); 3956 EXPECT_EQ(ERR_IO_PENDING, rv); 3957 3958 rv = callback2.WaitForResult(); 3959 EXPECT_EQ(OK, rv); 3960 3961 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 3962 3963 response = trans->GetResponseInfo(); 3964 ASSERT_TRUE(response != NULL); 3965 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3966 3967 TestCompletionCallback callback3; 3968 3969 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback()); 3970 EXPECT_EQ(ERR_IO_PENDING, rv); 3971 3972 rv = callback3.WaitForResult(); 3973 EXPECT_EQ(OK, rv); 3974 3975 response = trans->GetResponseInfo(); 3976 ASSERT_TRUE(response != NULL); 3977 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3978 EXPECT_EQ(13, response->headers->GetContentLength()); 3979} 3980 3981// Enter a wrong password, and then the correct one. 3982TEST_P(HttpNetworkTransactionTest, NTLMAuth2) { 3983 HttpRequestInfo request; 3984 request.method = "GET"; 3985 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 3986 request.load_flags = 0; 3987 3988 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2, 3989 MockGetHostName); 3990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3991 3992 MockWrite data_writes1[] = { 3993 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 3994 "Host: 172.22.68.17\r\n" 3995 "Connection: keep-alive\r\n\r\n"), 3996 }; 3997 3998 MockRead data_reads1[] = { 3999 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4000 // Negotiate and NTLM are often requested together. However, we only want 4001 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 4002 // the header that requests Negotiate for this test. 4003 MockRead("WWW-Authenticate: NTLM\r\n"), 4004 MockRead("Connection: close\r\n"), 4005 MockRead("Content-Length: 42\r\n"), 4006 MockRead("Content-Type: text/html\r\n\r\n"), 4007 // Missing content -- won't matter, as connection will be reset. 4008 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4009 }; 4010 4011 MockWrite data_writes2[] = { 4012 // After restarting with a null identity, this is the 4013 // request we should be issuing -- the final header line contains a Type 4014 // 1 message. 4015 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4016 "Host: 172.22.68.17\r\n" 4017 "Connection: keep-alive\r\n" 4018 "Authorization: NTLM " 4019 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4020 4021 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4022 // (the credentials for the origin server). The second request continues 4023 // on the same connection. 4024 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4025 "Host: 172.22.68.17\r\n" 4026 "Connection: keep-alive\r\n" 4027 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4028 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4029 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY" 4030 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj" 4031 "4Ww7b7E=\r\n\r\n"), 4032 }; 4033 4034 MockRead data_reads2[] = { 4035 // The origin server responds with a Type 2 message. 4036 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4037 MockRead("WWW-Authenticate: NTLM " 4038 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo" 4039 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4040 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4041 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4042 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4043 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4044 "BtAAAAAAA=\r\n"), 4045 MockRead("Content-Length: 42\r\n"), 4046 MockRead("Content-Type: text/html\r\n\r\n"), 4047 MockRead("You are not authorized to view this page\r\n"), 4048 4049 // Wrong password. 4050 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4051 MockRead("WWW-Authenticate: NTLM\r\n"), 4052 MockRead("Connection: close\r\n"), 4053 MockRead("Content-Length: 42\r\n"), 4054 MockRead("Content-Type: text/html\r\n\r\n"), 4055 // Missing content -- won't matter, as connection will be reset. 4056 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4057 }; 4058 4059 MockWrite data_writes3[] = { 4060 // After restarting with a null identity, this is the 4061 // request we should be issuing -- the final header line contains a Type 4062 // 1 message. 4063 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4064 "Host: 172.22.68.17\r\n" 4065 "Connection: keep-alive\r\n" 4066 "Authorization: NTLM " 4067 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4068 4069 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4070 // (the credentials for the origin server). The second request continues 4071 // on the same connection. 4072 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4073 "Host: 172.22.68.17\r\n" 4074 "Connection: keep-alive\r\n" 4075 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4076 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4077 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54" 4078 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI" 4079 "+4MUm7c=\r\n\r\n"), 4080 }; 4081 4082 MockRead data_reads3[] = { 4083 // The origin server responds with a Type 2 message. 4084 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4085 MockRead("WWW-Authenticate: NTLM " 4086 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo" 4087 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4088 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4089 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4090 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4091 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4092 "BtAAAAAAA=\r\n"), 4093 MockRead("Content-Length: 42\r\n"), 4094 MockRead("Content-Type: text/html\r\n\r\n"), 4095 MockRead("You are not authorized to view this page\r\n"), 4096 4097 // Lastly we get the desired content. 4098 MockRead("HTTP/1.1 200 OK\r\n"), 4099 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 4100 MockRead("Content-Length: 13\r\n\r\n"), 4101 MockRead("Please Login\r\n"), 4102 MockRead(SYNCHRONOUS, OK), 4103 }; 4104 4105 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4106 data_writes1, arraysize(data_writes1)); 4107 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4108 data_writes2, arraysize(data_writes2)); 4109 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4110 data_writes3, arraysize(data_writes3)); 4111 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4112 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4113 session_deps_.socket_factory->AddSocketDataProvider(&data3); 4114 4115 TestCompletionCallback callback1; 4116 4117 scoped_ptr<HttpTransaction> trans( 4118 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4119 4120 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4121 EXPECT_EQ(ERR_IO_PENDING, rv); 4122 4123 rv = callback1.WaitForResult(); 4124 EXPECT_EQ(OK, rv); 4125 4126 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4127 4128 const HttpResponseInfo* response = trans->GetResponseInfo(); 4129 ASSERT_TRUE(response != NULL); 4130 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4131 4132 TestCompletionCallback callback2; 4133 4134 // Enter the wrong password. 4135 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword), 4136 callback2.callback()); 4137 EXPECT_EQ(ERR_IO_PENDING, rv); 4138 4139 rv = callback2.WaitForResult(); 4140 EXPECT_EQ(OK, rv); 4141 4142 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4143 TestCompletionCallback callback3; 4144 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback()); 4145 EXPECT_EQ(ERR_IO_PENDING, rv); 4146 rv = callback3.WaitForResult(); 4147 EXPECT_EQ(OK, rv); 4148 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4149 4150 response = trans->GetResponseInfo(); 4151 ASSERT_FALSE(response == NULL); 4152 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4153 4154 TestCompletionCallback callback4; 4155 4156 // Now enter the right password. 4157 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM), 4158 callback4.callback()); 4159 EXPECT_EQ(ERR_IO_PENDING, rv); 4160 4161 rv = callback4.WaitForResult(); 4162 EXPECT_EQ(OK, rv); 4163 4164 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4165 4166 TestCompletionCallback callback5; 4167 4168 // One more roundtrip 4169 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback()); 4170 EXPECT_EQ(ERR_IO_PENDING, rv); 4171 4172 rv = callback5.WaitForResult(); 4173 EXPECT_EQ(OK, rv); 4174 4175 response = trans->GetResponseInfo(); 4176 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4177 EXPECT_EQ(13, response->headers->GetContentLength()); 4178} 4179#endif // NTLM_PORTABLE 4180 4181// Test reading a server response which has only headers, and no body. 4182// After some maximum number of bytes is consumed, the transaction should 4183// fail with ERR_RESPONSE_HEADERS_TOO_BIG. 4184TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) { 4185 HttpRequestInfo request; 4186 request.method = "GET"; 4187 request.url = GURL("http://www.google.com/"); 4188 request.load_flags = 0; 4189 4190 scoped_ptr<HttpTransaction> trans( 4191 new HttpNetworkTransaction(DEFAULT_PRIORITY, 4192 CreateSession(&session_deps_))); 4193 4194 // Respond with 300 kb of headers (we should fail after 256 kb). 4195 std::string large_headers_string; 4196 FillLargeHeadersString(&large_headers_string, 300 * 1024); 4197 4198 MockRead data_reads[] = { 4199 MockRead("HTTP/1.0 200 OK\r\n"), 4200 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()), 4201 MockRead("\r\nBODY"), 4202 MockRead(SYNCHRONOUS, OK), 4203 }; 4204 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4205 session_deps_.socket_factory->AddSocketDataProvider(&data); 4206 4207 TestCompletionCallback callback; 4208 4209 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4210 EXPECT_EQ(ERR_IO_PENDING, rv); 4211 4212 rv = callback.WaitForResult(); 4213 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv); 4214 4215 const HttpResponseInfo* response = trans->GetResponseInfo(); 4216 EXPECT_TRUE(response == NULL); 4217} 4218 4219// Make sure that we don't try to reuse a TCPClientSocket when failing to 4220// establish tunnel. 4221// http://code.google.com/p/chromium/issues/detail?id=3772 4222TEST_P(HttpNetworkTransactionTest, 4223 DontRecycleTransportSocketForSSLTunnel) { 4224 HttpRequestInfo request; 4225 request.method = "GET"; 4226 request.url = GURL("https://www.google.com/"); 4227 request.load_flags = 0; 4228 4229 // Configure against proxy server "myproxy:70". 4230 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 4231 4232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4233 4234 scoped_ptr<HttpTransaction> trans( 4235 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4236 4237 // Since we have proxy, should try to establish tunnel. 4238 MockWrite data_writes1[] = { 4239 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4240 "Host: www.google.com\r\n" 4241 "Proxy-Connection: keep-alive\r\n\r\n"), 4242 }; 4243 4244 // The proxy responds to the connect with a 404, using a persistent 4245 // connection. Usually a proxy would return 501 (not implemented), 4246 // or 200 (tunnel established). 4247 MockRead data_reads1[] = { 4248 MockRead("HTTP/1.1 404 Not Found\r\n"), 4249 MockRead("Content-Length: 10\r\n\r\n"), 4250 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 4251 }; 4252 4253 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4254 data_writes1, arraysize(data_writes1)); 4255 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4256 4257 TestCompletionCallback callback1; 4258 4259 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4260 EXPECT_EQ(ERR_IO_PENDING, rv); 4261 4262 rv = callback1.WaitForResult(); 4263 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 4264 4265 const HttpResponseInfo* response = trans->GetResponseInfo(); 4266 EXPECT_TRUE(response == NULL); 4267 4268 // Empty the current queue. This is necessary because idle sockets are 4269 // added to the connection pool asynchronously with a PostTask. 4270 base::MessageLoop::current()->RunUntilIdle(); 4271 4272 // We now check to make sure the TCPClientSocket was not added back to 4273 // the pool. 4274 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4275 trans.reset(); 4276 base::MessageLoop::current()->RunUntilIdle(); 4277 // Make sure that the socket didn't get recycled after calling the destructor. 4278 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4279} 4280 4281// Make sure that we recycle a socket after reading all of the response body. 4282TEST_P(HttpNetworkTransactionTest, RecycleSocket) { 4283 HttpRequestInfo request; 4284 request.method = "GET"; 4285 request.url = GURL("http://www.google.com/"); 4286 request.load_flags = 0; 4287 4288 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4289 4290 scoped_ptr<HttpTransaction> trans( 4291 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4292 4293 MockRead data_reads[] = { 4294 // A part of the response body is received with the response headers. 4295 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"), 4296 // The rest of the response body is received in two parts. 4297 MockRead("lo"), 4298 MockRead(" world"), 4299 MockRead("junk"), // Should not be read!! 4300 MockRead(SYNCHRONOUS, OK), 4301 }; 4302 4303 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4304 session_deps_.socket_factory->AddSocketDataProvider(&data); 4305 4306 TestCompletionCallback callback; 4307 4308 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4309 EXPECT_EQ(ERR_IO_PENDING, rv); 4310 4311 rv = callback.WaitForResult(); 4312 EXPECT_EQ(OK, rv); 4313 4314 const HttpResponseInfo* response = trans->GetResponseInfo(); 4315 ASSERT_TRUE(response != NULL); 4316 4317 EXPECT_TRUE(response->headers.get() != NULL); 4318 std::string status_line = response->headers->GetStatusLine(); 4319 EXPECT_EQ("HTTP/1.1 200 OK", status_line); 4320 4321 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4322 4323 std::string response_data; 4324 rv = ReadTransaction(trans.get(), &response_data); 4325 EXPECT_EQ(OK, rv); 4326 EXPECT_EQ("hello world", response_data); 4327 4328 // Empty the current queue. This is necessary because idle sockets are 4329 // added to the connection pool asynchronously with a PostTask. 4330 base::MessageLoop::current()->RunUntilIdle(); 4331 4332 // We now check to make sure the socket was added back to the pool. 4333 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get())); 4334} 4335 4336// Make sure that we recycle a SSL socket after reading all of the response 4337// body. 4338TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) { 4339 HttpRequestInfo request; 4340 request.method = "GET"; 4341 request.url = GURL("https://www.google.com/"); 4342 request.load_flags = 0; 4343 4344 MockWrite data_writes[] = { 4345 MockWrite("GET / HTTP/1.1\r\n" 4346 "Host: www.google.com\r\n" 4347 "Connection: keep-alive\r\n\r\n"), 4348 }; 4349 4350 MockRead data_reads[] = { 4351 MockRead("HTTP/1.1 200 OK\r\n"), 4352 MockRead("Content-Length: 11\r\n\r\n"), 4353 MockRead("hello world"), 4354 MockRead(SYNCHRONOUS, OK), 4355 }; 4356 4357 SSLSocketDataProvider ssl(ASYNC, OK); 4358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 4359 4360 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4361 data_writes, arraysize(data_writes)); 4362 session_deps_.socket_factory->AddSocketDataProvider(&data); 4363 4364 TestCompletionCallback callback; 4365 4366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4367 scoped_ptr<HttpTransaction> trans( 4368 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4369 4370 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4371 4372 EXPECT_EQ(ERR_IO_PENDING, rv); 4373 EXPECT_EQ(OK, callback.WaitForResult()); 4374 4375 const HttpResponseInfo* response = trans->GetResponseInfo(); 4376 ASSERT_TRUE(response != NULL); 4377 ASSERT_TRUE(response->headers.get() != NULL); 4378 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4379 4380 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4381 4382 std::string response_data; 4383 rv = ReadTransaction(trans.get(), &response_data); 4384 EXPECT_EQ(OK, rv); 4385 EXPECT_EQ("hello world", response_data); 4386 4387 // Empty the current queue. This is necessary because idle sockets are 4388 // added to the connection pool asynchronously with a PostTask. 4389 base::MessageLoop::current()->RunUntilIdle(); 4390 4391 // We now check to make sure the socket was added back to the pool. 4392 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4393} 4394 4395// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it 4396// from the pool and make sure that we recover okay. 4397TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) { 4398 HttpRequestInfo request; 4399 request.method = "GET"; 4400 request.url = GURL("https://www.google.com/"); 4401 request.load_flags = 0; 4402 4403 MockWrite data_writes[] = { 4404 MockWrite("GET / HTTP/1.1\r\n" 4405 "Host: www.google.com\r\n" 4406 "Connection: keep-alive\r\n\r\n"), 4407 MockWrite("GET / HTTP/1.1\r\n" 4408 "Host: www.google.com\r\n" 4409 "Connection: keep-alive\r\n\r\n"), 4410 }; 4411 4412 MockRead data_reads[] = { 4413 MockRead("HTTP/1.1 200 OK\r\n"), 4414 MockRead("Content-Length: 11\r\n\r\n"), 4415 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 4416 MockRead("hello world"), 4417 MockRead(ASYNC, 0, 0) // EOF 4418 }; 4419 4420 SSLSocketDataProvider ssl(ASYNC, OK); 4421 SSLSocketDataProvider ssl2(ASYNC, OK); 4422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 4423 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 4424 4425 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4426 data_writes, arraysize(data_writes)); 4427 StaticSocketDataProvider data2(data_reads, arraysize(data_reads), 4428 data_writes, arraysize(data_writes)); 4429 session_deps_.socket_factory->AddSocketDataProvider(&data); 4430 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4431 4432 TestCompletionCallback callback; 4433 4434 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4435 scoped_ptr<HttpTransaction> trans( 4436 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4437 4438 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4439 4440 EXPECT_EQ(ERR_IO_PENDING, rv); 4441 EXPECT_EQ(OK, callback.WaitForResult()); 4442 4443 const HttpResponseInfo* response = trans->GetResponseInfo(); 4444 ASSERT_TRUE(response != NULL); 4445 ASSERT_TRUE(response->headers.get() != NULL); 4446 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4447 4448 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4449 4450 std::string response_data; 4451 rv = ReadTransaction(trans.get(), &response_data); 4452 EXPECT_EQ(OK, rv); 4453 EXPECT_EQ("hello world", response_data); 4454 4455 // Empty the current queue. This is necessary because idle sockets are 4456 // added to the connection pool asynchronously with a PostTask. 4457 base::MessageLoop::current()->RunUntilIdle(); 4458 4459 // We now check to make sure the socket was added back to the pool. 4460 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4461 4462 // Now start the second transaction, which should reuse the previous socket. 4463 4464 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4465 4466 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4467 4468 EXPECT_EQ(ERR_IO_PENDING, rv); 4469 EXPECT_EQ(OK, callback.WaitForResult()); 4470 4471 response = trans->GetResponseInfo(); 4472 ASSERT_TRUE(response != NULL); 4473 ASSERT_TRUE(response->headers.get() != NULL); 4474 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4475 4476 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4477 4478 rv = ReadTransaction(trans.get(), &response_data); 4479 EXPECT_EQ(OK, rv); 4480 EXPECT_EQ("hello world", response_data); 4481 4482 // Empty the current queue. This is necessary because idle sockets are 4483 // added to the connection pool asynchronously with a PostTask. 4484 base::MessageLoop::current()->RunUntilIdle(); 4485 4486 // We now check to make sure the socket was added back to the pool. 4487 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4488} 4489 4490// Make sure that we recycle a socket after a zero-length response. 4491// http://crbug.com/9880 4492TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { 4493 HttpRequestInfo request; 4494 request.method = "GET"; 4495 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&" 4496 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&" 4497 "e=17259,18167,19592,19773,19981,20133,20173,20233&" 4498 "rt=prt.2642,ol.2649,xjs.2951"); 4499 request.load_flags = 0; 4500 4501 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4502 4503 scoped_ptr<HttpTransaction> trans( 4504 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4505 4506 MockRead data_reads[] = { 4507 MockRead("HTTP/1.1 204 No Content\r\n" 4508 "Content-Length: 0\r\n" 4509 "Content-Type: text/html\r\n\r\n"), 4510 MockRead("junk"), // Should not be read!! 4511 MockRead(SYNCHRONOUS, OK), 4512 }; 4513 4514 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4515 session_deps_.socket_factory->AddSocketDataProvider(&data); 4516 4517 TestCompletionCallback callback; 4518 4519 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4520 EXPECT_EQ(ERR_IO_PENDING, rv); 4521 4522 rv = callback.WaitForResult(); 4523 EXPECT_EQ(OK, rv); 4524 4525 const HttpResponseInfo* response = trans->GetResponseInfo(); 4526 ASSERT_TRUE(response != NULL); 4527 4528 EXPECT_TRUE(response->headers.get() != NULL); 4529 std::string status_line = response->headers->GetStatusLine(); 4530 EXPECT_EQ("HTTP/1.1 204 No Content", status_line); 4531 4532 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4533 4534 std::string response_data; 4535 rv = ReadTransaction(trans.get(), &response_data); 4536 EXPECT_EQ(OK, rv); 4537 EXPECT_EQ("", response_data); 4538 4539 // Empty the current queue. This is necessary because idle sockets are 4540 // added to the connection pool asynchronously with a PostTask. 4541 base::MessageLoop::current()->RunUntilIdle(); 4542 4543 // We now check to make sure the socket was added back to the pool. 4544 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get())); 4545} 4546 4547TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { 4548 ScopedVector<UploadElementReader> element_readers; 4549 element_readers.push_back(new UploadBytesElementReader("foo", 3)); 4550 UploadDataStream upload_data_stream(&element_readers, 0); 4551 4552 HttpRequestInfo request[2]; 4553 // Transaction 1: a GET request that succeeds. The socket is recycled 4554 // after use. 4555 request[0].method = "GET"; 4556 request[0].url = GURL("http://www.google.com/"); 4557 request[0].load_flags = 0; 4558 // Transaction 2: a POST request. Reuses the socket kept alive from 4559 // transaction 1. The first attempts fails when writing the POST data. 4560 // This causes the transaction to retry with a new socket. The second 4561 // attempt succeeds. 4562 request[1].method = "POST"; 4563 request[1].url = GURL("http://www.google.com/login.cgi"); 4564 request[1].upload_data_stream = &upload_data_stream; 4565 request[1].load_flags = 0; 4566 4567 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4568 4569 // The first socket is used for transaction 1 and the first attempt of 4570 // transaction 2. 4571 4572 // The response of transaction 1. 4573 MockRead data_reads1[] = { 4574 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"), 4575 MockRead("hello world"), 4576 MockRead(SYNCHRONOUS, OK), 4577 }; 4578 // The mock write results of transaction 1 and the first attempt of 4579 // transaction 2. 4580 MockWrite data_writes1[] = { 4581 MockWrite(SYNCHRONOUS, 64), // GET 4582 MockWrite(SYNCHRONOUS, 93), // POST 4583 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data 4584 }; 4585 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4586 data_writes1, arraysize(data_writes1)); 4587 4588 // The second socket is used for the second attempt of transaction 2. 4589 4590 // The response of transaction 2. 4591 MockRead data_reads2[] = { 4592 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"), 4593 MockRead("welcome"), 4594 MockRead(SYNCHRONOUS, OK), 4595 }; 4596 // The mock write results of the second attempt of transaction 2. 4597 MockWrite data_writes2[] = { 4598 MockWrite(SYNCHRONOUS, 93), // POST 4599 MockWrite(SYNCHRONOUS, 3), // POST data 4600 }; 4601 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4602 data_writes2, arraysize(data_writes2)); 4603 4604 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4605 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4606 4607 const char* kExpectedResponseData[] = { 4608 "hello world", "welcome" 4609 }; 4610 4611 for (int i = 0; i < 2; ++i) { 4612 scoped_ptr<HttpTransaction> trans( 4613 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4614 4615 TestCompletionCallback callback; 4616 4617 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog()); 4618 EXPECT_EQ(ERR_IO_PENDING, rv); 4619 4620 rv = callback.WaitForResult(); 4621 EXPECT_EQ(OK, rv); 4622 4623 const HttpResponseInfo* response = trans->GetResponseInfo(); 4624 ASSERT_TRUE(response != NULL); 4625 4626 EXPECT_TRUE(response->headers.get() != NULL); 4627 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4628 4629 std::string response_data; 4630 rv = ReadTransaction(trans.get(), &response_data); 4631 EXPECT_EQ(OK, rv); 4632 EXPECT_EQ(kExpectedResponseData[i], response_data); 4633 } 4634} 4635 4636// Test the request-challenge-retry sequence for basic auth when there is 4637// an identity in the URL. The request should be sent as normal, but when 4638// it fails the identity from the URL is used to answer the challenge. 4639TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) { 4640 HttpRequestInfo request; 4641 request.method = "GET"; 4642 request.url = GURL("http://foo:b@r@www.google.com/"); 4643 request.load_flags = LOAD_NORMAL; 4644 4645 scoped_ptr<HttpTransaction> trans( 4646 new HttpNetworkTransaction(DEFAULT_PRIORITY, 4647 CreateSession(&session_deps_))); 4648 4649 // The password contains an escaped character -- for this test to pass it 4650 // will need to be unescaped by HttpNetworkTransaction. 4651 EXPECT_EQ("b%40r", request.url.password()); 4652 4653 MockWrite data_writes1[] = { 4654 MockWrite("GET / HTTP/1.1\r\n" 4655 "Host: www.google.com\r\n" 4656 "Connection: keep-alive\r\n\r\n"), 4657 }; 4658 4659 MockRead data_reads1[] = { 4660 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4661 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4662 MockRead("Content-Length: 10\r\n\r\n"), 4663 MockRead(SYNCHRONOUS, ERR_FAILED), 4664 }; 4665 4666 // After the challenge above, the transaction will be restarted using the 4667 // identity from the url (foo, b@r) to answer the challenge. 4668 MockWrite data_writes2[] = { 4669 MockWrite("GET / HTTP/1.1\r\n" 4670 "Host: www.google.com\r\n" 4671 "Connection: keep-alive\r\n" 4672 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"), 4673 }; 4674 4675 MockRead data_reads2[] = { 4676 MockRead("HTTP/1.0 200 OK\r\n"), 4677 MockRead("Content-Length: 100\r\n\r\n"), 4678 MockRead(SYNCHRONOUS, OK), 4679 }; 4680 4681 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4682 data_writes1, arraysize(data_writes1)); 4683 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4684 data_writes2, arraysize(data_writes2)); 4685 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4686 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4687 4688 TestCompletionCallback callback1; 4689 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4690 EXPECT_EQ(ERR_IO_PENDING, rv); 4691 rv = callback1.WaitForResult(); 4692 EXPECT_EQ(OK, rv); 4693 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4694 4695 TestCompletionCallback callback2; 4696 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 4697 EXPECT_EQ(ERR_IO_PENDING, rv); 4698 rv = callback2.WaitForResult(); 4699 EXPECT_EQ(OK, rv); 4700 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4701 4702 const HttpResponseInfo* response = trans->GetResponseInfo(); 4703 ASSERT_TRUE(response != NULL); 4704 4705 // There is no challenge info, since the identity in URL worked. 4706 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4707 4708 EXPECT_EQ(100, response->headers->GetContentLength()); 4709 4710 // Empty the current queue. 4711 base::MessageLoop::current()->RunUntilIdle(); 4712} 4713 4714// Test the request-challenge-retry sequence for basic auth when there is an 4715// incorrect identity in the URL. The identity from the URL should be used only 4716// once. 4717TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) { 4718 HttpRequestInfo request; 4719 request.method = "GET"; 4720 // Note: the URL has a username:password in it. The password "baz" is 4721 // wrong (should be "bar"). 4722 request.url = GURL("http://foo:baz@www.google.com/"); 4723 4724 request.load_flags = LOAD_NORMAL; 4725 4726 scoped_ptr<HttpTransaction> trans( 4727 new HttpNetworkTransaction(DEFAULT_PRIORITY, 4728 CreateSession(&session_deps_))); 4729 4730 MockWrite data_writes1[] = { 4731 MockWrite("GET / HTTP/1.1\r\n" 4732 "Host: www.google.com\r\n" 4733 "Connection: keep-alive\r\n\r\n"), 4734 }; 4735 4736 MockRead data_reads1[] = { 4737 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4738 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4739 MockRead("Content-Length: 10\r\n\r\n"), 4740 MockRead(SYNCHRONOUS, ERR_FAILED), 4741 }; 4742 4743 // After the challenge above, the transaction will be restarted using the 4744 // identity from the url (foo, baz) to answer the challenge. 4745 MockWrite data_writes2[] = { 4746 MockWrite("GET / HTTP/1.1\r\n" 4747 "Host: www.google.com\r\n" 4748 "Connection: keep-alive\r\n" 4749 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 4750 }; 4751 4752 MockRead data_reads2[] = { 4753 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4755 MockRead("Content-Length: 10\r\n\r\n"), 4756 MockRead(SYNCHRONOUS, ERR_FAILED), 4757 }; 4758 4759 // After the challenge above, the transaction will be restarted using the 4760 // identity supplied by the user (foo, bar) to answer the challenge. 4761 MockWrite data_writes3[] = { 4762 MockWrite("GET / HTTP/1.1\r\n" 4763 "Host: www.google.com\r\n" 4764 "Connection: keep-alive\r\n" 4765 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 4766 }; 4767 4768 MockRead data_reads3[] = { 4769 MockRead("HTTP/1.0 200 OK\r\n"), 4770 MockRead("Content-Length: 100\r\n\r\n"), 4771 MockRead(SYNCHRONOUS, OK), 4772 }; 4773 4774 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4775 data_writes1, arraysize(data_writes1)); 4776 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4777 data_writes2, arraysize(data_writes2)); 4778 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4779 data_writes3, arraysize(data_writes3)); 4780 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4781 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4782 session_deps_.socket_factory->AddSocketDataProvider(&data3); 4783 4784 TestCompletionCallback callback1; 4785 4786 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4787 EXPECT_EQ(ERR_IO_PENDING, rv); 4788 4789 rv = callback1.WaitForResult(); 4790 EXPECT_EQ(OK, rv); 4791 4792 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4793 TestCompletionCallback callback2; 4794 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 4795 EXPECT_EQ(ERR_IO_PENDING, rv); 4796 rv = callback2.WaitForResult(); 4797 EXPECT_EQ(OK, rv); 4798 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4799 4800 const HttpResponseInfo* response = trans->GetResponseInfo(); 4801 ASSERT_TRUE(response != NULL); 4802 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 4803 4804 TestCompletionCallback callback3; 4805 rv = trans->RestartWithAuth( 4806 AuthCredentials(kFoo, kBar), callback3.callback()); 4807 EXPECT_EQ(ERR_IO_PENDING, rv); 4808 rv = callback3.WaitForResult(); 4809 EXPECT_EQ(OK, rv); 4810 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4811 4812 response = trans->GetResponseInfo(); 4813 ASSERT_TRUE(response != NULL); 4814 4815 // There is no challenge info, since the identity worked. 4816 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4817 4818 EXPECT_EQ(100, response->headers->GetContentLength()); 4819 4820 // Empty the current queue. 4821 base::MessageLoop::current()->RunUntilIdle(); 4822} 4823 4824// Test that previously tried username/passwords for a realm get re-used. 4825TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) { 4826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4827 4828 // Transaction 1: authenticate (foo, bar) on MyRealm1 4829 { 4830 HttpRequestInfo request; 4831 request.method = "GET"; 4832 request.url = GURL("http://www.google.com/x/y/z"); 4833 request.load_flags = 0; 4834 4835 scoped_ptr<HttpTransaction> trans( 4836 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4837 4838 MockWrite data_writes1[] = { 4839 MockWrite("GET /x/y/z HTTP/1.1\r\n" 4840 "Host: www.google.com\r\n" 4841 "Connection: keep-alive\r\n\r\n"), 4842 }; 4843 4844 MockRead data_reads1[] = { 4845 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4846 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4847 MockRead("Content-Length: 10000\r\n\r\n"), 4848 MockRead(SYNCHRONOUS, ERR_FAILED), 4849 }; 4850 4851 // Resend with authorization (username=foo, password=bar) 4852 MockWrite data_writes2[] = { 4853 MockWrite("GET /x/y/z HTTP/1.1\r\n" 4854 "Host: www.google.com\r\n" 4855 "Connection: keep-alive\r\n" 4856 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 4857 }; 4858 4859 // Sever accepts the authorization. 4860 MockRead data_reads2[] = { 4861 MockRead("HTTP/1.0 200 OK\r\n"), 4862 MockRead("Content-Length: 100\r\n\r\n"), 4863 MockRead(SYNCHRONOUS, OK), 4864 }; 4865 4866 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4867 data_writes1, arraysize(data_writes1)); 4868 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4869 data_writes2, arraysize(data_writes2)); 4870 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4871 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4872 4873 TestCompletionCallback callback1; 4874 4875 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4876 EXPECT_EQ(ERR_IO_PENDING, rv); 4877 4878 rv = callback1.WaitForResult(); 4879 EXPECT_EQ(OK, rv); 4880 4881 const HttpResponseInfo* response = trans->GetResponseInfo(); 4882 ASSERT_TRUE(response != NULL); 4883 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 4884 4885 TestCompletionCallback callback2; 4886 4887 rv = trans->RestartWithAuth( 4888 AuthCredentials(kFoo, kBar), callback2.callback()); 4889 EXPECT_EQ(ERR_IO_PENDING, rv); 4890 4891 rv = callback2.WaitForResult(); 4892 EXPECT_EQ(OK, rv); 4893 4894 response = trans->GetResponseInfo(); 4895 ASSERT_TRUE(response != NULL); 4896 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4897 EXPECT_EQ(100, response->headers->GetContentLength()); 4898 } 4899 4900 // ------------------------------------------------------------------------ 4901 4902 // Transaction 2: authenticate (foo2, bar2) on MyRealm2 4903 { 4904 HttpRequestInfo request; 4905 request.method = "GET"; 4906 // Note that Transaction 1 was at /x/y/z, so this is in the same 4907 // protection space as MyRealm1. 4908 request.url = GURL("http://www.google.com/x/y/a/b"); 4909 request.load_flags = 0; 4910 4911 scoped_ptr<HttpTransaction> trans( 4912 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4913 4914 MockWrite data_writes1[] = { 4915 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 4916 "Host: www.google.com\r\n" 4917 "Connection: keep-alive\r\n" 4918 // Send preemptive authorization for MyRealm1 4919 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 4920 }; 4921 4922 // The server didn't like the preemptive authorization, and 4923 // challenges us for a different realm (MyRealm2). 4924 MockRead data_reads1[] = { 4925 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4926 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"), 4927 MockRead("Content-Length: 10000\r\n\r\n"), 4928 MockRead(SYNCHRONOUS, ERR_FAILED), 4929 }; 4930 4931 // Resend with authorization for MyRealm2 (username=foo2, password=bar2) 4932 MockWrite data_writes2[] = { 4933 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 4934 "Host: www.google.com\r\n" 4935 "Connection: keep-alive\r\n" 4936 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 4937 }; 4938 4939 // Sever accepts the authorization. 4940 MockRead data_reads2[] = { 4941 MockRead("HTTP/1.0 200 OK\r\n"), 4942 MockRead("Content-Length: 100\r\n\r\n"), 4943 MockRead(SYNCHRONOUS, OK), 4944 }; 4945 4946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4947 data_writes1, arraysize(data_writes1)); 4948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4949 data_writes2, arraysize(data_writes2)); 4950 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4951 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4952 4953 TestCompletionCallback callback1; 4954 4955 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4956 EXPECT_EQ(ERR_IO_PENDING, rv); 4957 4958 rv = callback1.WaitForResult(); 4959 EXPECT_EQ(OK, rv); 4960 4961 const HttpResponseInfo* response = trans->GetResponseInfo(); 4962 ASSERT_TRUE(response != NULL); 4963 ASSERT_TRUE(response->auth_challenge.get()); 4964 EXPECT_FALSE(response->auth_challenge->is_proxy); 4965 EXPECT_EQ("www.google.com:80", 4966 response->auth_challenge->challenger.ToString()); 4967 EXPECT_EQ("MyRealm2", response->auth_challenge->realm); 4968 EXPECT_EQ("basic", response->auth_challenge->scheme); 4969 4970 TestCompletionCallback callback2; 4971 4972 rv = trans->RestartWithAuth( 4973 AuthCredentials(kFoo2, kBar2), callback2.callback()); 4974 EXPECT_EQ(ERR_IO_PENDING, rv); 4975 4976 rv = callback2.WaitForResult(); 4977 EXPECT_EQ(OK, rv); 4978 4979 response = trans->GetResponseInfo(); 4980 ASSERT_TRUE(response != NULL); 4981 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4982 EXPECT_EQ(100, response->headers->GetContentLength()); 4983 } 4984 4985 // ------------------------------------------------------------------------ 4986 4987 // Transaction 3: Resend a request in MyRealm's protection space -- 4988 // succeed with preemptive authorization. 4989 { 4990 HttpRequestInfo request; 4991 request.method = "GET"; 4992 request.url = GURL("http://www.google.com/x/y/z2"); 4993 request.load_flags = 0; 4994 4995 scoped_ptr<HttpTransaction> trans( 4996 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4997 4998 MockWrite data_writes1[] = { 4999 MockWrite("GET /x/y/z2 HTTP/1.1\r\n" 5000 "Host: www.google.com\r\n" 5001 "Connection: keep-alive\r\n" 5002 // The authorization for MyRealm1 gets sent preemptively 5003 // (since the url is in the same protection space) 5004 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5005 }; 5006 5007 // Sever accepts the preemptive authorization 5008 MockRead data_reads1[] = { 5009 MockRead("HTTP/1.0 200 OK\r\n"), 5010 MockRead("Content-Length: 100\r\n\r\n"), 5011 MockRead(SYNCHRONOUS, OK), 5012 }; 5013 5014 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5015 data_writes1, arraysize(data_writes1)); 5016 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5017 5018 TestCompletionCallback callback1; 5019 5020 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5021 EXPECT_EQ(ERR_IO_PENDING, rv); 5022 5023 rv = callback1.WaitForResult(); 5024 EXPECT_EQ(OK, rv); 5025 5026 const HttpResponseInfo* response = trans->GetResponseInfo(); 5027 ASSERT_TRUE(response != NULL); 5028 5029 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5030 EXPECT_EQ(100, response->headers->GetContentLength()); 5031 } 5032 5033 // ------------------------------------------------------------------------ 5034 5035 // Transaction 4: request another URL in MyRealm (however the 5036 // url is not known to belong to the protection space, so no pre-auth). 5037 { 5038 HttpRequestInfo request; 5039 request.method = "GET"; 5040 request.url = GURL("http://www.google.com/x/1"); 5041 request.load_flags = 0; 5042 5043 scoped_ptr<HttpTransaction> trans( 5044 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5045 5046 MockWrite data_writes1[] = { 5047 MockWrite("GET /x/1 HTTP/1.1\r\n" 5048 "Host: www.google.com\r\n" 5049 "Connection: keep-alive\r\n\r\n"), 5050 }; 5051 5052 MockRead data_reads1[] = { 5053 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5054 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5055 MockRead("Content-Length: 10000\r\n\r\n"), 5056 MockRead(SYNCHRONOUS, ERR_FAILED), 5057 }; 5058 5059 // Resend with authorization from MyRealm's cache. 5060 MockWrite data_writes2[] = { 5061 MockWrite("GET /x/1 HTTP/1.1\r\n" 5062 "Host: www.google.com\r\n" 5063 "Connection: keep-alive\r\n" 5064 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5065 }; 5066 5067 // Sever accepts the authorization. 5068 MockRead data_reads2[] = { 5069 MockRead("HTTP/1.0 200 OK\r\n"), 5070 MockRead("Content-Length: 100\r\n\r\n"), 5071 MockRead(SYNCHRONOUS, OK), 5072 }; 5073 5074 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5075 data_writes1, arraysize(data_writes1)); 5076 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5077 data_writes2, arraysize(data_writes2)); 5078 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5079 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5080 5081 TestCompletionCallback callback1; 5082 5083 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5084 EXPECT_EQ(ERR_IO_PENDING, rv); 5085 5086 rv = callback1.WaitForResult(); 5087 EXPECT_EQ(OK, rv); 5088 5089 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5090 TestCompletionCallback callback2; 5091 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5092 EXPECT_EQ(ERR_IO_PENDING, rv); 5093 rv = callback2.WaitForResult(); 5094 EXPECT_EQ(OK, rv); 5095 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5096 5097 const HttpResponseInfo* response = trans->GetResponseInfo(); 5098 ASSERT_TRUE(response != NULL); 5099 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5100 EXPECT_EQ(100, response->headers->GetContentLength()); 5101 } 5102 5103 // ------------------------------------------------------------------------ 5104 5105 // Transaction 5: request a URL in MyRealm, but the server rejects the 5106 // cached identity. Should invalidate and re-prompt. 5107 { 5108 HttpRequestInfo request; 5109 request.method = "GET"; 5110 request.url = GURL("http://www.google.com/p/q/t"); 5111 request.load_flags = 0; 5112 5113 scoped_ptr<HttpTransaction> trans( 5114 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5115 5116 MockWrite data_writes1[] = { 5117 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5118 "Host: www.google.com\r\n" 5119 "Connection: keep-alive\r\n\r\n"), 5120 }; 5121 5122 MockRead data_reads1[] = { 5123 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5124 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5125 MockRead("Content-Length: 10000\r\n\r\n"), 5126 MockRead(SYNCHRONOUS, ERR_FAILED), 5127 }; 5128 5129 // Resend with authorization from cache for MyRealm. 5130 MockWrite data_writes2[] = { 5131 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5132 "Host: www.google.com\r\n" 5133 "Connection: keep-alive\r\n" 5134 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5135 }; 5136 5137 // Sever rejects the authorization. 5138 MockRead data_reads2[] = { 5139 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5140 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5141 MockRead("Content-Length: 10000\r\n\r\n"), 5142 MockRead(SYNCHRONOUS, ERR_FAILED), 5143 }; 5144 5145 // At this point we should prompt for new credentials for MyRealm. 5146 // Restart with username=foo3, password=foo4. 5147 MockWrite data_writes3[] = { 5148 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5149 "Host: www.google.com\r\n" 5150 "Connection: keep-alive\r\n" 5151 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"), 5152 }; 5153 5154 // Sever accepts the authorization. 5155 MockRead data_reads3[] = { 5156 MockRead("HTTP/1.0 200 OK\r\n"), 5157 MockRead("Content-Length: 100\r\n\r\n"), 5158 MockRead(SYNCHRONOUS, OK), 5159 }; 5160 5161 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5162 data_writes1, arraysize(data_writes1)); 5163 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5164 data_writes2, arraysize(data_writes2)); 5165 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 5166 data_writes3, arraysize(data_writes3)); 5167 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5168 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5169 session_deps_.socket_factory->AddSocketDataProvider(&data3); 5170 5171 TestCompletionCallback callback1; 5172 5173 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5174 EXPECT_EQ(ERR_IO_PENDING, rv); 5175 5176 rv = callback1.WaitForResult(); 5177 EXPECT_EQ(OK, rv); 5178 5179 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5180 TestCompletionCallback callback2; 5181 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5182 EXPECT_EQ(ERR_IO_PENDING, rv); 5183 rv = callback2.WaitForResult(); 5184 EXPECT_EQ(OK, rv); 5185 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5186 5187 const HttpResponseInfo* response = trans->GetResponseInfo(); 5188 ASSERT_TRUE(response != NULL); 5189 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5190 5191 TestCompletionCallback callback3; 5192 5193 rv = trans->RestartWithAuth( 5194 AuthCredentials(kFoo3, kBar3), callback3.callback()); 5195 EXPECT_EQ(ERR_IO_PENDING, rv); 5196 5197 rv = callback3.WaitForResult(); 5198 EXPECT_EQ(OK, rv); 5199 5200 response = trans->GetResponseInfo(); 5201 ASSERT_TRUE(response != NULL); 5202 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5203 EXPECT_EQ(100, response->headers->GetContentLength()); 5204 } 5205} 5206 5207// Tests that nonce count increments when multiple auth attempts 5208// are started with the same nonce. 5209TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) { 5210 HttpAuthHandlerDigest::Factory* digest_factory = 5211 new HttpAuthHandlerDigest::Factory(); 5212 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator = 5213 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef"); 5214 digest_factory->set_nonce_generator(nonce_generator); 5215 session_deps_.http_auth_handler_factory.reset(digest_factory); 5216 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5217 5218 // Transaction 1: authenticate (foo, bar) on MyRealm1 5219 { 5220 HttpRequestInfo request; 5221 request.method = "GET"; 5222 request.url = GURL("http://www.google.com/x/y/z"); 5223 request.load_flags = 0; 5224 5225 scoped_ptr<HttpTransaction> trans( 5226 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5227 5228 MockWrite data_writes1[] = { 5229 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5230 "Host: www.google.com\r\n" 5231 "Connection: keep-alive\r\n\r\n"), 5232 }; 5233 5234 MockRead data_reads1[] = { 5235 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5236 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", " 5237 "algorithm=MD5, qop=\"auth\"\r\n\r\n"), 5238 MockRead(SYNCHRONOUS, OK), 5239 }; 5240 5241 // Resend with authorization (username=foo, password=bar) 5242 MockWrite data_writes2[] = { 5243 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5244 "Host: www.google.com\r\n" 5245 "Connection: keep-alive\r\n" 5246 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 5247 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, " 5248 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, " 5249 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"), 5250 }; 5251 5252 // Sever accepts the authorization. 5253 MockRead data_reads2[] = { 5254 MockRead("HTTP/1.0 200 OK\r\n"), 5255 MockRead(SYNCHRONOUS, OK), 5256 }; 5257 5258 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5259 data_writes1, arraysize(data_writes1)); 5260 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5261 data_writes2, arraysize(data_writes2)); 5262 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5263 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5264 5265 TestCompletionCallback callback1; 5266 5267 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5268 EXPECT_EQ(ERR_IO_PENDING, rv); 5269 5270 rv = callback1.WaitForResult(); 5271 EXPECT_EQ(OK, rv); 5272 5273 const HttpResponseInfo* response = trans->GetResponseInfo(); 5274 ASSERT_TRUE(response != NULL); 5275 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get())); 5276 5277 TestCompletionCallback callback2; 5278 5279 rv = trans->RestartWithAuth( 5280 AuthCredentials(kFoo, kBar), callback2.callback()); 5281 EXPECT_EQ(ERR_IO_PENDING, rv); 5282 5283 rv = callback2.WaitForResult(); 5284 EXPECT_EQ(OK, rv); 5285 5286 response = trans->GetResponseInfo(); 5287 ASSERT_TRUE(response != NULL); 5288 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5289 } 5290 5291 // ------------------------------------------------------------------------ 5292 5293 // Transaction 2: Request another resource in digestive's protection space. 5294 // This will preemptively add an Authorization header which should have an 5295 // "nc" value of 2 (as compared to 1 in the first use. 5296 { 5297 HttpRequestInfo request; 5298 request.method = "GET"; 5299 // Note that Transaction 1 was at /x/y/z, so this is in the same 5300 // protection space as digest. 5301 request.url = GURL("http://www.google.com/x/y/a/b"); 5302 request.load_flags = 0; 5303 5304 scoped_ptr<HttpTransaction> trans( 5305 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5306 5307 MockWrite data_writes1[] = { 5308 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5309 "Host: www.google.com\r\n" 5310 "Connection: keep-alive\r\n" 5311 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 5312 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, " 5313 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, " 5314 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"), 5315 }; 5316 5317 // Sever accepts the authorization. 5318 MockRead data_reads1[] = { 5319 MockRead("HTTP/1.0 200 OK\r\n"), 5320 MockRead("Content-Length: 100\r\n\r\n"), 5321 MockRead(SYNCHRONOUS, OK), 5322 }; 5323 5324 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5325 data_writes1, arraysize(data_writes1)); 5326 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5327 5328 TestCompletionCallback callback1; 5329 5330 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5331 EXPECT_EQ(ERR_IO_PENDING, rv); 5332 5333 rv = callback1.WaitForResult(); 5334 EXPECT_EQ(OK, rv); 5335 5336 const HttpResponseInfo* response = trans->GetResponseInfo(); 5337 ASSERT_TRUE(response != NULL); 5338 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5339 } 5340} 5341 5342// Test the ResetStateForRestart() private method. 5343TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) { 5344 // Create a transaction (the dependencies aren't important). 5345 scoped_ptr<HttpNetworkTransaction> trans( 5346 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5347 CreateSession(&session_deps_))); 5348 5349 // Setup some state (which we expect ResetStateForRestart() will clear). 5350 trans->read_buf_ = new IOBuffer(15); 5351 trans->read_buf_len_ = 15; 5352 trans->request_headers_.SetHeader("Authorization", "NTLM"); 5353 5354 // Setup state in response_ 5355 HttpResponseInfo* response = &trans->response_; 5356 response->auth_challenge = new AuthChallengeInfo(); 5357 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical. 5358 response->response_time = base::Time::Now(); 5359 response->was_cached = true; // (Wouldn't ever actually be true...) 5360 5361 { // Setup state for response_.vary_data 5362 HttpRequestInfo request; 5363 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n"); 5364 std::replace(temp.begin(), temp.end(), '\n', '\0'); 5365 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp)); 5366 request.extra_headers.SetHeader("Foo", "1"); 5367 request.extra_headers.SetHeader("bar", "23"); 5368 EXPECT_TRUE(response->vary_data.Init(request, *headers.get())); 5369 } 5370 5371 // Cause the above state to be reset. 5372 trans->ResetStateForRestart(); 5373 5374 // Verify that the state that needed to be reset, has been reset. 5375 EXPECT_TRUE(trans->read_buf_.get() == NULL); 5376 EXPECT_EQ(0, trans->read_buf_len_); 5377 EXPECT_TRUE(trans->request_headers_.IsEmpty()); 5378 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5379 EXPECT_TRUE(response->headers.get() == NULL); 5380 EXPECT_FALSE(response->was_cached); 5381 EXPECT_EQ(0U, response->ssl_info.cert_status); 5382 EXPECT_FALSE(response->vary_data.is_valid()); 5383} 5384 5385// Test HTTPS connections to a site with a bad certificate 5386TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) { 5387 HttpRequestInfo request; 5388 request.method = "GET"; 5389 request.url = GURL("https://www.google.com/"); 5390 request.load_flags = 0; 5391 5392 scoped_ptr<HttpTransaction> trans( 5393 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5394 CreateSession(&session_deps_))); 5395 5396 MockWrite data_writes[] = { 5397 MockWrite("GET / HTTP/1.1\r\n" 5398 "Host: www.google.com\r\n" 5399 "Connection: keep-alive\r\n\r\n"), 5400 }; 5401 5402 MockRead data_reads[] = { 5403 MockRead("HTTP/1.0 200 OK\r\n"), 5404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5405 MockRead("Content-Length: 100\r\n\r\n"), 5406 MockRead(SYNCHRONOUS, OK), 5407 }; 5408 5409 StaticSocketDataProvider ssl_bad_certificate; 5410 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5411 data_writes, arraysize(data_writes)); 5412 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 5413 SSLSocketDataProvider ssl(ASYNC, OK); 5414 5415 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 5416 session_deps_.socket_factory->AddSocketDataProvider(&data); 5417 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 5418 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 5419 5420 TestCompletionCallback callback; 5421 5422 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5423 EXPECT_EQ(ERR_IO_PENDING, rv); 5424 5425 rv = callback.WaitForResult(); 5426 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 5427 5428 rv = trans->RestartIgnoringLastError(callback.callback()); 5429 EXPECT_EQ(ERR_IO_PENDING, rv); 5430 5431 rv = callback.WaitForResult(); 5432 EXPECT_EQ(OK, rv); 5433 5434 const HttpResponseInfo* response = trans->GetResponseInfo(); 5435 5436 ASSERT_TRUE(response != NULL); 5437 EXPECT_EQ(100, response->headers->GetContentLength()); 5438} 5439 5440// Test HTTPS connections to a site with a bad certificate, going through a 5441// proxy 5442TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { 5443 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 5444 5445 HttpRequestInfo request; 5446 request.method = "GET"; 5447 request.url = GURL("https://www.google.com/"); 5448 request.load_flags = 0; 5449 5450 MockWrite proxy_writes[] = { 5451 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5452 "Host: www.google.com\r\n" 5453 "Proxy-Connection: keep-alive\r\n\r\n"), 5454 }; 5455 5456 MockRead proxy_reads[] = { 5457 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5458 MockRead(SYNCHRONOUS, OK) 5459 }; 5460 5461 MockWrite data_writes[] = { 5462 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5463 "Host: www.google.com\r\n" 5464 "Proxy-Connection: keep-alive\r\n\r\n"), 5465 MockWrite("GET / HTTP/1.1\r\n" 5466 "Host: www.google.com\r\n" 5467 "Connection: keep-alive\r\n\r\n"), 5468 }; 5469 5470 MockRead data_reads[] = { 5471 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5472 MockRead("HTTP/1.0 200 OK\r\n"), 5473 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5474 MockRead("Content-Length: 100\r\n\r\n"), 5475 MockRead(SYNCHRONOUS, OK), 5476 }; 5477 5478 StaticSocketDataProvider ssl_bad_certificate( 5479 proxy_reads, arraysize(proxy_reads), 5480 proxy_writes, arraysize(proxy_writes)); 5481 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5482 data_writes, arraysize(data_writes)); 5483 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 5484 SSLSocketDataProvider ssl(ASYNC, OK); 5485 5486 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 5487 session_deps_.socket_factory->AddSocketDataProvider(&data); 5488 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 5489 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 5490 5491 TestCompletionCallback callback; 5492 5493 for (int i = 0; i < 2; i++) { 5494 session_deps_.socket_factory->ResetNextMockIndexes(); 5495 5496 scoped_ptr<HttpTransaction> trans( 5497 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5498 CreateSession(&session_deps_))); 5499 5500 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5501 EXPECT_EQ(ERR_IO_PENDING, rv); 5502 5503 rv = callback.WaitForResult(); 5504 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 5505 5506 rv = trans->RestartIgnoringLastError(callback.callback()); 5507 EXPECT_EQ(ERR_IO_PENDING, rv); 5508 5509 rv = callback.WaitForResult(); 5510 EXPECT_EQ(OK, rv); 5511 5512 const HttpResponseInfo* response = trans->GetResponseInfo(); 5513 5514 ASSERT_TRUE(response != NULL); 5515 EXPECT_EQ(100, response->headers->GetContentLength()); 5516 } 5517} 5518 5519 5520// Test HTTPS connections to a site, going through an HTTPS proxy 5521TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { 5522 session_deps_.proxy_service.reset( 5523 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 5524 CapturingNetLog net_log; 5525 session_deps_.net_log = &net_log; 5526 5527 HttpRequestInfo request; 5528 request.method = "GET"; 5529 request.url = GURL("https://www.google.com/"); 5530 request.load_flags = 0; 5531 5532 MockWrite data_writes[] = { 5533 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5534 "Host: www.google.com\r\n" 5535 "Proxy-Connection: keep-alive\r\n\r\n"), 5536 MockWrite("GET / HTTP/1.1\r\n" 5537 "Host: www.google.com\r\n" 5538 "Connection: keep-alive\r\n\r\n"), 5539 }; 5540 5541 MockRead data_reads[] = { 5542 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5543 MockRead("HTTP/1.1 200 OK\r\n"), 5544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5545 MockRead("Content-Length: 100\r\n\r\n"), 5546 MockRead(SYNCHRONOUS, OK), 5547 }; 5548 5549 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5550 data_writes, arraysize(data_writes)); 5551 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5552 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel 5553 5554 session_deps_.socket_factory->AddSocketDataProvider(&data); 5555 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5556 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl); 5557 5558 TestCompletionCallback callback; 5559 5560 scoped_ptr<HttpTransaction> trans( 5561 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5562 CreateSession(&session_deps_))); 5563 5564 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5565 EXPECT_EQ(ERR_IO_PENDING, rv); 5566 5567 rv = callback.WaitForResult(); 5568 EXPECT_EQ(OK, rv); 5569 const HttpResponseInfo* response = trans->GetResponseInfo(); 5570 5571 ASSERT_TRUE(response != NULL); 5572 5573 EXPECT_TRUE(response->headers->IsKeepAlive()); 5574 EXPECT_EQ(200, response->headers->response_code()); 5575 EXPECT_EQ(100, response->headers->GetContentLength()); 5576 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 5577 5578 LoadTimingInfo load_timing_info; 5579 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 5580 TestLoadTimingNotReusedWithPac(load_timing_info, 5581 CONNECT_TIMING_HAS_SSL_TIMES); 5582} 5583 5584// Test an HTTPS Proxy's ability to redirect a CONNECT request 5585TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { 5586 session_deps_.proxy_service.reset( 5587 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 5588 CapturingNetLog net_log; 5589 session_deps_.net_log = &net_log; 5590 5591 HttpRequestInfo request; 5592 request.method = "GET"; 5593 request.url = GURL("https://www.google.com/"); 5594 request.load_flags = 0; 5595 5596 MockWrite data_writes[] = { 5597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5598 "Host: www.google.com\r\n" 5599 "Proxy-Connection: keep-alive\r\n\r\n"), 5600 }; 5601 5602 MockRead data_reads[] = { 5603 MockRead("HTTP/1.1 302 Redirect\r\n"), 5604 MockRead("Location: http://login.example.com/\r\n"), 5605 MockRead("Content-Length: 0\r\n\r\n"), 5606 MockRead(SYNCHRONOUS, OK), 5607 }; 5608 5609 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5610 data_writes, arraysize(data_writes)); 5611 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5612 5613 session_deps_.socket_factory->AddSocketDataProvider(&data); 5614 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5615 5616 TestCompletionCallback callback; 5617 5618 scoped_ptr<HttpTransaction> trans( 5619 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5620 CreateSession(&session_deps_))); 5621 5622 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5623 EXPECT_EQ(ERR_IO_PENDING, rv); 5624 5625 rv = callback.WaitForResult(); 5626 EXPECT_EQ(OK, rv); 5627 const HttpResponseInfo* response = trans->GetResponseInfo(); 5628 5629 ASSERT_TRUE(response != NULL); 5630 5631 EXPECT_EQ(302, response->headers->response_code()); 5632 std::string url; 5633 EXPECT_TRUE(response->headers->IsRedirect(&url)); 5634 EXPECT_EQ("http://login.example.com/", url); 5635 5636 // In the case of redirects from proxies, HttpNetworkTransaction returns 5637 // timing for the proxy connection instead of the connection to the host, 5638 // and no send / receive times. 5639 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse. 5640 LoadTimingInfo load_timing_info; 5641 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 5642 5643 EXPECT_FALSE(load_timing_info.socket_reused); 5644 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 5645 5646 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 5647 EXPECT_LE(load_timing_info.proxy_resolve_start, 5648 load_timing_info.proxy_resolve_end); 5649 EXPECT_LE(load_timing_info.proxy_resolve_end, 5650 load_timing_info.connect_timing.connect_start); 5651 ExpectConnectTimingHasTimes( 5652 load_timing_info.connect_timing, 5653 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES); 5654 5655 EXPECT_TRUE(load_timing_info.send_start.is_null()); 5656 EXPECT_TRUE(load_timing_info.send_end.is_null()); 5657 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 5658} 5659 5660// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request 5661TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { 5662 session_deps_.proxy_service.reset( 5663 ProxyService::CreateFixed("https://proxy:70")); 5664 5665 HttpRequestInfo request; 5666 request.method = "GET"; 5667 request.url = GURL("https://www.google.com/"); 5668 request.load_flags = 0; 5669 5670 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 5671 scoped_ptr<SpdyFrame> goaway( 5672 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 5673 MockWrite data_writes[] = { 5674 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), 5675 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS), 5676 }; 5677 5678 static const char* const kExtraHeaders[] = { 5679 "location", 5680 "http://login.example.com/", 5681 }; 5682 scoped_ptr<SpdyFrame> resp( 5683 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders, 5684 arraysize(kExtraHeaders)/2, 1)); 5685 MockRead data_reads[] = { 5686 CreateMockRead(*resp.get(), 1, SYNCHRONOUS), 5687 MockRead(ASYNC, 0, 2), // EOF 5688 }; 5689 5690 DelayedSocketData data( 5691 1, // wait for one write to finish before reading. 5692 data_reads, arraysize(data_reads), 5693 data_writes, arraysize(data_writes)); 5694 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5695 proxy_ssl.SetNextProto(GetParam()); 5696 5697 session_deps_.socket_factory->AddSocketDataProvider(&data); 5698 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5699 5700 TestCompletionCallback callback; 5701 5702 scoped_ptr<HttpTransaction> trans( 5703 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5704 CreateSession(&session_deps_))); 5705 5706 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5707 EXPECT_EQ(ERR_IO_PENDING, rv); 5708 5709 rv = callback.WaitForResult(); 5710 EXPECT_EQ(OK, rv); 5711 const HttpResponseInfo* response = trans->GetResponseInfo(); 5712 5713 ASSERT_TRUE(response != NULL); 5714 5715 EXPECT_EQ(302, response->headers->response_code()); 5716 std::string url; 5717 EXPECT_TRUE(response->headers->IsRedirect(&url)); 5718 EXPECT_EQ("http://login.example.com/", url); 5719} 5720 5721// Test that an HTTPS proxy's response to a CONNECT request is filtered. 5722TEST_P(HttpNetworkTransactionTest, 5723 ErrorResponseToHttpsConnectViaHttpsProxy) { 5724 session_deps_.proxy_service.reset( 5725 ProxyService::CreateFixed("https://proxy:70")); 5726 5727 HttpRequestInfo request; 5728 request.method = "GET"; 5729 request.url = GURL("https://www.google.com/"); 5730 request.load_flags = 0; 5731 5732 MockWrite data_writes[] = { 5733 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5734 "Host: www.google.com\r\n" 5735 "Proxy-Connection: keep-alive\r\n\r\n"), 5736 }; 5737 5738 MockRead data_reads[] = { 5739 MockRead("HTTP/1.1 404 Not Found\r\n"), 5740 MockRead("Content-Length: 23\r\n\r\n"), 5741 MockRead("The host does not exist"), 5742 MockRead(SYNCHRONOUS, OK), 5743 }; 5744 5745 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5746 data_writes, arraysize(data_writes)); 5747 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5748 5749 session_deps_.socket_factory->AddSocketDataProvider(&data); 5750 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5751 5752 TestCompletionCallback callback; 5753 5754 scoped_ptr<HttpTransaction> trans( 5755 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5756 CreateSession(&session_deps_))); 5757 5758 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5759 EXPECT_EQ(ERR_IO_PENDING, rv); 5760 5761 rv = callback.WaitForResult(); 5762 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 5763 5764 // TODO(ttuttle): Anything else to check here? 5765} 5766 5767// Test that a SPDY proxy's response to a CONNECT request is filtered. 5768TEST_P(HttpNetworkTransactionTest, 5769 ErrorResponseToHttpsConnectViaSpdyProxy) { 5770 session_deps_.proxy_service.reset( 5771 ProxyService::CreateFixed("https://proxy:70")); 5772 5773 HttpRequestInfo request; 5774 request.method = "GET"; 5775 request.url = GURL("https://www.google.com/"); 5776 request.load_flags = 0; 5777 5778 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 5779 scoped_ptr<SpdyFrame> rst( 5780 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 5781 MockWrite data_writes[] = { 5782 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), 5783 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS), 5784 }; 5785 5786 static const char* const kExtraHeaders[] = { 5787 "location", 5788 "http://login.example.com/", 5789 }; 5790 scoped_ptr<SpdyFrame> resp( 5791 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders, 5792 arraysize(kExtraHeaders)/2, 1)); 5793 scoped_ptr<SpdyFrame> body( 5794 spdy_util_.ConstructSpdyBodyFrame( 5795 1, "The host does not exist", 23, true)); 5796 MockRead data_reads[] = { 5797 CreateMockRead(*resp.get(), 1, SYNCHRONOUS), 5798 CreateMockRead(*body.get(), 2, SYNCHRONOUS), 5799 MockRead(ASYNC, 0, 4), // EOF 5800 }; 5801 5802 DelayedSocketData data( 5803 1, // wait for one write to finish before reading. 5804 data_reads, arraysize(data_reads), 5805 data_writes, arraysize(data_writes)); 5806 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5807 proxy_ssl.SetNextProto(GetParam()); 5808 5809 session_deps_.socket_factory->AddSocketDataProvider(&data); 5810 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5811 5812 TestCompletionCallback callback; 5813 5814 scoped_ptr<HttpTransaction> trans( 5815 new HttpNetworkTransaction(DEFAULT_PRIORITY, 5816 CreateSession(&session_deps_))); 5817 5818 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5819 EXPECT_EQ(ERR_IO_PENDING, rv); 5820 5821 rv = callback.WaitForResult(); 5822 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 5823 5824 // TODO(ttuttle): Anything else to check here? 5825} 5826 5827// Test the request-challenge-retry sequence for basic auth, through 5828// a SPDY proxy over a single SPDY session. 5829TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) { 5830 HttpRequestInfo request; 5831 request.method = "GET"; 5832 request.url = GURL("https://www.google.com/"); 5833 // when the no authentication data flag is set. 5834 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 5835 5836 // Configure against https proxy server "myproxy:70". 5837 session_deps_.proxy_service.reset( 5838 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); 5839 CapturingBoundNetLog log; 5840 session_deps_.net_log = log.bound().net_log(); 5841 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5842 5843 // Since we have proxy, should try to establish tunnel. 5844 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 5845 scoped_ptr<SpdyFrame> rst( 5846 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 5847 5848 // After calling trans->RestartWithAuth(), this is the request we should 5849 // be issuing -- the final header line contains the credentials. 5850 const char* const kAuthCredentials[] = { 5851 "proxy-authorization", "Basic Zm9vOmJhcg==", 5852 }; 5853 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect( 5854 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3)); 5855 // fetch https://www.google.com/ via HTTP 5856 const char get[] = "GET / HTTP/1.1\r\n" 5857 "Host: www.google.com\r\n" 5858 "Connection: keep-alive\r\n\r\n"; 5859 scoped_ptr<SpdyFrame> wrapped_get( 5860 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false)); 5861 5862 MockWrite spdy_writes[] = { 5863 CreateMockWrite(*req, 1, ASYNC), 5864 CreateMockWrite(*rst, 4, ASYNC), 5865 CreateMockWrite(*connect2, 5), 5866 CreateMockWrite(*wrapped_get, 8), 5867 }; 5868 5869 // The proxy responds to the connect with a 407, using a persistent 5870 // connection. 5871 const char* const kAuthChallenge[] = { 5872 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required", 5873 spdy_util_.GetVersionKey(), "HTTP/1.1", 5874 "proxy-authenticate", "Basic realm=\"MyRealm1\"", 5875 }; 5876 5877 scoped_ptr<SpdyFrame> conn_auth_resp( 5878 spdy_util_.ConstructSpdyControlFrame(NULL, 5879 0, 5880 false, 5881 1, 5882 LOWEST, 5883 SYN_REPLY, 5884 CONTROL_FLAG_NONE, 5885 kAuthChallenge, 5886 arraysize(kAuthChallenge), 5887 0)); 5888 5889 scoped_ptr<SpdyFrame> conn_resp( 5890 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 5891 const char resp[] = "HTTP/1.1 200 OK\r\n" 5892 "Content-Length: 5\r\n\r\n"; 5893 5894 scoped_ptr<SpdyFrame> wrapped_get_resp( 5895 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false)); 5896 scoped_ptr<SpdyFrame> wrapped_body( 5897 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false)); 5898 MockRead spdy_reads[] = { 5899 CreateMockRead(*conn_auth_resp, 2, ASYNC), 5900 CreateMockRead(*conn_resp, 6, ASYNC), 5901 CreateMockRead(*wrapped_get_resp, 9, ASYNC), 5902 CreateMockRead(*wrapped_body, 10, ASYNC), 5903 MockRead(ASYNC, OK, 11), // EOF. May or may not be read. 5904 }; 5905 5906 OrderedSocketData spdy_data( 5907 spdy_reads, arraysize(spdy_reads), 5908 spdy_writes, arraysize(spdy_writes)); 5909 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 5910 // Negotiate SPDY to the proxy 5911 SSLSocketDataProvider proxy(ASYNC, OK); 5912 proxy.SetNextProto(GetParam()); 5913 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 5914 // Vanilla SSL to the server 5915 SSLSocketDataProvider server(ASYNC, OK); 5916 session_deps_.socket_factory->AddSSLSocketDataProvider(&server); 5917 5918 TestCompletionCallback callback1; 5919 5920 scoped_ptr<HttpTransaction> trans( 5921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5922 5923 int rv = trans->Start(&request, callback1.callback(), log.bound()); 5924 EXPECT_EQ(ERR_IO_PENDING, rv); 5925 5926 rv = callback1.WaitForResult(); 5927 EXPECT_EQ(OK, rv); 5928 net::CapturingNetLog::CapturedEntryList entries; 5929 log.GetEntries(&entries); 5930 size_t pos = ExpectLogContainsSomewhere( 5931 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 5932 NetLog::PHASE_NONE); 5933 ExpectLogContainsSomewhere( 5934 entries, pos, 5935 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 5936 NetLog::PHASE_NONE); 5937 5938 const HttpResponseInfo* response = trans->GetResponseInfo(); 5939 ASSERT_TRUE(response != NULL); 5940 ASSERT_FALSE(response->headers.get() == NULL); 5941 EXPECT_EQ(407, response->headers->response_code()); 5942 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 5943 EXPECT_TRUE(response->auth_challenge.get() != NULL); 5944 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 5945 5946 TestCompletionCallback callback2; 5947 5948 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), 5949 callback2.callback()); 5950 EXPECT_EQ(ERR_IO_PENDING, rv); 5951 5952 rv = callback2.WaitForResult(); 5953 EXPECT_EQ(OK, rv); 5954 5955 response = trans->GetResponseInfo(); 5956 ASSERT_TRUE(response != NULL); 5957 5958 EXPECT_TRUE(response->headers->IsKeepAlive()); 5959 EXPECT_EQ(200, response->headers->response_code()); 5960 EXPECT_EQ(5, response->headers->GetContentLength()); 5961 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 5962 5963 // The password prompt info should not be set. 5964 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5965 5966 LoadTimingInfo load_timing_info; 5967 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 5968 TestLoadTimingNotReusedWithPac(load_timing_info, 5969 CONNECT_TIMING_HAS_SSL_TIMES); 5970 5971 trans.reset(); 5972 session->CloseAllConnections(); 5973} 5974 5975// Test that an explicitly trusted SPDY proxy can push a resource from an 5976// origin that is different from that of its associated resource. 5977TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) { 5978 HttpRequestInfo request; 5979 HttpRequestInfo push_request; 5980 5981 request.method = "GET"; 5982 request.url = GURL("http://www.google.com/"); 5983 push_request.method = "GET"; 5984 push_request.url = GURL("http://www.another-origin.com/foo.dat"); 5985 5986 // Configure against https proxy server "myproxy:70". 5987 session_deps_.proxy_service.reset( 5988 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); 5989 CapturingBoundNetLog log; 5990 session_deps_.net_log = log.bound().net_log(); 5991 5992 // Enable cross-origin push. 5993 session_deps_.trusted_spdy_proxy = "myproxy:70"; 5994 5995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5996 5997 scoped_ptr<SpdyFrame> stream1_syn( 5998 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 5999 6000 MockWrite spdy_writes[] = { 6001 CreateMockWrite(*stream1_syn, 1, ASYNC), 6002 }; 6003 6004 scoped_ptr<SpdyFrame> 6005 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 6006 6007 scoped_ptr<SpdyFrame> 6008 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6009 6010 scoped_ptr<SpdyFrame> 6011 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 6012 0, 6013 2, 6014 1, 6015 "http://www.another-origin.com/foo.dat")); 6016 const char kPushedData[] = "pushed"; 6017 scoped_ptr<SpdyFrame> stream2_body( 6018 spdy_util_.ConstructSpdyBodyFrame( 6019 2, kPushedData, strlen(kPushedData), true)); 6020 6021 MockRead spdy_reads[] = { 6022 CreateMockRead(*stream1_reply, 2, ASYNC), 6023 CreateMockRead(*stream2_syn, 3, ASYNC), 6024 CreateMockRead(*stream1_body, 4, ASYNC), 6025 CreateMockRead(*stream2_body, 5, ASYNC), 6026 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 6027 }; 6028 6029 OrderedSocketData spdy_data( 6030 spdy_reads, arraysize(spdy_reads), 6031 spdy_writes, arraysize(spdy_writes)); 6032 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6033 // Negotiate SPDY to the proxy 6034 SSLSocketDataProvider proxy(ASYNC, OK); 6035 proxy.SetNextProto(GetParam()); 6036 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6037 6038 scoped_ptr<HttpTransaction> trans( 6039 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6040 TestCompletionCallback callback; 6041 int rv = trans->Start(&request, callback.callback(), log.bound()); 6042 EXPECT_EQ(ERR_IO_PENDING, rv); 6043 6044 rv = callback.WaitForResult(); 6045 EXPECT_EQ(OK, rv); 6046 const HttpResponseInfo* response = trans->GetResponseInfo(); 6047 6048 scoped_ptr<HttpTransaction> push_trans( 6049 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6050 rv = push_trans->Start(&push_request, callback.callback(), log.bound()); 6051 EXPECT_EQ(ERR_IO_PENDING, rv); 6052 6053 rv = callback.WaitForResult(); 6054 EXPECT_EQ(OK, rv); 6055 const HttpResponseInfo* push_response = push_trans->GetResponseInfo(); 6056 6057 ASSERT_TRUE(response != NULL); 6058 EXPECT_TRUE(response->headers->IsKeepAlive()); 6059 6060 EXPECT_EQ(200, response->headers->response_code()); 6061 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6062 6063 std::string response_data; 6064 rv = ReadTransaction(trans.get(), &response_data); 6065 EXPECT_EQ(OK, rv); 6066 EXPECT_EQ("hello!", response_data); 6067 6068 LoadTimingInfo load_timing_info; 6069 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6070 TestLoadTimingNotReusedWithPac(load_timing_info, 6071 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6072 6073 // Verify the pushed stream. 6074 EXPECT_TRUE(push_response->headers.get() != NULL); 6075 EXPECT_EQ(200, push_response->headers->response_code()); 6076 6077 rv = ReadTransaction(push_trans.get(), &response_data); 6078 EXPECT_EQ(OK, rv); 6079 EXPECT_EQ("pushed", response_data); 6080 6081 LoadTimingInfo push_load_timing_info; 6082 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info)); 6083 TestLoadTimingReusedWithPac(push_load_timing_info); 6084 // The transactions should share a socket ID, despite being for different 6085 // origins. 6086 EXPECT_EQ(load_timing_info.socket_log_id, 6087 push_load_timing_info.socket_log_id); 6088 6089 trans.reset(); 6090 push_trans.reset(); 6091 session->CloseAllConnections(); 6092} 6093 6094// Test that an explicitly trusted SPDY proxy cannot push HTTPS content. 6095TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) { 6096 HttpRequestInfo request; 6097 6098 request.method = "GET"; 6099 request.url = GURL("http://www.google.com/"); 6100 6101 // Configure against https proxy server "myproxy:70". 6102 session_deps_.proxy_service.reset( 6103 ProxyService::CreateFixed("https://myproxy:70")); 6104 CapturingBoundNetLog log; 6105 session_deps_.net_log = log.bound().net_log(); 6106 6107 // Enable cross-origin push. 6108 session_deps_.trusted_spdy_proxy = "myproxy:70"; 6109 6110 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6111 6112 scoped_ptr<SpdyFrame> stream1_syn( 6113 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 6114 6115 scoped_ptr<SpdyFrame> push_rst( 6116 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 6117 6118 MockWrite spdy_writes[] = { 6119 CreateMockWrite(*stream1_syn, 1, ASYNC), 6120 CreateMockWrite(*push_rst, 4), 6121 }; 6122 6123 scoped_ptr<SpdyFrame> 6124 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 6125 6126 scoped_ptr<SpdyFrame> 6127 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6128 6129 scoped_ptr<SpdyFrame> 6130 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 6131 0, 6132 2, 6133 1, 6134 "https://www.another-origin.com/foo.dat")); 6135 6136 MockRead spdy_reads[] = { 6137 CreateMockRead(*stream1_reply, 2, ASYNC), 6138 CreateMockRead(*stream2_syn, 3, ASYNC), 6139 CreateMockRead(*stream1_body, 5, ASYNC), 6140 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 6141 }; 6142 6143 OrderedSocketData spdy_data( 6144 spdy_reads, arraysize(spdy_reads), 6145 spdy_writes, arraysize(spdy_writes)); 6146 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6147 // Negotiate SPDY to the proxy 6148 SSLSocketDataProvider proxy(ASYNC, OK); 6149 proxy.SetNextProto(GetParam()); 6150 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6151 6152 scoped_ptr<HttpTransaction> trans( 6153 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6154 TestCompletionCallback callback; 6155 int rv = trans->Start(&request, callback.callback(), log.bound()); 6156 EXPECT_EQ(ERR_IO_PENDING, rv); 6157 6158 rv = callback.WaitForResult(); 6159 EXPECT_EQ(OK, rv); 6160 const HttpResponseInfo* response = trans->GetResponseInfo(); 6161 6162 ASSERT_TRUE(response != NULL); 6163 EXPECT_TRUE(response->headers->IsKeepAlive()); 6164 6165 EXPECT_EQ(200, response->headers->response_code()); 6166 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6167 6168 std::string response_data; 6169 rv = ReadTransaction(trans.get(), &response_data); 6170 EXPECT_EQ(OK, rv); 6171 EXPECT_EQ("hello!", response_data); 6172 6173 trans.reset(); 6174 session->CloseAllConnections(); 6175} 6176 6177// Test HTTPS connections to a site with a bad certificate, going through an 6178// HTTPS proxy 6179TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { 6180 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 6181 "https://proxy:70")); 6182 6183 HttpRequestInfo request; 6184 request.method = "GET"; 6185 request.url = GURL("https://www.google.com/"); 6186 request.load_flags = 0; 6187 6188 // Attempt to fetch the URL from a server with a bad cert 6189 MockWrite bad_cert_writes[] = { 6190 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6191 "Host: www.google.com\r\n" 6192 "Proxy-Connection: keep-alive\r\n\r\n"), 6193 }; 6194 6195 MockRead bad_cert_reads[] = { 6196 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6197 MockRead(SYNCHRONOUS, OK) 6198 }; 6199 6200 // Attempt to fetch the URL with a good cert 6201 MockWrite good_data_writes[] = { 6202 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6203 "Host: www.google.com\r\n" 6204 "Proxy-Connection: keep-alive\r\n\r\n"), 6205 MockWrite("GET / HTTP/1.1\r\n" 6206 "Host: www.google.com\r\n" 6207 "Connection: keep-alive\r\n\r\n"), 6208 }; 6209 6210 MockRead good_cert_reads[] = { 6211 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6212 MockRead("HTTP/1.0 200 OK\r\n"), 6213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6214 MockRead("Content-Length: 100\r\n\r\n"), 6215 MockRead(SYNCHRONOUS, OK), 6216 }; 6217 6218 StaticSocketDataProvider ssl_bad_certificate( 6219 bad_cert_reads, arraysize(bad_cert_reads), 6220 bad_cert_writes, arraysize(bad_cert_writes)); 6221 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads), 6222 good_data_writes, arraysize(good_data_writes)); 6223 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 6224 SSLSocketDataProvider ssl(ASYNC, OK); 6225 6226 // SSL to the proxy, then CONNECT request, then SSL with bad certificate 6227 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6228 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 6229 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 6230 6231 // SSL to the proxy, then CONNECT request, then valid SSL certificate 6232 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6233 session_deps_.socket_factory->AddSocketDataProvider(&data); 6234 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6235 6236 TestCompletionCallback callback; 6237 6238 scoped_ptr<HttpTransaction> trans( 6239 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6240 CreateSession(&session_deps_))); 6241 6242 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6243 EXPECT_EQ(ERR_IO_PENDING, rv); 6244 6245 rv = callback.WaitForResult(); 6246 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 6247 6248 rv = trans->RestartIgnoringLastError(callback.callback()); 6249 EXPECT_EQ(ERR_IO_PENDING, rv); 6250 6251 rv = callback.WaitForResult(); 6252 EXPECT_EQ(OK, rv); 6253 6254 const HttpResponseInfo* response = trans->GetResponseInfo(); 6255 6256 ASSERT_TRUE(response != NULL); 6257 EXPECT_EQ(100, response->headers->GetContentLength()); 6258} 6259 6260TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) { 6261 HttpRequestInfo request; 6262 request.method = "GET"; 6263 request.url = GURL("http://www.google.com/"); 6264 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 6265 "Chromium Ultra Awesome X Edition"); 6266 6267 scoped_ptr<HttpTransaction> trans( 6268 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6269 CreateSession(&session_deps_))); 6270 6271 MockWrite data_writes[] = { 6272 MockWrite("GET / HTTP/1.1\r\n" 6273 "Host: www.google.com\r\n" 6274 "Connection: keep-alive\r\n" 6275 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 6276 }; 6277 6278 // Lastly, the server responds with the actual content. 6279 MockRead data_reads[] = { 6280 MockRead("HTTP/1.0 200 OK\r\n"), 6281 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6282 MockRead("Content-Length: 100\r\n\r\n"), 6283 MockRead(SYNCHRONOUS, OK), 6284 }; 6285 6286 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6287 data_writes, arraysize(data_writes)); 6288 session_deps_.socket_factory->AddSocketDataProvider(&data); 6289 6290 TestCompletionCallback callback; 6291 6292 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6293 EXPECT_EQ(ERR_IO_PENDING, rv); 6294 6295 rv = callback.WaitForResult(); 6296 EXPECT_EQ(OK, rv); 6297} 6298 6299TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) { 6300 HttpRequestInfo request; 6301 request.method = "GET"; 6302 request.url = GURL("https://www.google.com/"); 6303 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 6304 "Chromium Ultra Awesome X Edition"); 6305 6306 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 6307 scoped_ptr<HttpTransaction> trans( 6308 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6309 CreateSession(&session_deps_))); 6310 6311 MockWrite data_writes[] = { 6312 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6313 "Host: www.google.com\r\n" 6314 "Proxy-Connection: keep-alive\r\n" 6315 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 6316 }; 6317 MockRead data_reads[] = { 6318 // Return an error, so the transaction stops here (this test isn't 6319 // interested in the rest). 6320 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 6321 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 6322 MockRead("Proxy-Connection: close\r\n\r\n"), 6323 }; 6324 6325 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6326 data_writes, arraysize(data_writes)); 6327 session_deps_.socket_factory->AddSocketDataProvider(&data); 6328 6329 TestCompletionCallback callback; 6330 6331 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6332 EXPECT_EQ(ERR_IO_PENDING, rv); 6333 6334 rv = callback.WaitForResult(); 6335 EXPECT_EQ(OK, rv); 6336} 6337 6338TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) { 6339 HttpRequestInfo request; 6340 request.method = "GET"; 6341 request.url = GURL("http://www.google.com/"); 6342 request.load_flags = 0; 6343 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer, 6344 "http://the.previous.site.com/"); 6345 6346 scoped_ptr<HttpTransaction> trans( 6347 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6348 CreateSession(&session_deps_))); 6349 6350 MockWrite data_writes[] = { 6351 MockWrite("GET / HTTP/1.1\r\n" 6352 "Host: www.google.com\r\n" 6353 "Connection: keep-alive\r\n" 6354 "Referer: http://the.previous.site.com/\r\n\r\n"), 6355 }; 6356 6357 // Lastly, the server responds with the actual content. 6358 MockRead data_reads[] = { 6359 MockRead("HTTP/1.0 200 OK\r\n"), 6360 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6361 MockRead("Content-Length: 100\r\n\r\n"), 6362 MockRead(SYNCHRONOUS, OK), 6363 }; 6364 6365 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6366 data_writes, arraysize(data_writes)); 6367 session_deps_.socket_factory->AddSocketDataProvider(&data); 6368 6369 TestCompletionCallback callback; 6370 6371 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6372 EXPECT_EQ(ERR_IO_PENDING, rv); 6373 6374 rv = callback.WaitForResult(); 6375 EXPECT_EQ(OK, rv); 6376} 6377 6378TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) { 6379 HttpRequestInfo request; 6380 request.method = "POST"; 6381 request.url = GURL("http://www.google.com/"); 6382 6383 scoped_ptr<HttpTransaction> trans( 6384 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6385 CreateSession(&session_deps_))); 6386 6387 MockWrite data_writes[] = { 6388 MockWrite("POST / HTTP/1.1\r\n" 6389 "Host: www.google.com\r\n" 6390 "Connection: keep-alive\r\n" 6391 "Content-Length: 0\r\n\r\n"), 6392 }; 6393 6394 // Lastly, the server responds with the actual content. 6395 MockRead data_reads[] = { 6396 MockRead("HTTP/1.0 200 OK\r\n"), 6397 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6398 MockRead("Content-Length: 100\r\n\r\n"), 6399 MockRead(SYNCHRONOUS, OK), 6400 }; 6401 6402 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6403 data_writes, arraysize(data_writes)); 6404 session_deps_.socket_factory->AddSocketDataProvider(&data); 6405 6406 TestCompletionCallback callback; 6407 6408 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6409 EXPECT_EQ(ERR_IO_PENDING, rv); 6410 6411 rv = callback.WaitForResult(); 6412 EXPECT_EQ(OK, rv); 6413} 6414 6415TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) { 6416 HttpRequestInfo request; 6417 request.method = "PUT"; 6418 request.url = GURL("http://www.google.com/"); 6419 6420 scoped_ptr<HttpTransaction> trans( 6421 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6422 CreateSession(&session_deps_))); 6423 6424 MockWrite data_writes[] = { 6425 MockWrite("PUT / HTTP/1.1\r\n" 6426 "Host: www.google.com\r\n" 6427 "Connection: keep-alive\r\n" 6428 "Content-Length: 0\r\n\r\n"), 6429 }; 6430 6431 // Lastly, the server responds with the actual content. 6432 MockRead data_reads[] = { 6433 MockRead("HTTP/1.0 200 OK\r\n"), 6434 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6435 MockRead("Content-Length: 100\r\n\r\n"), 6436 MockRead(SYNCHRONOUS, OK), 6437 }; 6438 6439 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6440 data_writes, arraysize(data_writes)); 6441 session_deps_.socket_factory->AddSocketDataProvider(&data); 6442 6443 TestCompletionCallback callback; 6444 6445 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6446 EXPECT_EQ(ERR_IO_PENDING, rv); 6447 6448 rv = callback.WaitForResult(); 6449 EXPECT_EQ(OK, rv); 6450} 6451 6452TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) { 6453 HttpRequestInfo request; 6454 request.method = "HEAD"; 6455 request.url = GURL("http://www.google.com/"); 6456 6457 scoped_ptr<HttpTransaction> trans( 6458 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6459 CreateSession(&session_deps_))); 6460 6461 MockWrite data_writes[] = { 6462 MockWrite("HEAD / HTTP/1.1\r\n" 6463 "Host: www.google.com\r\n" 6464 "Connection: keep-alive\r\n" 6465 "Content-Length: 0\r\n\r\n"), 6466 }; 6467 6468 // Lastly, the server responds with the actual content. 6469 MockRead data_reads[] = { 6470 MockRead("HTTP/1.0 200 OK\r\n"), 6471 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6472 MockRead("Content-Length: 100\r\n\r\n"), 6473 MockRead(SYNCHRONOUS, OK), 6474 }; 6475 6476 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6477 data_writes, arraysize(data_writes)); 6478 session_deps_.socket_factory->AddSocketDataProvider(&data); 6479 6480 TestCompletionCallback callback; 6481 6482 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6483 EXPECT_EQ(ERR_IO_PENDING, rv); 6484 6485 rv = callback.WaitForResult(); 6486 EXPECT_EQ(OK, rv); 6487} 6488 6489TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) { 6490 HttpRequestInfo request; 6491 request.method = "GET"; 6492 request.url = GURL("http://www.google.com/"); 6493 request.load_flags = LOAD_BYPASS_CACHE; 6494 6495 scoped_ptr<HttpTransaction> trans( 6496 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6497 CreateSession(&session_deps_))); 6498 6499 MockWrite data_writes[] = { 6500 MockWrite("GET / HTTP/1.1\r\n" 6501 "Host: www.google.com\r\n" 6502 "Connection: keep-alive\r\n" 6503 "Pragma: no-cache\r\n" 6504 "Cache-Control: no-cache\r\n\r\n"), 6505 }; 6506 6507 // Lastly, the server responds with the actual content. 6508 MockRead data_reads[] = { 6509 MockRead("HTTP/1.0 200 OK\r\n"), 6510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6511 MockRead("Content-Length: 100\r\n\r\n"), 6512 MockRead(SYNCHRONOUS, OK), 6513 }; 6514 6515 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6516 data_writes, arraysize(data_writes)); 6517 session_deps_.socket_factory->AddSocketDataProvider(&data); 6518 6519 TestCompletionCallback callback; 6520 6521 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6522 EXPECT_EQ(ERR_IO_PENDING, rv); 6523 6524 rv = callback.WaitForResult(); 6525 EXPECT_EQ(OK, rv); 6526} 6527 6528TEST_P(HttpNetworkTransactionTest, 6529 BuildRequest_CacheControlValidateCache) { 6530 HttpRequestInfo request; 6531 request.method = "GET"; 6532 request.url = GURL("http://www.google.com/"); 6533 request.load_flags = LOAD_VALIDATE_CACHE; 6534 6535 scoped_ptr<HttpTransaction> trans( 6536 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6537 CreateSession(&session_deps_))); 6538 6539 MockWrite data_writes[] = { 6540 MockWrite("GET / HTTP/1.1\r\n" 6541 "Host: www.google.com\r\n" 6542 "Connection: keep-alive\r\n" 6543 "Cache-Control: max-age=0\r\n\r\n"), 6544 }; 6545 6546 // Lastly, the server responds with the actual content. 6547 MockRead data_reads[] = { 6548 MockRead("HTTP/1.0 200 OK\r\n"), 6549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6550 MockRead("Content-Length: 100\r\n\r\n"), 6551 MockRead(SYNCHRONOUS, OK), 6552 }; 6553 6554 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6555 data_writes, arraysize(data_writes)); 6556 session_deps_.socket_factory->AddSocketDataProvider(&data); 6557 6558 TestCompletionCallback callback; 6559 6560 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6561 EXPECT_EQ(ERR_IO_PENDING, rv); 6562 6563 rv = callback.WaitForResult(); 6564 EXPECT_EQ(OK, rv); 6565} 6566 6567TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) { 6568 HttpRequestInfo request; 6569 request.method = "GET"; 6570 request.url = GURL("http://www.google.com/"); 6571 request.extra_headers.SetHeader("FooHeader", "Bar"); 6572 6573 scoped_ptr<HttpTransaction> trans( 6574 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6575 CreateSession(&session_deps_))); 6576 6577 MockWrite data_writes[] = { 6578 MockWrite("GET / HTTP/1.1\r\n" 6579 "Host: www.google.com\r\n" 6580 "Connection: keep-alive\r\n" 6581 "FooHeader: Bar\r\n\r\n"), 6582 }; 6583 6584 // Lastly, the server responds with the actual content. 6585 MockRead data_reads[] = { 6586 MockRead("HTTP/1.0 200 OK\r\n"), 6587 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6588 MockRead("Content-Length: 100\r\n\r\n"), 6589 MockRead(SYNCHRONOUS, OK), 6590 }; 6591 6592 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6593 data_writes, arraysize(data_writes)); 6594 session_deps_.socket_factory->AddSocketDataProvider(&data); 6595 6596 TestCompletionCallback callback; 6597 6598 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6599 EXPECT_EQ(ERR_IO_PENDING, rv); 6600 6601 rv = callback.WaitForResult(); 6602 EXPECT_EQ(OK, rv); 6603} 6604 6605TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) { 6606 HttpRequestInfo request; 6607 request.method = "GET"; 6608 request.url = GURL("http://www.google.com/"); 6609 request.extra_headers.SetHeader("referer", "www.foo.com"); 6610 request.extra_headers.SetHeader("hEllo", "Kitty"); 6611 request.extra_headers.SetHeader("FoO", "bar"); 6612 6613 scoped_ptr<HttpTransaction> trans( 6614 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6615 CreateSession(&session_deps_))); 6616 6617 MockWrite data_writes[] = { 6618 MockWrite("GET / HTTP/1.1\r\n" 6619 "Host: www.google.com\r\n" 6620 "Connection: keep-alive\r\n" 6621 "referer: www.foo.com\r\n" 6622 "hEllo: Kitty\r\n" 6623 "FoO: bar\r\n\r\n"), 6624 }; 6625 6626 // Lastly, the server responds with the actual content. 6627 MockRead data_reads[] = { 6628 MockRead("HTTP/1.0 200 OK\r\n"), 6629 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6630 MockRead("Content-Length: 100\r\n\r\n"), 6631 MockRead(SYNCHRONOUS, OK), 6632 }; 6633 6634 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6635 data_writes, arraysize(data_writes)); 6636 session_deps_.socket_factory->AddSocketDataProvider(&data); 6637 6638 TestCompletionCallback callback; 6639 6640 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6641 EXPECT_EQ(ERR_IO_PENDING, rv); 6642 6643 rv = callback.WaitForResult(); 6644 EXPECT_EQ(OK, rv); 6645} 6646 6647TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) { 6648 HttpRequestInfo request; 6649 request.method = "GET"; 6650 request.url = GURL("http://www.google.com/"); 6651 request.load_flags = 0; 6652 6653 session_deps_.proxy_service.reset( 6654 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080")); 6655 CapturingNetLog net_log; 6656 session_deps_.net_log = &net_log; 6657 6658 scoped_ptr<HttpTransaction> trans( 6659 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6660 CreateSession(&session_deps_))); 6661 6662 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; 6663 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 6664 6665 MockWrite data_writes[] = { 6666 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)), 6667 MockWrite("GET / HTTP/1.1\r\n" 6668 "Host: www.google.com\r\n" 6669 "Connection: keep-alive\r\n\r\n") 6670 }; 6671 6672 MockRead data_reads[] = { 6673 MockRead(ASYNC, read_buffer, arraysize(read_buffer)), 6674 MockRead("HTTP/1.0 200 OK\r\n"), 6675 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6676 MockRead("Payload"), 6677 MockRead(SYNCHRONOUS, OK) 6678 }; 6679 6680 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6681 data_writes, arraysize(data_writes)); 6682 session_deps_.socket_factory->AddSocketDataProvider(&data); 6683 6684 TestCompletionCallback callback; 6685 6686 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6687 EXPECT_EQ(ERR_IO_PENDING, rv); 6688 6689 rv = callback.WaitForResult(); 6690 EXPECT_EQ(OK, rv); 6691 6692 const HttpResponseInfo* response = trans->GetResponseInfo(); 6693 ASSERT_TRUE(response != NULL); 6694 6695 LoadTimingInfo load_timing_info; 6696 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6697 TestLoadTimingNotReusedWithPac(load_timing_info, 6698 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6699 6700 std::string response_text; 6701 rv = ReadTransaction(trans.get(), &response_text); 6702 EXPECT_EQ(OK, rv); 6703 EXPECT_EQ("Payload", response_text); 6704} 6705 6706TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) { 6707 HttpRequestInfo request; 6708 request.method = "GET"; 6709 request.url = GURL("https://www.google.com/"); 6710 request.load_flags = 0; 6711 6712 session_deps_.proxy_service.reset( 6713 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080")); 6714 CapturingNetLog net_log; 6715 session_deps_.net_log = &net_log; 6716 6717 scoped_ptr<HttpTransaction> trans( 6718 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6719 CreateSession(&session_deps_))); 6720 6721 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 }; 6722 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 6723 6724 MockWrite data_writes[] = { 6725 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer), 6726 arraysize(write_buffer)), 6727 MockWrite("GET / HTTP/1.1\r\n" 6728 "Host: www.google.com\r\n" 6729 "Connection: keep-alive\r\n\r\n") 6730 }; 6731 6732 MockRead data_reads[] = { 6733 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer), 6734 arraysize(read_buffer)), 6735 MockRead("HTTP/1.0 200 OK\r\n"), 6736 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6737 MockRead("Payload"), 6738 MockRead(SYNCHRONOUS, OK) 6739 }; 6740 6741 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6742 data_writes, arraysize(data_writes)); 6743 session_deps_.socket_factory->AddSocketDataProvider(&data); 6744 6745 SSLSocketDataProvider ssl(ASYNC, OK); 6746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6747 6748 TestCompletionCallback callback; 6749 6750 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6751 EXPECT_EQ(ERR_IO_PENDING, rv); 6752 6753 rv = callback.WaitForResult(); 6754 EXPECT_EQ(OK, rv); 6755 6756 LoadTimingInfo load_timing_info; 6757 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6758 TestLoadTimingNotReusedWithPac(load_timing_info, 6759 CONNECT_TIMING_HAS_SSL_TIMES); 6760 6761 const HttpResponseInfo* response = trans->GetResponseInfo(); 6762 ASSERT_TRUE(response != NULL); 6763 6764 std::string response_text; 6765 rv = ReadTransaction(trans.get(), &response_text); 6766 EXPECT_EQ(OK, rv); 6767 EXPECT_EQ("Payload", response_text); 6768} 6769 6770TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) { 6771 HttpRequestInfo request; 6772 request.method = "GET"; 6773 request.url = GURL("http://www.google.com/"); 6774 request.load_flags = 0; 6775 6776 session_deps_.proxy_service.reset( 6777 ProxyService::CreateFixed("socks4://myproxy:1080")); 6778 CapturingNetLog net_log; 6779 session_deps_.net_log = &net_log; 6780 6781 scoped_ptr<HttpTransaction> trans( 6782 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6783 CreateSession(&session_deps_))); 6784 6785 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; 6786 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 6787 6788 MockWrite data_writes[] = { 6789 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)), 6790 MockWrite("GET / HTTP/1.1\r\n" 6791 "Host: www.google.com\r\n" 6792 "Connection: keep-alive\r\n\r\n") 6793 }; 6794 6795 MockRead data_reads[] = { 6796 MockRead(ASYNC, read_buffer, arraysize(read_buffer)), 6797 MockRead("HTTP/1.0 200 OK\r\n"), 6798 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6799 MockRead("Payload"), 6800 MockRead(SYNCHRONOUS, OK) 6801 }; 6802 6803 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6804 data_writes, arraysize(data_writes)); 6805 session_deps_.socket_factory->AddSocketDataProvider(&data); 6806 6807 TestCompletionCallback callback; 6808 6809 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6810 EXPECT_EQ(ERR_IO_PENDING, rv); 6811 6812 rv = callback.WaitForResult(); 6813 EXPECT_EQ(OK, rv); 6814 6815 const HttpResponseInfo* response = trans->GetResponseInfo(); 6816 ASSERT_TRUE(response != NULL); 6817 6818 LoadTimingInfo load_timing_info; 6819 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6820 TestLoadTimingNotReused(load_timing_info, 6821 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6822 6823 std::string response_text; 6824 rv = ReadTransaction(trans.get(), &response_text); 6825 EXPECT_EQ(OK, rv); 6826 EXPECT_EQ("Payload", response_text); 6827} 6828 6829TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) { 6830 HttpRequestInfo request; 6831 request.method = "GET"; 6832 request.url = GURL("http://www.google.com/"); 6833 request.load_flags = 0; 6834 6835 session_deps_.proxy_service.reset( 6836 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080")); 6837 CapturingNetLog net_log; 6838 session_deps_.net_log = &net_log; 6839 6840 scoped_ptr<HttpTransaction> trans( 6841 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6842 CreateSession(&session_deps_))); 6843 6844 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; 6845 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; 6846 const char kSOCKS5OkRequest[] = { 6847 0x05, // Version 6848 0x01, // Command (CONNECT) 6849 0x00, // Reserved. 6850 0x03, // Address type (DOMAINNAME). 6851 0x0E, // Length of domain (14) 6852 // Domain string: 6853 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', 6854 0x00, 0x50, // 16-bit port (80) 6855 }; 6856 const char kSOCKS5OkResponse[] = 6857 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 }; 6858 6859 MockWrite data_writes[] = { 6860 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), 6861 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)), 6862 MockWrite("GET / HTTP/1.1\r\n" 6863 "Host: www.google.com\r\n" 6864 "Connection: keep-alive\r\n\r\n") 6865 }; 6866 6867 MockRead data_reads[] = { 6868 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), 6869 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), 6870 MockRead("HTTP/1.0 200 OK\r\n"), 6871 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6872 MockRead("Payload"), 6873 MockRead(SYNCHRONOUS, OK) 6874 }; 6875 6876 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6877 data_writes, arraysize(data_writes)); 6878 session_deps_.socket_factory->AddSocketDataProvider(&data); 6879 6880 TestCompletionCallback callback; 6881 6882 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6883 EXPECT_EQ(ERR_IO_PENDING, rv); 6884 6885 rv = callback.WaitForResult(); 6886 EXPECT_EQ(OK, rv); 6887 6888 const HttpResponseInfo* response = trans->GetResponseInfo(); 6889 ASSERT_TRUE(response != NULL); 6890 6891 LoadTimingInfo load_timing_info; 6892 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6893 TestLoadTimingNotReusedWithPac(load_timing_info, 6894 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6895 6896 std::string response_text; 6897 rv = ReadTransaction(trans.get(), &response_text); 6898 EXPECT_EQ(OK, rv); 6899 EXPECT_EQ("Payload", response_text); 6900} 6901 6902TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) { 6903 HttpRequestInfo request; 6904 request.method = "GET"; 6905 request.url = GURL("https://www.google.com/"); 6906 request.load_flags = 0; 6907 6908 session_deps_.proxy_service.reset( 6909 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080")); 6910 CapturingNetLog net_log; 6911 session_deps_.net_log = &net_log; 6912 6913 scoped_ptr<HttpTransaction> trans( 6914 new HttpNetworkTransaction(DEFAULT_PRIORITY, 6915 CreateSession(&session_deps_))); 6916 6917 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; 6918 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; 6919 const unsigned char kSOCKS5OkRequest[] = { 6920 0x05, // Version 6921 0x01, // Command (CONNECT) 6922 0x00, // Reserved. 6923 0x03, // Address type (DOMAINNAME). 6924 0x0E, // Length of domain (14) 6925 // Domain string: 6926 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', 6927 0x01, 0xBB, // 16-bit port (443) 6928 }; 6929 6930 const char kSOCKS5OkResponse[] = 6931 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 }; 6932 6933 MockWrite data_writes[] = { 6934 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), 6935 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest), 6936 arraysize(kSOCKS5OkRequest)), 6937 MockWrite("GET / HTTP/1.1\r\n" 6938 "Host: www.google.com\r\n" 6939 "Connection: keep-alive\r\n\r\n") 6940 }; 6941 6942 MockRead data_reads[] = { 6943 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), 6944 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), 6945 MockRead("HTTP/1.0 200 OK\r\n"), 6946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6947 MockRead("Payload"), 6948 MockRead(SYNCHRONOUS, OK) 6949 }; 6950 6951 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6952 data_writes, arraysize(data_writes)); 6953 session_deps_.socket_factory->AddSocketDataProvider(&data); 6954 6955 SSLSocketDataProvider ssl(ASYNC, OK); 6956 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6957 6958 TestCompletionCallback callback; 6959 6960 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6961 EXPECT_EQ(ERR_IO_PENDING, rv); 6962 6963 rv = callback.WaitForResult(); 6964 EXPECT_EQ(OK, rv); 6965 6966 const HttpResponseInfo* response = trans->GetResponseInfo(); 6967 ASSERT_TRUE(response != NULL); 6968 6969 LoadTimingInfo load_timing_info; 6970 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6971 TestLoadTimingNotReusedWithPac(load_timing_info, 6972 CONNECT_TIMING_HAS_SSL_TIMES); 6973 6974 std::string response_text; 6975 rv = ReadTransaction(trans.get(), &response_text); 6976 EXPECT_EQ(OK, rv); 6977 EXPECT_EQ("Payload", response_text); 6978} 6979 6980namespace { 6981 6982// Tests that for connection endpoints the group names are correctly set. 6983 6984struct GroupNameTest { 6985 std::string proxy_server; 6986 std::string url; 6987 std::string expected_group_name; 6988 bool ssl; 6989}; 6990 6991scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests( 6992 NextProto next_proto, 6993 SpdySessionDependencies* session_deps_) { 6994 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_)); 6995 6996 base::WeakPtr<HttpServerProperties> http_server_properties = 6997 session->http_server_properties(); 6998 http_server_properties->SetAlternateProtocol( 6999 HostPortPair("host.with.alternate", 80), 443, 7000 AlternateProtocolFromNextProto(next_proto)); 7001 7002 return session; 7003} 7004 7005int GroupNameTransactionHelper( 7006 const std::string& url, 7007 const scoped_refptr<HttpNetworkSession>& session) { 7008 HttpRequestInfo request; 7009 request.method = "GET"; 7010 request.url = GURL(url); 7011 request.load_flags = 0; 7012 7013 scoped_ptr<HttpTransaction> trans( 7014 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7015 7016 TestCompletionCallback callback; 7017 7018 // We do not complete this request, the dtor will clean the transaction up. 7019 return trans->Start(&request, callback.callback(), BoundNetLog()); 7020} 7021 7022} // namespace 7023 7024TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) { 7025 const GroupNameTest tests[] = { 7026 { 7027 "", // unused 7028 "http://www.google.com/direct", 7029 "www.google.com:80", 7030 false, 7031 }, 7032 { 7033 "", // unused 7034 "http://[2001:1418:13:1::25]/direct", 7035 "[2001:1418:13:1::25]:80", 7036 false, 7037 }, 7038 7039 // SSL Tests 7040 { 7041 "", // unused 7042 "https://www.google.com/direct_ssl", 7043 "ssl/www.google.com:443", 7044 true, 7045 }, 7046 { 7047 "", // unused 7048 "https://[2001:1418:13:1::25]/direct", 7049 "ssl/[2001:1418:13:1::25]:443", 7050 true, 7051 }, 7052 { 7053 "", // unused 7054 "http://host.with.alternate/direct", 7055 "ssl/host.with.alternate:443", 7056 true, 7057 }, 7058 }; 7059 7060 HttpStreamFactory::set_use_alternate_protocols(true); 7061 7062 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 7063 session_deps_.proxy_service.reset( 7064 ProxyService::CreateFixed(tests[i].proxy_server)); 7065 scoped_refptr<HttpNetworkSession> session( 7066 SetupSessionForGroupNameTests(GetParam(), &session_deps_)); 7067 7068 HttpNetworkSessionPeer peer(session); 7069 CaptureGroupNameTransportSocketPool* transport_conn_pool = 7070 new CaptureGroupNameTransportSocketPool(NULL, NULL); 7071 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 7072 new CaptureGroupNameSSLSocketPool(NULL, NULL); 7073 MockClientSocketPoolManager* mock_pool_manager = 7074 new MockClientSocketPoolManager; 7075 mock_pool_manager->SetTransportSocketPool(transport_conn_pool); 7076 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); 7077 peer.SetClientSocketPoolManager(mock_pool_manager); 7078 7079 EXPECT_EQ(ERR_IO_PENDING, 7080 GroupNameTransactionHelper(tests[i].url, session)); 7081 if (tests[i].ssl) 7082 EXPECT_EQ(tests[i].expected_group_name, 7083 ssl_conn_pool->last_group_name_received()); 7084 else 7085 EXPECT_EQ(tests[i].expected_group_name, 7086 transport_conn_pool->last_group_name_received()); 7087 } 7088 7089} 7090 7091TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) { 7092 const GroupNameTest tests[] = { 7093 { 7094 "http_proxy", 7095 "http://www.google.com/http_proxy_normal", 7096 "www.google.com:80", 7097 false, 7098 }, 7099 7100 // SSL Tests 7101 { 7102 "http_proxy", 7103 "https://www.google.com/http_connect_ssl", 7104 "ssl/www.google.com:443", 7105 true, 7106 }, 7107 7108 { 7109 "http_proxy", 7110 "http://host.with.alternate/direct", 7111 "ssl/host.with.alternate:443", 7112 true, 7113 }, 7114 7115 { 7116 "http_proxy", 7117 "ftp://ftp.google.com/http_proxy_normal", 7118 "ftp/ftp.google.com:21", 7119 false, 7120 }, 7121 }; 7122 7123 HttpStreamFactory::set_use_alternate_protocols(true); 7124 7125 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 7126 session_deps_.proxy_service.reset( 7127 ProxyService::CreateFixed(tests[i].proxy_server)); 7128 scoped_refptr<HttpNetworkSession> session( 7129 SetupSessionForGroupNameTests(GetParam(), &session_deps_)); 7130 7131 HttpNetworkSessionPeer peer(session); 7132 7133 HostPortPair proxy_host("http_proxy", 80); 7134 CaptureGroupNameHttpProxySocketPool* http_proxy_pool = 7135 new CaptureGroupNameHttpProxySocketPool(NULL, NULL); 7136 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 7137 new CaptureGroupNameSSLSocketPool(NULL, NULL); 7138 7139 MockClientSocketPoolManager* mock_pool_manager = 7140 new MockClientSocketPoolManager; 7141 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool); 7142 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); 7143 peer.SetClientSocketPoolManager(mock_pool_manager); 7144 7145 EXPECT_EQ(ERR_IO_PENDING, 7146 GroupNameTransactionHelper(tests[i].url, session)); 7147 if (tests[i].ssl) 7148 EXPECT_EQ(tests[i].expected_group_name, 7149 ssl_conn_pool->last_group_name_received()); 7150 else 7151 EXPECT_EQ(tests[i].expected_group_name, 7152 http_proxy_pool->last_group_name_received()); 7153 } 7154} 7155 7156TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) { 7157 const GroupNameTest tests[] = { 7158 { 7159 "socks4://socks_proxy:1080", 7160 "http://www.google.com/socks4_direct", 7161 "socks4/www.google.com:80", 7162 false, 7163 }, 7164 { 7165 "socks5://socks_proxy:1080", 7166 "http://www.google.com/socks5_direct", 7167 "socks5/www.google.com:80", 7168 false, 7169 }, 7170 7171 // SSL Tests 7172 { 7173 "socks4://socks_proxy:1080", 7174 "https://www.google.com/socks4_ssl", 7175 "socks4/ssl/www.google.com:443", 7176 true, 7177 }, 7178 { 7179 "socks5://socks_proxy:1080", 7180 "https://www.google.com/socks5_ssl", 7181 "socks5/ssl/www.google.com:443", 7182 true, 7183 }, 7184 7185 { 7186 "socks4://socks_proxy:1080", 7187 "http://host.with.alternate/direct", 7188 "socks4/ssl/host.with.alternate:443", 7189 true, 7190 }, 7191 }; 7192 7193 HttpStreamFactory::set_use_alternate_protocols(true); 7194 7195 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 7196 session_deps_.proxy_service.reset( 7197 ProxyService::CreateFixed(tests[i].proxy_server)); 7198 scoped_refptr<HttpNetworkSession> session( 7199 SetupSessionForGroupNameTests(GetParam(), &session_deps_)); 7200 7201 HttpNetworkSessionPeer peer(session); 7202 7203 HostPortPair proxy_host("socks_proxy", 1080); 7204 CaptureGroupNameSOCKSSocketPool* socks_conn_pool = 7205 new CaptureGroupNameSOCKSSocketPool(NULL, NULL); 7206 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 7207 new CaptureGroupNameSSLSocketPool(NULL, NULL); 7208 7209 MockClientSocketPoolManager* mock_pool_manager = 7210 new MockClientSocketPoolManager; 7211 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool); 7212 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); 7213 peer.SetClientSocketPoolManager(mock_pool_manager); 7214 7215 scoped_ptr<HttpTransaction> trans( 7216 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7217 7218 EXPECT_EQ(ERR_IO_PENDING, 7219 GroupNameTransactionHelper(tests[i].url, session)); 7220 if (tests[i].ssl) 7221 EXPECT_EQ(tests[i].expected_group_name, 7222 ssl_conn_pool->last_group_name_received()); 7223 else 7224 EXPECT_EQ(tests[i].expected_group_name, 7225 socks_conn_pool->last_group_name_received()); 7226 } 7227} 7228 7229TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) { 7230 HttpRequestInfo request; 7231 request.method = "GET"; 7232 request.url = GURL("http://www.google.com/"); 7233 7234 session_deps_.proxy_service.reset( 7235 ProxyService::CreateFixed("myproxy:70;foobar:80")); 7236 7237 // This simulates failure resolving all hostnames; that means we will fail 7238 // connecting to both proxies (myproxy:70 and foobar:80). 7239 session_deps_.host_resolver->rules()->AddSimulatedFailure("*"); 7240 7241 scoped_ptr<HttpTransaction> trans( 7242 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7243 CreateSession(&session_deps_))); 7244 7245 TestCompletionCallback callback; 7246 7247 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7248 EXPECT_EQ(ERR_IO_PENDING, rv); 7249 7250 rv = callback.WaitForResult(); 7251 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv); 7252} 7253 7254// Base test to make sure that when the load flags for a request specify to 7255// bypass the cache, the DNS cache is not used. 7256void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper( 7257 int load_flags) { 7258 // Issue a request, asking to bypass the cache(s). 7259 HttpRequestInfo request; 7260 request.method = "GET"; 7261 request.load_flags = load_flags; 7262 request.url = GURL("http://www.google.com/"); 7263 7264 // Select a host resolver that does caching. 7265 session_deps_.host_resolver.reset(new MockCachingHostResolver); 7266 7267 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY, 7268 CreateSession(&session_deps_))); 7269 7270 // Warm up the host cache so it has an entry for "www.google.com". 7271 AddressList addrlist; 7272 TestCompletionCallback callback; 7273 int rv = session_deps_.host_resolver->Resolve( 7274 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist, 7275 callback.callback(), NULL, BoundNetLog()); 7276 EXPECT_EQ(ERR_IO_PENDING, rv); 7277 rv = callback.WaitForResult(); 7278 EXPECT_EQ(OK, rv); 7279 7280 // Verify that it was added to host cache, by doing a subsequent async lookup 7281 // and confirming it completes synchronously. 7282 rv = session_deps_.host_resolver->Resolve( 7283 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist, 7284 callback.callback(), NULL, BoundNetLog()); 7285 ASSERT_EQ(OK, rv); 7286 7287 // Inject a failure the next time that "www.google.com" is resolved. This way 7288 // we can tell if the next lookup hit the cache, or the "network". 7289 // (cache --> success, "network" --> failure). 7290 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com"); 7291 7292 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the 7293 // first read -- this won't be reached as the host resolution will fail first. 7294 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) }; 7295 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7296 session_deps_.socket_factory->AddSocketDataProvider(&data); 7297 7298 // Run the request. 7299 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7300 ASSERT_EQ(ERR_IO_PENDING, rv); 7301 rv = callback.WaitForResult(); 7302 7303 // If we bypassed the cache, we would have gotten a failure while resolving 7304 // "www.google.com". 7305 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); 7306} 7307 7308// There are multiple load flags that should trigger the host cache bypass. 7309// Test each in isolation: 7310TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) { 7311 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE); 7312} 7313 7314TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) { 7315 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE); 7316} 7317 7318TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) { 7319 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE); 7320} 7321 7322// Make sure we can handle an error when writing the request. 7323TEST_P(HttpNetworkTransactionTest, RequestWriteError) { 7324 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7325 7326 HttpRequestInfo request; 7327 request.method = "GET"; 7328 request.url = GURL("http://www.foo.com/"); 7329 request.load_flags = 0; 7330 7331 MockWrite write_failure[] = { 7332 MockWrite(ASYNC, ERR_CONNECTION_RESET), 7333 }; 7334 StaticSocketDataProvider data(NULL, 0, 7335 write_failure, arraysize(write_failure)); 7336 session_deps_.socket_factory->AddSocketDataProvider(&data); 7337 7338 TestCompletionCallback callback; 7339 7340 scoped_ptr<HttpTransaction> trans( 7341 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7342 CreateSession(&session_deps_))); 7343 7344 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7345 EXPECT_EQ(ERR_IO_PENDING, rv); 7346 7347 rv = callback.WaitForResult(); 7348 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 7349} 7350 7351// Check that a connection closed after the start of the headers finishes ok. 7352TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { 7353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7354 7355 HttpRequestInfo request; 7356 request.method = "GET"; 7357 request.url = GURL("http://www.foo.com/"); 7358 request.load_flags = 0; 7359 7360 MockRead data_reads[] = { 7361 MockRead("HTTP/1."), 7362 MockRead(SYNCHRONOUS, OK), 7363 }; 7364 7365 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7366 session_deps_.socket_factory->AddSocketDataProvider(&data); 7367 7368 TestCompletionCallback callback; 7369 7370 scoped_ptr<HttpTransaction> trans( 7371 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7372 CreateSession(&session_deps_))); 7373 7374 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7375 EXPECT_EQ(ERR_IO_PENDING, rv); 7376 7377 rv = callback.WaitForResult(); 7378 EXPECT_EQ(OK, rv); 7379 7380 const HttpResponseInfo* response = trans->GetResponseInfo(); 7381 ASSERT_TRUE(response != NULL); 7382 7383 EXPECT_TRUE(response->headers.get() != NULL); 7384 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7385 7386 std::string response_data; 7387 rv = ReadTransaction(trans.get(), &response_data); 7388 EXPECT_EQ(OK, rv); 7389 EXPECT_EQ("", response_data); 7390} 7391 7392// Make sure that a dropped connection while draining the body for auth 7393// restart does the right thing. 7394TEST_P(HttpNetworkTransactionTest, DrainResetOK) { 7395 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7396 7397 HttpRequestInfo request; 7398 request.method = "GET"; 7399 request.url = GURL("http://www.google.com/"); 7400 request.load_flags = 0; 7401 7402 MockWrite data_writes1[] = { 7403 MockWrite("GET / HTTP/1.1\r\n" 7404 "Host: www.google.com\r\n" 7405 "Connection: keep-alive\r\n\r\n"), 7406 }; 7407 7408 MockRead data_reads1[] = { 7409 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 7410 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 7411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7412 MockRead("Content-Length: 14\r\n\r\n"), 7413 MockRead("Unauth"), 7414 MockRead(ASYNC, ERR_CONNECTION_RESET), 7415 }; 7416 7417 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 7418 data_writes1, arraysize(data_writes1)); 7419 session_deps_.socket_factory->AddSocketDataProvider(&data1); 7420 7421 // After calling trans->RestartWithAuth(), this is the request we should 7422 // be issuing -- the final header line contains the credentials. 7423 MockWrite data_writes2[] = { 7424 MockWrite("GET / HTTP/1.1\r\n" 7425 "Host: www.google.com\r\n" 7426 "Connection: keep-alive\r\n" 7427 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 7428 }; 7429 7430 // Lastly, the server responds with the actual content. 7431 MockRead data_reads2[] = { 7432 MockRead("HTTP/1.1 200 OK\r\n"), 7433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7434 MockRead("Content-Length: 100\r\n\r\n"), 7435 MockRead(SYNCHRONOUS, OK), 7436 }; 7437 7438 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 7439 data_writes2, arraysize(data_writes2)); 7440 session_deps_.socket_factory->AddSocketDataProvider(&data2); 7441 7442 TestCompletionCallback callback1; 7443 7444 scoped_ptr<HttpTransaction> trans( 7445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7446 7447 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 7448 EXPECT_EQ(ERR_IO_PENDING, rv); 7449 7450 rv = callback1.WaitForResult(); 7451 EXPECT_EQ(OK, rv); 7452 7453 const HttpResponseInfo* response = trans->GetResponseInfo(); 7454 ASSERT_TRUE(response != NULL); 7455 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 7456 7457 TestCompletionCallback callback2; 7458 7459 rv = trans->RestartWithAuth( 7460 AuthCredentials(kFoo, kBar), callback2.callback()); 7461 EXPECT_EQ(ERR_IO_PENDING, rv); 7462 7463 rv = callback2.WaitForResult(); 7464 EXPECT_EQ(OK, rv); 7465 7466 response = trans->GetResponseInfo(); 7467 ASSERT_TRUE(response != NULL); 7468 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7469 EXPECT_EQ(100, response->headers->GetContentLength()); 7470} 7471 7472// Test HTTPS connections going through a proxy that sends extra data. 7473TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) { 7474 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 7475 7476 HttpRequestInfo request; 7477 request.method = "GET"; 7478 request.url = GURL("https://www.google.com/"); 7479 request.load_flags = 0; 7480 7481 MockRead proxy_reads[] = { 7482 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"), 7483 MockRead(SYNCHRONOUS, OK) 7484 }; 7485 7486 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0); 7487 SSLSocketDataProvider ssl(ASYNC, OK); 7488 7489 session_deps_.socket_factory->AddSocketDataProvider(&data); 7490 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 7491 7492 TestCompletionCallback callback; 7493 7494 session_deps_.socket_factory->ResetNextMockIndexes(); 7495 7496 scoped_ptr<HttpTransaction> trans( 7497 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7498 CreateSession(&session_deps_))); 7499 7500 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7501 EXPECT_EQ(ERR_IO_PENDING, rv); 7502 7503 rv = callback.WaitForResult(); 7504 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 7505} 7506 7507TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) { 7508 HttpRequestInfo request; 7509 request.method = "GET"; 7510 request.url = GURL("http://www.google.com/"); 7511 request.load_flags = 0; 7512 7513 scoped_ptr<HttpTransaction> trans( 7514 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7515 CreateSession(&session_deps_))); 7516 7517 MockRead data_reads[] = { 7518 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"), 7519 MockRead(SYNCHRONOUS, OK), 7520 }; 7521 7522 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7523 session_deps_.socket_factory->AddSocketDataProvider(&data); 7524 7525 TestCompletionCallback callback; 7526 7527 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7528 EXPECT_EQ(ERR_IO_PENDING, rv); 7529 7530 EXPECT_EQ(OK, callback.WaitForResult()); 7531 7532 const HttpResponseInfo* response = trans->GetResponseInfo(); 7533 ASSERT_TRUE(response != NULL); 7534 7535 EXPECT_TRUE(response->headers.get() != NULL); 7536 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7537 7538 std::string response_data; 7539 rv = ReadTransaction(trans.get(), &response_data); 7540 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 7541} 7542 7543TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { 7544 base::FilePath temp_file_path; 7545 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path)); 7546 const uint64 kFakeSize = 100000; // file is actually blank 7547 UploadFileElementReader::ScopedOverridingContentLengthForTests 7548 overriding_content_length(kFakeSize); 7549 7550 ScopedVector<UploadElementReader> element_readers; 7551 element_readers.push_back( 7552 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 7553 temp_file_path, 7554 0, 7555 kuint64max, 7556 base::Time())); 7557 UploadDataStream upload_data_stream(&element_readers, 0); 7558 7559 HttpRequestInfo request; 7560 request.method = "POST"; 7561 request.url = GURL("http://www.google.com/upload"); 7562 request.upload_data_stream = &upload_data_stream; 7563 request.load_flags = 0; 7564 7565 scoped_ptr<HttpTransaction> trans( 7566 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7567 CreateSession(&session_deps_))); 7568 7569 MockRead data_reads[] = { 7570 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 7571 MockRead("hello world"), 7572 MockRead(SYNCHRONOUS, OK), 7573 }; 7574 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7575 session_deps_.socket_factory->AddSocketDataProvider(&data); 7576 7577 TestCompletionCallback callback; 7578 7579 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7580 EXPECT_EQ(ERR_IO_PENDING, rv); 7581 7582 rv = callback.WaitForResult(); 7583 EXPECT_EQ(OK, rv); 7584 7585 const HttpResponseInfo* response = trans->GetResponseInfo(); 7586 ASSERT_TRUE(response != NULL); 7587 7588 EXPECT_TRUE(response->headers.get() != NULL); 7589 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7590 7591 std::string response_data; 7592 rv = ReadTransaction(trans.get(), &response_data); 7593 EXPECT_EQ(OK, rv); 7594 EXPECT_EQ("hello world", response_data); 7595 7596 base::DeleteFile(temp_file_path, false); 7597} 7598 7599TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { 7600 base::FilePath temp_file; 7601 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file)); 7602 std::string temp_file_content("Unreadable file."); 7603 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(), 7604 temp_file_content.length())); 7605 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file)); 7606 7607 ScopedVector<UploadElementReader> element_readers; 7608 element_readers.push_back( 7609 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 7610 temp_file, 7611 0, 7612 kuint64max, 7613 base::Time())); 7614 UploadDataStream upload_data_stream(&element_readers, 0); 7615 7616 HttpRequestInfo request; 7617 request.method = "POST"; 7618 request.url = GURL("http://www.google.com/upload"); 7619 request.upload_data_stream = &upload_data_stream; 7620 request.load_flags = 0; 7621 7622 // If we try to upload an unreadable file, the network stack should report 7623 // the file size as zero and upload zero bytes for that file. 7624 scoped_ptr<HttpTransaction> trans( 7625 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7626 CreateSession(&session_deps_))); 7627 7628 MockRead data_reads[] = { 7629 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 7630 MockRead(SYNCHRONOUS, OK), 7631 }; 7632 MockWrite data_writes[] = { 7633 MockWrite("POST /upload HTTP/1.1\r\n" 7634 "Host: www.google.com\r\n" 7635 "Connection: keep-alive\r\n" 7636 "Content-Length: 0\r\n\r\n"), 7637 MockWrite(SYNCHRONOUS, OK), 7638 }; 7639 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, 7640 arraysize(data_writes)); 7641 session_deps_.socket_factory->AddSocketDataProvider(&data); 7642 7643 TestCompletionCallback callback; 7644 7645 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7646 EXPECT_EQ(ERR_IO_PENDING, rv); 7647 7648 rv = callback.WaitForResult(); 7649 EXPECT_EQ(OK, rv); 7650 7651 const HttpResponseInfo* response = trans->GetResponseInfo(); 7652 ASSERT_TRUE(response != NULL); 7653 EXPECT_TRUE(response->headers.get() != NULL); 7654 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7655 7656 base::DeleteFile(temp_file, false); 7657} 7658 7659TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) { 7660 base::FilePath temp_file; 7661 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file)); 7662 std::string temp_file_contents("Unreadable file."); 7663 std::string unreadable_contents(temp_file_contents.length(), '\0'); 7664 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(), 7665 temp_file_contents.length())); 7666 7667 ScopedVector<UploadElementReader> element_readers; 7668 element_readers.push_back( 7669 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 7670 temp_file, 7671 0, 7672 kuint64max, 7673 base::Time())); 7674 UploadDataStream upload_data_stream(&element_readers, 0); 7675 7676 HttpRequestInfo request; 7677 request.method = "POST"; 7678 request.url = GURL("http://www.google.com/upload"); 7679 request.upload_data_stream = &upload_data_stream; 7680 request.load_flags = 0; 7681 7682 scoped_ptr<HttpTransaction> trans( 7683 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7684 CreateSession(&session_deps_))); 7685 7686 MockRead data_reads[] = { 7687 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 7688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 7689 MockRead("Content-Length: 0\r\n\r\n"), // No response body. 7690 7691 MockRead("HTTP/1.1 200 OK\r\n"), 7692 MockRead("Content-Length: 0\r\n\r\n"), 7693 MockRead(SYNCHRONOUS, OK), 7694 }; 7695 MockWrite data_writes[] = { 7696 MockWrite("POST /upload HTTP/1.1\r\n" 7697 "Host: www.google.com\r\n" 7698 "Connection: keep-alive\r\n" 7699 "Content-Length: 16\r\n\r\n"), 7700 MockWrite(SYNCHRONOUS, temp_file_contents.c_str()), 7701 7702 MockWrite("POST /upload HTTP/1.1\r\n" 7703 "Host: www.google.com\r\n" 7704 "Connection: keep-alive\r\n" 7705 "Content-Length: 0\r\n" 7706 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 7707 MockWrite(SYNCHRONOUS, unreadable_contents.c_str(), 7708 temp_file_contents.length()), 7709 MockWrite(SYNCHRONOUS, OK), 7710 }; 7711 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, 7712 arraysize(data_writes)); 7713 session_deps_.socket_factory->AddSocketDataProvider(&data); 7714 7715 TestCompletionCallback callback1; 7716 7717 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 7718 EXPECT_EQ(ERR_IO_PENDING, rv); 7719 7720 rv = callback1.WaitForResult(); 7721 EXPECT_EQ(OK, rv); 7722 7723 const HttpResponseInfo* response = trans->GetResponseInfo(); 7724 ASSERT_TRUE(response != NULL); 7725 ASSERT_TRUE(response->headers.get() != NULL); 7726 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine()); 7727 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 7728 7729 // Now make the file unreadable and try again. 7730 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file)); 7731 7732 TestCompletionCallback callback2; 7733 7734 rv = trans->RestartWithAuth( 7735 AuthCredentials(kFoo, kBar), callback2.callback()); 7736 EXPECT_EQ(ERR_IO_PENDING, rv); 7737 7738 rv = callback2.WaitForResult(); 7739 EXPECT_EQ(OK, rv); 7740 7741 response = trans->GetResponseInfo(); 7742 ASSERT_TRUE(response != NULL); 7743 EXPECT_TRUE(response->headers.get() != NULL); 7744 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7745 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7746 7747 base::DeleteFile(temp_file, false); 7748} 7749 7750// Tests that changes to Auth realms are treated like auth rejections. 7751TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) { 7752 7753 HttpRequestInfo request; 7754 request.method = "GET"; 7755 request.url = GURL("http://www.google.com/"); 7756 request.load_flags = 0; 7757 7758 // First transaction will request a resource and receive a Basic challenge 7759 // with realm="first_realm". 7760 MockWrite data_writes1[] = { 7761 MockWrite("GET / HTTP/1.1\r\n" 7762 "Host: www.google.com\r\n" 7763 "Connection: keep-alive\r\n" 7764 "\r\n"), 7765 }; 7766 MockRead data_reads1[] = { 7767 MockRead("HTTP/1.1 401 Unauthorized\r\n" 7768 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n" 7769 "\r\n"), 7770 }; 7771 7772 // After calling trans->RestartWithAuth(), provide an Authentication header 7773 // for first_realm. The server will reject and provide a challenge with 7774 // second_realm. 7775 MockWrite data_writes2[] = { 7776 MockWrite("GET / HTTP/1.1\r\n" 7777 "Host: www.google.com\r\n" 7778 "Connection: keep-alive\r\n" 7779 "Authorization: Basic Zmlyc3Q6YmF6\r\n" 7780 "\r\n"), 7781 }; 7782 MockRead data_reads2[] = { 7783 MockRead("HTTP/1.1 401 Unauthorized\r\n" 7784 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n" 7785 "\r\n"), 7786 }; 7787 7788 // This again fails, and goes back to first_realm. Make sure that the 7789 // entry is removed from cache. 7790 MockWrite data_writes3[] = { 7791 MockWrite("GET / HTTP/1.1\r\n" 7792 "Host: www.google.com\r\n" 7793 "Connection: keep-alive\r\n" 7794 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n" 7795 "\r\n"), 7796 }; 7797 MockRead data_reads3[] = { 7798 MockRead("HTTP/1.1 401 Unauthorized\r\n" 7799 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n" 7800 "\r\n"), 7801 }; 7802 7803 // Try one last time (with the correct password) and get the resource. 7804 MockWrite data_writes4[] = { 7805 MockWrite("GET / HTTP/1.1\r\n" 7806 "Host: www.google.com\r\n" 7807 "Connection: keep-alive\r\n" 7808 "Authorization: Basic Zmlyc3Q6YmFy\r\n" 7809 "\r\n"), 7810 }; 7811 MockRead data_reads4[] = { 7812 MockRead("HTTP/1.1 200 OK\r\n" 7813 "Content-Type: text/html; charset=iso-8859-1\r\n" 7814 "Content-Length: 5\r\n" 7815 "\r\n" 7816 "hello"), 7817 }; 7818 7819 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 7820 data_writes1, arraysize(data_writes1)); 7821 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 7822 data_writes2, arraysize(data_writes2)); 7823 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 7824 data_writes3, arraysize(data_writes3)); 7825 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4), 7826 data_writes4, arraysize(data_writes4)); 7827 session_deps_.socket_factory->AddSocketDataProvider(&data1); 7828 session_deps_.socket_factory->AddSocketDataProvider(&data2); 7829 session_deps_.socket_factory->AddSocketDataProvider(&data3); 7830 session_deps_.socket_factory->AddSocketDataProvider(&data4); 7831 7832 TestCompletionCallback callback1; 7833 7834 scoped_ptr<HttpTransaction> trans( 7835 new HttpNetworkTransaction(DEFAULT_PRIORITY, 7836 CreateSession(&session_deps_))); 7837 7838 // Issue the first request with Authorize headers. There should be a 7839 // password prompt for first_realm waiting to be filled in after the 7840 // transaction completes. 7841 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 7842 EXPECT_EQ(ERR_IO_PENDING, rv); 7843 rv = callback1.WaitForResult(); 7844 EXPECT_EQ(OK, rv); 7845 const HttpResponseInfo* response = trans->GetResponseInfo(); 7846 ASSERT_TRUE(response != NULL); 7847 const AuthChallengeInfo* challenge = response->auth_challenge.get(); 7848 ASSERT_FALSE(challenge == NULL); 7849 EXPECT_FALSE(challenge->is_proxy); 7850 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString()); 7851 EXPECT_EQ("first_realm", challenge->realm); 7852 EXPECT_EQ("basic", challenge->scheme); 7853 7854 // Issue the second request with an incorrect password. There should be a 7855 // password prompt for second_realm waiting to be filled in after the 7856 // transaction completes. 7857 TestCompletionCallback callback2; 7858 rv = trans->RestartWithAuth( 7859 AuthCredentials(kFirst, kBaz), callback2.callback()); 7860 EXPECT_EQ(ERR_IO_PENDING, rv); 7861 rv = callback2.WaitForResult(); 7862 EXPECT_EQ(OK, rv); 7863 response = trans->GetResponseInfo(); 7864 ASSERT_TRUE(response != NULL); 7865 challenge = response->auth_challenge.get(); 7866 ASSERT_FALSE(challenge == NULL); 7867 EXPECT_FALSE(challenge->is_proxy); 7868 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString()); 7869 EXPECT_EQ("second_realm", challenge->realm); 7870 EXPECT_EQ("basic", challenge->scheme); 7871 7872 // Issue the third request with another incorrect password. There should be 7873 // a password prompt for first_realm waiting to be filled in. If the password 7874 // prompt is not present, it indicates that the HttpAuthCacheEntry for 7875 // first_realm was not correctly removed. 7876 TestCompletionCallback callback3; 7877 rv = trans->RestartWithAuth( 7878 AuthCredentials(kSecond, kFou), callback3.callback()); 7879 EXPECT_EQ(ERR_IO_PENDING, rv); 7880 rv = callback3.WaitForResult(); 7881 EXPECT_EQ(OK, rv); 7882 response = trans->GetResponseInfo(); 7883 ASSERT_TRUE(response != NULL); 7884 challenge = response->auth_challenge.get(); 7885 ASSERT_FALSE(challenge == NULL); 7886 EXPECT_FALSE(challenge->is_proxy); 7887 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString()); 7888 EXPECT_EQ("first_realm", challenge->realm); 7889 EXPECT_EQ("basic", challenge->scheme); 7890 7891 // Issue the fourth request with the correct password and username. 7892 TestCompletionCallback callback4; 7893 rv = trans->RestartWithAuth( 7894 AuthCredentials(kFirst, kBar), callback4.callback()); 7895 EXPECT_EQ(ERR_IO_PENDING, rv); 7896 rv = callback4.WaitForResult(); 7897 EXPECT_EQ(OK, rv); 7898 response = trans->GetResponseInfo(); 7899 ASSERT_TRUE(response != NULL); 7900 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7901} 7902 7903TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) { 7904 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 7905 HttpStreamFactory::set_use_alternate_protocols(true); 7906 7907 std::string alternate_protocol_http_header = 7908 GetAlternateProtocolHttpHeader(); 7909 7910 MockRead data_reads[] = { 7911 MockRead("HTTP/1.1 200 OK\r\n"), 7912 MockRead(alternate_protocol_http_header.c_str()), 7913 MockRead("hello world"), 7914 MockRead(SYNCHRONOUS, OK), 7915 }; 7916 7917 HttpRequestInfo request; 7918 request.method = "GET"; 7919 request.url = GURL("http://www.google.com/"); 7920 request.load_flags = 0; 7921 7922 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7923 7924 session_deps_.socket_factory->AddSocketDataProvider(&data); 7925 7926 TestCompletionCallback callback; 7927 7928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7929 scoped_ptr<HttpTransaction> trans( 7930 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7931 7932 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7933 EXPECT_EQ(ERR_IO_PENDING, rv); 7934 7935 HostPortPair http_host_port_pair("www.google.com", 80); 7936 const HttpServerProperties& http_server_properties = 7937 *session->http_server_properties(); 7938 EXPECT_FALSE( 7939 http_server_properties.HasAlternateProtocol(http_host_port_pair)); 7940 7941 EXPECT_EQ(OK, callback.WaitForResult()); 7942 7943 const HttpResponseInfo* response = trans->GetResponseInfo(); 7944 ASSERT_TRUE(response != NULL); 7945 ASSERT_TRUE(response->headers.get() != NULL); 7946 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 7947 EXPECT_FALSE(response->was_fetched_via_spdy); 7948 EXPECT_FALSE(response->was_npn_negotiated); 7949 7950 std::string response_data; 7951 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 7952 EXPECT_EQ("hello world", response_data); 7953 7954 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair)); 7955 const PortAlternateProtocolPair alternate = 7956 http_server_properties.GetAlternateProtocol(http_host_port_pair); 7957 PortAlternateProtocolPair expected_alternate; 7958 expected_alternate.port = 443; 7959 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam()); 7960 EXPECT_TRUE(expected_alternate.Equals(alternate)); 7961} 7962 7963TEST_P(HttpNetworkTransactionTest, 7964 MarkBrokenAlternateProtocolAndFallback) { 7965 HttpStreamFactory::set_use_alternate_protocols(true); 7966 7967 HttpRequestInfo request; 7968 request.method = "GET"; 7969 request.url = GURL("http://www.google.com/"); 7970 request.load_flags = 0; 7971 7972 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 7973 StaticSocketDataProvider first_data; 7974 first_data.set_connect_data(mock_connect); 7975 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 7976 7977 MockRead data_reads[] = { 7978 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 7979 MockRead("hello world"), 7980 MockRead(ASYNC, OK), 7981 }; 7982 StaticSocketDataProvider second_data( 7983 data_reads, arraysize(data_reads), NULL, 0); 7984 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 7985 7986 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7987 7988 base::WeakPtr<HttpServerProperties> http_server_properties = 7989 session->http_server_properties(); 7990 // Port must be < 1024, or the header will be ignored (since initial port was 7991 // port 80 (another restricted port). 7992 http_server_properties->SetAlternateProtocol( 7993 HostPortPair::FromURL(request.url), 7994 666 /* port is ignored by MockConnect anyway */, 7995 AlternateProtocolFromNextProto(GetParam())); 7996 7997 scoped_ptr<HttpTransaction> trans( 7998 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7999 TestCompletionCallback callback; 8000 8001 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8002 EXPECT_EQ(ERR_IO_PENDING, rv); 8003 EXPECT_EQ(OK, callback.WaitForResult()); 8004 8005 const HttpResponseInfo* response = trans->GetResponseInfo(); 8006 ASSERT_TRUE(response != NULL); 8007 ASSERT_TRUE(response->headers.get() != NULL); 8008 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8009 8010 std::string response_data; 8011 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8012 EXPECT_EQ("hello world", response_data); 8013 8014 ASSERT_TRUE(http_server_properties->HasAlternateProtocol( 8015 HostPortPair::FromURL(request.url))); 8016 const PortAlternateProtocolPair alternate = 8017 http_server_properties->GetAlternateProtocol( 8018 HostPortPair::FromURL(request.url)); 8019 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol); 8020} 8021 8022TEST_P(HttpNetworkTransactionTest, 8023 AlternateProtocolPortRestrictedBlocked) { 8024 // Ensure that we're not allowed to redirect traffic via an alternate 8025 // protocol to an unrestricted (port >= 1024) when the original traffic was 8026 // on a restricted port (port < 1024). Ensure that we can redirect in all 8027 // other cases. 8028 HttpStreamFactory::set_use_alternate_protocols(true); 8029 8030 HttpRequestInfo restricted_port_request; 8031 restricted_port_request.method = "GET"; 8032 restricted_port_request.url = GURL("http://www.google.com:1023/"); 8033 restricted_port_request.load_flags = 0; 8034 8035 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8036 StaticSocketDataProvider first_data; 8037 first_data.set_connect_data(mock_connect); 8038 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8039 8040 MockRead data_reads[] = { 8041 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8042 MockRead("hello world"), 8043 MockRead(ASYNC, OK), 8044 }; 8045 StaticSocketDataProvider second_data( 8046 data_reads, arraysize(data_reads), NULL, 0); 8047 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8048 8049 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8050 8051 base::WeakPtr<HttpServerProperties> http_server_properties = 8052 session->http_server_properties(); 8053 const int kUnrestrictedAlternatePort = 1024; 8054 http_server_properties->SetAlternateProtocol( 8055 HostPortPair::FromURL(restricted_port_request.url), 8056 kUnrestrictedAlternatePort, 8057 AlternateProtocolFromNextProto(GetParam())); 8058 8059 scoped_ptr<HttpTransaction> trans( 8060 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8061 TestCompletionCallback callback; 8062 8063 int rv = trans->Start( 8064 &restricted_port_request, 8065 callback.callback(), BoundNetLog()); 8066 EXPECT_EQ(ERR_IO_PENDING, rv); 8067 // Invalid change to unrestricted port should fail. 8068 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult()); 8069} 8070 8071TEST_P(HttpNetworkTransactionTest, 8072 AlternateProtocolPortRestrictedPermitted) { 8073 // Ensure that we're allowed to redirect traffic via an alternate 8074 // protocol to an unrestricted (port >= 1024) when the original traffic was 8075 // on a restricted port (port < 1024) if we set 8076 // enable_user_alternate_protocol_ports. 8077 8078 HttpStreamFactory::set_use_alternate_protocols(true); 8079 session_deps_.enable_user_alternate_protocol_ports = true; 8080 8081 HttpRequestInfo restricted_port_request; 8082 restricted_port_request.method = "GET"; 8083 restricted_port_request.url = GURL("http://www.google.com:1023/"); 8084 restricted_port_request.load_flags = 0; 8085 8086 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8087 StaticSocketDataProvider first_data; 8088 first_data.set_connect_data(mock_connect); 8089 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8090 8091 MockRead data_reads[] = { 8092 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8093 MockRead("hello world"), 8094 MockRead(ASYNC, OK), 8095 }; 8096 StaticSocketDataProvider second_data( 8097 data_reads, arraysize(data_reads), NULL, 0); 8098 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8099 8100 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8101 8102 base::WeakPtr<HttpServerProperties> http_server_properties = 8103 session->http_server_properties(); 8104 const int kUnrestrictedAlternatePort = 1024; 8105 http_server_properties->SetAlternateProtocol( 8106 HostPortPair::FromURL(restricted_port_request.url), 8107 kUnrestrictedAlternatePort, 8108 AlternateProtocolFromNextProto(GetParam())); 8109 8110 scoped_ptr<HttpTransaction> trans( 8111 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8112 TestCompletionCallback callback; 8113 8114 EXPECT_EQ(ERR_IO_PENDING, trans->Start( 8115 &restricted_port_request, 8116 callback.callback(), BoundNetLog())); 8117 // Change to unrestricted port should succeed. 8118 EXPECT_EQ(OK, callback.WaitForResult()); 8119} 8120 8121TEST_P(HttpNetworkTransactionTest, 8122 AlternateProtocolPortRestrictedAllowed) { 8123 // Ensure that we're not allowed to redirect traffic via an alternate 8124 // protocol to an unrestricted (port >= 1024) when the original traffic was 8125 // on a restricted port (port < 1024). Ensure that we can redirect in all 8126 // other cases. 8127 HttpStreamFactory::set_use_alternate_protocols(true); 8128 8129 HttpRequestInfo restricted_port_request; 8130 restricted_port_request.method = "GET"; 8131 restricted_port_request.url = GURL("http://www.google.com:1023/"); 8132 restricted_port_request.load_flags = 0; 8133 8134 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8135 StaticSocketDataProvider first_data; 8136 first_data.set_connect_data(mock_connect); 8137 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8138 8139 MockRead data_reads[] = { 8140 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8141 MockRead("hello world"), 8142 MockRead(ASYNC, OK), 8143 }; 8144 StaticSocketDataProvider second_data( 8145 data_reads, arraysize(data_reads), NULL, 0); 8146 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8147 8148 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8149 8150 base::WeakPtr<HttpServerProperties> http_server_properties = 8151 session->http_server_properties(); 8152 const int kRestrictedAlternatePort = 80; 8153 http_server_properties->SetAlternateProtocol( 8154 HostPortPair::FromURL(restricted_port_request.url), 8155 kRestrictedAlternatePort, 8156 AlternateProtocolFromNextProto(GetParam())); 8157 8158 scoped_ptr<HttpTransaction> trans( 8159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8160 TestCompletionCallback callback; 8161 8162 int rv = trans->Start( 8163 &restricted_port_request, 8164 callback.callback(), BoundNetLog()); 8165 EXPECT_EQ(ERR_IO_PENDING, rv); 8166 // Valid change to restricted port should pass. 8167 EXPECT_EQ(OK, callback.WaitForResult()); 8168} 8169 8170TEST_P(HttpNetworkTransactionTest, 8171 AlternateProtocolPortUnrestrictedAllowed1) { 8172 // Ensure that we're not allowed to redirect traffic via an alternate 8173 // protocol to an unrestricted (port >= 1024) when the original traffic was 8174 // on a restricted port (port < 1024). Ensure that we can redirect in all 8175 // other cases. 8176 HttpStreamFactory::set_use_alternate_protocols(true); 8177 8178 HttpRequestInfo unrestricted_port_request; 8179 unrestricted_port_request.method = "GET"; 8180 unrestricted_port_request.url = GURL("http://www.google.com:1024/"); 8181 unrestricted_port_request.load_flags = 0; 8182 8183 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8184 StaticSocketDataProvider first_data; 8185 first_data.set_connect_data(mock_connect); 8186 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8187 8188 MockRead data_reads[] = { 8189 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8190 MockRead("hello world"), 8191 MockRead(ASYNC, OK), 8192 }; 8193 StaticSocketDataProvider second_data( 8194 data_reads, arraysize(data_reads), NULL, 0); 8195 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8196 8197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8198 8199 base::WeakPtr<HttpServerProperties> http_server_properties = 8200 session->http_server_properties(); 8201 const int kRestrictedAlternatePort = 80; 8202 http_server_properties->SetAlternateProtocol( 8203 HostPortPair::FromURL(unrestricted_port_request.url), 8204 kRestrictedAlternatePort, 8205 AlternateProtocolFromNextProto(GetParam())); 8206 8207 scoped_ptr<HttpTransaction> trans( 8208 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8209 TestCompletionCallback callback; 8210 8211 int rv = trans->Start( 8212 &unrestricted_port_request, callback.callback(), BoundNetLog()); 8213 EXPECT_EQ(ERR_IO_PENDING, rv); 8214 // Valid change to restricted port should pass. 8215 EXPECT_EQ(OK, callback.WaitForResult()); 8216} 8217 8218TEST_P(HttpNetworkTransactionTest, 8219 AlternateProtocolPortUnrestrictedAllowed2) { 8220 // Ensure that we're not allowed to redirect traffic via an alternate 8221 // protocol to an unrestricted (port >= 1024) when the original traffic was 8222 // on a restricted port (port < 1024). Ensure that we can redirect in all 8223 // other cases. 8224 HttpStreamFactory::set_use_alternate_protocols(true); 8225 8226 HttpRequestInfo unrestricted_port_request; 8227 unrestricted_port_request.method = "GET"; 8228 unrestricted_port_request.url = GURL("http://www.google.com:1024/"); 8229 unrestricted_port_request.load_flags = 0; 8230 8231 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8232 StaticSocketDataProvider first_data; 8233 first_data.set_connect_data(mock_connect); 8234 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8235 8236 MockRead data_reads[] = { 8237 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8238 MockRead("hello world"), 8239 MockRead(ASYNC, OK), 8240 }; 8241 StaticSocketDataProvider second_data( 8242 data_reads, arraysize(data_reads), NULL, 0); 8243 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8244 8245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8246 8247 base::WeakPtr<HttpServerProperties> http_server_properties = 8248 session->http_server_properties(); 8249 const int kUnrestrictedAlternatePort = 1024; 8250 http_server_properties->SetAlternateProtocol( 8251 HostPortPair::FromURL(unrestricted_port_request.url), 8252 kUnrestrictedAlternatePort, 8253 AlternateProtocolFromNextProto(GetParam())); 8254 8255 scoped_ptr<HttpTransaction> trans( 8256 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8257 TestCompletionCallback callback; 8258 8259 int rv = trans->Start( 8260 &unrestricted_port_request, callback.callback(), BoundNetLog()); 8261 EXPECT_EQ(ERR_IO_PENDING, rv); 8262 // Valid change to an unrestricted port should pass. 8263 EXPECT_EQ(OK, callback.WaitForResult()); 8264} 8265 8266TEST_P(HttpNetworkTransactionTest, 8267 AlternateProtocolUnsafeBlocked) { 8268 // Ensure that we're not allowed to redirect traffic via an alternate 8269 // protocol to an unsafe port, and that we resume the second 8270 // HttpStreamFactoryImpl::Job once the alternate protocol request fails. 8271 HttpStreamFactory::set_use_alternate_protocols(true); 8272 8273 HttpRequestInfo request; 8274 request.method = "GET"; 8275 request.url = GURL("http://www.google.com/"); 8276 request.load_flags = 0; 8277 8278 // The alternate protocol request will error out before we attempt to connect, 8279 // so only the standard HTTP request will try to connect. 8280 MockRead data_reads[] = { 8281 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8282 MockRead("hello world"), 8283 MockRead(ASYNC, OK), 8284 }; 8285 StaticSocketDataProvider data( 8286 data_reads, arraysize(data_reads), NULL, 0); 8287 session_deps_.socket_factory->AddSocketDataProvider(&data); 8288 8289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8290 8291 base::WeakPtr<HttpServerProperties> http_server_properties = 8292 session->http_server_properties(); 8293 const int kUnsafePort = 7; 8294 http_server_properties->SetAlternateProtocol( 8295 HostPortPair::FromURL(request.url), 8296 kUnsafePort, 8297 AlternateProtocolFromNextProto(GetParam())); 8298 8299 scoped_ptr<HttpTransaction> trans( 8300 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8301 TestCompletionCallback callback; 8302 8303 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8304 EXPECT_EQ(ERR_IO_PENDING, rv); 8305 // The HTTP request should succeed. 8306 EXPECT_EQ(OK, callback.WaitForResult()); 8307 8308 // Disable alternate protocol before the asserts. 8309 HttpStreamFactory::set_use_alternate_protocols(false); 8310 8311 const HttpResponseInfo* response = trans->GetResponseInfo(); 8312 ASSERT_TRUE(response != NULL); 8313 ASSERT_TRUE(response->headers.get() != NULL); 8314 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8315 8316 std::string response_data; 8317 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8318 EXPECT_EQ("hello world", response_data); 8319} 8320 8321TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { 8322 HttpStreamFactory::set_use_alternate_protocols(true); 8323 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8324 8325 HttpRequestInfo request; 8326 request.method = "GET"; 8327 request.url = GURL("http://www.google.com/"); 8328 request.load_flags = 0; 8329 8330 std::string alternate_protocol_http_header = 8331 GetAlternateProtocolHttpHeader(); 8332 8333 MockRead data_reads[] = { 8334 MockRead("HTTP/1.1 200 OK\r\n"), 8335 MockRead(alternate_protocol_http_header.c_str()), 8336 MockRead("hello world"), 8337 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8338 MockRead(ASYNC, OK) 8339 }; 8340 8341 StaticSocketDataProvider first_transaction( 8342 data_reads, arraysize(data_reads), NULL, 0); 8343 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8344 8345 SSLSocketDataProvider ssl(ASYNC, OK); 8346 ssl.SetNextProto(GetParam()); 8347 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8348 8349 scoped_ptr<SpdyFrame> req( 8350 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8351 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 8352 8353 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8354 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8355 MockRead spdy_reads[] = { 8356 CreateMockRead(*resp), 8357 CreateMockRead(*data), 8358 MockRead(ASYNC, 0, 0), 8359 }; 8360 8361 DelayedSocketData spdy_data( 8362 1, // wait for one write to finish before reading. 8363 spdy_reads, arraysize(spdy_reads), 8364 spdy_writes, arraysize(spdy_writes)); 8365 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8366 8367 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8368 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 8369 NULL, 0, NULL, 0); 8370 hanging_non_alternate_protocol_socket.set_connect_data( 8371 never_finishing_connect); 8372 session_deps_.socket_factory->AddSocketDataProvider( 8373 &hanging_non_alternate_protocol_socket); 8374 8375 TestCompletionCallback callback; 8376 8377 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8378 scoped_ptr<HttpTransaction> trans( 8379 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8380 8381 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8382 EXPECT_EQ(ERR_IO_PENDING, rv); 8383 EXPECT_EQ(OK, callback.WaitForResult()); 8384 8385 const HttpResponseInfo* response = trans->GetResponseInfo(); 8386 ASSERT_TRUE(response != NULL); 8387 ASSERT_TRUE(response->headers.get() != NULL); 8388 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8389 8390 std::string response_data; 8391 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8392 EXPECT_EQ("hello world", response_data); 8393 8394 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8395 8396 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8397 EXPECT_EQ(ERR_IO_PENDING, rv); 8398 EXPECT_EQ(OK, callback.WaitForResult()); 8399 8400 response = trans->GetResponseInfo(); 8401 ASSERT_TRUE(response != NULL); 8402 ASSERT_TRUE(response->headers.get() != NULL); 8403 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8404 EXPECT_TRUE(response->was_fetched_via_spdy); 8405 EXPECT_TRUE(response->was_npn_negotiated); 8406 8407 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8408 EXPECT_EQ("hello!", response_data); 8409} 8410 8411TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { 8412 HttpStreamFactory::set_use_alternate_protocols(true); 8413 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8414 8415 HttpRequestInfo request; 8416 request.method = "GET"; 8417 request.url = GURL("http://www.google.com/"); 8418 request.load_flags = 0; 8419 8420 std::string alternate_protocol_http_header = 8421 GetAlternateProtocolHttpHeader(); 8422 8423 MockRead data_reads[] = { 8424 MockRead("HTTP/1.1 200 OK\r\n"), 8425 MockRead(alternate_protocol_http_header.c_str()), 8426 MockRead("hello world"), 8427 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8428 MockRead(ASYNC, OK), 8429 }; 8430 8431 StaticSocketDataProvider first_transaction( 8432 data_reads, arraysize(data_reads), NULL, 0); 8433 // Socket 1 is the HTTP transaction with the Alternate-Protocol header. 8434 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8435 8436 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8437 StaticSocketDataProvider hanging_socket( 8438 NULL, 0, NULL, 0); 8439 hanging_socket.set_connect_data(never_finishing_connect); 8440 // Socket 2 and 3 are the hanging Alternate-Protocol and 8441 // non-Alternate-Protocol jobs from the 2nd transaction. 8442 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); 8443 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); 8444 8445 SSLSocketDataProvider ssl(ASYNC, OK); 8446 ssl.SetNextProto(GetParam()); 8447 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8448 8449 scoped_ptr<SpdyFrame> req1( 8450 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8451 scoped_ptr<SpdyFrame> req2( 8452 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 8453 MockWrite spdy_writes[] = { 8454 CreateMockWrite(*req1), 8455 CreateMockWrite(*req2), 8456 }; 8457 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8458 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8459 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 8460 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 8461 MockRead spdy_reads[] = { 8462 CreateMockRead(*resp1), 8463 CreateMockRead(*data1), 8464 CreateMockRead(*resp2), 8465 CreateMockRead(*data2), 8466 MockRead(ASYNC, 0, 0), 8467 }; 8468 8469 DelayedSocketData spdy_data( 8470 2, // wait for writes to finish before reading. 8471 spdy_reads, arraysize(spdy_reads), 8472 spdy_writes, arraysize(spdy_writes)); 8473 // Socket 4 is the successful Alternate-Protocol for transaction 3. 8474 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8475 8476 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3. 8477 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); 8478 8479 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8480 TestCompletionCallback callback1; 8481 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 8482 8483 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog()); 8484 EXPECT_EQ(ERR_IO_PENDING, rv); 8485 EXPECT_EQ(OK, callback1.WaitForResult()); 8486 8487 const HttpResponseInfo* response = trans1.GetResponseInfo(); 8488 ASSERT_TRUE(response != NULL); 8489 ASSERT_TRUE(response->headers.get() != NULL); 8490 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8491 8492 std::string response_data; 8493 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 8494 EXPECT_EQ("hello world", response_data); 8495 8496 TestCompletionCallback callback2; 8497 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 8498 rv = trans2.Start(&request, callback2.callback(), BoundNetLog()); 8499 EXPECT_EQ(ERR_IO_PENDING, rv); 8500 8501 TestCompletionCallback callback3; 8502 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get()); 8503 rv = trans3.Start(&request, callback3.callback(), BoundNetLog()); 8504 EXPECT_EQ(ERR_IO_PENDING, rv); 8505 8506 EXPECT_EQ(OK, callback2.WaitForResult()); 8507 EXPECT_EQ(OK, callback3.WaitForResult()); 8508 8509 response = trans2.GetResponseInfo(); 8510 ASSERT_TRUE(response != NULL); 8511 ASSERT_TRUE(response->headers.get() != NULL); 8512 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8513 EXPECT_TRUE(response->was_fetched_via_spdy); 8514 EXPECT_TRUE(response->was_npn_negotiated); 8515 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 8516 EXPECT_EQ("hello!", response_data); 8517 8518 response = trans3.GetResponseInfo(); 8519 ASSERT_TRUE(response != NULL); 8520 ASSERT_TRUE(response->headers.get() != NULL); 8521 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8522 EXPECT_TRUE(response->was_fetched_via_spdy); 8523 EXPECT_TRUE(response->was_npn_negotiated); 8524 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data)); 8525 EXPECT_EQ("hello!", response_data); 8526} 8527 8528TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) { 8529 HttpStreamFactory::set_use_alternate_protocols(true); 8530 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8531 8532 HttpRequestInfo request; 8533 request.method = "GET"; 8534 request.url = GURL("http://www.google.com/"); 8535 request.load_flags = 0; 8536 8537 std::string alternate_protocol_http_header = 8538 GetAlternateProtocolHttpHeader(); 8539 8540 MockRead data_reads[] = { 8541 MockRead("HTTP/1.1 200 OK\r\n"), 8542 MockRead(alternate_protocol_http_header.c_str()), 8543 MockRead("hello world"), 8544 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8545 MockRead(ASYNC, OK), 8546 }; 8547 8548 StaticSocketDataProvider first_transaction( 8549 data_reads, arraysize(data_reads), NULL, 0); 8550 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8551 8552 SSLSocketDataProvider ssl(ASYNC, OK); 8553 ssl.SetNextProto(GetParam()); 8554 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8555 8556 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8557 StaticSocketDataProvider hanging_alternate_protocol_socket( 8558 NULL, 0, NULL, 0); 8559 hanging_alternate_protocol_socket.set_connect_data( 8560 never_finishing_connect); 8561 session_deps_.socket_factory->AddSocketDataProvider( 8562 &hanging_alternate_protocol_socket); 8563 8564 // 2nd request is just a copy of the first one, over HTTP again. 8565 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8566 8567 TestCompletionCallback callback; 8568 8569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8570 scoped_ptr<HttpTransaction> trans( 8571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8572 8573 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8574 EXPECT_EQ(ERR_IO_PENDING, rv); 8575 EXPECT_EQ(OK, callback.WaitForResult()); 8576 8577 const HttpResponseInfo* response = trans->GetResponseInfo(); 8578 ASSERT_TRUE(response != NULL); 8579 ASSERT_TRUE(response->headers.get() != NULL); 8580 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8581 8582 std::string response_data; 8583 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8584 EXPECT_EQ("hello world", response_data); 8585 8586 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8587 8588 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8589 EXPECT_EQ(ERR_IO_PENDING, rv); 8590 EXPECT_EQ(OK, callback.WaitForResult()); 8591 8592 response = trans->GetResponseInfo(); 8593 ASSERT_TRUE(response != NULL); 8594 ASSERT_TRUE(response->headers.get() != NULL); 8595 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8596 EXPECT_FALSE(response->was_fetched_via_spdy); 8597 EXPECT_FALSE(response->was_npn_negotiated); 8598 8599 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8600 EXPECT_EQ("hello world", response_data); 8601} 8602 8603class CapturingProxyResolver : public ProxyResolver { 8604 public: 8605 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {} 8606 virtual ~CapturingProxyResolver() {} 8607 8608 virtual int GetProxyForURL(const GURL& url, 8609 ProxyInfo* results, 8610 const CompletionCallback& callback, 8611 RequestHandle* request, 8612 const BoundNetLog& net_log) OVERRIDE { 8613 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP, 8614 HostPortPair("myproxy", 80)); 8615 results->UseProxyServer(proxy_server); 8616 resolved_.push_back(url); 8617 return OK; 8618 } 8619 8620 virtual void CancelRequest(RequestHandle request) OVERRIDE { 8621 NOTREACHED(); 8622 } 8623 8624 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { 8625 NOTREACHED(); 8626 return LOAD_STATE_IDLE; 8627 } 8628 8629 virtual void CancelSetPacScript() OVERRIDE { 8630 NOTREACHED(); 8631 } 8632 8633 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&, 8634 const CompletionCallback& /*callback*/) OVERRIDE { 8635 return OK; 8636 } 8637 8638 const std::vector<GURL>& resolved() const { return resolved_; } 8639 8640 private: 8641 std::vector<GURL> resolved_; 8642 8643 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver); 8644}; 8645 8646TEST_P(HttpNetworkTransactionTest, 8647 UseAlternateProtocolForTunneledNpnSpdy) { 8648 HttpStreamFactory::set_use_alternate_protocols(true); 8649 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8650 8651 ProxyConfig proxy_config; 8652 proxy_config.set_auto_detect(true); 8653 proxy_config.set_pac_url(GURL("http://fooproxyurl")); 8654 8655 CapturingProxyResolver* capturing_proxy_resolver = 8656 new CapturingProxyResolver(); 8657 session_deps_.proxy_service.reset(new ProxyService( 8658 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver, 8659 NULL)); 8660 CapturingNetLog net_log; 8661 session_deps_.net_log = &net_log; 8662 8663 HttpRequestInfo request; 8664 request.method = "GET"; 8665 request.url = GURL("http://www.google.com/"); 8666 request.load_flags = 0; 8667 8668 std::string alternate_protocol_http_header = 8669 GetAlternateProtocolHttpHeader(); 8670 8671 MockRead data_reads[] = { 8672 MockRead("HTTP/1.1 200 OK\r\n"), 8673 MockRead(alternate_protocol_http_header.c_str()), 8674 MockRead("hello world"), 8675 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8676 MockRead(ASYNC, OK), 8677 }; 8678 8679 StaticSocketDataProvider first_transaction( 8680 data_reads, arraysize(data_reads), NULL, 0); 8681 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8682 8683 SSLSocketDataProvider ssl(ASYNC, OK); 8684 ssl.SetNextProto(GetParam()); 8685 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8686 8687 scoped_ptr<SpdyFrame> req( 8688 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8689 MockWrite spdy_writes[] = { 8690 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 8691 "Host: www.google.com\r\n" 8692 "Proxy-Connection: keep-alive\r\n\r\n"), // 0 8693 CreateMockWrite(*req), // 3 8694 }; 8695 8696 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; 8697 8698 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8699 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8700 MockRead spdy_reads[] = { 8701 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1 8702 CreateMockRead(*resp.get(), 4), // 2, 4 8703 CreateMockRead(*data.get(), 4), // 5 8704 MockRead(ASYNC, 0, 0, 4), // 6 8705 }; 8706 8707 OrderedSocketData spdy_data( 8708 spdy_reads, arraysize(spdy_reads), 8709 spdy_writes, arraysize(spdy_writes)); 8710 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8711 8712 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8713 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 8714 NULL, 0, NULL, 0); 8715 hanging_non_alternate_protocol_socket.set_connect_data( 8716 never_finishing_connect); 8717 session_deps_.socket_factory->AddSocketDataProvider( 8718 &hanging_non_alternate_protocol_socket); 8719 8720 TestCompletionCallback callback; 8721 8722 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8723 scoped_ptr<HttpTransaction> trans( 8724 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8725 8726 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8727 EXPECT_EQ(ERR_IO_PENDING, rv); 8728 EXPECT_EQ(OK, callback.WaitForResult()); 8729 8730 const HttpResponseInfo* response = trans->GetResponseInfo(); 8731 ASSERT_TRUE(response != NULL); 8732 ASSERT_TRUE(response->headers.get() != NULL); 8733 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8734 EXPECT_FALSE(response->was_fetched_via_spdy); 8735 EXPECT_FALSE(response->was_npn_negotiated); 8736 8737 std::string response_data; 8738 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8739 EXPECT_EQ("hello world", response_data); 8740 8741 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8742 8743 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8744 EXPECT_EQ(ERR_IO_PENDING, rv); 8745 EXPECT_EQ(OK, callback.WaitForResult()); 8746 8747 response = trans->GetResponseInfo(); 8748 ASSERT_TRUE(response != NULL); 8749 ASSERT_TRUE(response->headers.get() != NULL); 8750 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8751 EXPECT_TRUE(response->was_fetched_via_spdy); 8752 EXPECT_TRUE(response->was_npn_negotiated); 8753 8754 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8755 EXPECT_EQ("hello!", response_data); 8756 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size()); 8757 EXPECT_EQ("http://www.google.com/", 8758 capturing_proxy_resolver->resolved()[0].spec()); 8759 EXPECT_EQ("https://www.google.com/", 8760 capturing_proxy_resolver->resolved()[1].spec()); 8761 8762 LoadTimingInfo load_timing_info; 8763 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 8764 TestLoadTimingNotReusedWithPac(load_timing_info, 8765 CONNECT_TIMING_HAS_SSL_TIMES); 8766} 8767 8768TEST_P(HttpNetworkTransactionTest, 8769 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) { 8770 HttpStreamFactory::set_use_alternate_protocols(true); 8771 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8772 8773 HttpRequestInfo request; 8774 request.method = "GET"; 8775 request.url = GURL("http://www.google.com/"); 8776 request.load_flags = 0; 8777 8778 std::string alternate_protocol_http_header = 8779 GetAlternateProtocolHttpHeader(); 8780 8781 MockRead data_reads[] = { 8782 MockRead("HTTP/1.1 200 OK\r\n"), 8783 MockRead(alternate_protocol_http_header.c_str()), 8784 MockRead("hello world"), 8785 MockRead(ASYNC, OK), 8786 }; 8787 8788 StaticSocketDataProvider first_transaction( 8789 data_reads, arraysize(data_reads), NULL, 0); 8790 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8791 8792 SSLSocketDataProvider ssl(ASYNC, OK); 8793 ssl.SetNextProto(GetParam()); 8794 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8795 8796 scoped_ptr<SpdyFrame> req( 8797 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8798 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 8799 8800 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8801 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8802 MockRead spdy_reads[] = { 8803 CreateMockRead(*resp), 8804 CreateMockRead(*data), 8805 MockRead(ASYNC, 0, 0), 8806 }; 8807 8808 DelayedSocketData spdy_data( 8809 1, // wait for one write to finish before reading. 8810 spdy_reads, arraysize(spdy_reads), 8811 spdy_writes, arraysize(spdy_writes)); 8812 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8813 8814 TestCompletionCallback callback; 8815 8816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8817 8818 scoped_ptr<HttpTransaction> trans( 8819 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8820 8821 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8822 EXPECT_EQ(ERR_IO_PENDING, rv); 8823 EXPECT_EQ(OK, callback.WaitForResult()); 8824 8825 const HttpResponseInfo* response = trans->GetResponseInfo(); 8826 ASSERT_TRUE(response != NULL); 8827 ASSERT_TRUE(response->headers.get() != NULL); 8828 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8829 8830 std::string response_data; 8831 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8832 EXPECT_EQ("hello world", response_data); 8833 8834 // Set up an initial SpdySession in the pool to reuse. 8835 HostPortPair host_port_pair("www.google.com", 443); 8836 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), 8837 kPrivacyModeDisabled); 8838 base::WeakPtr<SpdySession> spdy_session = 8839 CreateSecureSpdySession(session, key, BoundNetLog()); 8840 8841 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8842 8843 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8844 EXPECT_EQ(ERR_IO_PENDING, rv); 8845 EXPECT_EQ(OK, callback.WaitForResult()); 8846 8847 response = trans->GetResponseInfo(); 8848 ASSERT_TRUE(response != NULL); 8849 ASSERT_TRUE(response->headers.get() != NULL); 8850 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8851 EXPECT_TRUE(response->was_fetched_via_spdy); 8852 EXPECT_TRUE(response->was_npn_negotiated); 8853 8854 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8855 EXPECT_EQ("hello!", response_data); 8856} 8857 8858// GenerateAuthToken is a mighty big test. 8859// It tests all permutation of GenerateAuthToken behavior: 8860// - Synchronous and Asynchronous completion. 8861// - OK or error on completion. 8862// - Direct connection, non-authenticating proxy, and authenticating proxy. 8863// - HTTP or HTTPS backend (to include proxy tunneling). 8864// - Non-authenticating and authenticating backend. 8865// 8866// In all, there are 44 reasonable permuations (for example, if there are 8867// problems generating an auth token for an authenticating proxy, we don't 8868// need to test all permutations of the backend server). 8869// 8870// The test proceeds by going over each of the configuration cases, and 8871// potentially running up to three rounds in each of the tests. The TestConfig 8872// specifies both the configuration for the test as well as the expectations 8873// for the results. 8874TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { 8875 static const char kServer[] = "http://www.example.com"; 8876 static const char kSecureServer[] = "https://www.example.com"; 8877 static const char kProxy[] = "myproxy:70"; 8878 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS; 8879 8880 enum AuthTiming { 8881 AUTH_NONE, 8882 AUTH_SYNC, 8883 AUTH_ASYNC, 8884 }; 8885 8886 const MockWrite kGet( 8887 "GET / HTTP/1.1\r\n" 8888 "Host: www.example.com\r\n" 8889 "Connection: keep-alive\r\n\r\n"); 8890 const MockWrite kGetProxy( 8891 "GET http://www.example.com/ HTTP/1.1\r\n" 8892 "Host: www.example.com\r\n" 8893 "Proxy-Connection: keep-alive\r\n\r\n"); 8894 const MockWrite kGetAuth( 8895 "GET / HTTP/1.1\r\n" 8896 "Host: www.example.com\r\n" 8897 "Connection: keep-alive\r\n" 8898 "Authorization: auth_token\r\n\r\n"); 8899 const MockWrite kGetProxyAuth( 8900 "GET http://www.example.com/ HTTP/1.1\r\n" 8901 "Host: www.example.com\r\n" 8902 "Proxy-Connection: keep-alive\r\n" 8903 "Proxy-Authorization: auth_token\r\n\r\n"); 8904 const MockWrite kGetAuthThroughProxy( 8905 "GET http://www.example.com/ HTTP/1.1\r\n" 8906 "Host: www.example.com\r\n" 8907 "Proxy-Connection: keep-alive\r\n" 8908 "Authorization: auth_token\r\n\r\n"); 8909 const MockWrite kGetAuthWithProxyAuth( 8910 "GET http://www.example.com/ HTTP/1.1\r\n" 8911 "Host: www.example.com\r\n" 8912 "Proxy-Connection: keep-alive\r\n" 8913 "Proxy-Authorization: auth_token\r\n" 8914 "Authorization: auth_token\r\n\r\n"); 8915 const MockWrite kConnect( 8916 "CONNECT www.example.com:443 HTTP/1.1\r\n" 8917 "Host: www.example.com\r\n" 8918 "Proxy-Connection: keep-alive\r\n\r\n"); 8919 const MockWrite kConnectProxyAuth( 8920 "CONNECT www.example.com:443 HTTP/1.1\r\n" 8921 "Host: www.example.com\r\n" 8922 "Proxy-Connection: keep-alive\r\n" 8923 "Proxy-Authorization: auth_token\r\n\r\n"); 8924 8925 const MockRead kSuccess( 8926 "HTTP/1.1 200 OK\r\n" 8927 "Content-Type: text/html; charset=iso-8859-1\r\n" 8928 "Content-Length: 3\r\n\r\n" 8929 "Yes"); 8930 const MockRead kFailure( 8931 "Should not be called."); 8932 const MockRead kServerChallenge( 8933 "HTTP/1.1 401 Unauthorized\r\n" 8934 "WWW-Authenticate: Mock realm=server\r\n" 8935 "Content-Type: text/html; charset=iso-8859-1\r\n" 8936 "Content-Length: 14\r\n\r\n" 8937 "Unauthorized\r\n"); 8938 const MockRead kProxyChallenge( 8939 "HTTP/1.1 407 Unauthorized\r\n" 8940 "Proxy-Authenticate: Mock realm=proxy\r\n" 8941 "Proxy-Connection: close\r\n" 8942 "Content-Type: text/html; charset=iso-8859-1\r\n" 8943 "Content-Length: 14\r\n\r\n" 8944 "Unauthorized\r\n"); 8945 const MockRead kProxyConnected( 8946 "HTTP/1.1 200 Connection Established\r\n\r\n"); 8947 8948 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with 8949 // no constructors, but the C++ compiler on Windows warns about 8950 // unspecified data in compound literals. So, moved to using constructors, 8951 // and TestRound's created with the default constructor should not be used. 8952 struct TestRound { 8953 TestRound() 8954 : expected_rv(ERR_UNEXPECTED), 8955 extra_write(NULL), 8956 extra_read(NULL) { 8957 } 8958 TestRound(const MockWrite& write_arg, const MockRead& read_arg, 8959 int expected_rv_arg) 8960 : write(write_arg), 8961 read(read_arg), 8962 expected_rv(expected_rv_arg), 8963 extra_write(NULL), 8964 extra_read(NULL) { 8965 } 8966 TestRound(const MockWrite& write_arg, const MockRead& read_arg, 8967 int expected_rv_arg, const MockWrite* extra_write_arg, 8968 const MockRead* extra_read_arg) 8969 : write(write_arg), 8970 read(read_arg), 8971 expected_rv(expected_rv_arg), 8972 extra_write(extra_write_arg), 8973 extra_read(extra_read_arg) { 8974 } 8975 MockWrite write; 8976 MockRead read; 8977 int expected_rv; 8978 const MockWrite* extra_write; 8979 const MockRead* extra_read; 8980 }; 8981 8982 static const int kNoSSL = 500; 8983 8984 struct TestConfig { 8985 const char* proxy_url; 8986 AuthTiming proxy_auth_timing; 8987 int proxy_auth_rv; 8988 const char* server_url; 8989 AuthTiming server_auth_timing; 8990 int server_auth_rv; 8991 int num_auth_rounds; 8992 int first_ssl_round; 8993 TestRound rounds[3]; 8994 } test_configs[] = { 8995 // Non-authenticating HTTP server with a direct connection. 8996 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL, 8997 { TestRound(kGet, kSuccess, OK)}}, 8998 // Authenticating HTTP server with a direct connection. 8999 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL, 9000 { TestRound(kGet, kServerChallenge, OK), 9001 TestRound(kGetAuth, kSuccess, OK)}}, 9002 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL, 9003 { TestRound(kGet, kServerChallenge, OK), 9004 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9005 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL, 9006 { TestRound(kGet, kServerChallenge, OK), 9007 TestRound(kGetAuth, kSuccess, OK)}}, 9008 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL, 9009 { TestRound(kGet, kServerChallenge, OK), 9010 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9011 // Non-authenticating HTTP server through a non-authenticating proxy. 9012 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL, 9013 { TestRound(kGetProxy, kSuccess, OK)}}, 9014 // Authenticating HTTP server through a non-authenticating proxy. 9015 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL, 9016 { TestRound(kGetProxy, kServerChallenge, OK), 9017 TestRound(kGetAuthThroughProxy, kSuccess, OK)}}, 9018 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL, 9019 { TestRound(kGetProxy, kServerChallenge, OK), 9020 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}}, 9021 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL, 9022 { TestRound(kGetProxy, kServerChallenge, OK), 9023 TestRound(kGetAuthThroughProxy, kSuccess, OK)}}, 9024 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL, 9025 { TestRound(kGetProxy, kServerChallenge, OK), 9026 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}}, 9027 // Non-authenticating HTTP server through an authenticating proxy. 9028 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL, 9029 { TestRound(kGetProxy, kProxyChallenge, OK), 9030 TestRound(kGetProxyAuth, kSuccess, OK)}}, 9031 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL, 9032 { TestRound(kGetProxy, kProxyChallenge, OK), 9033 TestRound(kGetProxyAuth, kFailure, kAuthErr)}}, 9034 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL, 9035 { TestRound(kGetProxy, kProxyChallenge, OK), 9036 TestRound(kGetProxyAuth, kSuccess, OK)}}, 9037 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL, 9038 { TestRound(kGetProxy, kProxyChallenge, OK), 9039 TestRound(kGetProxyAuth, kFailure, kAuthErr)}}, 9040 // Authenticating HTTP server through an authenticating proxy. 9041 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL, 9042 { TestRound(kGetProxy, kProxyChallenge, OK), 9043 TestRound(kGetProxyAuth, kServerChallenge, OK), 9044 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9045 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL, 9046 { TestRound(kGetProxy, kProxyChallenge, OK), 9047 TestRound(kGetProxyAuth, kServerChallenge, OK), 9048 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9049 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL, 9050 { TestRound(kGetProxy, kProxyChallenge, OK), 9051 TestRound(kGetProxyAuth, kServerChallenge, OK), 9052 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9053 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL, 9054 { TestRound(kGetProxy, kProxyChallenge, OK), 9055 TestRound(kGetProxyAuth, kServerChallenge, OK), 9056 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9057 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL, 9058 { TestRound(kGetProxy, kProxyChallenge, OK), 9059 TestRound(kGetProxyAuth, kServerChallenge, OK), 9060 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9061 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL, 9062 { TestRound(kGetProxy, kProxyChallenge, OK), 9063 TestRound(kGetProxyAuth, kServerChallenge, OK), 9064 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9065 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL, 9066 { TestRound(kGetProxy, kProxyChallenge, OK), 9067 TestRound(kGetProxyAuth, kServerChallenge, OK), 9068 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9069 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL, 9070 { TestRound(kGetProxy, kProxyChallenge, OK), 9071 TestRound(kGetProxyAuth, kServerChallenge, OK), 9072 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9073 // Non-authenticating HTTPS server with a direct connection. 9074 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0, 9075 { TestRound(kGet, kSuccess, OK)}}, 9076 // Authenticating HTTPS server with a direct connection. 9077 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0, 9078 { TestRound(kGet, kServerChallenge, OK), 9079 TestRound(kGetAuth, kSuccess, OK)}}, 9080 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0, 9081 { TestRound(kGet, kServerChallenge, OK), 9082 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9083 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0, 9084 { TestRound(kGet, kServerChallenge, OK), 9085 TestRound(kGetAuth, kSuccess, OK)}}, 9086 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0, 9087 { TestRound(kGet, kServerChallenge, OK), 9088 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9089 // Non-authenticating HTTPS server with a non-authenticating proxy. 9090 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0, 9091 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}}, 9092 // Authenticating HTTPS server through a non-authenticating proxy. 9093 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0, 9094 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9095 TestRound(kGetAuth, kSuccess, OK)}}, 9096 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0, 9097 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9098 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9099 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0, 9100 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9101 TestRound(kGetAuth, kSuccess, OK)}}, 9102 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0, 9103 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9104 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9105 // Non-Authenticating HTTPS server through an authenticating proxy. 9106 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1, 9107 { TestRound(kConnect, kProxyChallenge, OK), 9108 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}}, 9109 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL, 9110 { TestRound(kConnect, kProxyChallenge, OK), 9111 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}}, 9112 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1, 9113 { TestRound(kConnect, kProxyChallenge, OK), 9114 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}}, 9115 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL, 9116 { TestRound(kConnect, kProxyChallenge, OK), 9117 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}}, 9118 // Authenticating HTTPS server through an authenticating proxy. 9119 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1, 9120 { TestRound(kConnect, kProxyChallenge, OK), 9121 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9122 &kGet, &kServerChallenge), 9123 TestRound(kGetAuth, kSuccess, OK)}}, 9124 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1, 9125 { TestRound(kConnect, kProxyChallenge, OK), 9126 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9127 &kGet, &kServerChallenge), 9128 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9129 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1, 9130 { TestRound(kConnect, kProxyChallenge, OK), 9131 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9132 &kGet, &kServerChallenge), 9133 TestRound(kGetAuth, kSuccess, OK)}}, 9134 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1, 9135 { TestRound(kConnect, kProxyChallenge, OK), 9136 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9137 &kGet, &kServerChallenge), 9138 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9139 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1, 9140 { TestRound(kConnect, kProxyChallenge, OK), 9141 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9142 &kGet, &kServerChallenge), 9143 TestRound(kGetAuth, kSuccess, OK)}}, 9144 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1, 9145 { TestRound(kConnect, kProxyChallenge, OK), 9146 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9147 &kGet, &kServerChallenge), 9148 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9149 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1, 9150 { TestRound(kConnect, kProxyChallenge, OK), 9151 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9152 &kGet, &kServerChallenge), 9153 TestRound(kGetAuth, kSuccess, OK)}}, 9154 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1, 9155 { TestRound(kConnect, kProxyChallenge, OK), 9156 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9157 &kGet, &kServerChallenge), 9158 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9159 }; 9160 9161 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) { 9162 HttpAuthHandlerMock::Factory* auth_factory( 9163 new HttpAuthHandlerMock::Factory()); 9164 session_deps_.http_auth_handler_factory.reset(auth_factory); 9165 const TestConfig& test_config = test_configs[i]; 9166 9167 // Set up authentication handlers as necessary. 9168 if (test_config.proxy_auth_timing != AUTH_NONE) { 9169 for (int n = 0; n < 2; n++) { 9170 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 9171 std::string auth_challenge = "Mock realm=proxy"; 9172 GURL origin(test_config.proxy_url); 9173 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 9174 auth_challenge.end()); 9175 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY, 9176 origin, BoundNetLog()); 9177 auth_handler->SetGenerateExpectation( 9178 test_config.proxy_auth_timing == AUTH_ASYNC, 9179 test_config.proxy_auth_rv); 9180 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY); 9181 } 9182 } 9183 if (test_config.server_auth_timing != AUTH_NONE) { 9184 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 9185 std::string auth_challenge = "Mock realm=server"; 9186 GURL origin(test_config.server_url); 9187 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 9188 auth_challenge.end()); 9189 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, 9190 origin, BoundNetLog()); 9191 auth_handler->SetGenerateExpectation( 9192 test_config.server_auth_timing == AUTH_ASYNC, 9193 test_config.server_auth_rv); 9194 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER); 9195 } 9196 if (test_config.proxy_url) { 9197 session_deps_.proxy_service.reset( 9198 ProxyService::CreateFixed(test_config.proxy_url)); 9199 } else { 9200 session_deps_.proxy_service.reset(ProxyService::CreateDirect()); 9201 } 9202 9203 HttpRequestInfo request; 9204 request.method = "GET"; 9205 request.url = GURL(test_config.server_url); 9206 request.load_flags = 0; 9207 9208 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9209 HttpNetworkTransaction trans( 9210 DEFAULT_PRIORITY, CreateSession(&session_deps_)); 9211 9212 for (int round = 0; round < test_config.num_auth_rounds; ++round) { 9213 const TestRound& read_write_round = test_config.rounds[round]; 9214 9215 // Set up expected reads and writes. 9216 MockRead reads[2]; 9217 reads[0] = read_write_round.read; 9218 size_t length_reads = 1; 9219 if (read_write_round.extra_read) { 9220 reads[1] = *read_write_round.extra_read; 9221 length_reads = 2; 9222 } 9223 9224 MockWrite writes[2]; 9225 writes[0] = read_write_round.write; 9226 size_t length_writes = 1; 9227 if (read_write_round.extra_write) { 9228 writes[1] = *read_write_round.extra_write; 9229 length_writes = 2; 9230 } 9231 StaticSocketDataProvider data_provider( 9232 reads, length_reads, writes, length_writes); 9233 session_deps_.socket_factory->AddSocketDataProvider(&data_provider); 9234 9235 // Add an SSL sequence if necessary. 9236 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK); 9237 if (round >= test_config.first_ssl_round) 9238 session_deps_.socket_factory->AddSSLSocketDataProvider( 9239 &ssl_socket_data_provider); 9240 9241 // Start or restart the transaction. 9242 TestCompletionCallback callback; 9243 int rv; 9244 if (round == 0) { 9245 rv = trans.Start(&request, callback.callback(), BoundNetLog()); 9246 } else { 9247 rv = trans.RestartWithAuth( 9248 AuthCredentials(kFoo, kBar), callback.callback()); 9249 } 9250 if (rv == ERR_IO_PENDING) 9251 rv = callback.WaitForResult(); 9252 9253 // Compare results with expected data. 9254 EXPECT_EQ(read_write_round.expected_rv, rv); 9255 const HttpResponseInfo* response = trans.GetResponseInfo(); 9256 if (read_write_round.expected_rv == OK) { 9257 ASSERT_TRUE(response != NULL); 9258 } else { 9259 EXPECT_TRUE(response == NULL); 9260 EXPECT_EQ(round + 1, test_config.num_auth_rounds); 9261 continue; 9262 } 9263 if (round + 1 < test_config.num_auth_rounds) { 9264 EXPECT_FALSE(response->auth_challenge.get() == NULL); 9265 } else { 9266 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9267 } 9268 } 9269 } 9270} 9271 9272TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) { 9273 // Do multi-round authentication and make sure it works correctly. 9274 HttpAuthHandlerMock::Factory* auth_factory( 9275 new HttpAuthHandlerMock::Factory()); 9276 session_deps_.http_auth_handler_factory.reset(auth_factory); 9277 session_deps_.proxy_service.reset(ProxyService::CreateDirect()); 9278 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1"); 9279 session_deps_.host_resolver->set_synchronous_mode(true); 9280 9281 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 9282 auth_handler->set_connection_based(true); 9283 std::string auth_challenge = "Mock realm=server"; 9284 GURL origin("http://www.example.com"); 9285 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 9286 auth_challenge.end()); 9287 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, 9288 origin, BoundNetLog()); 9289 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER); 9290 9291 int rv = OK; 9292 const HttpResponseInfo* response = NULL; 9293 HttpRequestInfo request; 9294 request.method = "GET"; 9295 request.url = origin; 9296 request.load_flags = 0; 9297 9298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9299 9300 // Use a TCP Socket Pool with only one connection per group. This is used 9301 // to validate that the TCP socket is not released to the pool between 9302 // each round of multi-round authentication. 9303 HttpNetworkSessionPeer session_peer(session); 9304 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP"); 9305 TransportClientSocketPool* transport_pool = new TransportClientSocketPool( 9306 50, // Max sockets for pool 9307 1, // Max sockets per group 9308 &transport_pool_histograms, 9309 session_deps_.host_resolver.get(), 9310 session_deps_.socket_factory.get(), 9311 session_deps_.net_log); 9312 MockClientSocketPoolManager* mock_pool_manager = 9313 new MockClientSocketPoolManager; 9314 mock_pool_manager->SetTransportSocketPool(transport_pool); 9315 session_peer.SetClientSocketPoolManager(mock_pool_manager); 9316 9317 scoped_ptr<HttpTransaction> trans( 9318 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9319 TestCompletionCallback callback; 9320 9321 const MockWrite kGet( 9322 "GET / HTTP/1.1\r\n" 9323 "Host: www.example.com\r\n" 9324 "Connection: keep-alive\r\n\r\n"); 9325 const MockWrite kGetAuth( 9326 "GET / HTTP/1.1\r\n" 9327 "Host: www.example.com\r\n" 9328 "Connection: keep-alive\r\n" 9329 "Authorization: auth_token\r\n\r\n"); 9330 9331 const MockRead kServerChallenge( 9332 "HTTP/1.1 401 Unauthorized\r\n" 9333 "WWW-Authenticate: Mock realm=server\r\n" 9334 "Content-Type: text/html; charset=iso-8859-1\r\n" 9335 "Content-Length: 14\r\n\r\n" 9336 "Unauthorized\r\n"); 9337 const MockRead kSuccess( 9338 "HTTP/1.1 200 OK\r\n" 9339 "Content-Type: text/html; charset=iso-8859-1\r\n" 9340 "Content-Length: 3\r\n\r\n" 9341 "Yes"); 9342 9343 MockWrite writes[] = { 9344 // First round 9345 kGet, 9346 // Second round 9347 kGetAuth, 9348 // Third round 9349 kGetAuth, 9350 // Fourth round 9351 kGetAuth, 9352 // Competing request 9353 kGet, 9354 }; 9355 MockRead reads[] = { 9356 // First round 9357 kServerChallenge, 9358 // Second round 9359 kServerChallenge, 9360 // Third round 9361 kServerChallenge, 9362 // Fourth round 9363 kSuccess, 9364 // Competing response 9365 kSuccess, 9366 }; 9367 StaticSocketDataProvider data_provider(reads, arraysize(reads), 9368 writes, arraysize(writes)); 9369 session_deps_.socket_factory->AddSocketDataProvider(&data_provider); 9370 9371 const char* const kSocketGroup = "www.example.com:80"; 9372 9373 // First round of authentication. 9374 auth_handler->SetGenerateExpectation(false, OK); 9375 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9376 if (rv == ERR_IO_PENDING) 9377 rv = callback.WaitForResult(); 9378 EXPECT_EQ(OK, rv); 9379 response = trans->GetResponseInfo(); 9380 ASSERT_TRUE(response != NULL); 9381 EXPECT_FALSE(response->auth_challenge.get() == NULL); 9382 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9383 9384 // In between rounds, another request comes in for the same domain. 9385 // It should not be able to grab the TCP socket that trans has already 9386 // claimed. 9387 scoped_ptr<HttpTransaction> trans_compete( 9388 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9389 TestCompletionCallback callback_compete; 9390 rv = trans_compete->Start( 9391 &request, callback_compete.callback(), BoundNetLog()); 9392 EXPECT_EQ(ERR_IO_PENDING, rv); 9393 // callback_compete.WaitForResult at this point would stall forever, 9394 // since the HttpNetworkTransaction does not release the request back to 9395 // the pool until after authentication completes. 9396 9397 // Second round of authentication. 9398 auth_handler->SetGenerateExpectation(false, OK); 9399 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback()); 9400 if (rv == ERR_IO_PENDING) 9401 rv = callback.WaitForResult(); 9402 EXPECT_EQ(OK, rv); 9403 response = trans->GetResponseInfo(); 9404 ASSERT_TRUE(response != NULL); 9405 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9406 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9407 9408 // Third round of authentication. 9409 auth_handler->SetGenerateExpectation(false, OK); 9410 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback()); 9411 if (rv == ERR_IO_PENDING) 9412 rv = callback.WaitForResult(); 9413 EXPECT_EQ(OK, rv); 9414 response = trans->GetResponseInfo(); 9415 ASSERT_TRUE(response != NULL); 9416 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9417 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9418 9419 // Fourth round of authentication, which completes successfully. 9420 auth_handler->SetGenerateExpectation(false, OK); 9421 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback()); 9422 if (rv == ERR_IO_PENDING) 9423 rv = callback.WaitForResult(); 9424 EXPECT_EQ(OK, rv); 9425 response = trans->GetResponseInfo(); 9426 ASSERT_TRUE(response != NULL); 9427 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9428 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9429 9430 // Read the body since the fourth round was successful. This will also 9431 // release the socket back to the pool. 9432 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50)); 9433 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 9434 if (rv == ERR_IO_PENDING) 9435 rv = callback.WaitForResult(); 9436 EXPECT_EQ(3, rv); 9437 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 9438 EXPECT_EQ(0, rv); 9439 // There are still 0 idle sockets, since the trans_compete transaction 9440 // will be handed it immediately after trans releases it to the group. 9441 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9442 9443 // The competing request can now finish. Wait for the headers and then 9444 // read the body. 9445 rv = callback_compete.WaitForResult(); 9446 EXPECT_EQ(OK, rv); 9447 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback()); 9448 if (rv == ERR_IO_PENDING) 9449 rv = callback.WaitForResult(); 9450 EXPECT_EQ(3, rv); 9451 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback()); 9452 EXPECT_EQ(0, rv); 9453 9454 // Finally, the socket is released to the group. 9455 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9456} 9457 9458// This tests the case that a request is issued via http instead of spdy after 9459// npn is negotiated. 9460TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) { 9461 HttpStreamFactory::set_use_alternate_protocols(true); 9462 std::vector<NextProto> next_protos; 9463 next_protos.push_back(kProtoHTTP11); 9464 HttpStreamFactory::SetNextProtos(next_protos); 9465 HttpRequestInfo request; 9466 request.method = "GET"; 9467 request.url = GURL("https://www.google.com/"); 9468 request.load_flags = 0; 9469 9470 MockWrite data_writes[] = { 9471 MockWrite("GET / HTTP/1.1\r\n" 9472 "Host: www.google.com\r\n" 9473 "Connection: keep-alive\r\n\r\n"), 9474 }; 9475 9476 std::string alternate_protocol_http_header = 9477 GetAlternateProtocolHttpHeader(); 9478 9479 MockRead data_reads[] = { 9480 MockRead("HTTP/1.1 200 OK\r\n"), 9481 MockRead(alternate_protocol_http_header.c_str()), 9482 MockRead("hello world"), 9483 MockRead(SYNCHRONOUS, OK), 9484 }; 9485 9486 SSLSocketDataProvider ssl(ASYNC, OK); 9487 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 9488 ssl.next_proto = "http/1.1"; 9489 ssl.protocol_negotiated = kProtoHTTP11; 9490 9491 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9492 9493 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 9494 data_writes, arraysize(data_writes)); 9495 session_deps_.socket_factory->AddSocketDataProvider(&data); 9496 9497 TestCompletionCallback callback; 9498 9499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9500 scoped_ptr<HttpTransaction> trans( 9501 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9502 9503 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9504 9505 EXPECT_EQ(ERR_IO_PENDING, rv); 9506 EXPECT_EQ(OK, callback.WaitForResult()); 9507 9508 const HttpResponseInfo* response = trans->GetResponseInfo(); 9509 ASSERT_TRUE(response != NULL); 9510 ASSERT_TRUE(response->headers.get() != NULL); 9511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 9512 9513 std::string response_data; 9514 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 9515 EXPECT_EQ("hello world", response_data); 9516 9517 EXPECT_FALSE(response->was_fetched_via_spdy); 9518 EXPECT_TRUE(response->was_npn_negotiated); 9519} 9520 9521TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) { 9522 // Simulate the SSL handshake completing with an NPN negotiation 9523 // followed by an immediate server closing of the socket. 9524 // Fix crash: http://crbug.com/46369 9525 HttpStreamFactory::set_use_alternate_protocols(true); 9526 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 9527 9528 HttpRequestInfo request; 9529 request.method = "GET"; 9530 request.url = GURL("https://www.google.com/"); 9531 request.load_flags = 0; 9532 9533 SSLSocketDataProvider ssl(ASYNC, OK); 9534 ssl.SetNextProto(GetParam()); 9535 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9536 9537 scoped_ptr<SpdyFrame> req( 9538 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 9539 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 9540 9541 MockRead spdy_reads[] = { 9542 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately. 9543 }; 9544 9545 DelayedSocketData spdy_data( 9546 0, // don't wait in this case, immediate hangup. 9547 spdy_reads, arraysize(spdy_reads), 9548 spdy_writes, arraysize(spdy_writes)); 9549 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 9550 9551 TestCompletionCallback callback; 9552 9553 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9554 scoped_ptr<HttpTransaction> trans( 9555 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9556 9557 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9558 EXPECT_EQ(ERR_IO_PENDING, rv); 9559 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult()); 9560} 9561 9562// A subclass of HttpAuthHandlerMock that records the request URL when 9563// it gets it. This is needed since the auth handler may get destroyed 9564// before we get a chance to query it. 9565class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock { 9566 public: 9567 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {} 9568 9569 virtual ~UrlRecordingHttpAuthHandlerMock() {} 9570 9571 protected: 9572 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials, 9573 const HttpRequestInfo* request, 9574 const CompletionCallback& callback, 9575 std::string* auth_token) OVERRIDE { 9576 *url_ = request->url; 9577 return HttpAuthHandlerMock::GenerateAuthTokenImpl( 9578 credentials, request, callback, auth_token); 9579 } 9580 9581 private: 9582 GURL* url_; 9583}; 9584 9585TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { 9586 // This test ensures that the URL passed into the proxy is upgraded 9587 // to https when doing an Alternate Protocol upgrade. 9588 HttpStreamFactory::set_use_alternate_protocols(true); 9589 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 9590 9591 session_deps_.proxy_service.reset( 9592 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 9593 CapturingNetLog net_log; 9594 session_deps_.net_log = &net_log; 9595 GURL request_url; 9596 { 9597 HttpAuthHandlerMock::Factory* auth_factory = 9598 new HttpAuthHandlerMock::Factory(); 9599 UrlRecordingHttpAuthHandlerMock* auth_handler = 9600 new UrlRecordingHttpAuthHandlerMock(&request_url); 9601 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY); 9602 auth_factory->set_do_init_from_challenge(true); 9603 session_deps_.http_auth_handler_factory.reset(auth_factory); 9604 } 9605 9606 HttpRequestInfo request; 9607 request.method = "GET"; 9608 request.url = GURL("http://www.google.com"); 9609 request.load_flags = 0; 9610 9611 // First round goes unauthenticated through the proxy. 9612 MockWrite data_writes_1[] = { 9613 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 9614 "Host: www.google.com\r\n" 9615 "Proxy-Connection: keep-alive\r\n" 9616 "\r\n"), 9617 }; 9618 MockRead data_reads_1[] = { 9619 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 9620 MockRead("HTTP/1.1 200 OK\r\n" 9621 "Alternate-Protocol: 443:npn-spdy/2\r\n" 9622 "Proxy-Connection: close\r\n" 9623 "\r\n"), 9624 }; 9625 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), 9626 data_writes_1, arraysize(data_writes_1)); 9627 9628 // Second round tries to tunnel to www.google.com due to the 9629 // Alternate-Protocol announcement in the first round. It fails due 9630 // to a proxy authentication challenge. 9631 // After the failure, a tunnel is established to www.google.com using 9632 // Proxy-Authorization headers. There is then a SPDY request round. 9633 // 9634 // NOTE: Despite the "Proxy-Connection: Close", these are done on the 9635 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket 9636 // does a Disconnect and Connect on the same socket, rather than trying 9637 // to obtain a new one. 9638 // 9639 // NOTE: Originally, the proxy response to the second CONNECT request 9640 // simply returned another 407 so the unit test could skip the SSL connection 9641 // establishment and SPDY framing issues. Alas, the 9642 // retry-http-when-alternate-protocol fails logic kicks in, which was more 9643 // complicated to set up expectations for than the SPDY session. 9644 9645 scoped_ptr<SpdyFrame> req( 9646 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 9647 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 9648 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 9649 9650 MockWrite data_writes_2[] = { 9651 // First connection attempt without Proxy-Authorization. 9652 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 9653 "Host: www.google.com\r\n" 9654 "Proxy-Connection: keep-alive\r\n" 9655 "\r\n"), 9656 9657 // Second connection attempt with Proxy-Authorization. 9658 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 9659 "Host: www.google.com\r\n" 9660 "Proxy-Connection: keep-alive\r\n" 9661 "Proxy-Authorization: auth_token\r\n" 9662 "\r\n"), 9663 9664 // SPDY request 9665 CreateMockWrite(*req), 9666 }; 9667 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" 9668 "Proxy-Authenticate: Mock\r\n" 9669 "Proxy-Connection: close\r\n" 9670 "\r\n"); 9671 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; 9672 MockRead data_reads_2[] = { 9673 // First connection attempt fails 9674 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), 9675 MockRead(ASYNC, kRejectConnectResponse, 9676 arraysize(kRejectConnectResponse) - 1, 1), 9677 9678 // Second connection attempt passes 9679 MockRead(ASYNC, kAcceptConnectResponse, 9680 arraysize(kAcceptConnectResponse) -1, 4), 9681 9682 // SPDY response 9683 CreateMockRead(*resp.get(), 6), 9684 CreateMockRead(*data.get(), 6), 9685 MockRead(ASYNC, 0, 0, 6), 9686 }; 9687 OrderedSocketData data_2( 9688 data_reads_2, arraysize(data_reads_2), 9689 data_writes_2, arraysize(data_writes_2)); 9690 9691 SSLSocketDataProvider ssl(ASYNC, OK); 9692 ssl.SetNextProto(GetParam()); 9693 9694 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 9695 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 9696 NULL, 0, NULL, 0); 9697 hanging_non_alternate_protocol_socket.set_connect_data( 9698 never_finishing_connect); 9699 9700 session_deps_.socket_factory->AddSocketDataProvider(&data_1); 9701 session_deps_.socket_factory->AddSocketDataProvider(&data_2); 9702 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9703 session_deps_.socket_factory->AddSocketDataProvider( 9704 &hanging_non_alternate_protocol_socket); 9705 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9706 9707 // First round should work and provide the Alternate-Protocol state. 9708 TestCompletionCallback callback_1; 9709 scoped_ptr<HttpTransaction> trans_1( 9710 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9711 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog()); 9712 EXPECT_EQ(ERR_IO_PENDING, rv); 9713 EXPECT_EQ(OK, callback_1.WaitForResult()); 9714 9715 // Second round should attempt a tunnel connect and get an auth challenge. 9716 TestCompletionCallback callback_2; 9717 scoped_ptr<HttpTransaction> trans_2( 9718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9719 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog()); 9720 EXPECT_EQ(ERR_IO_PENDING, rv); 9721 EXPECT_EQ(OK, callback_2.WaitForResult()); 9722 const HttpResponseInfo* response = trans_2->GetResponseInfo(); 9723 ASSERT_TRUE(response != NULL); 9724 ASSERT_FALSE(response->auth_challenge.get() == NULL); 9725 9726 // Restart with auth. Tunnel should work and response received. 9727 TestCompletionCallback callback_3; 9728 rv = trans_2->RestartWithAuth( 9729 AuthCredentials(kFoo, kBar), callback_3.callback()); 9730 EXPECT_EQ(ERR_IO_PENDING, rv); 9731 EXPECT_EQ(OK, callback_3.WaitForResult()); 9732 9733 // After all that work, these two lines (or actually, just the scheme) are 9734 // what this test is all about. Make sure it happens correctly. 9735 EXPECT_EQ("https", request_url.scheme()); 9736 EXPECT_EQ("www.google.com", request_url.host()); 9737 9738 LoadTimingInfo load_timing_info; 9739 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info)); 9740 TestLoadTimingNotReusedWithPac(load_timing_info, 9741 CONNECT_TIMING_HAS_SSL_TIMES); 9742} 9743 9744// Test that if we cancel the transaction as the connection is completing, that 9745// everything tears down correctly. 9746TEST_P(HttpNetworkTransactionTest, SimpleCancel) { 9747 // Setup everything about the connection to complete synchronously, so that 9748 // after calling HttpNetworkTransaction::Start, the only thing we're waiting 9749 // for is the callback from the HttpStreamRequest. 9750 // Then cancel the transaction. 9751 // Verify that we don't crash. 9752 MockConnect mock_connect(SYNCHRONOUS, OK); 9753 MockRead data_reads[] = { 9754 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"), 9755 MockRead(SYNCHRONOUS, "hello world"), 9756 MockRead(SYNCHRONOUS, OK), 9757 }; 9758 9759 HttpRequestInfo request; 9760 request.method = "GET"; 9761 request.url = GURL("http://www.google.com/"); 9762 request.load_flags = 0; 9763 9764 session_deps_.host_resolver->set_synchronous_mode(true); 9765 scoped_ptr<HttpTransaction> trans( 9766 new HttpNetworkTransaction(DEFAULT_PRIORITY, 9767 CreateSession(&session_deps_))); 9768 9769 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 9770 data.set_connect_data(mock_connect); 9771 session_deps_.socket_factory->AddSocketDataProvider(&data); 9772 9773 TestCompletionCallback callback; 9774 9775 CapturingBoundNetLog log; 9776 int rv = trans->Start(&request, callback.callback(), log.bound()); 9777 EXPECT_EQ(ERR_IO_PENDING, rv); 9778 trans.reset(); // Cancel the transaction here. 9779 9780 base::MessageLoop::current()->RunUntilIdle(); 9781} 9782 9783// Test a basic GET request through a proxy. 9784TEST_P(HttpNetworkTransactionTest, ProxyGet) { 9785 session_deps_.proxy_service.reset( 9786 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 9787 CapturingBoundNetLog log; 9788 session_deps_.net_log = log.bound().net_log(); 9789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9790 9791 HttpRequestInfo request; 9792 request.method = "GET"; 9793 request.url = GURL("http://www.google.com/"); 9794 9795 MockWrite data_writes1[] = { 9796 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 9797 "Host: www.google.com\r\n" 9798 "Proxy-Connection: keep-alive\r\n\r\n"), 9799 }; 9800 9801 MockRead data_reads1[] = { 9802 MockRead("HTTP/1.1 200 OK\r\n"), 9803 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 9804 MockRead("Content-Length: 100\r\n\r\n"), 9805 MockRead(SYNCHRONOUS, OK), 9806 }; 9807 9808 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 9809 data_writes1, arraysize(data_writes1)); 9810 session_deps_.socket_factory->AddSocketDataProvider(&data1); 9811 9812 TestCompletionCallback callback1; 9813 9814 scoped_ptr<HttpTransaction> trans( 9815 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9816 9817 int rv = trans->Start(&request, callback1.callback(), log.bound()); 9818 EXPECT_EQ(ERR_IO_PENDING, rv); 9819 9820 rv = callback1.WaitForResult(); 9821 EXPECT_EQ(OK, rv); 9822 9823 const HttpResponseInfo* response = trans->GetResponseInfo(); 9824 ASSERT_TRUE(response != NULL); 9825 9826 EXPECT_TRUE(response->headers->IsKeepAlive()); 9827 EXPECT_EQ(200, response->headers->response_code()); 9828 EXPECT_EQ(100, response->headers->GetContentLength()); 9829 EXPECT_TRUE(response->was_fetched_via_proxy); 9830 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 9831 9832 LoadTimingInfo load_timing_info; 9833 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 9834 TestLoadTimingNotReusedWithPac(load_timing_info, 9835 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 9836} 9837 9838// Test a basic HTTPS GET request through a proxy. 9839TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) { 9840 session_deps_.proxy_service.reset( 9841 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 9842 CapturingBoundNetLog log; 9843 session_deps_.net_log = log.bound().net_log(); 9844 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9845 9846 HttpRequestInfo request; 9847 request.method = "GET"; 9848 request.url = GURL("https://www.google.com/"); 9849 9850 // Since we have proxy, should try to establish tunnel. 9851 MockWrite data_writes1[] = { 9852 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 9853 "Host: www.google.com\r\n" 9854 "Proxy-Connection: keep-alive\r\n\r\n"), 9855 9856 MockWrite("GET / HTTP/1.1\r\n" 9857 "Host: www.google.com\r\n" 9858 "Connection: keep-alive\r\n\r\n"), 9859 }; 9860 9861 MockRead data_reads1[] = { 9862 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 9863 9864 MockRead("HTTP/1.1 200 OK\r\n"), 9865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 9866 MockRead("Content-Length: 100\r\n\r\n"), 9867 MockRead(SYNCHRONOUS, OK), 9868 }; 9869 9870 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 9871 data_writes1, arraysize(data_writes1)); 9872 session_deps_.socket_factory->AddSocketDataProvider(&data1); 9873 SSLSocketDataProvider ssl(ASYNC, OK); 9874 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9875 9876 TestCompletionCallback callback1; 9877 9878 scoped_ptr<HttpTransaction> trans( 9879 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9880 9881 int rv = trans->Start(&request, callback1.callback(), log.bound()); 9882 EXPECT_EQ(ERR_IO_PENDING, rv); 9883 9884 rv = callback1.WaitForResult(); 9885 EXPECT_EQ(OK, rv); 9886 net::CapturingNetLog::CapturedEntryList entries; 9887 log.GetEntries(&entries); 9888 size_t pos = ExpectLogContainsSomewhere( 9889 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 9890 NetLog::PHASE_NONE); 9891 ExpectLogContainsSomewhere( 9892 entries, pos, 9893 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 9894 NetLog::PHASE_NONE); 9895 9896 const HttpResponseInfo* response = trans->GetResponseInfo(); 9897 ASSERT_TRUE(response != NULL); 9898 9899 EXPECT_TRUE(response->headers->IsKeepAlive()); 9900 EXPECT_EQ(200, response->headers->response_code()); 9901 EXPECT_EQ(100, response->headers->GetContentLength()); 9902 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 9903 EXPECT_TRUE(response->was_fetched_via_proxy); 9904 9905 LoadTimingInfo load_timing_info; 9906 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 9907 TestLoadTimingNotReusedWithPac(load_timing_info, 9908 CONNECT_TIMING_HAS_SSL_TIMES); 9909} 9910 9911// Test a basic HTTPS GET request through a proxy, but the server hangs up 9912// while establishing the tunnel. 9913TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) { 9914 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 9915 CapturingBoundNetLog log; 9916 session_deps_.net_log = log.bound().net_log(); 9917 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9918 9919 HttpRequestInfo request; 9920 request.method = "GET"; 9921 request.url = GURL("https://www.google.com/"); 9922 9923 // Since we have proxy, should try to establish tunnel. 9924 MockWrite data_writes1[] = { 9925 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 9926 "Host: www.google.com\r\n" 9927 "Proxy-Connection: keep-alive\r\n\r\n"), 9928 9929 MockWrite("GET / HTTP/1.1\r\n" 9930 "Host: www.google.com\r\n" 9931 "Connection: keep-alive\r\n\r\n"), 9932 }; 9933 9934 MockRead data_reads1[] = { 9935 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 9936 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 9937 MockRead(ASYNC, 0, 0), // EOF 9938 }; 9939 9940 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 9941 data_writes1, arraysize(data_writes1)); 9942 session_deps_.socket_factory->AddSocketDataProvider(&data1); 9943 SSLSocketDataProvider ssl(ASYNC, OK); 9944 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9945 9946 TestCompletionCallback callback1; 9947 9948 scoped_ptr<HttpTransaction> trans( 9949 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9950 9951 int rv = trans->Start(&request, callback1.callback(), log.bound()); 9952 EXPECT_EQ(ERR_IO_PENDING, rv); 9953 9954 rv = callback1.WaitForResult(); 9955 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 9956 net::CapturingNetLog::CapturedEntryList entries; 9957 log.GetEntries(&entries); 9958 size_t pos = ExpectLogContainsSomewhere( 9959 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 9960 NetLog::PHASE_NONE); 9961 ExpectLogContainsSomewhere( 9962 entries, pos, 9963 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 9964 NetLog::PHASE_NONE); 9965} 9966 9967// Test for crbug.com/55424. 9968TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { 9969 scoped_ptr<SpdyFrame> req( 9970 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 9971 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 9972 9973 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 9974 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 9975 MockRead spdy_reads[] = { 9976 CreateMockRead(*resp), 9977 CreateMockRead(*data), 9978 MockRead(ASYNC, 0, 0), 9979 }; 9980 9981 DelayedSocketData spdy_data( 9982 1, // wait for one write to finish before reading. 9983 spdy_reads, arraysize(spdy_reads), 9984 spdy_writes, arraysize(spdy_writes)); 9985 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 9986 9987 SSLSocketDataProvider ssl(ASYNC, OK); 9988 ssl.SetNextProto(GetParam()); 9989 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9990 9991 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9992 9993 // Set up an initial SpdySession in the pool to reuse. 9994 HostPortPair host_port_pair("www.google.com", 443); 9995 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), 9996 kPrivacyModeDisabled); 9997 base::WeakPtr<SpdySession> spdy_session = 9998 CreateInsecureSpdySession(session, key, BoundNetLog()); 9999 10000 HttpRequestInfo request; 10001 request.method = "GET"; 10002 request.url = GURL("https://www.google.com/"); 10003 request.load_flags = 0; 10004 10005 // This is the important line that marks this as a preconnect. 10006 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED; 10007 10008 scoped_ptr<HttpTransaction> trans( 10009 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10010 10011 TestCompletionCallback callback; 10012 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 10013 EXPECT_EQ(ERR_IO_PENDING, rv); 10014 EXPECT_EQ(OK, callback.WaitForResult()); 10015} 10016 10017// Given a net error, cause that error to be returned from the first Write() 10018// call and verify that the HttpTransaction fails with that error. 10019void HttpNetworkTransactionTest::CheckErrorIsPassedBack( 10020 int error, IoMode mode) { 10021 net::HttpRequestInfo request_info; 10022 request_info.url = GURL("https://www.example.com/"); 10023 request_info.method = "GET"; 10024 request_info.load_flags = net::LOAD_NORMAL; 10025 10026 SSLSocketDataProvider ssl_data(mode, OK); 10027 net::MockWrite data_writes[] = { 10028 net::MockWrite(mode, error), 10029 }; 10030 net::StaticSocketDataProvider data(NULL, 0, 10031 data_writes, arraysize(data_writes)); 10032 session_deps_.socket_factory->AddSocketDataProvider(&data); 10033 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data); 10034 10035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10036 scoped_ptr<HttpTransaction> trans( 10037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10038 10039 TestCompletionCallback callback; 10040 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); 10041 if (rv == net::ERR_IO_PENDING) 10042 rv = callback.WaitForResult(); 10043 ASSERT_EQ(error, rv); 10044} 10045 10046TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) { 10047 // Just check a grab bag of cert errors. 10048 static const int kErrors[] = { 10049 ERR_CERT_COMMON_NAME_INVALID, 10050 ERR_CERT_AUTHORITY_INVALID, 10051 ERR_CERT_DATE_INVALID, 10052 }; 10053 for (size_t i = 0; i < arraysize(kErrors); i++) { 10054 CheckErrorIsPassedBack(kErrors[i], ASYNC); 10055 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS); 10056 } 10057} 10058 10059// Ensure that a client certificate is removed from the SSL client auth 10060// cache when: 10061// 1) No proxy is involved. 10062// 2) TLS False Start is disabled. 10063// 3) The initial TLS handshake requests a client certificate. 10064// 4) The client supplies an invalid/unacceptable certificate. 10065TEST_P(HttpNetworkTransactionTest, 10066 ClientAuthCertCache_Direct_NoFalseStart) { 10067 net::HttpRequestInfo request_info; 10068 request_info.url = GURL("https://www.example.com/"); 10069 request_info.method = "GET"; 10070 request_info.load_flags = net::LOAD_NORMAL; 10071 10072 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 10073 cert_request->host_and_port = "www.example.com:443"; 10074 10075 // [ssl_]data1 contains the data for the first SSL handshake. When a 10076 // CertificateRequest is received for the first time, the handshake will 10077 // be aborted to allow the caller to provide a certificate. 10078 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 10079 ssl_data1.cert_request_info = cert_request.get(); 10080 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); 10081 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 10082 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10083 10084 // [ssl_]data2 contains the data for the second SSL handshake. When TLS 10085 // False Start is not being used, the result of the SSL handshake will be 10086 // returned as part of the SSLClientSocket::Connect() call. This test 10087 // matches the result of a server sending a handshake_failure alert, 10088 // rather than a Finished message, because it requires a client 10089 // certificate and none was supplied. 10090 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10091 ssl_data2.cert_request_info = cert_request.get(); 10092 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); 10093 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); 10094 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10095 10096 // [ssl_]data3 contains the data for the third SSL handshake. When a 10097 // connection to a server fails during an SSL handshake, 10098 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous 10099 // connection was attempted with TLSv1.1. This is transparent to the caller 10100 // of the HttpNetworkTransaction. Because this test failure is due to 10101 // requiring a client certificate, this fallback handshake should also 10102 // fail. 10103 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10104 ssl_data3.cert_request_info = cert_request.get(); 10105 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); 10106 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); 10107 session_deps_.socket_factory->AddSocketDataProvider(&data3); 10108 10109 // [ssl_]data4 contains the data for the fourth SSL handshake. When a 10110 // connection to a server fails during an SSL handshake, 10111 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous 10112 // connection was attempted with TLSv1. This is transparent to the caller 10113 // of the HttpNetworkTransaction. Because this test failure is due to 10114 // requiring a client certificate, this fallback handshake should also 10115 // fail. 10116 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10117 ssl_data4.cert_request_info = cert_request.get(); 10118 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); 10119 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0); 10120 session_deps_.socket_factory->AddSocketDataProvider(&data4); 10121 10122 // Need one more if TLSv1.2 is enabled. 10123 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10124 ssl_data5.cert_request_info = cert_request.get(); 10125 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); 10126 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0); 10127 session_deps_.socket_factory->AddSocketDataProvider(&data5); 10128 10129 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10130 scoped_ptr<HttpTransaction> trans( 10131 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10132 10133 // Begin the SSL handshake with the peer. This consumes ssl_data1. 10134 TestCompletionCallback callback; 10135 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); 10136 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10137 10138 // Complete the SSL handshake, which should abort due to requiring a 10139 // client certificate. 10140 rv = callback.WaitForResult(); 10141 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 10142 10143 // Indicate that no certificate should be supplied. From the perspective 10144 // of SSLClientCertCache, NULL is just as meaningful as a real 10145 // certificate, so this is the same as supply a 10146 // legitimate-but-unacceptable certificate. 10147 rv = trans->RestartWithCertificate(NULL, callback.callback()); 10148 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10149 10150 // Ensure the certificate was added to the client auth cache before 10151 // allowing the connection to continue restarting. 10152 scoped_refptr<X509Certificate> client_cert; 10153 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 10154 &client_cert)); 10155 ASSERT_EQ(NULL, client_cert.get()); 10156 10157 // Restart the handshake. This will consume ssl_data2, which fails, and 10158 // then consume ssl_data3 and ssl_data4, both of which should also fail. 10159 // The result code is checked against what ssl_data4 should return. 10160 rv = callback.WaitForResult(); 10161 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 10162 10163 // Ensure that the client certificate is removed from the cache on a 10164 // handshake failure. 10165 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 10166 &client_cert)); 10167} 10168 10169// Ensure that a client certificate is removed from the SSL client auth 10170// cache when: 10171// 1) No proxy is involved. 10172// 2) TLS False Start is enabled. 10173// 3) The initial TLS handshake requests a client certificate. 10174// 4) The client supplies an invalid/unacceptable certificate. 10175TEST_P(HttpNetworkTransactionTest, 10176 ClientAuthCertCache_Direct_FalseStart) { 10177 net::HttpRequestInfo request_info; 10178 request_info.url = GURL("https://www.example.com/"); 10179 request_info.method = "GET"; 10180 request_info.load_flags = net::LOAD_NORMAL; 10181 10182 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 10183 cert_request->host_and_port = "www.example.com:443"; 10184 10185 // When TLS False Start is used, SSLClientSocket::Connect() calls will 10186 // return successfully after reading up to the peer's Certificate message. 10187 // This is to allow the caller to call SSLClientSocket::Write(), which can 10188 // enqueue application data to be sent in the same packet as the 10189 // ChangeCipherSpec and Finished messages. 10190 // The actual handshake will be finished when SSLClientSocket::Read() is 10191 // called, which expects to process the peer's ChangeCipherSpec and 10192 // Finished messages. If there was an error negotiating with the peer, 10193 // such as due to the peer requiring a client certificate when none was 10194 // supplied, the alert sent by the peer won't be processed until Read() is 10195 // called. 10196 10197 // Like the non-False Start case, when a client certificate is requested by 10198 // the peer, the handshake is aborted during the Connect() call. 10199 // [ssl_]data1 represents the initial SSL handshake with the peer. 10200 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 10201 ssl_data1.cert_request_info = cert_request.get(); 10202 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); 10203 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 10204 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10205 10206 // When a client certificate is supplied, Connect() will not be aborted 10207 // when the peer requests the certificate. Instead, the handshake will 10208 // artificially succeed, allowing the caller to write the HTTP request to 10209 // the socket. The handshake messages are not processed until Read() is 10210 // called, which then detects that the handshake was aborted, due to the 10211 // peer sending a handshake_failure because it requires a client 10212 // certificate. 10213 SSLSocketDataProvider ssl_data2(ASYNC, net::OK); 10214 ssl_data2.cert_request_info = cert_request.get(); 10215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); 10216 net::MockRead data2_reads[] = { 10217 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR), 10218 }; 10219 net::StaticSocketDataProvider data2( 10220 data2_reads, arraysize(data2_reads), NULL, 0); 10221 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10222 10223 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is 10224 // the data for the SSL handshake once the TLSv1.1 connection falls back to 10225 // TLSv1. It has the same behaviour as [ssl_]data2. 10226 SSLSocketDataProvider ssl_data3(ASYNC, net::OK); 10227 ssl_data3.cert_request_info = cert_request.get(); 10228 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); 10229 net::StaticSocketDataProvider data3( 10230 data2_reads, arraysize(data2_reads), NULL, 0); 10231 session_deps_.socket_factory->AddSocketDataProvider(&data3); 10232 10233 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection 10234 // falls back to SSLv3. It has the same behaviour as [ssl_]data2. 10235 SSLSocketDataProvider ssl_data4(ASYNC, net::OK); 10236 ssl_data4.cert_request_info = cert_request.get(); 10237 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); 10238 net::StaticSocketDataProvider data4( 10239 data2_reads, arraysize(data2_reads), NULL, 0); 10240 session_deps_.socket_factory->AddSocketDataProvider(&data4); 10241 10242 // Need one more if TLSv1.2 is enabled. 10243 SSLSocketDataProvider ssl_data5(ASYNC, net::OK); 10244 ssl_data5.cert_request_info = cert_request.get(); 10245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); 10246 net::StaticSocketDataProvider data5( 10247 data2_reads, arraysize(data2_reads), NULL, 0); 10248 session_deps_.socket_factory->AddSocketDataProvider(&data5); 10249 10250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10251 scoped_ptr<HttpTransaction> trans( 10252 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10253 10254 // Begin the initial SSL handshake. 10255 TestCompletionCallback callback; 10256 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); 10257 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10258 10259 // Complete the SSL handshake, which should abort due to requiring a 10260 // client certificate. 10261 rv = callback.WaitForResult(); 10262 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 10263 10264 // Indicate that no certificate should be supplied. From the perspective 10265 // of SSLClientCertCache, NULL is just as meaningful as a real 10266 // certificate, so this is the same as supply a 10267 // legitimate-but-unacceptable certificate. 10268 rv = trans->RestartWithCertificate(NULL, callback.callback()); 10269 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10270 10271 // Ensure the certificate was added to the client auth cache before 10272 // allowing the connection to continue restarting. 10273 scoped_refptr<X509Certificate> client_cert; 10274 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 10275 &client_cert)); 10276 ASSERT_EQ(NULL, client_cert.get()); 10277 10278 // Restart the handshake. This will consume ssl_data2, which fails, and 10279 // then consume ssl_data3 and ssl_data4, both of which should also fail. 10280 // The result code is checked against what ssl_data4 should return. 10281 rv = callback.WaitForResult(); 10282 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 10283 10284 // Ensure that the client certificate is removed from the cache on a 10285 // handshake failure. 10286 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 10287 &client_cert)); 10288} 10289 10290// Ensure that a client certificate is removed from the SSL client auth 10291// cache when: 10292// 1) An HTTPS proxy is involved. 10293// 3) The HTTPS proxy requests a client certificate. 10294// 4) The client supplies an invalid/unacceptable certificate for the 10295// proxy. 10296// The test is repeated twice, first for connecting to an HTTPS endpoint, 10297// then for connecting to an HTTP endpoint. 10298TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) { 10299 session_deps_.proxy_service.reset( 10300 ProxyService::CreateFixed("https://proxy:70")); 10301 CapturingBoundNetLog log; 10302 session_deps_.net_log = log.bound().net_log(); 10303 10304 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 10305 cert_request->host_and_port = "proxy:70"; 10306 10307 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of 10308 // [ssl_]data[1-3]. Rather than represending the endpoint 10309 // (www.example.com:443), they represent failures with the HTTPS proxy 10310 // (proxy:70). 10311 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 10312 ssl_data1.cert_request_info = cert_request.get(); 10313 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); 10314 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 10315 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10316 10317 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10318 ssl_data2.cert_request_info = cert_request.get(); 10319 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); 10320 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); 10321 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10322 10323 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3. 10324#if 0 10325 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10326 ssl_data3.cert_request_info = cert_request.get(); 10327 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); 10328 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); 10329 session_deps_.socket_factory->AddSocketDataProvider(&data3); 10330#endif 10331 10332 net::HttpRequestInfo requests[2]; 10333 requests[0].url = GURL("https://www.example.com/"); 10334 requests[0].method = "GET"; 10335 requests[0].load_flags = net::LOAD_NORMAL; 10336 10337 requests[1].url = GURL("http://www.example.com/"); 10338 requests[1].method = "GET"; 10339 requests[1].load_flags = net::LOAD_NORMAL; 10340 10341 for (size_t i = 0; i < arraysize(requests); ++i) { 10342 session_deps_.socket_factory->ResetNextMockIndexes(); 10343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10344 scoped_ptr<HttpNetworkTransaction> trans( 10345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10346 10347 // Begin the SSL handshake with the proxy. 10348 TestCompletionCallback callback; 10349 int rv = trans->Start( 10350 &requests[i], callback.callback(), net::BoundNetLog()); 10351 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10352 10353 // Complete the SSL handshake, which should abort due to requiring a 10354 // client certificate. 10355 rv = callback.WaitForResult(); 10356 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 10357 10358 // Indicate that no certificate should be supplied. From the perspective 10359 // of SSLClientCertCache, NULL is just as meaningful as a real 10360 // certificate, so this is the same as supply a 10361 // legitimate-but-unacceptable certificate. 10362 rv = trans->RestartWithCertificate(NULL, callback.callback()); 10363 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10364 10365 // Ensure the certificate was added to the client auth cache before 10366 // allowing the connection to continue restarting. 10367 scoped_refptr<X509Certificate> client_cert; 10368 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70", 10369 &client_cert)); 10370 ASSERT_EQ(NULL, client_cert.get()); 10371 // Ensure the certificate was NOT cached for the endpoint. This only 10372 // applies to HTTPS requests, but is fine to check for HTTP requests. 10373 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 10374 &client_cert)); 10375 10376 // Restart the handshake. This will consume ssl_data2, which fails, and 10377 // then consume ssl_data3, which should also fail. The result code is 10378 // checked against what ssl_data3 should return. 10379 rv = callback.WaitForResult(); 10380 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv); 10381 10382 // Now that the new handshake has failed, ensure that the client 10383 // certificate was removed from the client auth cache. 10384 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70", 10385 &client_cert)); 10386 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443", 10387 &client_cert)); 10388 } 10389} 10390 10391// Unlike TEST/TEST_F, which are macros that expand to further macros, 10392// TEST_P is a macro that expands directly to code that stringizes the 10393// arguments. As a result, macros passed as parameters (such as prefix 10394// or test_case_name) will not be expanded by the preprocessor. To 10395// work around this, indirect the macro for TEST_P, so that the 10396// pre-processor will expand macros such as MAYBE_test_name before 10397// instantiating the test. 10398#define WRAPPED_TEST_P(test_case_name, test_name) \ 10399 TEST_P(test_case_name, test_name) 10400 10401// Times out on Win7 dbg(2) bot. http://crbug.com/124776 10402#if defined(OS_WIN) 10403#define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling 10404#else 10405#define MAYBE_UseIPConnectionPooling UseIPConnectionPooling 10406#endif 10407WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) { 10408 HttpStreamFactory::set_use_alternate_protocols(true); 10409 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 10410 10411 // Set up a special HttpNetworkSession with a MockCachingHostResolver. 10412 session_deps_.host_resolver.reset(new MockCachingHostResolver()); 10413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10414 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); 10415 pool_peer.DisableDomainAuthenticationVerification(); 10416 10417 SSLSocketDataProvider ssl(ASYNC, OK); 10418 ssl.SetNextProto(GetParam()); 10419 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10420 10421 scoped_ptr<SpdyFrame> host1_req( 10422 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10423 scoped_ptr<SpdyFrame> host2_req( 10424 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST)); 10425 MockWrite spdy_writes[] = { 10426 CreateMockWrite(*host1_req, 1), 10427 CreateMockWrite(*host2_req, 4), 10428 }; 10429 scoped_ptr<SpdyFrame> host1_resp( 10430 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10431 scoped_ptr<SpdyFrame> host1_resp_body( 10432 spdy_util_.ConstructSpdyBodyFrame(1, true)); 10433 scoped_ptr<SpdyFrame> host2_resp( 10434 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10435 scoped_ptr<SpdyFrame> host2_resp_body( 10436 spdy_util_.ConstructSpdyBodyFrame(3, true)); 10437 MockRead spdy_reads[] = { 10438 CreateMockRead(*host1_resp, 2), 10439 CreateMockRead(*host1_resp_body, 3), 10440 CreateMockRead(*host2_resp, 5), 10441 CreateMockRead(*host2_resp_body, 6), 10442 MockRead(ASYNC, 0, 7), 10443 }; 10444 10445 IPAddressNumber ip; 10446 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); 10447 IPEndPoint peer_addr = IPEndPoint(ip, 443); 10448 MockConnect connect(ASYNC, OK, peer_addr); 10449 OrderedSocketData spdy_data( 10450 connect, 10451 spdy_reads, arraysize(spdy_reads), 10452 spdy_writes, arraysize(spdy_writes)); 10453 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10454 10455 TestCompletionCallback callback; 10456 HttpRequestInfo request1; 10457 request1.method = "GET"; 10458 request1.url = GURL("https://www.google.com/"); 10459 request1.load_flags = 0; 10460 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 10461 10462 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); 10463 EXPECT_EQ(ERR_IO_PENDING, rv); 10464 EXPECT_EQ(OK, callback.WaitForResult()); 10465 10466 const HttpResponseInfo* response = trans1.GetResponseInfo(); 10467 ASSERT_TRUE(response != NULL); 10468 ASSERT_TRUE(response->headers.get() != NULL); 10469 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10470 10471 std::string response_data; 10472 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 10473 EXPECT_EQ("hello!", response_data); 10474 10475 // Preload www.gmail.com into HostCache. 10476 HostPortPair host_port("www.gmail.com", 443); 10477 HostResolver::RequestInfo resolve_info(host_port); 10478 AddressList ignored; 10479 rv = session_deps_.host_resolver->Resolve(resolve_info, &ignored, 10480 callback.callback(), NULL, 10481 BoundNetLog()); 10482 EXPECT_EQ(ERR_IO_PENDING, rv); 10483 rv = callback.WaitForResult(); 10484 EXPECT_EQ(OK, rv); 10485 10486 HttpRequestInfo request2; 10487 request2.method = "GET"; 10488 request2.url = GURL("https://www.gmail.com/"); 10489 request2.load_flags = 0; 10490 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 10491 10492 rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); 10493 EXPECT_EQ(ERR_IO_PENDING, rv); 10494 EXPECT_EQ(OK, callback.WaitForResult()); 10495 10496 response = trans2.GetResponseInfo(); 10497 ASSERT_TRUE(response != NULL); 10498 ASSERT_TRUE(response->headers.get() != NULL); 10499 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10500 EXPECT_TRUE(response->was_fetched_via_spdy); 10501 EXPECT_TRUE(response->was_npn_negotiated); 10502 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 10503 EXPECT_EQ("hello!", response_data); 10504} 10505#undef MAYBE_UseIPConnectionPooling 10506 10507TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) { 10508 HttpStreamFactory::set_use_alternate_protocols(true); 10509 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 10510 10511 // Set up a special HttpNetworkSession with a MockCachingHostResolver. 10512 session_deps_.host_resolver.reset(new MockCachingHostResolver()); 10513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10514 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); 10515 pool_peer.DisableDomainAuthenticationVerification(); 10516 10517 SSLSocketDataProvider ssl(ASYNC, OK); 10518 ssl.SetNextProto(GetParam()); 10519 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10520 10521 scoped_ptr<SpdyFrame> host1_req( 10522 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10523 scoped_ptr<SpdyFrame> host2_req( 10524 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST)); 10525 MockWrite spdy_writes[] = { 10526 CreateMockWrite(*host1_req, 1), 10527 CreateMockWrite(*host2_req, 4), 10528 }; 10529 scoped_ptr<SpdyFrame> host1_resp( 10530 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10531 scoped_ptr<SpdyFrame> host1_resp_body( 10532 spdy_util_.ConstructSpdyBodyFrame(1, true)); 10533 scoped_ptr<SpdyFrame> host2_resp( 10534 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10535 scoped_ptr<SpdyFrame> host2_resp_body( 10536 spdy_util_.ConstructSpdyBodyFrame(3, true)); 10537 MockRead spdy_reads[] = { 10538 CreateMockRead(*host1_resp, 2), 10539 CreateMockRead(*host1_resp_body, 3), 10540 CreateMockRead(*host2_resp, 5), 10541 CreateMockRead(*host2_resp_body, 6), 10542 MockRead(ASYNC, 0, 7), 10543 }; 10544 10545 IPAddressNumber ip; 10546 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); 10547 IPEndPoint peer_addr = IPEndPoint(ip, 443); 10548 MockConnect connect(ASYNC, OK, peer_addr); 10549 OrderedSocketData spdy_data( 10550 connect, 10551 spdy_reads, arraysize(spdy_reads), 10552 spdy_writes, arraysize(spdy_writes)); 10553 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10554 10555 TestCompletionCallback callback; 10556 HttpRequestInfo request1; 10557 request1.method = "GET"; 10558 request1.url = GURL("https://www.google.com/"); 10559 request1.load_flags = 0; 10560 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 10561 10562 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); 10563 EXPECT_EQ(ERR_IO_PENDING, rv); 10564 EXPECT_EQ(OK, callback.WaitForResult()); 10565 10566 const HttpResponseInfo* response = trans1.GetResponseInfo(); 10567 ASSERT_TRUE(response != NULL); 10568 ASSERT_TRUE(response->headers.get() != NULL); 10569 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10570 10571 std::string response_data; 10572 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 10573 EXPECT_EQ("hello!", response_data); 10574 10575 HttpRequestInfo request2; 10576 request2.method = "GET"; 10577 request2.url = GURL("https://www.gmail.com/"); 10578 request2.load_flags = 0; 10579 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 10580 10581 rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); 10582 EXPECT_EQ(ERR_IO_PENDING, rv); 10583 EXPECT_EQ(OK, callback.WaitForResult()); 10584 10585 response = trans2.GetResponseInfo(); 10586 ASSERT_TRUE(response != NULL); 10587 ASSERT_TRUE(response->headers.get() != NULL); 10588 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10589 EXPECT_TRUE(response->was_fetched_via_spdy); 10590 EXPECT_TRUE(response->was_npn_negotiated); 10591 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 10592 EXPECT_EQ("hello!", response_data); 10593} 10594 10595class OneTimeCachingHostResolver : public net::HostResolver { 10596 public: 10597 explicit OneTimeCachingHostResolver(const HostPortPair& host_port) 10598 : host_port_(host_port) {} 10599 virtual ~OneTimeCachingHostResolver() {} 10600 10601 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); } 10602 10603 // HostResolver methods: 10604 virtual int Resolve(const RequestInfo& info, 10605 AddressList* addresses, 10606 const CompletionCallback& callback, 10607 RequestHandle* out_req, 10608 const BoundNetLog& net_log) OVERRIDE { 10609 return host_resolver_.Resolve( 10610 info, addresses, callback, out_req, net_log); 10611 } 10612 10613 virtual int ResolveFromCache(const RequestInfo& info, 10614 AddressList* addresses, 10615 const BoundNetLog& net_log) OVERRIDE { 10616 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log); 10617 if (rv == OK && info.host_port_pair().Equals(host_port_)) 10618 host_resolver_.GetHostCache()->clear(); 10619 return rv; 10620 } 10621 10622 virtual void CancelRequest(RequestHandle req) OVERRIDE { 10623 host_resolver_.CancelRequest(req); 10624 } 10625 10626 MockCachingHostResolver* GetMockHostResolver() { 10627 return &host_resolver_; 10628 } 10629 10630 private: 10631 MockCachingHostResolver host_resolver_; 10632 const HostPortPair host_port_; 10633}; 10634 10635// Times out on Win7 dbg(2) bot. http://crbug.com/124776 10636#if defined(OS_WIN) 10637#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \ 10638 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration 10639#else 10640#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \ 10641 UseIPConnectionPoolingWithHostCacheExpiration 10642#endif 10643WRAPPED_TEST_P(HttpNetworkTransactionTest, 10644 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) { 10645// Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_ 10646// prefix doesn't work with parametrized tests). 10647#if defined(OS_WIN) 10648 return; 10649#endif 10650 10651 HttpStreamFactory::set_use_alternate_protocols(true); 10652 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 10653 10654 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver. 10655 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443)); 10656 HttpNetworkSession::Params params = 10657 SpdySessionDependencies::CreateSessionParams(&session_deps_); 10658 params.host_resolver = &host_resolver; 10659 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10660 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); 10661 pool_peer.DisableDomainAuthenticationVerification(); 10662 10663 SSLSocketDataProvider ssl(ASYNC, OK); 10664 ssl.SetNextProto(GetParam()); 10665 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10666 10667 scoped_ptr<SpdyFrame> host1_req( 10668 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10669 scoped_ptr<SpdyFrame> host2_req( 10670 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST)); 10671 MockWrite spdy_writes[] = { 10672 CreateMockWrite(*host1_req, 1), 10673 CreateMockWrite(*host2_req, 4), 10674 }; 10675 scoped_ptr<SpdyFrame> host1_resp( 10676 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10677 scoped_ptr<SpdyFrame> host1_resp_body( 10678 spdy_util_.ConstructSpdyBodyFrame(1, true)); 10679 scoped_ptr<SpdyFrame> host2_resp( 10680 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10681 scoped_ptr<SpdyFrame> host2_resp_body( 10682 spdy_util_.ConstructSpdyBodyFrame(3, true)); 10683 MockRead spdy_reads[] = { 10684 CreateMockRead(*host1_resp, 2), 10685 CreateMockRead(*host1_resp_body, 3), 10686 CreateMockRead(*host2_resp, 5), 10687 CreateMockRead(*host2_resp_body, 6), 10688 MockRead(ASYNC, 0, 7), 10689 }; 10690 10691 IPAddressNumber ip; 10692 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); 10693 IPEndPoint peer_addr = IPEndPoint(ip, 443); 10694 MockConnect connect(ASYNC, OK, peer_addr); 10695 OrderedSocketData spdy_data( 10696 connect, 10697 spdy_reads, arraysize(spdy_reads), 10698 spdy_writes, arraysize(spdy_writes)); 10699 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10700 10701 TestCompletionCallback callback; 10702 HttpRequestInfo request1; 10703 request1.method = "GET"; 10704 request1.url = GURL("https://www.google.com/"); 10705 request1.load_flags = 0; 10706 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 10707 10708 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); 10709 EXPECT_EQ(ERR_IO_PENDING, rv); 10710 EXPECT_EQ(OK, callback.WaitForResult()); 10711 10712 const HttpResponseInfo* response = trans1.GetResponseInfo(); 10713 ASSERT_TRUE(response != NULL); 10714 ASSERT_TRUE(response->headers.get() != NULL); 10715 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10716 10717 std::string response_data; 10718 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 10719 EXPECT_EQ("hello!", response_data); 10720 10721 // Preload cache entries into HostCache. 10722 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443)); 10723 AddressList ignored; 10724 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), 10725 NULL, BoundNetLog()); 10726 EXPECT_EQ(ERR_IO_PENDING, rv); 10727 rv = callback.WaitForResult(); 10728 EXPECT_EQ(OK, rv); 10729 10730 HttpRequestInfo request2; 10731 request2.method = "GET"; 10732 request2.url = GURL("https://www.gmail.com/"); 10733 request2.load_flags = 0; 10734 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 10735 10736 rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); 10737 EXPECT_EQ(ERR_IO_PENDING, rv); 10738 EXPECT_EQ(OK, callback.WaitForResult()); 10739 10740 response = trans2.GetResponseInfo(); 10741 ASSERT_TRUE(response != NULL); 10742 ASSERT_TRUE(response->headers.get() != NULL); 10743 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10744 EXPECT_TRUE(response->was_fetched_via_spdy); 10745 EXPECT_TRUE(response->was_npn_negotiated); 10746 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 10747 EXPECT_EQ("hello!", response_data); 10748} 10749#undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration 10750 10751TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) { 10752 MockRead data_reads1[] = { 10753 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION), 10754 }; 10755 MockRead data_reads2[] = { 10756 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 10757 MockRead("hello world"), 10758 MockRead(SYNCHRONOUS, OK), 10759 }; 10760 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0); 10761 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0); 10762 StaticSocketDataProvider* data[] = { &data1, &data2 }; 10763 10764 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data)); 10765 10766 EXPECT_EQ(OK, out.rv); 10767 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 10768 EXPECT_EQ("hello world", out.response_data); 10769} 10770 10771TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) { 10772 MockWrite data_writes1[] = { 10773 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION), 10774 }; 10775 MockWrite data_writes2[] = { 10776 MockWrite("GET / HTTP/1.1\r\n" 10777 "Host: www.google.com\r\n" 10778 "Connection: keep-alive\r\n\r\n"), 10779 }; 10780 MockRead data_reads2[] = { 10781 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 10782 MockRead("hello world"), 10783 MockRead(SYNCHRONOUS, OK), 10784 }; 10785 StaticSocketDataProvider data1(NULL, 0, 10786 data_writes1, arraysize(data_writes1)); 10787 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 10788 data_writes2, arraysize(data_writes2)); 10789 StaticSocketDataProvider* data[] = { &data1, &data2 }; 10790 10791 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data)); 10792 10793 EXPECT_EQ(OK, out.rv); 10794 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 10795 EXPECT_EQ("hello world", out.response_data); 10796} 10797 10798TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) { 10799 const std::string https_url = "https://www.google.com/"; 10800 const std::string http_url = "http://www.google.com:443/"; 10801 10802 // SPDY GET for HTTPS URL 10803 scoped_ptr<SpdyFrame> req1( 10804 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST)); 10805 10806 MockWrite writes1[] = { 10807 CreateMockWrite(*req1, 0), 10808 }; 10809 10810 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10811 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 10812 MockRead reads1[] = { 10813 CreateMockRead(*resp1, 1), 10814 CreateMockRead(*body1, 2), 10815 MockRead(ASYNC, ERR_IO_PENDING, 3) 10816 }; 10817 10818 DelayedSocketData data1( 10819 1, reads1, arraysize(reads1), 10820 writes1, arraysize(writes1)); 10821 MockConnect connect_data1(ASYNC, OK); 10822 data1.set_connect_data(connect_data1); 10823 10824 // HTTP GET for the HTTP URL 10825 MockWrite writes2[] = { 10826 MockWrite(ASYNC, 4, 10827 "GET / HTTP/1.1\r\n" 10828 "Host: www.google.com:443\r\n" 10829 "Connection: keep-alive\r\n\r\n"), 10830 }; 10831 10832 MockRead reads2[] = { 10833 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 10834 MockRead(ASYNC, 6, "hello"), 10835 MockRead(ASYNC, 7, OK), 10836 }; 10837 10838 DelayedSocketData data2( 10839 1, reads2, arraysize(reads2), 10840 writes2, arraysize(writes2)); 10841 10842 SSLSocketDataProvider ssl(ASYNC, OK); 10843 ssl.SetNextProto(GetParam()); 10844 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10845 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10846 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10847 10848 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10849 10850 // Start the first transaction to set up the SpdySession 10851 HttpRequestInfo request1; 10852 request1.method = "GET"; 10853 request1.url = GURL(https_url); 10854 request1.load_flags = 0; 10855 HttpNetworkTransaction trans1(LOWEST, session.get()); 10856 TestCompletionCallback callback1; 10857 EXPECT_EQ(ERR_IO_PENDING, 10858 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 10859 base::MessageLoop::current()->RunUntilIdle(); 10860 10861 EXPECT_EQ(OK, callback1.WaitForResult()); 10862 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 10863 10864 // Now, start the HTTP request 10865 HttpRequestInfo request2; 10866 request2.method = "GET"; 10867 request2.url = GURL(http_url); 10868 request2.load_flags = 0; 10869 HttpNetworkTransaction trans2(MEDIUM, session.get()); 10870 TestCompletionCallback callback2; 10871 EXPECT_EQ(ERR_IO_PENDING, 10872 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 10873 base::MessageLoop::current()->RunUntilIdle(); 10874 10875 EXPECT_EQ(OK, callback2.WaitForResult()); 10876 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy); 10877} 10878 10879TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) { 10880 const std::string https_url = "https://www.google.com/"; 10881 const std::string http_url = "http://www.google.com:443/"; 10882 10883 // SPDY GET for HTTPS URL (through CONNECT tunnel) 10884 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1)); 10885 scoped_ptr<SpdyFrame> req1( 10886 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST)); 10887 10888 // SPDY GET for HTTP URL (through the proxy, but not the tunnel) 10889 scoped_ptr<SpdyFrame> wrapped_req1( 10890 spdy_util_.ConstructWrappedSpdyFrame(req1, 1)); 10891 const char* const headers[] = { 10892 spdy_util_.GetMethodKey(), "GET", 10893 spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/", 10894 spdy_util_.GetHostKey(), "www.google.com:443", 10895 spdy_util_.GetSchemeKey(), "http", 10896 spdy_util_.GetVersionKey(), "HTTP/1.1" 10897 }; 10898 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame( 10899 NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN, 10900 headers, arraysize(headers), 0)); 10901 10902 MockWrite writes1[] = { 10903 CreateMockWrite(*connect, 0), 10904 CreateMockWrite(*wrapped_req1, 2), 10905 CreateMockWrite(*req2, 5), 10906 }; 10907 10908 scoped_ptr<SpdyFrame> conn_resp( 10909 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10910 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10911 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 10912 scoped_ptr<SpdyFrame> wrapped_resp1( 10913 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1)); 10914 scoped_ptr<SpdyFrame> wrapped_body1( 10915 spdy_util_.ConstructWrappedSpdyFrame(body1, 1)); 10916 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10917 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 10918 MockRead reads1[] = { 10919 CreateMockRead(*conn_resp, 1), 10920 CreateMockRead(*wrapped_resp1, 3), 10921 CreateMockRead(*wrapped_body1, 4), 10922 CreateMockRead(*resp2, 6), 10923 CreateMockRead(*body2, 7), 10924 MockRead(ASYNC, ERR_IO_PENDING, 8) 10925 }; 10926 10927 DeterministicSocketData data1(reads1, arraysize(reads1), 10928 writes1, arraysize(writes1)); 10929 MockConnect connect_data1(ASYNC, OK); 10930 data1.set_connect_data(connect_data1); 10931 10932 session_deps_.proxy_service.reset( 10933 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 10934 CapturingNetLog log; 10935 session_deps_.net_log = &log; 10936 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy 10937 ssl1.SetNextProto(GetParam()); 10938 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); 10939 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server 10940 ssl2.SetNextProto(GetParam()); 10941 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 10942 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1); 10943 10944 scoped_refptr<HttpNetworkSession> session( 10945 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 10946 10947 // Start the first transaction to set up the SpdySession 10948 HttpRequestInfo request1; 10949 request1.method = "GET"; 10950 request1.url = GURL(https_url); 10951 request1.load_flags = 0; 10952 HttpNetworkTransaction trans1(LOWEST, session.get()); 10953 TestCompletionCallback callback1; 10954 EXPECT_EQ(ERR_IO_PENDING, 10955 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 10956 base::MessageLoop::current()->RunUntilIdle(); 10957 data1.RunFor(4); 10958 10959 EXPECT_EQ(OK, callback1.WaitForResult()); 10960 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 10961 10962 LoadTimingInfo load_timing_info1; 10963 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1)); 10964 TestLoadTimingNotReusedWithPac(load_timing_info1, 10965 CONNECT_TIMING_HAS_SSL_TIMES); 10966 10967 // Now, start the HTTP request 10968 HttpRequestInfo request2; 10969 request2.method = "GET"; 10970 request2.url = GURL(http_url); 10971 request2.load_flags = 0; 10972 HttpNetworkTransaction trans2(MEDIUM, session.get()); 10973 TestCompletionCallback callback2; 10974 EXPECT_EQ(ERR_IO_PENDING, 10975 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 10976 base::MessageLoop::current()->RunUntilIdle(); 10977 data1.RunFor(3); 10978 10979 EXPECT_EQ(OK, callback2.WaitForResult()); 10980 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 10981 10982 LoadTimingInfo load_timing_info2; 10983 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2)); 10984 // The established SPDY sessions is considered reused by the HTTP request. 10985 TestLoadTimingReusedWithPac(load_timing_info2); 10986 // HTTP requests over a SPDY session should have a different connection 10987 // socket_log_id than requests over a tunnel. 10988 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 10989} 10990 10991TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) { 10992 HttpStreamFactory::set_force_spdy_always(true); 10993 const std::string https_url = "https://www.google.com/"; 10994 const std::string http_url = "http://www.google.com:443/"; 10995 10996 // SPDY GET for HTTPS URL 10997 scoped_ptr<SpdyFrame> req1( 10998 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST)); 10999 // SPDY GET for the HTTP URL 11000 scoped_ptr<SpdyFrame> req2( 11001 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM)); 11002 11003 MockWrite writes[] = { 11004 CreateMockWrite(*req1, 1), 11005 CreateMockWrite(*req2, 4), 11006 }; 11007 11008 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11009 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11010 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 11011 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 11012 MockRead reads[] = { 11013 CreateMockRead(*resp1, 2), 11014 CreateMockRead(*body1, 3), 11015 CreateMockRead(*resp2, 5), 11016 CreateMockRead(*body2, 6), 11017 MockRead(ASYNC, ERR_IO_PENDING, 7) 11018 }; 11019 11020 OrderedSocketData data(reads, arraysize(reads), 11021 writes, arraysize(writes)); 11022 11023 SSLSocketDataProvider ssl(ASYNC, OK); 11024 ssl.SetNextProto(GetParam()); 11025 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 11026 session_deps_.socket_factory->AddSocketDataProvider(&data); 11027 11028 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11029 11030 // Start the first transaction to set up the SpdySession 11031 HttpRequestInfo request1; 11032 request1.method = "GET"; 11033 request1.url = GURL(https_url); 11034 request1.load_flags = 0; 11035 HttpNetworkTransaction trans1(LOWEST, session.get()); 11036 TestCompletionCallback callback1; 11037 EXPECT_EQ(ERR_IO_PENDING, 11038 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11039 base::MessageLoop::current()->RunUntilIdle(); 11040 11041 EXPECT_EQ(OK, callback1.WaitForResult()); 11042 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 11043 11044 // Now, start the HTTP request 11045 HttpRequestInfo request2; 11046 request2.method = "GET"; 11047 request2.url = GURL(http_url); 11048 request2.load_flags = 0; 11049 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11050 TestCompletionCallback callback2; 11051 EXPECT_EQ(ERR_IO_PENDING, 11052 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11053 base::MessageLoop::current()->RunUntilIdle(); 11054 11055 EXPECT_EQ(OK, callback2.WaitForResult()); 11056 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11057} 11058 11059// Test that in the case where we have a SPDY session to a SPDY proxy 11060// that we do not pool other origins that resolve to the same IP when 11061// the certificate does not match the new origin. 11062// http://crbug.com/134690 11063TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) { 11064 const std::string url1 = "http://www.google.com/"; 11065 const std::string url2 = "https://mail.google.com/"; 11066 const std::string ip_addr = "1.2.3.4"; 11067 11068 // SPDY GET for HTTP URL (through SPDY proxy) 11069 scoped_ptr<SpdyHeaderBlock> headers( 11070 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/")); 11071 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame( 11072 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 11073 11074 MockWrite writes1[] = { 11075 CreateMockWrite(*req1, 0), 11076 }; 11077 11078 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11079 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11080 MockRead reads1[] = { 11081 CreateMockRead(*resp1, 1), 11082 CreateMockRead(*body1, 2), 11083 MockRead(ASYNC, OK, 3) // EOF 11084 }; 11085 11086 scoped_ptr<DeterministicSocketData> data1( 11087 new DeterministicSocketData(reads1, arraysize(reads1), 11088 writes1, arraysize(writes1))); 11089 IPAddressNumber ip; 11090 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip)); 11091 IPEndPoint peer_addr = IPEndPoint(ip, 443); 11092 MockConnect connect_data1(ASYNC, OK, peer_addr); 11093 data1->set_connect_data(connect_data1); 11094 11095 // SPDY GET for HTTPS URL (direct) 11096 scoped_ptr<SpdyFrame> req2( 11097 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM)); 11098 11099 MockWrite writes2[] = { 11100 CreateMockWrite(*req2, 0), 11101 }; 11102 11103 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11104 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11105 MockRead reads2[] = { 11106 CreateMockRead(*resp2, 1), 11107 CreateMockRead(*body2, 2), 11108 MockRead(ASYNC, OK, 3) // EOF 11109 }; 11110 11111 scoped_ptr<DeterministicSocketData> data2( 11112 new DeterministicSocketData(reads2, arraysize(reads2), 11113 writes2, arraysize(writes2))); 11114 MockConnect connect_data2(ASYNC, OK); 11115 data2->set_connect_data(connect_data2); 11116 11117 // Set up a proxy config that sends HTTP requests to a proxy, and 11118 // all others direct. 11119 ProxyConfig proxy_config; 11120 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443"); 11121 CapturingProxyResolver* capturing_proxy_resolver = 11122 new CapturingProxyResolver(); 11123 session_deps_.proxy_service.reset(new ProxyService( 11124 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver, 11125 NULL)); 11126 11127 // Load a valid cert. Note, that this does not need to 11128 // be valid for proxy because the MockSSLClientSocket does 11129 // not actually verify it. But SpdySession will use this 11130 // to see if it is valid for the new origin 11131 base::FilePath certs_dir = GetTestCertsDirectory(); 11132 scoped_refptr<X509Certificate> server_cert( 11133 ImportCertFromFile(certs_dir, "ok_cert.pem")); 11134 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); 11135 11136 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy 11137 ssl1.SetNextProto(GetParam()); 11138 ssl1.cert = server_cert; 11139 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); 11140 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11141 data1.get()); 11142 11143 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server 11144 ssl2.SetNextProto(GetParam()); 11145 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 11146 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11147 data2.get()); 11148 11149 session_deps_.host_resolver.reset(new MockCachingHostResolver()); 11150 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr); 11151 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr); 11152 11153 scoped_refptr<HttpNetworkSession> session( 11154 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 11155 11156 // Start the first transaction to set up the SpdySession 11157 HttpRequestInfo request1; 11158 request1.method = "GET"; 11159 request1.url = GURL(url1); 11160 request1.load_flags = 0; 11161 HttpNetworkTransaction trans1(LOWEST, session.get()); 11162 TestCompletionCallback callback1; 11163 ASSERT_EQ(ERR_IO_PENDING, 11164 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11165 data1->RunFor(3); 11166 11167 ASSERT_TRUE(callback1.have_result()); 11168 EXPECT_EQ(OK, callback1.WaitForResult()); 11169 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 11170 11171 // Now, start the HTTP request 11172 HttpRequestInfo request2; 11173 request2.method = "GET"; 11174 request2.url = GURL(url2); 11175 request2.load_flags = 0; 11176 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11177 TestCompletionCallback callback2; 11178 EXPECT_EQ(ERR_IO_PENDING, 11179 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11180 base::MessageLoop::current()->RunUntilIdle(); 11181 data2->RunFor(3); 11182 11183 ASSERT_TRUE(callback2.have_result()); 11184 EXPECT_EQ(OK, callback2.WaitForResult()); 11185 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11186} 11187 11188// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED 11189// error) in SPDY session, removes the socket from pool and closes the SPDY 11190// session. Verify that new url's from the same HttpNetworkSession (and a new 11191// SpdySession) do work. http://crbug.com/224701 11192TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) { 11193 const std::string https_url = "https://www.google.com/"; 11194 11195 MockRead reads1[] = { 11196 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0) 11197 }; 11198 11199 scoped_ptr<DeterministicSocketData> data1( 11200 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0)); 11201 data1->SetStop(1); 11202 11203 scoped_ptr<SpdyFrame> req2( 11204 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM)); 11205 MockWrite writes2[] = { 11206 CreateMockWrite(*req2, 0), 11207 }; 11208 11209 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11210 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11211 MockRead reads2[] = { 11212 CreateMockRead(*resp2, 1), 11213 CreateMockRead(*body2, 2), 11214 MockRead(ASYNC, OK, 3) // EOF 11215 }; 11216 11217 scoped_ptr<DeterministicSocketData> data2( 11218 new DeterministicSocketData(reads2, arraysize(reads2), 11219 writes2, arraysize(writes2))); 11220 11221 SSLSocketDataProvider ssl1(ASYNC, OK); 11222 ssl1.SetNextProto(GetParam()); 11223 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); 11224 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11225 data1.get()); 11226 11227 SSLSocketDataProvider ssl2(ASYNC, OK); 11228 ssl2.SetNextProto(GetParam()); 11229 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 11230 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11231 data2.get()); 11232 11233 scoped_refptr<HttpNetworkSession> session( 11234 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 11235 11236 // Start the first transaction to set up the SpdySession and verify that 11237 // connection was closed. 11238 HttpRequestInfo request1; 11239 request1.method = "GET"; 11240 request1.url = GURL(https_url); 11241 request1.load_flags = 0; 11242 HttpNetworkTransaction trans1(MEDIUM, session.get()); 11243 TestCompletionCallback callback1; 11244 EXPECT_EQ(ERR_IO_PENDING, 11245 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11246 base::MessageLoop::current()->RunUntilIdle(); 11247 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult()); 11248 11249 // Now, start the second request and make sure it succeeds. 11250 HttpRequestInfo request2; 11251 request2.method = "GET"; 11252 request2.url = GURL(https_url); 11253 request2.load_flags = 0; 11254 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11255 TestCompletionCallback callback2; 11256 EXPECT_EQ(ERR_IO_PENDING, 11257 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11258 base::MessageLoop::current()->RunUntilIdle(); 11259 data2->RunFor(3); 11260 11261 ASSERT_TRUE(callback2.have_result()); 11262 EXPECT_EQ(OK, callback2.WaitForResult()); 11263 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11264} 11265 11266TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) { 11267 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 11268 ClientSocketPoolManager::set_max_sockets_per_group( 11269 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 11270 ClientSocketPoolManager::set_max_sockets_per_pool( 11271 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 11272 11273 // Use two different hosts with different IPs so they don't get pooled. 11274 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1"); 11275 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2"); 11276 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11277 11278 SSLSocketDataProvider ssl1(ASYNC, OK); 11279 ssl1.SetNextProto(GetParam()); 11280 SSLSocketDataProvider ssl2(ASYNC, OK); 11281 ssl2.SetNextProto(GetParam()); 11282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1); 11283 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 11284 11285 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet( 11286 "https://www.a.com", false, 1, DEFAULT_PRIORITY)); 11287 MockWrite spdy1_writes[] = { 11288 CreateMockWrite(*host1_req, 1), 11289 }; 11290 scoped_ptr<SpdyFrame> host1_resp( 11291 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11292 scoped_ptr<SpdyFrame> host1_resp_body( 11293 spdy_util_.ConstructSpdyBodyFrame(1, true)); 11294 MockRead spdy1_reads[] = { 11295 CreateMockRead(*host1_resp, 2), 11296 CreateMockRead(*host1_resp_body, 3), 11297 MockRead(ASYNC, ERR_IO_PENDING, 4), 11298 }; 11299 11300 scoped_ptr<OrderedSocketData> spdy1_data( 11301 new OrderedSocketData( 11302 spdy1_reads, arraysize(spdy1_reads), 11303 spdy1_writes, arraysize(spdy1_writes))); 11304 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get()); 11305 11306 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet( 11307 "https://www.b.com", false, 1, DEFAULT_PRIORITY)); 11308 MockWrite spdy2_writes[] = { 11309 CreateMockWrite(*host2_req, 1), 11310 }; 11311 scoped_ptr<SpdyFrame> host2_resp( 11312 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11313 scoped_ptr<SpdyFrame> host2_resp_body( 11314 spdy_util_.ConstructSpdyBodyFrame(1, true)); 11315 MockRead spdy2_reads[] = { 11316 CreateMockRead(*host2_resp, 2), 11317 CreateMockRead(*host2_resp_body, 3), 11318 MockRead(ASYNC, ERR_IO_PENDING, 4), 11319 }; 11320 11321 scoped_ptr<OrderedSocketData> spdy2_data( 11322 new OrderedSocketData( 11323 spdy2_reads, arraysize(spdy2_reads), 11324 spdy2_writes, arraysize(spdy2_writes))); 11325 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get()); 11326 11327 MockWrite http_write[] = { 11328 MockWrite("GET / HTTP/1.1\r\n" 11329 "Host: www.a.com\r\n" 11330 "Connection: keep-alive\r\n\r\n"), 11331 }; 11332 11333 MockRead http_read[] = { 11334 MockRead("HTTP/1.1 200 OK\r\n"), 11335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 11336 MockRead("Content-Length: 6\r\n\r\n"), 11337 MockRead("hello!"), 11338 }; 11339 StaticSocketDataProvider http_data(http_read, arraysize(http_read), 11340 http_write, arraysize(http_write)); 11341 session_deps_.socket_factory->AddSocketDataProvider(&http_data); 11342 11343 HostPortPair host_port_pair_a("www.a.com", 443); 11344 SpdySessionKey spdy_session_key_a( 11345 host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled); 11346 EXPECT_FALSE( 11347 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11348 11349 TestCompletionCallback callback; 11350 HttpRequestInfo request1; 11351 request1.method = "GET"; 11352 request1.url = GURL("https://www.a.com/"); 11353 request1.load_flags = 0; 11354 scoped_ptr<HttpNetworkTransaction> trans( 11355 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 11356 11357 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 11358 EXPECT_EQ(ERR_IO_PENDING, rv); 11359 EXPECT_EQ(OK, callback.WaitForResult()); 11360 11361 const HttpResponseInfo* response = trans->GetResponseInfo(); 11362 ASSERT_TRUE(response != NULL); 11363 ASSERT_TRUE(response->headers.get() != NULL); 11364 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 11365 EXPECT_TRUE(response->was_fetched_via_spdy); 11366 EXPECT_TRUE(response->was_npn_negotiated); 11367 11368 std::string response_data; 11369 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 11370 EXPECT_EQ("hello!", response_data); 11371 trans.reset(); 11372 EXPECT_TRUE( 11373 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11374 11375 HostPortPair host_port_pair_b("www.b.com", 443); 11376 SpdySessionKey spdy_session_key_b( 11377 host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled); 11378 EXPECT_FALSE( 11379 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); 11380 HttpRequestInfo request2; 11381 request2.method = "GET"; 11382 request2.url = GURL("https://www.b.com/"); 11383 request2.load_flags = 0; 11384 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 11385 11386 rv = trans->Start(&request2, callback.callback(), BoundNetLog()); 11387 EXPECT_EQ(ERR_IO_PENDING, rv); 11388 EXPECT_EQ(OK, callback.WaitForResult()); 11389 11390 response = trans->GetResponseInfo(); 11391 ASSERT_TRUE(response != NULL); 11392 ASSERT_TRUE(response->headers.get() != NULL); 11393 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 11394 EXPECT_TRUE(response->was_fetched_via_spdy); 11395 EXPECT_TRUE(response->was_npn_negotiated); 11396 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 11397 EXPECT_EQ("hello!", response_data); 11398 EXPECT_FALSE( 11399 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11400 EXPECT_TRUE( 11401 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); 11402 11403 HostPortPair host_port_pair_a1("www.a.com", 80); 11404 SpdySessionKey spdy_session_key_a1( 11405 host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled); 11406 EXPECT_FALSE( 11407 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1)); 11408 HttpRequestInfo request3; 11409 request3.method = "GET"; 11410 request3.url = GURL("http://www.a.com/"); 11411 request3.load_flags = 0; 11412 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 11413 11414 rv = trans->Start(&request3, callback.callback(), BoundNetLog()); 11415 EXPECT_EQ(ERR_IO_PENDING, rv); 11416 EXPECT_EQ(OK, callback.WaitForResult()); 11417 11418 response = trans->GetResponseInfo(); 11419 ASSERT_TRUE(response != NULL); 11420 ASSERT_TRUE(response->headers.get() != NULL); 11421 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 11422 EXPECT_FALSE(response->was_fetched_via_spdy); 11423 EXPECT_FALSE(response->was_npn_negotiated); 11424 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 11425 EXPECT_EQ("hello!", response_data); 11426 EXPECT_FALSE( 11427 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11428 EXPECT_FALSE( 11429 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); 11430} 11431 11432TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) { 11433 HttpRequestInfo request; 11434 request.method = "GET"; 11435 request.url = GURL("http://www.google.com/"); 11436 request.load_flags = 0; 11437 11438 scoped_ptr<HttpTransaction> trans( 11439 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11440 CreateSession(&session_deps_))); 11441 11442 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED); 11443 StaticSocketDataProvider data; 11444 data.set_connect_data(mock_connect); 11445 session_deps_.socket_factory->AddSocketDataProvider(&data); 11446 11447 TestCompletionCallback callback; 11448 11449 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11450 EXPECT_EQ(ERR_IO_PENDING, rv); 11451 11452 rv = callback.WaitForResult(); 11453 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); 11454 11455 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11456 11457 // We don't care whether this succeeds or fails, but it shouldn't crash. 11458 HttpRequestHeaders request_headers; 11459 trans->GetFullRequestHeaders(&request_headers); 11460} 11461 11462TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { 11463 HttpRequestInfo request; 11464 request.method = "GET"; 11465 request.url = GURL("http://www.google.com/"); 11466 request.load_flags = 0; 11467 11468 scoped_ptr<HttpTransaction> trans( 11469 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11470 CreateSession(&session_deps_))); 11471 11472 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 11473 StaticSocketDataProvider data; 11474 data.set_connect_data(mock_connect); 11475 session_deps_.socket_factory->AddSocketDataProvider(&data); 11476 11477 TestCompletionCallback callback; 11478 11479 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11480 EXPECT_EQ(ERR_IO_PENDING, rv); 11481 11482 rv = callback.WaitForResult(); 11483 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); 11484 11485 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11486 11487 // We don't care whether this succeeds or fails, but it shouldn't crash. 11488 HttpRequestHeaders request_headers; 11489 trans->GetFullRequestHeaders(&request_headers); 11490} 11491 11492TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) { 11493 HttpRequestInfo request; 11494 request.method = "GET"; 11495 request.url = GURL("http://www.google.com/"); 11496 request.load_flags = 0; 11497 11498 scoped_ptr<HttpTransaction> trans( 11499 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11500 CreateSession(&session_deps_))); 11501 11502 MockWrite data_writes[] = { 11503 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET), 11504 }; 11505 MockRead data_reads[] = { 11506 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 11507 }; 11508 11509 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11510 data_writes, arraysize(data_writes)); 11511 session_deps_.socket_factory->AddSocketDataProvider(&data); 11512 11513 TestCompletionCallback callback; 11514 11515 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11516 EXPECT_EQ(ERR_IO_PENDING, rv); 11517 11518 rv = callback.WaitForResult(); 11519 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11520 11521 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11522 11523 HttpRequestHeaders request_headers; 11524 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11525 EXPECT_TRUE(request_headers.HasHeader("Host")); 11526} 11527 11528TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) { 11529 HttpRequestInfo request; 11530 request.method = "GET"; 11531 request.url = GURL("http://www.google.com/"); 11532 request.load_flags = 0; 11533 11534 scoped_ptr<HttpTransaction> trans( 11535 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11536 CreateSession(&session_deps_))); 11537 11538 MockWrite data_writes[] = { 11539 MockWrite(ASYNC, ERR_CONNECTION_RESET), 11540 }; 11541 MockRead data_reads[] = { 11542 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 11543 }; 11544 11545 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11546 data_writes, arraysize(data_writes)); 11547 session_deps_.socket_factory->AddSocketDataProvider(&data); 11548 11549 TestCompletionCallback callback; 11550 11551 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11552 EXPECT_EQ(ERR_IO_PENDING, rv); 11553 11554 rv = callback.WaitForResult(); 11555 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11556 11557 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11558 11559 HttpRequestHeaders request_headers; 11560 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11561 EXPECT_TRUE(request_headers.HasHeader("Host")); 11562} 11563 11564TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) { 11565 HttpRequestInfo request; 11566 request.method = "GET"; 11567 request.url = GURL("http://www.google.com/"); 11568 request.load_flags = 0; 11569 11570 scoped_ptr<HttpTransaction> trans( 11571 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11572 CreateSession(&session_deps_))); 11573 11574 MockWrite data_writes[] = { 11575 MockWrite("GET / HTTP/1.1\r\n" 11576 "Host: www.google.com\r\n" 11577 "Connection: keep-alive\r\n\r\n"), 11578 }; 11579 MockRead data_reads[] = { 11580 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET), 11581 }; 11582 11583 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11584 data_writes, arraysize(data_writes)); 11585 session_deps_.socket_factory->AddSocketDataProvider(&data); 11586 11587 TestCompletionCallback callback; 11588 11589 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11590 EXPECT_EQ(ERR_IO_PENDING, rv); 11591 11592 rv = callback.WaitForResult(); 11593 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11594 11595 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11596 11597 HttpRequestHeaders request_headers; 11598 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11599 EXPECT_TRUE(request_headers.HasHeader("Host")); 11600} 11601 11602TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) { 11603 HttpRequestInfo request; 11604 request.method = "GET"; 11605 request.url = GURL("http://www.google.com/"); 11606 request.load_flags = 0; 11607 11608 scoped_ptr<HttpTransaction> trans( 11609 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11610 CreateSession(&session_deps_))); 11611 11612 MockWrite data_writes[] = { 11613 MockWrite("GET / HTTP/1.1\r\n" 11614 "Host: www.google.com\r\n" 11615 "Connection: keep-alive\r\n\r\n"), 11616 }; 11617 MockRead data_reads[] = { 11618 MockRead(ASYNC, ERR_CONNECTION_RESET), 11619 }; 11620 11621 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11622 data_writes, arraysize(data_writes)); 11623 session_deps_.socket_factory->AddSocketDataProvider(&data); 11624 11625 TestCompletionCallback callback; 11626 11627 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11628 EXPECT_EQ(ERR_IO_PENDING, rv); 11629 11630 rv = callback.WaitForResult(); 11631 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11632 11633 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11634 11635 HttpRequestHeaders request_headers; 11636 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11637 EXPECT_TRUE(request_headers.HasHeader("Host")); 11638} 11639 11640TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) { 11641 HttpRequestInfo request; 11642 request.method = "GET"; 11643 request.url = GURL("http://www.google.com/"); 11644 request.load_flags = 0; 11645 request.extra_headers.SetHeader("X-Foo", "bar"); 11646 11647 scoped_ptr<HttpTransaction> trans( 11648 new HttpNetworkTransaction(DEFAULT_PRIORITY, 11649 CreateSession(&session_deps_))); 11650 11651 MockWrite data_writes[] = { 11652 MockWrite("GET / HTTP/1.1\r\n" 11653 "Host: www.google.com\r\n" 11654 "Connection: keep-alive\r\n" 11655 "X-Foo: bar\r\n\r\n"), 11656 }; 11657 MockRead data_reads[] = { 11658 MockRead("HTTP/1.1 200 OK\r\n" 11659 "Content-Length: 5\r\n\r\n" 11660 "hello"), 11661 MockRead(ASYNC, ERR_UNEXPECTED), 11662 }; 11663 11664 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11665 data_writes, arraysize(data_writes)); 11666 session_deps_.socket_factory->AddSocketDataProvider(&data); 11667 11668 TestCompletionCallback callback; 11669 11670 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11671 EXPECT_EQ(ERR_IO_PENDING, rv); 11672 11673 rv = callback.WaitForResult(); 11674 EXPECT_EQ(OK, rv); 11675 11676 HttpRequestHeaders request_headers; 11677 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11678 std::string foo; 11679 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo)); 11680 EXPECT_EQ("bar", foo); 11681} 11682 11683} // namespace net 11684