http_network_transaction_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/memory/weak_ptr.h" 19#include "base/strings/string_util.h" 20#include "base/strings/utf_string_conversions.h" 21#include "base/test/test_file_util.h" 22#include "net/base/auth.h" 23#include "net/base/capturing_net_log.h" 24#include "net/base/completion_callback.h" 25#include "net/base/load_timing_info.h" 26#include "net/base/load_timing_info_test_util.h" 27#include "net/base/net_log.h" 28#include "net/base/net_log_unittest.h" 29#include "net/base/request_priority.h" 30#include "net/base/test_completion_callback.h" 31#include "net/base/test_data_directory.h" 32#include "net/base/upload_bytes_element_reader.h" 33#include "net/base/upload_data_stream.h" 34#include "net/base/upload_file_element_reader.h" 35#include "net/cert/mock_cert_verifier.h" 36#include "net/dns/host_cache.h" 37#include "net/dns/mock_host_resolver.h" 38#include "net/http/http_auth_handler_digest.h" 39#include "net/http/http_auth_handler_mock.h" 40#include "net/http/http_auth_handler_ntlm.h" 41#include "net/http/http_basic_stream.h" 42#include "net/http/http_network_session.h" 43#include "net/http/http_network_session_peer.h" 44#include "net/http/http_server_properties_impl.h" 45#include "net/http/http_stream.h" 46#include "net/http/http_stream_factory.h" 47#include "net/http/http_transaction_unittest.h" 48#include "net/proxy/proxy_config_service_fixed.h" 49#include "net/proxy/proxy_info.h" 50#include "net/proxy/proxy_resolver.h" 51#include "net/proxy/proxy_service.h" 52#include "net/socket/client_socket_factory.h" 53#include "net/socket/client_socket_pool_manager.h" 54#include "net/socket/mock_client_socket_pool_manager.h" 55#include "net/socket/next_proto.h" 56#include "net/socket/socket_test_util.h" 57#include "net/socket/ssl_client_socket.h" 58#include "net/spdy/spdy_framer.h" 59#include "net/spdy/spdy_session.h" 60#include "net/spdy/spdy_session_pool.h" 61#include "net/spdy/spdy_test_util_common.h" 62#include "net/ssl/ssl_cert_request_info.h" 63#include "net/ssl/ssl_config_service.h" 64#include "net/ssl/ssl_config_service_defaults.h" 65#include "net/ssl/ssl_info.h" 66#include "net/test/cert_test_util.h" 67#include "net/websockets/websocket_handshake_stream_base.h" 68#include "testing/gtest/include/gtest/gtest.h" 69#include "testing/platform_test.h" 70#include "url/gurl.h" 71 72using base::ASCIIToUTF16; 73 74//----------------------------------------------------------------------------- 75 76namespace { 77 78const base::string16 kBar(ASCIIToUTF16("bar")); 79const base::string16 kBar2(ASCIIToUTF16("bar2")); 80const base::string16 kBar3(ASCIIToUTF16("bar3")); 81const base::string16 kBaz(ASCIIToUTF16("baz")); 82const base::string16 kFirst(ASCIIToUTF16("first")); 83const base::string16 kFoo(ASCIIToUTF16("foo")); 84const base::string16 kFoo2(ASCIIToUTF16("foo2")); 85const base::string16 kFoo3(ASCIIToUTF16("foo3")); 86const base::string16 kFou(ASCIIToUTF16("fou")); 87const base::string16 kSecond(ASCIIToUTF16("second")); 88const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm")); 89const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword")); 90 91int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) { 92 return session->GetTransportSocketPool( 93 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); 94} 95 96int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) { 97 return session->GetSSLSocketPool( 98 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); 99} 100 101bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) { 102 return session->GetTransportSocketPool( 103 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled(); 104} 105 106// Takes in a Value created from a NetLogHttpResponseParameter, and returns 107// a JSONified list of headers as a single string. Uses single quotes instead 108// of double quotes for easier comparison. Returns false on failure. 109bool GetHeaders(base::DictionaryValue* params, std::string* headers) { 110 if (!params) 111 return false; 112 base::ListValue* header_list; 113 if (!params->GetList("headers", &header_list)) 114 return false; 115 std::string double_quote_headers; 116 base::JSONWriter::Write(header_list, &double_quote_headers); 117 base::ReplaceChars(double_quote_headers, "\"", "'", headers); 118 return true; 119} 120 121// Tests LoadTimingInfo in the case a socket is reused and no PAC script is 122// used. 123void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) { 124 EXPECT_TRUE(load_timing_info.socket_reused); 125 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 126 127 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); 128 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); 129 130 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 131 EXPECT_FALSE(load_timing_info.send_start.is_null()); 132 133 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 134 135 // Set at a higher level. 136 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 137 EXPECT_TRUE(load_timing_info.request_start.is_null()); 138 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 139} 140 141// Tests LoadTimingInfo in the case a new socket is used and no PAC script is 142// used. 143void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info, 144 int connect_timing_flags) { 145 EXPECT_FALSE(load_timing_info.socket_reused); 146 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 147 148 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); 149 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); 150 151 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 152 connect_timing_flags); 153 EXPECT_LE(load_timing_info.connect_timing.connect_end, 154 load_timing_info.send_start); 155 156 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 157 158 // Set at a higher level. 159 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 160 EXPECT_TRUE(load_timing_info.request_start.is_null()); 161 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 162} 163 164// Tests LoadTimingInfo in the case a socket is reused and a PAC script is 165// used. 166void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) { 167 EXPECT_TRUE(load_timing_info.socket_reused); 168 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 169 170 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 171 172 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 173 EXPECT_LE(load_timing_info.proxy_resolve_start, 174 load_timing_info.proxy_resolve_end); 175 EXPECT_LE(load_timing_info.proxy_resolve_end, 176 load_timing_info.send_start); 177 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 178 179 // Set at a higher level. 180 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 181 EXPECT_TRUE(load_timing_info.request_start.is_null()); 182 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 183} 184 185// Tests LoadTimingInfo in the case a new socket is used and a PAC script is 186// used. 187void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info, 188 int connect_timing_flags) { 189 EXPECT_FALSE(load_timing_info.socket_reused); 190 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 191 192 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 193 EXPECT_LE(load_timing_info.proxy_resolve_start, 194 load_timing_info.proxy_resolve_end); 195 EXPECT_LE(load_timing_info.proxy_resolve_end, 196 load_timing_info.connect_timing.connect_start); 197 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 198 connect_timing_flags); 199 EXPECT_LE(load_timing_info.connect_timing.connect_end, 200 load_timing_info.send_start); 201 202 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 203 204 // Set at a higher level. 205 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 206 EXPECT_TRUE(load_timing_info.request_start.is_null()); 207 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 208} 209 210} // namespace 211 212namespace net { 213 214namespace { 215 216HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) { 217 return SpdySessionDependencies::SpdyCreateSession(session_deps); 218} 219 220} // namespace 221 222class HttpNetworkTransactionTest 223 : public PlatformTest, 224 public ::testing::WithParamInterface<NextProto> { 225 public: 226 virtual ~HttpNetworkTransactionTest() { 227 // Important to restore the per-pool limit first, since the pool limit must 228 // always be greater than group limit, and the tests reduce both limits. 229 ClientSocketPoolManager::set_max_sockets_per_pool( 230 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_); 231 ClientSocketPoolManager::set_max_sockets_per_group( 232 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_); 233 } 234 235 protected: 236 HttpNetworkTransactionTest() 237 : spdy_util_(GetParam()), 238 session_deps_(GetParam()), 239 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( 240 HttpNetworkSession::NORMAL_SOCKET_POOL)), 241 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( 242 HttpNetworkSession::NORMAL_SOCKET_POOL)) { 243 } 244 245 struct SimpleGetHelperResult { 246 int rv; 247 std::string status_line; 248 std::string response_data; 249 int64 totalReceivedBytes; 250 LoadTimingInfo load_timing_info; 251 }; 252 253 virtual void SetUp() { 254 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 255 base::MessageLoop::current()->RunUntilIdle(); 256 } 257 258 virtual void TearDown() { 259 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 260 base::MessageLoop::current()->RunUntilIdle(); 261 // Empty the current queue. 262 base::MessageLoop::current()->RunUntilIdle(); 263 PlatformTest::TearDown(); 264 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 265 base::MessageLoop::current()->RunUntilIdle(); 266 HttpStreamFactory::set_use_alternate_protocols(false); 267 HttpStreamFactory::SetNextProtos(std::vector<NextProto>()); 268 } 269 270 // This is the expected return from a current server advertising SPDY. 271 std::string GetAlternateProtocolHttpHeader() { 272 return 273 std::string("Alternate-Protocol: 443:") + 274 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) + 275 "\r\n\r\n"; 276 } 277 278 // Either |write_failure| specifies a write failure or |read_failure| 279 // specifies a read failure when using a reused socket. In either case, the 280 // failure should cause the network transaction to resend the request, and the 281 // other argument should be NULL. 282 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure, 283 const MockRead* read_failure); 284 285 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[], 286 size_t data_count) { 287 SimpleGetHelperResult out; 288 289 HttpRequestInfo request; 290 request.method = "GET"; 291 request.url = GURL("http://www.google.com/"); 292 request.load_flags = 0; 293 294 CapturingBoundNetLog log; 295 session_deps_.net_log = log.bound().net_log(); 296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 297 scoped_ptr<HttpTransaction> trans( 298 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 299 300 for (size_t i = 0; i < data_count; ++i) { 301 session_deps_.socket_factory->AddSocketDataProvider(data[i]); 302 } 303 304 TestCompletionCallback callback; 305 306 EXPECT_TRUE(log.bound().IsLoggingAllEvents()); 307 int rv = trans->Start(&request, callback.callback(), log.bound()); 308 EXPECT_EQ(ERR_IO_PENDING, rv); 309 310 out.rv = callback.WaitForResult(); 311 312 // Even in the failure cases that use this function, connections are always 313 // successfully established before the error. 314 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info)); 315 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 316 317 if (out.rv != OK) 318 return out; 319 320 const HttpResponseInfo* response = trans->GetResponseInfo(); 321 // Can't use ASSERT_* inside helper functions like this, so 322 // return an error. 323 if (response == NULL || response->headers.get() == NULL) { 324 out.rv = ERR_UNEXPECTED; 325 return out; 326 } 327 out.status_line = response->headers->GetStatusLine(); 328 329 EXPECT_EQ("127.0.0.1", response->socket_address.host()); 330 EXPECT_EQ(80, response->socket_address.port()); 331 332 rv = ReadTransaction(trans.get(), &out.response_data); 333 EXPECT_EQ(OK, rv); 334 335 net::CapturingNetLog::CapturedEntryList entries; 336 log.GetEntries(&entries); 337 size_t pos = ExpectLogContainsSomewhere( 338 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 339 NetLog::PHASE_NONE); 340 ExpectLogContainsSomewhere( 341 entries, pos, 342 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS, 343 NetLog::PHASE_NONE); 344 345 std::string line; 346 EXPECT_TRUE(entries[pos].GetStringValue("line", &line)); 347 EXPECT_EQ("GET / HTTP/1.1\r\n", line); 348 349 HttpRequestHeaders request_headers; 350 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 351 std::string value; 352 EXPECT_TRUE(request_headers.GetHeader("Host", &value)); 353 EXPECT_EQ("www.google.com", value); 354 EXPECT_TRUE(request_headers.GetHeader("Connection", &value)); 355 EXPECT_EQ("keep-alive", value); 356 357 std::string response_headers; 358 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers)); 359 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']", 360 response_headers); 361 362 out.totalReceivedBytes = trans->GetTotalReceivedBytes(); 363 return out; 364 } 365 366 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[], 367 size_t reads_count) { 368 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0); 369 StaticSocketDataProvider* data[] = { &reads }; 370 return SimpleGetHelperForData(data, 1); 371 } 372 373 int64 ReadsSize(MockRead data_reads[], size_t reads_count) { 374 int64 size = 0; 375 for (size_t i = 0; i < reads_count; ++i) 376 size += data_reads[i].data_len; 377 return size; 378 } 379 380 void ConnectStatusHelperWithExpectedStatus(const MockRead& status, 381 int expected_status); 382 383 void ConnectStatusHelper(const MockRead& status); 384 385 void BypassHostCacheOnRefreshHelper(int load_flags); 386 387 void CheckErrorIsPassedBack(int error, IoMode mode); 388 389 SpdyTestUtil spdy_util_; 390 SpdySessionDependencies session_deps_; 391 392 // Original socket limits. Some tests set these. Safest to always restore 393 // them once each test has been run. 394 int old_max_group_sockets_; 395 int old_max_pool_sockets_; 396}; 397 398INSTANTIATE_TEST_CASE_P( 399 NextProto, 400 HttpNetworkTransactionTest, 401 testing::Values(kProtoDeprecatedSPDY2, 402 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2, 403 kProtoHTTP2Draft04)); 404 405namespace { 406 407class BeforeNetworkStartHandler { 408 public: 409 explicit BeforeNetworkStartHandler(bool defer) 410 : defer_on_before_network_start_(defer), 411 observed_before_network_start_(false) {} 412 413 void OnBeforeNetworkStart(bool* defer) { 414 *defer = defer_on_before_network_start_; 415 observed_before_network_start_ = true; 416 } 417 418 bool observed_before_network_start() const { 419 return observed_before_network_start_; 420 } 421 422 private: 423 const bool defer_on_before_network_start_; 424 bool observed_before_network_start_; 425 426 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler); 427}; 428 429// Fill |str| with a long header list that consumes >= |size| bytes. 430void FillLargeHeadersString(std::string* str, int size) { 431 const char* row = 432 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"; 433 const int sizeof_row = strlen(row); 434 const int num_rows = static_cast<int>( 435 ceil(static_cast<float>(size) / sizeof_row)); 436 const int sizeof_data = num_rows * sizeof_row; 437 DCHECK(sizeof_data >= size); 438 str->reserve(sizeof_data); 439 440 for (int i = 0; i < num_rows; ++i) 441 str->append(row, sizeof_row); 442} 443 444// Alternative functions that eliminate randomness and dependency on the local 445// host name so that the generated NTLM messages are reproducible. 446void MockGenerateRandom1(uint8* output, size_t n) { 447 static const uint8 bytes[] = { 448 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54 449 }; 450 static size_t current_byte = 0; 451 for (size_t i = 0; i < n; ++i) { 452 output[i] = bytes[current_byte++]; 453 current_byte %= arraysize(bytes); 454 } 455} 456 457void MockGenerateRandom2(uint8* output, size_t n) { 458 static const uint8 bytes[] = { 459 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1, 460 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f 461 }; 462 static size_t current_byte = 0; 463 for (size_t i = 0; i < n; ++i) { 464 output[i] = bytes[current_byte++]; 465 current_byte %= arraysize(bytes); 466 } 467} 468 469std::string MockGetHostName() { 470 return "WTC-WIN7"; 471} 472 473template<typename ParentPool> 474class CaptureGroupNameSocketPool : public ParentPool { 475 public: 476 CaptureGroupNameSocketPool(HostResolver* host_resolver, 477 CertVerifier* cert_verifier); 478 479 const std::string last_group_name_received() const { 480 return last_group_name_; 481 } 482 483 virtual int RequestSocket(const std::string& group_name, 484 const void* socket_params, 485 RequestPriority priority, 486 ClientSocketHandle* handle, 487 const CompletionCallback& callback, 488 const BoundNetLog& net_log) { 489 last_group_name_ = group_name; 490 return ERR_IO_PENDING; 491 } 492 virtual void CancelRequest(const std::string& group_name, 493 ClientSocketHandle* handle) {} 494 virtual void ReleaseSocket(const std::string& group_name, 495 scoped_ptr<StreamSocket> socket, 496 int id) {} 497 virtual void CloseIdleSockets() {} 498 virtual int IdleSocketCount() const { 499 return 0; 500 } 501 virtual int IdleSocketCountInGroup(const std::string& group_name) const { 502 return 0; 503 } 504 virtual LoadState GetLoadState(const std::string& group_name, 505 const ClientSocketHandle* handle) const { 506 return LOAD_STATE_IDLE; 507 } 508 virtual base::TimeDelta ConnectionTimeout() const { 509 return base::TimeDelta(); 510 } 511 512 private: 513 std::string last_group_name_; 514}; 515 516typedef CaptureGroupNameSocketPool<TransportClientSocketPool> 517CaptureGroupNameTransportSocketPool; 518typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool> 519CaptureGroupNameHttpProxySocketPool; 520typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool> 521CaptureGroupNameSOCKSSocketPool; 522typedef CaptureGroupNameSocketPool<SSLClientSocketPool> 523CaptureGroupNameSSLSocketPool; 524 525template<typename ParentPool> 526CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( 527 HostResolver* host_resolver, 528 CertVerifier* /* cert_verifier */) 529 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {} 530 531template<> 532CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( 533 HostResolver* host_resolver, 534 CertVerifier* /* cert_verifier */) 535 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {} 536 537template <> 538CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( 539 HostResolver* host_resolver, 540 CertVerifier* cert_verifier) 541 : SSLClientSocketPool(0, 542 0, 543 NULL, 544 host_resolver, 545 cert_verifier, 546 NULL, 547 NULL, 548 NULL, 549 std::string(), 550 NULL, 551 NULL, 552 NULL, 553 NULL, 554 NULL, 555 NULL) {} 556 557//----------------------------------------------------------------------------- 558 559// Helper functions for validating that AuthChallengeInfo's are correctly 560// configured for common cases. 561bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) { 562 if (!auth_challenge) 563 return false; 564 EXPECT_FALSE(auth_challenge->is_proxy); 565 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString()); 566 EXPECT_EQ("MyRealm1", auth_challenge->realm); 567 EXPECT_EQ("basic", auth_challenge->scheme); 568 return true; 569} 570 571bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) { 572 if (!auth_challenge) 573 return false; 574 EXPECT_TRUE(auth_challenge->is_proxy); 575 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString()); 576 EXPECT_EQ("MyRealm1", auth_challenge->realm); 577 EXPECT_EQ("basic", auth_challenge->scheme); 578 return true; 579} 580 581bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) { 582 if (!auth_challenge) 583 return false; 584 EXPECT_FALSE(auth_challenge->is_proxy); 585 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString()); 586 EXPECT_EQ("digestive", auth_challenge->realm); 587 EXPECT_EQ("digest", auth_challenge->scheme); 588 return true; 589} 590 591bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) { 592 if (!auth_challenge) 593 return false; 594 EXPECT_FALSE(auth_challenge->is_proxy); 595 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString()); 596 EXPECT_EQ(std::string(), auth_challenge->realm); 597 EXPECT_EQ("ntlm", auth_challenge->scheme); 598 return true; 599} 600 601} // namespace 602 603TEST_P(HttpNetworkTransactionTest, Basic) { 604 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 605 scoped_ptr<HttpTransaction> trans( 606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 607} 608 609TEST_P(HttpNetworkTransactionTest, SimpleGET) { 610 MockRead data_reads[] = { 611 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 612 MockRead("hello world"), 613 MockRead(SYNCHRONOUS, OK), 614 }; 615 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 616 arraysize(data_reads)); 617 EXPECT_EQ(OK, out.rv); 618 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 619 EXPECT_EQ("hello world", out.response_data); 620 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 621 EXPECT_EQ(reads_size, out.totalReceivedBytes); 622} 623 624// Response with no status line. 625TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) { 626 MockRead data_reads[] = { 627 MockRead("hello world"), 628 MockRead(SYNCHRONOUS, OK), 629 }; 630 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 631 arraysize(data_reads)); 632 EXPECT_EQ(OK, out.rv); 633 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 634 EXPECT_EQ("hello world", out.response_data); 635 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 636 EXPECT_EQ(reads_size, out.totalReceivedBytes); 637} 638 639// Allow up to 4 bytes of junk to precede status line. 640TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) { 641 MockRead data_reads[] = { 642 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 643 MockRead(SYNCHRONOUS, OK), 644 }; 645 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 646 arraysize(data_reads)); 647 EXPECT_EQ(OK, out.rv); 648 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 649 EXPECT_EQ("DATA", out.response_data); 650 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 651 EXPECT_EQ(reads_size, out.totalReceivedBytes); 652} 653 654// Allow up to 4 bytes of junk to precede status line. 655TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) { 656 MockRead data_reads[] = { 657 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 658 MockRead(SYNCHRONOUS, OK), 659 }; 660 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 661 arraysize(data_reads)); 662 EXPECT_EQ(OK, out.rv); 663 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 664 EXPECT_EQ("DATA", out.response_data); 665 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 666 EXPECT_EQ(reads_size, out.totalReceivedBytes); 667} 668 669// Beyond 4 bytes of slop and it should fail to find a status line. 670TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) { 671 MockRead data_reads[] = { 672 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"), 673 MockRead(SYNCHRONOUS, OK), 674 }; 675 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 676 arraysize(data_reads)); 677 EXPECT_EQ(OK, out.rv); 678 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 679 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data); 680 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 681 EXPECT_EQ(reads_size, out.totalReceivedBytes); 682} 683 684// Same as StatusLineJunk4Bytes, except the read chunks are smaller. 685TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) { 686 MockRead data_reads[] = { 687 MockRead("\n"), 688 MockRead("\n"), 689 MockRead("Q"), 690 MockRead("J"), 691 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 692 MockRead(SYNCHRONOUS, OK), 693 }; 694 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 695 arraysize(data_reads)); 696 EXPECT_EQ(OK, out.rv); 697 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 698 EXPECT_EQ("DATA", out.response_data); 699 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 700 EXPECT_EQ(reads_size, out.totalReceivedBytes); 701} 702 703// Close the connection before enough bytes to have a status line. 704TEST_P(HttpNetworkTransactionTest, StatusLinePartial) { 705 MockRead data_reads[] = { 706 MockRead("HTT"), 707 MockRead(SYNCHRONOUS, OK), 708 }; 709 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 710 arraysize(data_reads)); 711 EXPECT_EQ(OK, out.rv); 712 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 713 EXPECT_EQ("HTT", out.response_data); 714 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 715 EXPECT_EQ(reads_size, out.totalReceivedBytes); 716} 717 718// Simulate a 204 response, lacking a Content-Length header, sent over a 719// persistent connection. The response should still terminate since a 204 720// cannot have a response body. 721TEST_P(HttpNetworkTransactionTest, StopsReading204) { 722 char junk[] = "junk"; 723 MockRead data_reads[] = { 724 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 725 MockRead(junk), // Should not be read!! 726 MockRead(SYNCHRONOUS, OK), 727 }; 728 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 729 arraysize(data_reads)); 730 EXPECT_EQ(OK, out.rv); 731 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line); 732 EXPECT_EQ("", out.response_data); 733 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 734 int64 response_size = reads_size - strlen(junk); 735 EXPECT_EQ(response_size, out.totalReceivedBytes); 736} 737 738// A simple request using chunked encoding with some extra data after. 739// (Like might be seen in a pipelined response.) 740TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) { 741 std::string final_chunk = "0\r\n\r\n"; 742 std::string extra_data = "HTTP/1.1 200 OK\r\n"; 743 std::string last_read = final_chunk + extra_data; 744 MockRead data_reads[] = { 745 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"), 746 MockRead("5\r\nHello\r\n"), 747 MockRead("1\r\n"), 748 MockRead(" \r\n"), 749 MockRead("5\r\nworld\r\n"), 750 MockRead(last_read.data()), 751 MockRead(SYNCHRONOUS, OK), 752 }; 753 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 754 arraysize(data_reads)); 755 EXPECT_EQ(OK, out.rv); 756 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 757 EXPECT_EQ("Hello world", out.response_data); 758 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 759 int64 response_size = reads_size - extra_data.size(); 760 EXPECT_EQ(response_size, out.totalReceivedBytes); 761} 762 763// Next tests deal with http://crbug.com/56344. 764 765TEST_P(HttpNetworkTransactionTest, 766 MultipleContentLengthHeadersNoTransferEncoding) { 767 MockRead data_reads[] = { 768 MockRead("HTTP/1.1 200 OK\r\n"), 769 MockRead("Content-Length: 10\r\n"), 770 MockRead("Content-Length: 5\r\n\r\n"), 771 }; 772 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 773 arraysize(data_reads)); 774 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 775} 776 777TEST_P(HttpNetworkTransactionTest, 778 DuplicateContentLengthHeadersNoTransferEncoding) { 779 MockRead data_reads[] = { 780 MockRead("HTTP/1.1 200 OK\r\n"), 781 MockRead("Content-Length: 5\r\n"), 782 MockRead("Content-Length: 5\r\n\r\n"), 783 MockRead("Hello"), 784 }; 785 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 786 arraysize(data_reads)); 787 EXPECT_EQ(OK, out.rv); 788 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 789 EXPECT_EQ("Hello", out.response_data); 790} 791 792TEST_P(HttpNetworkTransactionTest, 793 ComplexContentLengthHeadersNoTransferEncoding) { 794 // More than 2 dupes. 795 { 796 MockRead data_reads[] = { 797 MockRead("HTTP/1.1 200 OK\r\n"), 798 MockRead("Content-Length: 5\r\n"), 799 MockRead("Content-Length: 5\r\n"), 800 MockRead("Content-Length: 5\r\n\r\n"), 801 MockRead("Hello"), 802 }; 803 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 804 arraysize(data_reads)); 805 EXPECT_EQ(OK, out.rv); 806 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 807 EXPECT_EQ("Hello", out.response_data); 808 } 809 // HTTP/1.0 810 { 811 MockRead data_reads[] = { 812 MockRead("HTTP/1.0 200 OK\r\n"), 813 MockRead("Content-Length: 5\r\n"), 814 MockRead("Content-Length: 5\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.0 200 OK", out.status_line); 822 EXPECT_EQ("Hello", out.response_data); 823 } 824 // 2 dupes and one mismatched. 825 { 826 MockRead data_reads[] = { 827 MockRead("HTTP/1.1 200 OK\r\n"), 828 MockRead("Content-Length: 10\r\n"), 829 MockRead("Content-Length: 10\r\n"), 830 MockRead("Content-Length: 5\r\n\r\n"), 831 }; 832 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 833 arraysize(data_reads)); 834 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 835 } 836} 837 838TEST_P(HttpNetworkTransactionTest, 839 MultipleContentLengthHeadersTransferEncoding) { 840 MockRead data_reads[] = { 841 MockRead("HTTP/1.1 200 OK\r\n"), 842 MockRead("Content-Length: 666\r\n"), 843 MockRead("Content-Length: 1337\r\n"), 844 MockRead("Transfer-Encoding: chunked\r\n\r\n"), 845 MockRead("5\r\nHello\r\n"), 846 MockRead("1\r\n"), 847 MockRead(" \r\n"), 848 MockRead("5\r\nworld\r\n"), 849 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), 850 MockRead(SYNCHRONOUS, OK), 851 }; 852 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 853 arraysize(data_reads)); 854 EXPECT_EQ(OK, out.rv); 855 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 856 EXPECT_EQ("Hello world", out.response_data); 857} 858 859// Next tests deal with http://crbug.com/98895. 860 861// Checks that a single Content-Disposition header results in no error. 862TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) { 863 MockRead data_reads[] = { 864 MockRead("HTTP/1.1 200 OK\r\n"), 865 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"), 866 MockRead("Content-Length: 5\r\n\r\n"), 867 MockRead("Hello"), 868 }; 869 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 870 arraysize(data_reads)); 871 EXPECT_EQ(OK, out.rv); 872 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 873 EXPECT_EQ("Hello", out.response_data); 874} 875 876// Checks that two identical Content-Disposition headers result in no error. 877TEST_P(HttpNetworkTransactionTest, 878 TwoIdenticalContentDispositionHeaders) { 879 MockRead data_reads[] = { 880 MockRead("HTTP/1.1 200 OK\r\n"), 881 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 882 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 883 MockRead("Content-Length: 5\r\n\r\n"), 884 MockRead("Hello"), 885 }; 886 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 887 arraysize(data_reads)); 888 EXPECT_EQ(OK, out.rv); 889 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 890 EXPECT_EQ("Hello", out.response_data); 891} 892 893// Checks that two distinct Content-Disposition headers result in an error. 894TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) { 895 MockRead data_reads[] = { 896 MockRead("HTTP/1.1 200 OK\r\n"), 897 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 898 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"), 899 MockRead("Content-Length: 5\r\n\r\n"), 900 MockRead("Hello"), 901 }; 902 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 903 arraysize(data_reads)); 904 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv); 905} 906 907// Checks that two identical Location headers result in no error. 908// Also tests Location header behavior. 909TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) { 910 MockRead data_reads[] = { 911 MockRead("HTTP/1.1 302 Redirect\r\n"), 912 MockRead("Location: http://good.com/\r\n"), 913 MockRead("Location: http://good.com/\r\n"), 914 MockRead("Content-Length: 0\r\n\r\n"), 915 MockRead(SYNCHRONOUS, OK), 916 }; 917 918 HttpRequestInfo request; 919 request.method = "GET"; 920 request.url = GURL("http://redirect.com/"); 921 request.load_flags = 0; 922 923 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 924 scoped_ptr<HttpTransaction> trans( 925 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 926 927 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 928 session_deps_.socket_factory->AddSocketDataProvider(&data); 929 930 TestCompletionCallback callback; 931 932 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 933 EXPECT_EQ(ERR_IO_PENDING, rv); 934 935 EXPECT_EQ(OK, callback.WaitForResult()); 936 937 const HttpResponseInfo* response = trans->GetResponseInfo(); 938 ASSERT_TRUE(response != NULL && response->headers.get() != NULL); 939 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine()); 940 std::string url; 941 EXPECT_TRUE(response->headers->IsRedirect(&url)); 942 EXPECT_EQ("http://good.com/", url); 943} 944 945// Checks that two distinct Location headers result in an error. 946TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) { 947 MockRead data_reads[] = { 948 MockRead("HTTP/1.1 302 Redirect\r\n"), 949 MockRead("Location: http://good.com/\r\n"), 950 MockRead("Location: http://evil.com/\r\n"), 951 MockRead("Content-Length: 0\r\n\r\n"), 952 MockRead(SYNCHRONOUS, OK), 953 }; 954 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 955 arraysize(data_reads)); 956 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv); 957} 958 959// Do a request using the HEAD method. Verify that we don't try to read the 960// message body (since HEAD has none). 961TEST_P(HttpNetworkTransactionTest, Head) { 962 HttpRequestInfo request; 963 request.method = "HEAD"; 964 request.url = GURL("http://www.google.com/"); 965 request.load_flags = 0; 966 967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 968 scoped_ptr<HttpTransaction> trans( 969 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 970 971 MockWrite data_writes1[] = { 972 MockWrite("HEAD / HTTP/1.1\r\n" 973 "Host: www.google.com\r\n" 974 "Connection: keep-alive\r\n" 975 "Content-Length: 0\r\n\r\n"), 976 }; 977 MockRead data_reads1[] = { 978 MockRead("HTTP/1.1 404 Not Found\r\n"), 979 MockRead("Server: Blah\r\n"), 980 MockRead("Content-Length: 1234\r\n\r\n"), 981 982 // No response body because the test stops reading here. 983 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 984 }; 985 986 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 987 data_writes1, arraysize(data_writes1)); 988 session_deps_.socket_factory->AddSocketDataProvider(&data1); 989 990 TestCompletionCallback callback1; 991 992 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 993 EXPECT_EQ(ERR_IO_PENDING, rv); 994 995 rv = callback1.WaitForResult(); 996 EXPECT_EQ(OK, rv); 997 998 const HttpResponseInfo* response = trans->GetResponseInfo(); 999 ASSERT_TRUE(response != NULL); 1000 1001 // Check that the headers got parsed. 1002 EXPECT_TRUE(response->headers.get() != NULL); 1003 EXPECT_EQ(1234, response->headers->GetContentLength()); 1004 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine()); 1005 1006 std::string server_header; 1007 void* iter = NULL; 1008 bool has_server_header = response->headers->EnumerateHeader( 1009 &iter, "Server", &server_header); 1010 EXPECT_TRUE(has_server_header); 1011 EXPECT_EQ("Blah", server_header); 1012 1013 // Reading should give EOF right away, since there is no message body 1014 // (despite non-zero content-length). 1015 std::string response_data; 1016 rv = ReadTransaction(trans.get(), &response_data); 1017 EXPECT_EQ(OK, rv); 1018 EXPECT_EQ("", response_data); 1019} 1020 1021TEST_P(HttpNetworkTransactionTest, ReuseConnection) { 1022 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1023 1024 MockRead data_reads[] = { 1025 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1026 MockRead("hello"), 1027 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1028 MockRead("world"), 1029 MockRead(SYNCHRONOUS, OK), 1030 }; 1031 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1032 session_deps_.socket_factory->AddSocketDataProvider(&data); 1033 1034 const char* const kExpectedResponseData[] = { 1035 "hello", "world" 1036 }; 1037 1038 for (int i = 0; i < 2; ++i) { 1039 HttpRequestInfo request; 1040 request.method = "GET"; 1041 request.url = GURL("http://www.google.com/"); 1042 request.load_flags = 0; 1043 1044 scoped_ptr<HttpTransaction> trans( 1045 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1046 1047 TestCompletionCallback callback; 1048 1049 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1050 EXPECT_EQ(ERR_IO_PENDING, rv); 1051 1052 rv = callback.WaitForResult(); 1053 EXPECT_EQ(OK, rv); 1054 1055 const HttpResponseInfo* response = trans->GetResponseInfo(); 1056 ASSERT_TRUE(response != NULL); 1057 1058 EXPECT_TRUE(response->headers.get() != NULL); 1059 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1060 1061 std::string response_data; 1062 rv = ReadTransaction(trans.get(), &response_data); 1063 EXPECT_EQ(OK, rv); 1064 EXPECT_EQ(kExpectedResponseData[i], response_data); 1065 } 1066} 1067 1068TEST_P(HttpNetworkTransactionTest, Ignores100) { 1069 ScopedVector<UploadElementReader> element_readers; 1070 element_readers.push_back(new UploadBytesElementReader("foo", 3)); 1071 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 1072 1073 HttpRequestInfo request; 1074 request.method = "POST"; 1075 request.url = GURL("http://www.foo.com/"); 1076 request.upload_data_stream = &upload_data_stream; 1077 request.load_flags = 0; 1078 1079 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1080 scoped_ptr<HttpTransaction> trans( 1081 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1082 1083 MockRead data_reads[] = { 1084 MockRead("HTTP/1.0 100 Continue\r\n\r\n"), 1085 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 1086 MockRead("hello world"), 1087 MockRead(SYNCHRONOUS, OK), 1088 }; 1089 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1090 session_deps_.socket_factory->AddSocketDataProvider(&data); 1091 1092 TestCompletionCallback callback; 1093 1094 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1095 EXPECT_EQ(ERR_IO_PENDING, rv); 1096 1097 rv = callback.WaitForResult(); 1098 EXPECT_EQ(OK, rv); 1099 1100 const HttpResponseInfo* response = trans->GetResponseInfo(); 1101 ASSERT_TRUE(response != NULL); 1102 1103 EXPECT_TRUE(response->headers.get() != NULL); 1104 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 1105 1106 std::string response_data; 1107 rv = ReadTransaction(trans.get(), &response_data); 1108 EXPECT_EQ(OK, rv); 1109 EXPECT_EQ("hello world", response_data); 1110} 1111 1112// This test is almost the same as Ignores100 above, but the response contains 1113// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is 1114// HTTP/1.1 and the two status headers are read in one read. 1115TEST_P(HttpNetworkTransactionTest, Ignores1xx) { 1116 HttpRequestInfo request; 1117 request.method = "GET"; 1118 request.url = GURL("http://www.foo.com/"); 1119 request.load_flags = 0; 1120 1121 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1122 scoped_ptr<HttpTransaction> trans( 1123 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1124 1125 MockRead data_reads[] = { 1126 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n" 1127 "HTTP/1.1 200 OK\r\n\r\n"), 1128 MockRead("hello world"), 1129 MockRead(SYNCHRONOUS, OK), 1130 }; 1131 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1132 session_deps_.socket_factory->AddSocketDataProvider(&data); 1133 1134 TestCompletionCallback callback; 1135 1136 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1137 EXPECT_EQ(ERR_IO_PENDING, rv); 1138 1139 rv = callback.WaitForResult(); 1140 EXPECT_EQ(OK, rv); 1141 1142 const HttpResponseInfo* response = trans->GetResponseInfo(); 1143 ASSERT_TRUE(response != NULL); 1144 1145 EXPECT_TRUE(response->headers.get() != NULL); 1146 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1147 1148 std::string response_data; 1149 rv = ReadTransaction(trans.get(), &response_data); 1150 EXPECT_EQ(OK, rv); 1151 EXPECT_EQ("hello world", response_data); 1152} 1153 1154TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) { 1155 HttpRequestInfo request; 1156 request.method = "POST"; 1157 request.url = GURL("http://www.foo.com/"); 1158 request.load_flags = 0; 1159 1160 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1161 scoped_ptr<HttpTransaction> trans( 1162 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1163 1164 MockRead data_reads[] = { 1165 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"), 1166 MockRead(ASYNC, 0), 1167 }; 1168 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1169 session_deps_.socket_factory->AddSocketDataProvider(&data); 1170 1171 TestCompletionCallback callback; 1172 1173 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1174 EXPECT_EQ(ERR_IO_PENDING, rv); 1175 1176 rv = callback.WaitForResult(); 1177 EXPECT_EQ(OK, rv); 1178 1179 std::string response_data; 1180 rv = ReadTransaction(trans.get(), &response_data); 1181 EXPECT_EQ(OK, rv); 1182 EXPECT_EQ("", response_data); 1183} 1184 1185TEST_P(HttpNetworkTransactionTest, EmptyResponse) { 1186 HttpRequestInfo request; 1187 request.method = "POST"; 1188 request.url = GURL("http://www.foo.com/"); 1189 request.load_flags = 0; 1190 1191 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1192 scoped_ptr<HttpTransaction> trans( 1193 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1194 1195 1196 MockRead data_reads[] = { 1197 MockRead(ASYNC, 0), 1198 }; 1199 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1200 session_deps_.socket_factory->AddSocketDataProvider(&data); 1201 1202 TestCompletionCallback callback; 1203 1204 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1205 EXPECT_EQ(ERR_IO_PENDING, rv); 1206 1207 rv = callback.WaitForResult(); 1208 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 1209} 1210 1211void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest( 1212 const MockWrite* write_failure, 1213 const MockRead* read_failure) { 1214 HttpRequestInfo request; 1215 request.method = "GET"; 1216 request.url = GURL("http://www.foo.com/"); 1217 request.load_flags = 0; 1218 1219 CapturingNetLog net_log; 1220 session_deps_.net_log = &net_log; 1221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1222 1223 // Written data for successfully sending both requests. 1224 MockWrite data1_writes[] = { 1225 MockWrite("GET / HTTP/1.1\r\n" 1226 "Host: www.foo.com\r\n" 1227 "Connection: keep-alive\r\n\r\n"), 1228 MockWrite("GET / HTTP/1.1\r\n" 1229 "Host: www.foo.com\r\n" 1230 "Connection: keep-alive\r\n\r\n") 1231 }; 1232 1233 // Read results for the first request. 1234 MockRead data1_reads[] = { 1235 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1236 MockRead("hello"), 1237 MockRead(ASYNC, OK), 1238 }; 1239 1240 if (write_failure) { 1241 ASSERT_TRUE(!read_failure); 1242 data1_writes[1] = *write_failure; 1243 } else { 1244 ASSERT_TRUE(read_failure); 1245 data1_reads[2] = *read_failure; 1246 } 1247 1248 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), 1249 data1_writes, arraysize(data1_writes)); 1250 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1251 1252 MockRead data2_reads[] = { 1253 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1254 MockRead("world"), 1255 MockRead(ASYNC, OK), 1256 }; 1257 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 1258 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1259 1260 const char* kExpectedResponseData[] = { 1261 "hello", "world" 1262 }; 1263 1264 uint32 first_socket_log_id = NetLog::Source::kInvalidId; 1265 for (int i = 0; i < 2; ++i) { 1266 TestCompletionCallback callback; 1267 1268 scoped_ptr<HttpTransaction> trans( 1269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1270 1271 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1272 EXPECT_EQ(ERR_IO_PENDING, rv); 1273 1274 rv = callback.WaitForResult(); 1275 EXPECT_EQ(OK, rv); 1276 1277 LoadTimingInfo load_timing_info; 1278 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1279 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 1280 if (i == 0) { 1281 first_socket_log_id = load_timing_info.socket_log_id; 1282 } else { 1283 // The second request should be using a new socket. 1284 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id); 1285 } 1286 1287 const HttpResponseInfo* response = trans->GetResponseInfo(); 1288 ASSERT_TRUE(response != NULL); 1289 1290 EXPECT_TRUE(response->headers.get() != NULL); 1291 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1292 1293 std::string response_data; 1294 rv = ReadTransaction(trans.get(), &response_data); 1295 EXPECT_EQ(OK, rv); 1296 EXPECT_EQ(kExpectedResponseData[i], response_data); 1297 } 1298} 1299 1300TEST_P(HttpNetworkTransactionTest, 1301 KeepAliveConnectionNotConnectedOnWrite) { 1302 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED); 1303 KeepAliveConnectionResendRequestTest(&write_failure, NULL); 1304} 1305 1306TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) { 1307 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET); 1308 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1309} 1310 1311TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) { 1312 MockRead read_failure(SYNCHRONOUS, OK); // EOF 1313 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1314} 1315 1316TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) { 1317 HttpRequestInfo request; 1318 request.method = "GET"; 1319 request.url = GURL("http://www.google.com/"); 1320 request.load_flags = 0; 1321 1322 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1323 scoped_ptr<HttpTransaction> trans( 1324 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1325 1326 MockRead data_reads[] = { 1327 MockRead(ASYNC, ERR_CONNECTION_RESET), 1328 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 1329 MockRead("hello world"), 1330 MockRead(SYNCHRONOUS, OK), 1331 }; 1332 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1333 session_deps_.socket_factory->AddSocketDataProvider(&data); 1334 1335 TestCompletionCallback callback; 1336 1337 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1338 EXPECT_EQ(ERR_IO_PENDING, rv); 1339 1340 rv = callback.WaitForResult(); 1341 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 1342 1343 const HttpResponseInfo* response = trans->GetResponseInfo(); 1344 EXPECT_TRUE(response == NULL); 1345} 1346 1347// What do various browsers do when the server closes a non-keepalive 1348// connection without sending any response header or body? 1349// 1350// IE7: error page 1351// Safari 3.1.2 (Windows): error page 1352// Firefox 3.0.1: blank page 1353// Opera 9.52: after five attempts, blank page 1354// Us with WinHTTP: error page (ERR_INVALID_RESPONSE) 1355// Us: error page (EMPTY_RESPONSE) 1356TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) { 1357 MockRead data_reads[] = { 1358 MockRead(SYNCHRONOUS, OK), // EOF 1359 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 1360 MockRead("hello world"), 1361 MockRead(SYNCHRONOUS, OK), 1362 }; 1363 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 1364 arraysize(data_reads)); 1365 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv); 1366} 1367 1368// Test that network access can be deferred and resumed. 1369TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) { 1370 HttpRequestInfo request; 1371 request.method = "GET"; 1372 request.url = GURL("http://www.google.com/"); 1373 request.load_flags = 0; 1374 1375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1376 scoped_ptr<HttpTransaction> trans( 1377 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1378 1379 // Defer on OnBeforeNetworkStart. 1380 BeforeNetworkStartHandler net_start_handler(true); // defer 1381 trans->SetBeforeNetworkStartCallback( 1382 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart, 1383 base::Unretained(&net_start_handler))); 1384 1385 MockRead data_reads[] = { 1386 MockRead("HTTP/1.0 200 OK\r\n"), 1387 MockRead("Content-Length: 5\r\n\r\n"), 1388 MockRead("hello"), 1389 MockRead(SYNCHRONOUS, 0), 1390 }; 1391 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1392 session_deps_.socket_factory->AddSocketDataProvider(&data); 1393 1394 TestCompletionCallback callback; 1395 1396 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1397 EXPECT_EQ(ERR_IO_PENDING, rv); 1398 base::MessageLoop::current()->RunUntilIdle(); 1399 1400 // Should have deferred for network start. 1401 EXPECT_TRUE(net_start_handler.observed_before_network_start()); 1402 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState()); 1403 EXPECT_TRUE(trans->GetResponseInfo() == NULL); 1404 1405 trans->ResumeNetworkStart(); 1406 rv = callback.WaitForResult(); 1407 EXPECT_EQ(OK, rv); 1408 EXPECT_TRUE(trans->GetResponseInfo() != NULL); 1409 1410 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1411 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1412 if (rv == ERR_IO_PENDING) 1413 rv = callback.WaitForResult(); 1414 EXPECT_EQ(5, rv); 1415 trans.reset(); 1416} 1417 1418// Test that network use can be deferred and canceled. 1419TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) { 1420 HttpRequestInfo request; 1421 request.method = "GET"; 1422 request.url = GURL("http://www.google.com/"); 1423 request.load_flags = 0; 1424 1425 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1426 scoped_ptr<HttpTransaction> trans( 1427 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1428 1429 // Defer on OnBeforeNetworkStart. 1430 BeforeNetworkStartHandler net_start_handler(true); // defer 1431 trans->SetBeforeNetworkStartCallback( 1432 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart, 1433 base::Unretained(&net_start_handler))); 1434 1435 TestCompletionCallback callback; 1436 1437 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1438 EXPECT_EQ(ERR_IO_PENDING, rv); 1439 base::MessageLoop::current()->RunUntilIdle(); 1440 1441 // Should have deferred for network start. 1442 EXPECT_TRUE(net_start_handler.observed_before_network_start()); 1443 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState()); 1444 EXPECT_TRUE(trans->GetResponseInfo() == NULL); 1445} 1446 1447// Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression 1448// tests. There was a bug causing HttpNetworkTransaction to hang in the 1449// destructor in such situations. 1450// See http://crbug.com/154712 and http://crbug.com/156609. 1451TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) { 1452 HttpRequestInfo request; 1453 request.method = "GET"; 1454 request.url = GURL("http://www.google.com/"); 1455 request.load_flags = 0; 1456 1457 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1458 scoped_ptr<HttpTransaction> trans( 1459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1460 1461 MockRead data_reads[] = { 1462 MockRead("HTTP/1.0 200 OK\r\n"), 1463 MockRead("Connection: keep-alive\r\n"), 1464 MockRead("Content-Length: 100\r\n\r\n"), 1465 MockRead("hello"), 1466 MockRead(SYNCHRONOUS, 0), 1467 }; 1468 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1469 session_deps_.socket_factory->AddSocketDataProvider(&data); 1470 1471 TestCompletionCallback callback; 1472 1473 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1474 EXPECT_EQ(ERR_IO_PENDING, rv); 1475 1476 rv = callback.WaitForResult(); 1477 EXPECT_EQ(OK, rv); 1478 1479 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1480 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1481 if (rv == ERR_IO_PENDING) 1482 rv = callback.WaitForResult(); 1483 EXPECT_EQ(5, rv); 1484 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1485 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 1486 1487 trans.reset(); 1488 base::MessageLoop::current()->RunUntilIdle(); 1489 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 1490} 1491 1492TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) { 1493 HttpRequestInfo request; 1494 request.method = "GET"; 1495 request.url = GURL("http://www.google.com/"); 1496 request.load_flags = 0; 1497 1498 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1499 scoped_ptr<HttpTransaction> trans( 1500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1501 1502 MockRead data_reads[] = { 1503 MockRead("HTTP/1.0 200 OK\r\n"), 1504 MockRead("Connection: keep-alive\r\n"), 1505 MockRead("Content-Length: 100\r\n\r\n"), 1506 MockRead(SYNCHRONOUS, 0), 1507 }; 1508 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1509 session_deps_.socket_factory->AddSocketDataProvider(&data); 1510 1511 TestCompletionCallback callback; 1512 1513 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1514 EXPECT_EQ(ERR_IO_PENDING, rv); 1515 1516 rv = callback.WaitForResult(); 1517 EXPECT_EQ(OK, rv); 1518 1519 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1520 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1521 if (rv == ERR_IO_PENDING) 1522 rv = callback.WaitForResult(); 1523 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 1524 1525 trans.reset(); 1526 base::MessageLoop::current()->RunUntilIdle(); 1527 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 1528} 1529 1530// Test that we correctly reuse a keep-alive connection after not explicitly 1531// reading the body. 1532TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { 1533 HttpRequestInfo request; 1534 request.method = "GET"; 1535 request.url = GURL("http://www.foo.com/"); 1536 request.load_flags = 0; 1537 1538 CapturingNetLog net_log; 1539 session_deps_.net_log = &net_log; 1540 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1541 1542 // Note that because all these reads happen in the same 1543 // StaticSocketDataProvider, it shows that the same socket is being reused for 1544 // all transactions. 1545 MockRead data1_reads[] = { 1546 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 1547 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"), 1548 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"), 1549 MockRead("HTTP/1.1 302 Found\r\n" 1550 "Content-Length: 0\r\n\r\n"), 1551 MockRead("HTTP/1.1 302 Found\r\n" 1552 "Content-Length: 5\r\n\r\n" 1553 "hello"), 1554 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 1555 "Content-Length: 0\r\n\r\n"), 1556 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 1557 "Content-Length: 5\r\n\r\n" 1558 "hello"), 1559 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1560 MockRead("hello"), 1561 }; 1562 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0); 1563 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1564 1565 MockRead data2_reads[] = { 1566 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 1567 }; 1568 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 1569 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1570 1571 const int kNumUnreadBodies = arraysize(data1_reads) - 2; 1572 std::string response_lines[kNumUnreadBodies]; 1573 1574 uint32 first_socket_log_id = NetLog::Source::kInvalidId; 1575 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) { 1576 TestCompletionCallback callback; 1577 1578 scoped_ptr<HttpTransaction> trans( 1579 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1580 1581 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1582 EXPECT_EQ(ERR_IO_PENDING, rv); 1583 1584 rv = callback.WaitForResult(); 1585 EXPECT_EQ(OK, rv); 1586 1587 LoadTimingInfo load_timing_info; 1588 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1589 if (i == 0) { 1590 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 1591 first_socket_log_id = load_timing_info.socket_log_id; 1592 } else { 1593 TestLoadTimingReused(load_timing_info); 1594 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id); 1595 } 1596 1597 const HttpResponseInfo* response = trans->GetResponseInfo(); 1598 ASSERT_TRUE(response != NULL); 1599 1600 ASSERT_TRUE(response->headers.get() != NULL); 1601 response_lines[i] = response->headers->GetStatusLine(); 1602 1603 // We intentionally don't read the response bodies. 1604 } 1605 1606 const char* const kStatusLines[] = { 1607 "HTTP/1.1 204 No Content", 1608 "HTTP/1.1 205 Reset Content", 1609 "HTTP/1.1 304 Not Modified", 1610 "HTTP/1.1 302 Found", 1611 "HTTP/1.1 302 Found", 1612 "HTTP/1.1 301 Moved Permanently", 1613 "HTTP/1.1 301 Moved Permanently", 1614 }; 1615 1616 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines), 1617 forgot_to_update_kStatusLines); 1618 1619 for (int i = 0; i < kNumUnreadBodies; ++i) 1620 EXPECT_EQ(kStatusLines[i], response_lines[i]); 1621 1622 TestCompletionCallback callback; 1623 scoped_ptr<HttpTransaction> trans( 1624 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1625 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1626 EXPECT_EQ(ERR_IO_PENDING, rv); 1627 rv = callback.WaitForResult(); 1628 EXPECT_EQ(OK, rv); 1629 const HttpResponseInfo* response = trans->GetResponseInfo(); 1630 ASSERT_TRUE(response != NULL); 1631 ASSERT_TRUE(response->headers.get() != NULL); 1632 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1633 std::string response_data; 1634 rv = ReadTransaction(trans.get(), &response_data); 1635 EXPECT_EQ(OK, rv); 1636 EXPECT_EQ("hello", response_data); 1637} 1638 1639// Test the request-challenge-retry sequence for basic auth. 1640// (basic auth is the easiest to mock, because it has no randomness). 1641TEST_P(HttpNetworkTransactionTest, BasicAuth) { 1642 HttpRequestInfo request; 1643 request.method = "GET"; 1644 request.url = GURL("http://www.google.com/"); 1645 request.load_flags = 0; 1646 1647 CapturingNetLog log; 1648 session_deps_.net_log = &log; 1649 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1650 scoped_ptr<HttpTransaction> trans( 1651 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1652 1653 MockWrite data_writes1[] = { 1654 MockWrite("GET / HTTP/1.1\r\n" 1655 "Host: www.google.com\r\n" 1656 "Connection: keep-alive\r\n\r\n"), 1657 }; 1658 1659 MockRead data_reads1[] = { 1660 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1661 // Give a couple authenticate options (only the middle one is actually 1662 // supported). 1663 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed. 1664 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1665 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 1666 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1667 // Large content-length -- won't matter, as connection will be reset. 1668 MockRead("Content-Length: 10000\r\n\r\n"), 1669 MockRead(SYNCHRONOUS, ERR_FAILED), 1670 }; 1671 1672 // After calling trans->RestartWithAuth(), this is the request we should 1673 // be issuing -- the final header line contains the credentials. 1674 MockWrite data_writes2[] = { 1675 MockWrite("GET / HTTP/1.1\r\n" 1676 "Host: www.google.com\r\n" 1677 "Connection: keep-alive\r\n" 1678 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1679 }; 1680 1681 // Lastly, the server responds with the actual content. 1682 MockRead data_reads2[] = { 1683 MockRead("HTTP/1.0 200 OK\r\n"), 1684 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1685 MockRead("Content-Length: 100\r\n\r\n"), 1686 MockRead(SYNCHRONOUS, OK), 1687 }; 1688 1689 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1690 data_writes1, arraysize(data_writes1)); 1691 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1692 data_writes2, arraysize(data_writes2)); 1693 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1694 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1695 1696 TestCompletionCallback callback1; 1697 1698 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1699 EXPECT_EQ(ERR_IO_PENDING, rv); 1700 1701 rv = callback1.WaitForResult(); 1702 EXPECT_EQ(OK, rv); 1703 1704 LoadTimingInfo load_timing_info1; 1705 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); 1706 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); 1707 1708 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1)); 1709 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); 1710 1711 const HttpResponseInfo* response = trans->GetResponseInfo(); 1712 ASSERT_TRUE(response != NULL); 1713 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1714 1715 TestCompletionCallback callback2; 1716 1717 rv = trans->RestartWithAuth( 1718 AuthCredentials(kFoo, kBar), callback2.callback()); 1719 EXPECT_EQ(ERR_IO_PENDING, rv); 1720 1721 rv = callback2.WaitForResult(); 1722 EXPECT_EQ(OK, rv); 1723 1724 LoadTimingInfo load_timing_info2; 1725 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); 1726 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES); 1727 // The load timing after restart should have a new socket ID, and times after 1728 // those of the first load timing. 1729 EXPECT_LE(load_timing_info1.receive_headers_end, 1730 load_timing_info2.connect_timing.connect_start); 1731 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 1732 1733 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2)); 1734 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes()); 1735 1736 response = trans->GetResponseInfo(); 1737 ASSERT_TRUE(response != NULL); 1738 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1739 EXPECT_EQ(100, response->headers->GetContentLength()); 1740} 1741 1742TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { 1743 HttpRequestInfo request; 1744 request.method = "GET"; 1745 request.url = GURL("http://www.google.com/"); 1746 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1747 1748 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1749 scoped_ptr<HttpTransaction> trans( 1750 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1751 1752 MockWrite data_writes[] = { 1753 MockWrite("GET / HTTP/1.1\r\n" 1754 "Host: www.google.com\r\n" 1755 "Connection: keep-alive\r\n\r\n"), 1756 }; 1757 1758 MockRead data_reads[] = { 1759 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1760 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1761 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1762 // Large content-length -- won't matter, as connection will be reset. 1763 MockRead("Content-Length: 10000\r\n\r\n"), 1764 MockRead(SYNCHRONOUS, ERR_FAILED), 1765 }; 1766 1767 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 1768 data_writes, arraysize(data_writes)); 1769 session_deps_.socket_factory->AddSocketDataProvider(&data); 1770 TestCompletionCallback callback; 1771 1772 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1773 EXPECT_EQ(ERR_IO_PENDING, rv); 1774 1775 rv = callback.WaitForResult(); 1776 EXPECT_EQ(0, rv); 1777 1778 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 1779 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes()); 1780 1781 const HttpResponseInfo* response = trans->GetResponseInfo(); 1782 ASSERT_TRUE(response != NULL); 1783 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1784} 1785 1786// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1787// connection. 1788TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) { 1789 HttpRequestInfo request; 1790 request.method = "GET"; 1791 request.url = GURL("http://www.google.com/"); 1792 request.load_flags = 0; 1793 1794 CapturingNetLog log; 1795 session_deps_.net_log = &log; 1796 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1797 1798 MockWrite data_writes1[] = { 1799 MockWrite("GET / HTTP/1.1\r\n" 1800 "Host: www.google.com\r\n" 1801 "Connection: keep-alive\r\n\r\n"), 1802 1803 // After calling trans->RestartWithAuth(), this is the request we should 1804 // be issuing -- the final header line contains the credentials. 1805 MockWrite("GET / HTTP/1.1\r\n" 1806 "Host: www.google.com\r\n" 1807 "Connection: keep-alive\r\n" 1808 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1809 }; 1810 1811 MockRead data_reads1[] = { 1812 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1813 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1814 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1815 MockRead("Content-Length: 14\r\n\r\n"), 1816 MockRead("Unauthorized\r\n"), 1817 1818 // Lastly, the server responds with the actual content. 1819 MockRead("HTTP/1.1 200 OK\r\n"), 1820 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1821 MockRead("Content-Length: 5\r\n\r\n"), 1822 MockRead("Hello"), 1823 }; 1824 1825 // If there is a regression where we disconnect a Keep-Alive 1826 // connection during an auth roundtrip, we'll end up reading this. 1827 MockRead data_reads2[] = { 1828 MockRead(SYNCHRONOUS, ERR_FAILED), 1829 }; 1830 1831 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1832 data_writes1, arraysize(data_writes1)); 1833 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1834 NULL, 0); 1835 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1836 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1837 1838 TestCompletionCallback callback1; 1839 1840 scoped_ptr<HttpTransaction> trans( 1841 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1842 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1843 EXPECT_EQ(ERR_IO_PENDING, rv); 1844 1845 rv = callback1.WaitForResult(); 1846 EXPECT_EQ(OK, rv); 1847 1848 LoadTimingInfo load_timing_info1; 1849 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); 1850 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); 1851 1852 const HttpResponseInfo* response = trans->GetResponseInfo(); 1853 ASSERT_TRUE(response != NULL); 1854 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1855 1856 TestCompletionCallback callback2; 1857 1858 rv = trans->RestartWithAuth( 1859 AuthCredentials(kFoo, kBar), callback2.callback()); 1860 EXPECT_EQ(ERR_IO_PENDING, rv); 1861 1862 rv = callback2.WaitForResult(); 1863 EXPECT_EQ(OK, rv); 1864 1865 LoadTimingInfo load_timing_info2; 1866 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); 1867 TestLoadTimingReused(load_timing_info2); 1868 // The load timing after restart should have the same socket ID, and times 1869 // those of the first load timing. 1870 EXPECT_LE(load_timing_info1.receive_headers_end, 1871 load_timing_info2.send_start); 1872 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 1873 1874 response = trans->GetResponseInfo(); 1875 ASSERT_TRUE(response != NULL); 1876 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1877 EXPECT_EQ(5, response->headers->GetContentLength()); 1878 1879 std::string response_data; 1880 rv = ReadTransaction(trans.get(), &response_data); 1881 EXPECT_EQ(OK, rv); 1882 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1)); 1883 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); 1884} 1885 1886// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1887// connection and with no response body to drain. 1888TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) { 1889 HttpRequestInfo request; 1890 request.method = "GET"; 1891 request.url = GURL("http://www.google.com/"); 1892 request.load_flags = 0; 1893 1894 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1895 1896 MockWrite data_writes1[] = { 1897 MockWrite("GET / HTTP/1.1\r\n" 1898 "Host: www.google.com\r\n" 1899 "Connection: keep-alive\r\n\r\n"), 1900 1901 // After calling trans->RestartWithAuth(), this is the request we should 1902 // be issuing -- the final header line contains the credentials. 1903 MockWrite("GET / HTTP/1.1\r\n" 1904 "Host: www.google.com\r\n" 1905 "Connection: keep-alive\r\n" 1906 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1907 }; 1908 1909 MockRead data_reads1[] = { 1910 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1911 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1912 MockRead("Content-Length: 0\r\n\r\n"), // No response body. 1913 1914 // Lastly, the server responds with the actual content. 1915 MockRead("HTTP/1.1 200 OK\r\n"), 1916 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1917 MockRead("Content-Length: 5\r\n\r\n"), 1918 MockRead("hello"), 1919 }; 1920 1921 // An incorrect reconnect would cause this to be read. 1922 MockRead data_reads2[] = { 1923 MockRead(SYNCHRONOUS, ERR_FAILED), 1924 }; 1925 1926 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1927 data_writes1, arraysize(data_writes1)); 1928 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1929 NULL, 0); 1930 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1931 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1932 1933 TestCompletionCallback callback1; 1934 1935 scoped_ptr<HttpTransaction> trans( 1936 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1937 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1938 EXPECT_EQ(ERR_IO_PENDING, rv); 1939 1940 rv = callback1.WaitForResult(); 1941 EXPECT_EQ(OK, rv); 1942 1943 const HttpResponseInfo* response = trans->GetResponseInfo(); 1944 ASSERT_TRUE(response != NULL); 1945 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1946 1947 TestCompletionCallback callback2; 1948 1949 rv = trans->RestartWithAuth( 1950 AuthCredentials(kFoo, kBar), callback2.callback()); 1951 EXPECT_EQ(ERR_IO_PENDING, rv); 1952 1953 rv = callback2.WaitForResult(); 1954 EXPECT_EQ(OK, rv); 1955 1956 response = trans->GetResponseInfo(); 1957 ASSERT_TRUE(response != NULL); 1958 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1959 EXPECT_EQ(5, response->headers->GetContentLength()); 1960} 1961 1962// Test the request-challenge-retry sequence for basic auth, over a keep-alive 1963// connection and with a large response body to drain. 1964TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) { 1965 HttpRequestInfo request; 1966 request.method = "GET"; 1967 request.url = GURL("http://www.google.com/"); 1968 request.load_flags = 0; 1969 1970 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1971 1972 MockWrite data_writes1[] = { 1973 MockWrite("GET / HTTP/1.1\r\n" 1974 "Host: www.google.com\r\n" 1975 "Connection: keep-alive\r\n\r\n"), 1976 1977 // After calling trans->RestartWithAuth(), this is the request we should 1978 // be issuing -- the final header line contains the credentials. 1979 MockWrite("GET / HTTP/1.1\r\n" 1980 "Host: www.google.com\r\n" 1981 "Connection: keep-alive\r\n" 1982 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1983 }; 1984 1985 // Respond with 5 kb of response body. 1986 std::string large_body_string("Unauthorized"); 1987 large_body_string.append(5 * 1024, ' '); 1988 large_body_string.append("\r\n"); 1989 1990 MockRead data_reads1[] = { 1991 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 1992 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1993 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1994 // 5134 = 12 + 5 * 1024 + 2 1995 MockRead("Content-Length: 5134\r\n\r\n"), 1996 MockRead(ASYNC, large_body_string.data(), large_body_string.size()), 1997 1998 // Lastly, the server responds with the actual content. 1999 MockRead("HTTP/1.1 200 OK\r\n"), 2000 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2001 MockRead("Content-Length: 5\r\n\r\n"), 2002 MockRead("hello"), 2003 }; 2004 2005 // An incorrect reconnect would cause this to be read. 2006 MockRead data_reads2[] = { 2007 MockRead(SYNCHRONOUS, ERR_FAILED), 2008 }; 2009 2010 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2011 data_writes1, arraysize(data_writes1)); 2012 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2013 NULL, 0); 2014 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2015 session_deps_.socket_factory->AddSocketDataProvider(&data2); 2016 2017 TestCompletionCallback callback1; 2018 2019 scoped_ptr<HttpTransaction> trans( 2020 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2021 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 2022 EXPECT_EQ(ERR_IO_PENDING, rv); 2023 2024 rv = callback1.WaitForResult(); 2025 EXPECT_EQ(OK, rv); 2026 2027 const HttpResponseInfo* response = trans->GetResponseInfo(); 2028 ASSERT_TRUE(response != NULL); 2029 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 2030 2031 TestCompletionCallback callback2; 2032 2033 rv = trans->RestartWithAuth( 2034 AuthCredentials(kFoo, kBar), callback2.callback()); 2035 EXPECT_EQ(ERR_IO_PENDING, rv); 2036 2037 rv = callback2.WaitForResult(); 2038 EXPECT_EQ(OK, rv); 2039 2040 response = trans->GetResponseInfo(); 2041 ASSERT_TRUE(response != NULL); 2042 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2043 EXPECT_EQ(5, response->headers->GetContentLength()); 2044} 2045 2046// Test the request-challenge-retry sequence for basic auth, over a keep-alive 2047// connection, but the server gets impatient and closes the connection. 2048TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) { 2049 HttpRequestInfo request; 2050 request.method = "GET"; 2051 request.url = GURL("http://www.google.com/"); 2052 request.load_flags = 0; 2053 2054 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2055 2056 MockWrite data_writes1[] = { 2057 MockWrite("GET / HTTP/1.1\r\n" 2058 "Host: www.google.com\r\n" 2059 "Connection: keep-alive\r\n\r\n"), 2060 // This simulates the seemingly successful write to a closed connection 2061 // if the bug is not fixed. 2062 MockWrite("GET / HTTP/1.1\r\n" 2063 "Host: www.google.com\r\n" 2064 "Connection: keep-alive\r\n" 2065 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2066 }; 2067 2068 MockRead data_reads1[] = { 2069 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 2070 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2071 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2072 MockRead("Content-Length: 14\r\n\r\n"), 2073 // Tell MockTCPClientSocket to simulate the server closing the connection. 2074 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 2075 MockRead("Unauthorized\r\n"), 2076 MockRead(SYNCHRONOUS, OK), // The server closes the connection. 2077 }; 2078 2079 // After calling trans->RestartWithAuth(), this is the request we should 2080 // be issuing -- the final header line contains the credentials. 2081 MockWrite data_writes2[] = { 2082 MockWrite("GET / HTTP/1.1\r\n" 2083 "Host: www.google.com\r\n" 2084 "Connection: keep-alive\r\n" 2085 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2086 }; 2087 2088 // Lastly, the server responds with the actual content. 2089 MockRead data_reads2[] = { 2090 MockRead("HTTP/1.1 200 OK\r\n"), 2091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2092 MockRead("Content-Length: 5\r\n\r\n"), 2093 MockRead("hello"), 2094 }; 2095 2096 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2097 data_writes1, arraysize(data_writes1)); 2098 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2099 data_writes2, arraysize(data_writes2)); 2100 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2101 session_deps_.socket_factory->AddSocketDataProvider(&data2); 2102 2103 TestCompletionCallback callback1; 2104 2105 scoped_ptr<HttpTransaction> trans( 2106 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2107 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 2108 EXPECT_EQ(ERR_IO_PENDING, rv); 2109 2110 rv = callback1.WaitForResult(); 2111 EXPECT_EQ(OK, rv); 2112 2113 const HttpResponseInfo* response = trans->GetResponseInfo(); 2114 ASSERT_TRUE(response != NULL); 2115 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 2116 2117 TestCompletionCallback callback2; 2118 2119 rv = trans->RestartWithAuth( 2120 AuthCredentials(kFoo, kBar), callback2.callback()); 2121 EXPECT_EQ(ERR_IO_PENDING, rv); 2122 2123 rv = callback2.WaitForResult(); 2124 EXPECT_EQ(OK, rv); 2125 2126 response = trans->GetResponseInfo(); 2127 ASSERT_TRUE(response != NULL); 2128 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2129 EXPECT_EQ(5, response->headers->GetContentLength()); 2130} 2131 2132// Test the request-challenge-retry sequence for basic auth, over a connection 2133// that requires a restart when setting up an SSL tunnel. 2134TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { 2135 HttpRequestInfo request; 2136 request.method = "GET"; 2137 request.url = GURL("https://www.google.com/"); 2138 // when the no authentication data flag is set. 2139 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 2140 2141 // Configure against proxy server "myproxy:70". 2142 session_deps_.proxy_service.reset( 2143 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 2144 CapturingBoundNetLog log; 2145 session_deps_.net_log = log.bound().net_log(); 2146 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2147 2148 // Since we have proxy, should try to establish tunnel. 2149 MockWrite data_writes1[] = { 2150 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2151 "Host: www.google.com\r\n" 2152 "Proxy-Connection: keep-alive\r\n\r\n"), 2153 2154 // After calling trans->RestartWithAuth(), this is the request we should 2155 // be issuing -- the final header line contains the credentials. 2156 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2157 "Host: www.google.com\r\n" 2158 "Proxy-Connection: keep-alive\r\n" 2159 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2160 2161 MockWrite("GET / HTTP/1.1\r\n" 2162 "Host: www.google.com\r\n" 2163 "Connection: keep-alive\r\n\r\n"), 2164 }; 2165 2166 // The proxy responds to the connect with a 407, using a persistent 2167 // connection. 2168 MockRead data_reads1[] = { 2169 // No credentials. 2170 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2171 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2172 MockRead("Proxy-Connection: close\r\n\r\n"), 2173 2174 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2175 2176 MockRead("HTTP/1.1 200 OK\r\n"), 2177 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2178 MockRead("Content-Length: 5\r\n\r\n"), 2179 MockRead(SYNCHRONOUS, "hello"), 2180 }; 2181 2182 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2183 data_writes1, arraysize(data_writes1)); 2184 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2185 SSLSocketDataProvider ssl(ASYNC, OK); 2186 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2187 2188 TestCompletionCallback callback1; 2189 2190 scoped_ptr<HttpTransaction> trans( 2191 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2192 2193 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2194 EXPECT_EQ(ERR_IO_PENDING, rv); 2195 2196 rv = callback1.WaitForResult(); 2197 EXPECT_EQ(OK, rv); 2198 net::CapturingNetLog::CapturedEntryList entries; 2199 log.GetEntries(&entries); 2200 size_t pos = ExpectLogContainsSomewhere( 2201 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2202 NetLog::PHASE_NONE); 2203 ExpectLogContainsSomewhere( 2204 entries, pos, 2205 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2206 NetLog::PHASE_NONE); 2207 2208 const HttpResponseInfo* response = trans->GetResponseInfo(); 2209 ASSERT_TRUE(response != NULL); 2210 ASSERT_FALSE(response->headers.get() == NULL); 2211 EXPECT_EQ(407, response->headers->response_code()); 2212 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2213 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2214 2215 LoadTimingInfo load_timing_info; 2216 // CONNECT requests and responses are handled at the connect job level, so 2217 // the transaction does not yet have a connection. 2218 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info)); 2219 2220 TestCompletionCallback callback2; 2221 2222 rv = trans->RestartWithAuth( 2223 AuthCredentials(kFoo, kBar), callback2.callback()); 2224 EXPECT_EQ(ERR_IO_PENDING, rv); 2225 2226 rv = callback2.WaitForResult(); 2227 EXPECT_EQ(OK, rv); 2228 2229 response = trans->GetResponseInfo(); 2230 ASSERT_TRUE(response != NULL); 2231 2232 EXPECT_TRUE(response->headers->IsKeepAlive()); 2233 EXPECT_EQ(200, response->headers->response_code()); 2234 EXPECT_EQ(5, response->headers->GetContentLength()); 2235 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2236 2237 // The password prompt info should not be set. 2238 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2239 2240 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2241 TestLoadTimingNotReusedWithPac(load_timing_info, 2242 CONNECT_TIMING_HAS_SSL_TIMES); 2243 2244 trans.reset(); 2245 session->CloseAllConnections(); 2246} 2247 2248// Test the request-challenge-retry sequence for basic auth, over a keep-alive 2249// proxy connection, when setting up an SSL tunnel. 2250TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { 2251 HttpRequestInfo request; 2252 request.method = "GET"; 2253 request.url = GURL("https://www.google.com/"); 2254 // Ensure that proxy authentication is attempted even 2255 // when the no authentication data flag is set. 2256 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 2257 2258 // Configure against proxy server "myproxy:70". 2259 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2260 CapturingBoundNetLog log; 2261 session_deps_.net_log = log.bound().net_log(); 2262 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2263 2264 scoped_ptr<HttpTransaction> trans( 2265 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2266 2267 // Since we have proxy, should try to establish tunnel. 2268 MockWrite data_writes1[] = { 2269 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2270 "Host: www.google.com\r\n" 2271 "Proxy-Connection: keep-alive\r\n\r\n"), 2272 2273 // After calling trans->RestartWithAuth(), this is the request we should 2274 // be issuing -- the final header line contains the credentials. 2275 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2276 "Host: www.google.com\r\n" 2277 "Proxy-Connection: keep-alive\r\n" 2278 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 2279 }; 2280 2281 // The proxy responds to the connect with a 407, using a persistent 2282 // connection. 2283 MockRead data_reads1[] = { 2284 // No credentials. 2285 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2286 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2287 MockRead("Content-Length: 10\r\n\r\n"), 2288 MockRead("0123456789"), 2289 2290 // Wrong credentials (wrong password). 2291 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2292 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2293 MockRead("Content-Length: 10\r\n\r\n"), 2294 // No response body because the test stops reading here. 2295 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 2296 }; 2297 2298 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2299 data_writes1, arraysize(data_writes1)); 2300 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2301 2302 TestCompletionCallback callback1; 2303 2304 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2305 EXPECT_EQ(ERR_IO_PENDING, rv); 2306 2307 rv = callback1.WaitForResult(); 2308 EXPECT_EQ(OK, rv); 2309 net::CapturingNetLog::CapturedEntryList entries; 2310 log.GetEntries(&entries); 2311 size_t pos = ExpectLogContainsSomewhere( 2312 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2313 NetLog::PHASE_NONE); 2314 ExpectLogContainsSomewhere( 2315 entries, pos, 2316 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2317 NetLog::PHASE_NONE); 2318 2319 const HttpResponseInfo* response = trans->GetResponseInfo(); 2320 ASSERT_TRUE(response != NULL); 2321 ASSERT_FALSE(response->headers.get() == NULL); 2322 EXPECT_TRUE(response->headers->IsKeepAlive()); 2323 EXPECT_EQ(407, response->headers->response_code()); 2324 EXPECT_EQ(10, response->headers->GetContentLength()); 2325 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2326 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2327 2328 TestCompletionCallback callback2; 2329 2330 // Wrong password (should be "bar"). 2331 rv = trans->RestartWithAuth( 2332 AuthCredentials(kFoo, kBaz), callback2.callback()); 2333 EXPECT_EQ(ERR_IO_PENDING, rv); 2334 2335 rv = callback2.WaitForResult(); 2336 EXPECT_EQ(OK, rv); 2337 2338 response = trans->GetResponseInfo(); 2339 ASSERT_TRUE(response != NULL); 2340 ASSERT_FALSE(response->headers.get() == NULL); 2341 EXPECT_TRUE(response->headers->IsKeepAlive()); 2342 EXPECT_EQ(407, response->headers->response_code()); 2343 EXPECT_EQ(10, response->headers->GetContentLength()); 2344 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2345 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2346 2347 // Flush the idle socket before the NetLog and HttpNetworkTransaction go 2348 // out of scope. 2349 session->CloseAllConnections(); 2350} 2351 2352// Test that we don't read the response body when we fail to establish a tunnel, 2353// even if the user cancels the proxy's auth attempt. 2354TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) { 2355 HttpRequestInfo request; 2356 request.method = "GET"; 2357 request.url = GURL("https://www.google.com/"); 2358 request.load_flags = 0; 2359 2360 // Configure against proxy server "myproxy:70". 2361 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2362 2363 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2364 2365 scoped_ptr<HttpTransaction> trans( 2366 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2367 2368 // Since we have proxy, should try to establish tunnel. 2369 MockWrite data_writes[] = { 2370 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2371 "Host: www.google.com\r\n" 2372 "Proxy-Connection: keep-alive\r\n\r\n"), 2373 }; 2374 2375 // The proxy responds to the connect with a 407. 2376 MockRead data_reads[] = { 2377 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2378 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2379 MockRead("Content-Length: 10\r\n\r\n"), 2380 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 2381 }; 2382 2383 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 2384 data_writes, arraysize(data_writes)); 2385 session_deps_.socket_factory->AddSocketDataProvider(&data); 2386 2387 TestCompletionCallback callback; 2388 2389 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 2390 EXPECT_EQ(ERR_IO_PENDING, rv); 2391 2392 rv = callback.WaitForResult(); 2393 EXPECT_EQ(OK, rv); 2394 2395 const HttpResponseInfo* response = trans->GetResponseInfo(); 2396 ASSERT_TRUE(response != NULL); 2397 2398 EXPECT_TRUE(response->headers->IsKeepAlive()); 2399 EXPECT_EQ(407, response->headers->response_code()); 2400 EXPECT_EQ(10, response->headers->GetContentLength()); 2401 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2402 2403 std::string response_data; 2404 rv = ReadTransaction(trans.get(), &response_data); 2405 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 2406 2407 // Flush the idle socket before the HttpNetworkTransaction goes out of scope. 2408 session->CloseAllConnections(); 2409} 2410 2411// Test when a server (non-proxy) returns a 407 (proxy-authenticate). 2412// The request should fail with ERR_UNEXPECTED_PROXY_AUTH. 2413TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) { 2414 HttpRequestInfo request; 2415 request.method = "GET"; 2416 request.url = GURL("http://www.google.com/"); 2417 request.load_flags = 0; 2418 2419 // We are using a DIRECT connection (i.e. no proxy) for this session. 2420 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2421 scoped_ptr<HttpTransaction> trans( 2422 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 2423 2424 MockWrite data_writes1[] = { 2425 MockWrite("GET / HTTP/1.1\r\n" 2426 "Host: www.google.com\r\n" 2427 "Connection: keep-alive\r\n\r\n"), 2428 }; 2429 2430 MockRead data_reads1[] = { 2431 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"), 2432 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2433 // Large content-length -- won't matter, as connection will be reset. 2434 MockRead("Content-Length: 10000\r\n\r\n"), 2435 MockRead(SYNCHRONOUS, ERR_FAILED), 2436 }; 2437 2438 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2439 data_writes1, arraysize(data_writes1)); 2440 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2441 2442 TestCompletionCallback callback; 2443 2444 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 2445 EXPECT_EQ(ERR_IO_PENDING, rv); 2446 2447 rv = callback.WaitForResult(); 2448 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 2449} 2450 2451// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication) 2452// through a non-authenticating proxy. The request should fail with 2453// ERR_UNEXPECTED_PROXY_AUTH. 2454// Note that it is impossible to detect if an HTTP server returns a 407 through 2455// a non-authenticating proxy - there is nothing to indicate whether the 2456// response came from the proxy or the server, so it is treated as if the proxy 2457// issued the challenge. 2458TEST_P(HttpNetworkTransactionTest, 2459 HttpsServerRequestsProxyAuthThroughProxy) { 2460 HttpRequestInfo request; 2461 request.method = "GET"; 2462 request.url = GURL("https://www.google.com/"); 2463 2464 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2465 CapturingBoundNetLog log; 2466 session_deps_.net_log = log.bound().net_log(); 2467 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2468 2469 // Since we have proxy, should try to establish tunnel. 2470 MockWrite data_writes1[] = { 2471 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2472 "Host: www.google.com\r\n" 2473 "Proxy-Connection: keep-alive\r\n\r\n"), 2474 2475 MockWrite("GET / HTTP/1.1\r\n" 2476 "Host: www.google.com\r\n" 2477 "Connection: keep-alive\r\n\r\n"), 2478 }; 2479 2480 MockRead data_reads1[] = { 2481 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2482 2483 MockRead("HTTP/1.1 407 Unauthorized\r\n"), 2484 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2485 MockRead("\r\n"), 2486 MockRead(SYNCHRONOUS, OK), 2487 }; 2488 2489 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2490 data_writes1, arraysize(data_writes1)); 2491 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2492 SSLSocketDataProvider ssl(ASYNC, OK); 2493 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2494 2495 TestCompletionCallback callback1; 2496 2497 scoped_ptr<HttpTransaction> trans( 2498 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2499 2500 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2501 EXPECT_EQ(ERR_IO_PENDING, rv); 2502 2503 rv = callback1.WaitForResult(); 2504 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 2505 net::CapturingNetLog::CapturedEntryList entries; 2506 log.GetEntries(&entries); 2507 size_t pos = ExpectLogContainsSomewhere( 2508 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2509 NetLog::PHASE_NONE); 2510 ExpectLogContainsSomewhere( 2511 entries, pos, 2512 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2513 NetLog::PHASE_NONE); 2514} 2515 2516// Test the load timing for HTTPS requests with an HTTP proxy. 2517TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) { 2518 HttpRequestInfo request1; 2519 request1.method = "GET"; 2520 request1.url = GURL("https://www.google.com/1"); 2521 2522 HttpRequestInfo request2; 2523 request2.method = "GET"; 2524 request2.url = GURL("https://www.google.com/2"); 2525 2526 // Configure against proxy server "myproxy:70". 2527 session_deps_.proxy_service.reset( 2528 ProxyService::CreateFixed("PROXY myproxy:70")); 2529 CapturingBoundNetLog log; 2530 session_deps_.net_log = log.bound().net_log(); 2531 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2532 2533 // Since we have proxy, should try to establish tunnel. 2534 MockWrite data_writes1[] = { 2535 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2536 "Host: www.google.com\r\n" 2537 "Proxy-Connection: keep-alive\r\n\r\n"), 2538 2539 MockWrite("GET /1 HTTP/1.1\r\n" 2540 "Host: www.google.com\r\n" 2541 "Connection: keep-alive\r\n\r\n"), 2542 2543 MockWrite("GET /2 HTTP/1.1\r\n" 2544 "Host: www.google.com\r\n" 2545 "Connection: keep-alive\r\n\r\n"), 2546 }; 2547 2548 // The proxy responds to the connect with a 407, using a persistent 2549 // connection. 2550 MockRead data_reads1[] = { 2551 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2552 2553 MockRead("HTTP/1.1 200 OK\r\n"), 2554 MockRead("Content-Length: 1\r\n\r\n"), 2555 MockRead(SYNCHRONOUS, "1"), 2556 2557 MockRead("HTTP/1.1 200 OK\r\n"), 2558 MockRead("Content-Length: 2\r\n\r\n"), 2559 MockRead(SYNCHRONOUS, "22"), 2560 }; 2561 2562 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2563 data_writes1, arraysize(data_writes1)); 2564 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2565 SSLSocketDataProvider ssl(ASYNC, OK); 2566 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2567 2568 TestCompletionCallback callback1; 2569 scoped_ptr<HttpTransaction> trans1( 2570 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2571 2572 int rv = trans1->Start(&request1, callback1.callback(), log.bound()); 2573 EXPECT_EQ(ERR_IO_PENDING, rv); 2574 2575 rv = callback1.WaitForResult(); 2576 EXPECT_EQ(OK, rv); 2577 2578 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 2579 ASSERT_TRUE(response1 != NULL); 2580 ASSERT_TRUE(response1->headers.get() != NULL); 2581 EXPECT_EQ(1, response1->headers->GetContentLength()); 2582 2583 LoadTimingInfo load_timing_info1; 2584 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1)); 2585 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES); 2586 2587 trans1.reset(); 2588 2589 TestCompletionCallback callback2; 2590 scoped_ptr<HttpTransaction> trans2( 2591 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2592 2593 rv = trans2->Start(&request2, callback2.callback(), log.bound()); 2594 EXPECT_EQ(ERR_IO_PENDING, rv); 2595 2596 rv = callback2.WaitForResult(); 2597 EXPECT_EQ(OK, rv); 2598 2599 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 2600 ASSERT_TRUE(response2 != NULL); 2601 ASSERT_TRUE(response2->headers.get() != NULL); 2602 EXPECT_EQ(2, response2->headers->GetContentLength()); 2603 2604 LoadTimingInfo load_timing_info2; 2605 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 2606 TestLoadTimingReused(load_timing_info2); 2607 2608 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2609 2610 trans2.reset(); 2611 session->CloseAllConnections(); 2612} 2613 2614// Test the load timing for HTTPS requests with an HTTP proxy and a PAC script. 2615TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) { 2616 HttpRequestInfo request1; 2617 request1.method = "GET"; 2618 request1.url = GURL("https://www.google.com/1"); 2619 2620 HttpRequestInfo request2; 2621 request2.method = "GET"; 2622 request2.url = GURL("https://www.google.com/2"); 2623 2624 // Configure against proxy server "myproxy:70". 2625 session_deps_.proxy_service.reset( 2626 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 2627 CapturingBoundNetLog log; 2628 session_deps_.net_log = log.bound().net_log(); 2629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2630 2631 // Since we have proxy, should try to establish tunnel. 2632 MockWrite data_writes1[] = { 2633 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2634 "Host: www.google.com\r\n" 2635 "Proxy-Connection: keep-alive\r\n\r\n"), 2636 2637 MockWrite("GET /1 HTTP/1.1\r\n" 2638 "Host: www.google.com\r\n" 2639 "Connection: keep-alive\r\n\r\n"), 2640 2641 MockWrite("GET /2 HTTP/1.1\r\n" 2642 "Host: www.google.com\r\n" 2643 "Connection: keep-alive\r\n\r\n"), 2644 }; 2645 2646 // The proxy responds to the connect with a 407, using a persistent 2647 // connection. 2648 MockRead data_reads1[] = { 2649 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2650 2651 MockRead("HTTP/1.1 200 OK\r\n"), 2652 MockRead("Content-Length: 1\r\n\r\n"), 2653 MockRead(SYNCHRONOUS, "1"), 2654 2655 MockRead("HTTP/1.1 200 OK\r\n"), 2656 MockRead("Content-Length: 2\r\n\r\n"), 2657 MockRead(SYNCHRONOUS, "22"), 2658 }; 2659 2660 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2661 data_writes1, arraysize(data_writes1)); 2662 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2663 SSLSocketDataProvider ssl(ASYNC, OK); 2664 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2665 2666 TestCompletionCallback callback1; 2667 scoped_ptr<HttpTransaction> trans1( 2668 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2669 2670 int rv = trans1->Start(&request1, callback1.callback(), log.bound()); 2671 EXPECT_EQ(ERR_IO_PENDING, rv); 2672 2673 rv = callback1.WaitForResult(); 2674 EXPECT_EQ(OK, rv); 2675 2676 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 2677 ASSERT_TRUE(response1 != NULL); 2678 ASSERT_TRUE(response1->headers.get() != NULL); 2679 EXPECT_EQ(1, response1->headers->GetContentLength()); 2680 2681 LoadTimingInfo load_timing_info1; 2682 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1)); 2683 TestLoadTimingNotReusedWithPac(load_timing_info1, 2684 CONNECT_TIMING_HAS_SSL_TIMES); 2685 2686 trans1.reset(); 2687 2688 TestCompletionCallback callback2; 2689 scoped_ptr<HttpTransaction> trans2( 2690 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2691 2692 rv = trans2->Start(&request2, callback2.callback(), log.bound()); 2693 EXPECT_EQ(ERR_IO_PENDING, rv); 2694 2695 rv = callback2.WaitForResult(); 2696 EXPECT_EQ(OK, rv); 2697 2698 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 2699 ASSERT_TRUE(response2 != NULL); 2700 ASSERT_TRUE(response2->headers.get() != NULL); 2701 EXPECT_EQ(2, response2->headers->GetContentLength()); 2702 2703 LoadTimingInfo load_timing_info2; 2704 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 2705 TestLoadTimingReusedWithPac(load_timing_info2); 2706 2707 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2708 2709 trans2.reset(); 2710 session->CloseAllConnections(); 2711} 2712 2713// Test a simple get through an HTTPS Proxy. 2714TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) { 2715 HttpRequestInfo request; 2716 request.method = "GET"; 2717 request.url = GURL("http://www.google.com/"); 2718 2719 // Configure against https proxy server "proxy:70". 2720 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2721 "https://proxy:70")); 2722 CapturingBoundNetLog log; 2723 session_deps_.net_log = log.bound().net_log(); 2724 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2725 2726 // Since we have proxy, should use full url 2727 MockWrite data_writes1[] = { 2728 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2729 "Host: www.google.com\r\n" 2730 "Proxy-Connection: keep-alive\r\n\r\n"), 2731 }; 2732 2733 MockRead data_reads1[] = { 2734 MockRead("HTTP/1.1 200 OK\r\n"), 2735 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2736 MockRead("Content-Length: 100\r\n\r\n"), 2737 MockRead(SYNCHRONOUS, OK), 2738 }; 2739 2740 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2741 data_writes1, arraysize(data_writes1)); 2742 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2743 SSLSocketDataProvider ssl(ASYNC, OK); 2744 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2745 2746 TestCompletionCallback callback1; 2747 2748 scoped_ptr<HttpTransaction> trans( 2749 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2750 2751 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2752 EXPECT_EQ(ERR_IO_PENDING, rv); 2753 2754 rv = callback1.WaitForResult(); 2755 EXPECT_EQ(OK, rv); 2756 2757 LoadTimingInfo load_timing_info; 2758 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2759 TestLoadTimingNotReused(load_timing_info, 2760 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 2761 2762 const HttpResponseInfo* response = trans->GetResponseInfo(); 2763 ASSERT_TRUE(response != NULL); 2764 2765 EXPECT_TRUE(response->headers->IsKeepAlive()); 2766 EXPECT_EQ(200, response->headers->response_code()); 2767 EXPECT_EQ(100, response->headers->GetContentLength()); 2768 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2769 2770 // The password prompt info should not be set. 2771 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2772} 2773 2774// Test a SPDY get through an HTTPS Proxy. 2775TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) { 2776 HttpRequestInfo request; 2777 request.method = "GET"; 2778 request.url = GURL("http://www.google.com/"); 2779 request.load_flags = 0; 2780 2781 // Configure against https proxy server "proxy:70". 2782 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2783 "https://proxy:70")); 2784 CapturingBoundNetLog log; 2785 session_deps_.net_log = log.bound().net_log(); 2786 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2787 2788 // fetch http://www.google.com/ via SPDY 2789 scoped_ptr<SpdyFrame> req( 2790 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 2791 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 2792 2793 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2794 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2795 MockRead spdy_reads[] = { 2796 CreateMockRead(*resp), 2797 CreateMockRead(*data), 2798 MockRead(ASYNC, 0, 0), 2799 }; 2800 2801 DelayedSocketData spdy_data( 2802 1, // wait for one write to finish before reading. 2803 spdy_reads, arraysize(spdy_reads), 2804 spdy_writes, arraysize(spdy_writes)); 2805 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 2806 2807 SSLSocketDataProvider ssl(ASYNC, OK); 2808 ssl.SetNextProto(GetParam()); 2809 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2810 2811 TestCompletionCallback callback1; 2812 2813 scoped_ptr<HttpTransaction> trans( 2814 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2815 2816 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2817 EXPECT_EQ(ERR_IO_PENDING, rv); 2818 2819 rv = callback1.WaitForResult(); 2820 EXPECT_EQ(OK, rv); 2821 2822 LoadTimingInfo load_timing_info; 2823 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2824 TestLoadTimingNotReused(load_timing_info, 2825 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 2826 2827 const HttpResponseInfo* response = trans->GetResponseInfo(); 2828 ASSERT_TRUE(response != NULL); 2829 ASSERT_TRUE(response->headers.get() != NULL); 2830 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 2831 2832 std::string response_data; 2833 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 2834 EXPECT_EQ(kUploadData, response_data); 2835} 2836 2837// Test a SPDY get through an HTTPS Proxy. 2838TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) { 2839 HttpRequestInfo request; 2840 request.method = "GET"; 2841 request.url = GURL("http://www.google.com/"); 2842 request.load_flags = 0; 2843 2844 // Configure against https proxy server "myproxy:70". 2845 session_deps_.proxy_service.reset( 2846 ProxyService::CreateFixed("https://myproxy:70")); 2847 CapturingBoundNetLog log; 2848 session_deps_.net_log = log.bound().net_log(); 2849 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2850 2851 // The first request will be a bare GET, the second request will be a 2852 // GET with a Proxy-Authorization header. 2853 scoped_ptr<SpdyFrame> req_get( 2854 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 2855 const char* const kExtraAuthorizationHeaders[] = { 2856 "proxy-authorization", "Basic Zm9vOmJhcg==" 2857 }; 2858 scoped_ptr<SpdyFrame> req_get_authorization( 2859 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 2860 arraysize(kExtraAuthorizationHeaders) / 2, 2861 false, 2862 3, 2863 LOWEST, 2864 false)); 2865 MockWrite spdy_writes[] = { 2866 CreateMockWrite(*req_get, 1), 2867 CreateMockWrite(*req_get_authorization, 4), 2868 }; 2869 2870 // The first response is a 407 proxy authentication challenge, and the second 2871 // response will be a 200 response since the second request includes a valid 2872 // Authorization header. 2873 const char* const kExtraAuthenticationHeaders[] = { 2874 "proxy-authenticate", "Basic realm=\"MyRealm1\"" 2875 }; 2876 scoped_ptr<SpdyFrame> resp_authentication( 2877 spdy_util_.ConstructSpdySynReplyError( 2878 "407 Proxy Authentication Required", 2879 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2, 2880 1)); 2881 scoped_ptr<SpdyFrame> body_authentication( 2882 spdy_util_.ConstructSpdyBodyFrame(1, true)); 2883 scoped_ptr<SpdyFrame> resp_data( 2884 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 2885 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true)); 2886 MockRead spdy_reads[] = { 2887 CreateMockRead(*resp_authentication, 2), 2888 CreateMockRead(*body_authentication, 3), 2889 CreateMockRead(*resp_data, 5), 2890 CreateMockRead(*body_data, 6), 2891 MockRead(ASYNC, 0, 7), 2892 }; 2893 2894 OrderedSocketData data( 2895 spdy_reads, arraysize(spdy_reads), 2896 spdy_writes, arraysize(spdy_writes)); 2897 session_deps_.socket_factory->AddSocketDataProvider(&data); 2898 2899 SSLSocketDataProvider ssl(ASYNC, OK); 2900 ssl.SetNextProto(GetParam()); 2901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2902 2903 TestCompletionCallback callback1; 2904 2905 scoped_ptr<HttpTransaction> trans( 2906 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2907 2908 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2909 EXPECT_EQ(ERR_IO_PENDING, rv); 2910 2911 rv = callback1.WaitForResult(); 2912 EXPECT_EQ(OK, rv); 2913 2914 const HttpResponseInfo* const response = trans->GetResponseInfo(); 2915 2916 ASSERT_TRUE(response != NULL); 2917 ASSERT_TRUE(response->headers.get() != NULL); 2918 EXPECT_EQ(407, response->headers->response_code()); 2919 EXPECT_TRUE(response->was_fetched_via_spdy); 2920 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2921 2922 TestCompletionCallback callback2; 2923 2924 rv = trans->RestartWithAuth( 2925 AuthCredentials(kFoo, kBar), callback2.callback()); 2926 EXPECT_EQ(ERR_IO_PENDING, rv); 2927 2928 rv = callback2.WaitForResult(); 2929 EXPECT_EQ(OK, rv); 2930 2931 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); 2932 2933 ASSERT_TRUE(response_restart != NULL); 2934 ASSERT_TRUE(response_restart->headers.get() != NULL); 2935 EXPECT_EQ(200, response_restart->headers->response_code()); 2936 // The password prompt info should not be set. 2937 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); 2938} 2939 2940// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server. 2941TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) { 2942 HttpRequestInfo request; 2943 request.method = "GET"; 2944 request.url = GURL("https://www.google.com/"); 2945 request.load_flags = 0; 2946 2947 // Configure against https proxy server "proxy:70". 2948 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2949 "https://proxy:70")); 2950 CapturingBoundNetLog log; 2951 session_deps_.net_log = log.bound().net_log(); 2952 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2953 2954 scoped_ptr<HttpTransaction> trans( 2955 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2956 2957 // CONNECT to www.google.com:443 via SPDY 2958 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 2959 LOWEST)); 2960 // fetch https://www.google.com/ via HTTP 2961 2962 const char get[] = "GET / HTTP/1.1\r\n" 2963 "Host: www.google.com\r\n" 2964 "Connection: keep-alive\r\n\r\n"; 2965 scoped_ptr<SpdyFrame> wrapped_get( 2966 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false)); 2967 scoped_ptr<SpdyFrame> conn_resp( 2968 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2969 const char resp[] = "HTTP/1.1 200 OK\r\n" 2970 "Content-Length: 10\r\n\r\n"; 2971 scoped_ptr<SpdyFrame> wrapped_get_resp( 2972 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false)); 2973 scoped_ptr<SpdyFrame> wrapped_body( 2974 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false)); 2975 scoped_ptr<SpdyFrame> window_update( 2976 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size())); 2977 2978 MockWrite spdy_writes[] = { 2979 CreateMockWrite(*connect, 1), 2980 CreateMockWrite(*wrapped_get, 3), 2981 CreateMockWrite(*window_update, 5), 2982 }; 2983 2984 MockRead spdy_reads[] = { 2985 CreateMockRead(*conn_resp, 2, ASYNC), 2986 CreateMockRead(*wrapped_get_resp, 4, ASYNC), 2987 CreateMockRead(*wrapped_body, 6, ASYNC), 2988 CreateMockRead(*wrapped_body, 7, ASYNC), 2989 MockRead(ASYNC, 0, 8), 2990 }; 2991 2992 OrderedSocketData spdy_data( 2993 spdy_reads, arraysize(spdy_reads), 2994 spdy_writes, arraysize(spdy_writes)); 2995 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 2996 2997 SSLSocketDataProvider ssl(ASYNC, OK); 2998 ssl.SetNextProto(GetParam()); 2999 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3000 SSLSocketDataProvider ssl2(ASYNC, OK); 3001 ssl2.was_npn_negotiated = false; 3002 ssl2.protocol_negotiated = kProtoUnknown; 3003 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 3004 3005 TestCompletionCallback callback1; 3006 3007 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3008 EXPECT_EQ(ERR_IO_PENDING, rv); 3009 3010 rv = callback1.WaitForResult(); 3011 EXPECT_EQ(OK, rv); 3012 3013 LoadTimingInfo load_timing_info; 3014 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3015 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3016 3017 const HttpResponseInfo* response = trans->GetResponseInfo(); 3018 ASSERT_TRUE(response != NULL); 3019 ASSERT_TRUE(response->headers.get() != NULL); 3020 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3021 3022 std::string response_data; 3023 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 3024 EXPECT_EQ("1234567890", response_data); 3025} 3026 3027// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server. 3028TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) { 3029 HttpRequestInfo request; 3030 request.method = "GET"; 3031 request.url = GURL("https://www.google.com/"); 3032 request.load_flags = 0; 3033 3034 // Configure against https proxy server "proxy:70". 3035 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3036 "https://proxy:70")); 3037 CapturingBoundNetLog log; 3038 session_deps_.net_log = log.bound().net_log(); 3039 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3040 3041 scoped_ptr<HttpTransaction> trans( 3042 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3043 3044 // CONNECT to www.google.com:443 via SPDY 3045 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3046 LOWEST)); 3047 // fetch https://www.google.com/ via SPDY 3048 const char* const kMyUrl = "https://www.google.com/"; 3049 scoped_ptr<SpdyFrame> get( 3050 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST)); 3051 scoped_ptr<SpdyFrame> wrapped_get( 3052 spdy_util_.ConstructWrappedSpdyFrame(get, 1)); 3053 scoped_ptr<SpdyFrame> conn_resp( 3054 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3055 scoped_ptr<SpdyFrame> get_resp( 3056 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3057 scoped_ptr<SpdyFrame> wrapped_get_resp( 3058 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1)); 3059 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3060 scoped_ptr<SpdyFrame> wrapped_body( 3061 spdy_util_.ConstructWrappedSpdyFrame(body, 1)); 3062 scoped_ptr<SpdyFrame> window_update_get_resp( 3063 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size())); 3064 scoped_ptr<SpdyFrame> window_update_body( 3065 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size())); 3066 3067 MockWrite spdy_writes[] = { 3068 CreateMockWrite(*connect, 1), 3069 CreateMockWrite(*wrapped_get, 3), 3070 CreateMockWrite(*window_update_get_resp, 5), 3071 CreateMockWrite(*window_update_body, 7), 3072 }; 3073 3074 MockRead spdy_reads[] = { 3075 CreateMockRead(*conn_resp, 2, ASYNC), 3076 CreateMockRead(*wrapped_get_resp, 4, ASYNC), 3077 CreateMockRead(*wrapped_body, 6, ASYNC), 3078 MockRead(ASYNC, 0, 8), 3079 }; 3080 3081 OrderedSocketData spdy_data( 3082 spdy_reads, arraysize(spdy_reads), 3083 spdy_writes, arraysize(spdy_writes)); 3084 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3085 3086 SSLSocketDataProvider ssl(ASYNC, OK); 3087 ssl.SetNextProto(GetParam()); 3088 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3089 SSLSocketDataProvider ssl2(ASYNC, OK); 3090 ssl2.SetNextProto(GetParam()); 3091 ssl2.protocol_negotiated = GetParam(); 3092 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 3093 3094 TestCompletionCallback callback1; 3095 3096 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3097 EXPECT_EQ(ERR_IO_PENDING, rv); 3098 3099 rv = callback1.WaitForResult(); 3100 EXPECT_EQ(OK, rv); 3101 3102 LoadTimingInfo load_timing_info; 3103 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3104 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3105 3106 const HttpResponseInfo* response = trans->GetResponseInfo(); 3107 ASSERT_TRUE(response != NULL); 3108 ASSERT_TRUE(response->headers.get() != NULL); 3109 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3110 3111 std::string response_data; 3112 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 3113 EXPECT_EQ(kUploadData, response_data); 3114} 3115 3116// Test a SPDY CONNECT failure through an HTTPS Proxy. 3117TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) { 3118 HttpRequestInfo request; 3119 request.method = "GET"; 3120 request.url = GURL("https://www.google.com/"); 3121 request.load_flags = 0; 3122 3123 // Configure against https proxy server "proxy:70". 3124 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3125 "https://proxy:70")); 3126 CapturingBoundNetLog log; 3127 session_deps_.net_log = log.bound().net_log(); 3128 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3129 3130 scoped_ptr<HttpTransaction> trans( 3131 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3132 3133 // CONNECT to www.google.com:443 via SPDY 3134 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3135 LOWEST)); 3136 scoped_ptr<SpdyFrame> get( 3137 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 3138 3139 MockWrite spdy_writes[] = { 3140 CreateMockWrite(*connect, 1), 3141 CreateMockWrite(*get, 3), 3142 }; 3143 3144 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1)); 3145 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3146 MockRead spdy_reads[] = { 3147 CreateMockRead(*resp, 2, ASYNC), 3148 MockRead(ASYNC, 0, 4), 3149 }; 3150 3151 OrderedSocketData spdy_data( 3152 spdy_reads, arraysize(spdy_reads), 3153 spdy_writes, arraysize(spdy_writes)); 3154 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3155 3156 SSLSocketDataProvider ssl(ASYNC, OK); 3157 ssl.SetNextProto(GetParam()); 3158 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3159 SSLSocketDataProvider ssl2(ASYNC, OK); 3160 ssl2.SetNextProto(GetParam()); 3161 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 3162 3163 TestCompletionCallback callback1; 3164 3165 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3166 EXPECT_EQ(ERR_IO_PENDING, rv); 3167 3168 rv = callback1.WaitForResult(); 3169 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 3170 3171 // TODO(ttuttle): Anything else to check here? 3172} 3173 3174// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY 3175// HTTPS Proxy to different servers. 3176TEST_P(HttpNetworkTransactionTest, 3177 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) { 3178 // Configure against https proxy server "proxy:70". 3179 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3180 "https://proxy:70")); 3181 CapturingBoundNetLog log; 3182 session_deps_.net_log = log.bound().net_log(); 3183 scoped_refptr<HttpNetworkSession> session( 3184 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3185 3186 HttpRequestInfo request1; 3187 request1.method = "GET"; 3188 request1.url = GURL("https://www.google.com/"); 3189 request1.load_flags = 0; 3190 3191 HttpRequestInfo request2; 3192 request2.method = "GET"; 3193 request2.url = GURL("https://news.google.com/"); 3194 request2.load_flags = 0; 3195 3196 // CONNECT to www.google.com:443 via SPDY. 3197 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3198 LOWEST)); 3199 scoped_ptr<SpdyFrame> conn_resp1( 3200 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3201 3202 // Fetch https://www.google.com/ via HTTP. 3203 const char get1[] = "GET / HTTP/1.1\r\n" 3204 "Host: www.google.com\r\n" 3205 "Connection: keep-alive\r\n\r\n"; 3206 scoped_ptr<SpdyFrame> wrapped_get1( 3207 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false)); 3208 const char resp1[] = "HTTP/1.1 200 OK\r\n" 3209 "Content-Length: 1\r\n\r\n"; 3210 scoped_ptr<SpdyFrame> wrapped_get_resp1( 3211 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false)); 3212 scoped_ptr<SpdyFrame> wrapped_body1( 3213 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false)); 3214 scoped_ptr<SpdyFrame> window_update( 3215 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size())); 3216 3217 // CONNECT to news.google.com:443 via SPDY. 3218 const char* const kConnectHeaders2[] = { 3219 spdy_util_.GetMethodKey(), "CONNECT", 3220 spdy_util_.GetPathKey(), "news.google.com:443", 3221 spdy_util_.GetHostKey(), "news.google.com", 3222 spdy_util_.GetVersionKey(), "HTTP/1.1", 3223 }; 3224 scoped_ptr<SpdyFrame> connect2( 3225 spdy_util_.ConstructSpdyControlFrame(NULL, 3226 0, 3227 /*compressed*/ false, 3228 3, 3229 LOWEST, 3230 SYN_STREAM, 3231 CONTROL_FLAG_NONE, 3232 kConnectHeaders2, 3233 arraysize(kConnectHeaders2), 3234 0)); 3235 scoped_ptr<SpdyFrame> conn_resp2( 3236 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3237 3238 // Fetch https://news.google.com/ via HTTP. 3239 const char get2[] = "GET / HTTP/1.1\r\n" 3240 "Host: news.google.com\r\n" 3241 "Connection: keep-alive\r\n\r\n"; 3242 scoped_ptr<SpdyFrame> wrapped_get2( 3243 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false)); 3244 const char resp2[] = "HTTP/1.1 200 OK\r\n" 3245 "Content-Length: 2\r\n\r\n"; 3246 scoped_ptr<SpdyFrame> wrapped_get_resp2( 3247 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false)); 3248 scoped_ptr<SpdyFrame> wrapped_body2( 3249 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false)); 3250 3251 MockWrite spdy_writes[] = { 3252 CreateMockWrite(*connect1, 0), 3253 CreateMockWrite(*wrapped_get1, 2), 3254 CreateMockWrite(*connect2, 5), 3255 CreateMockWrite(*wrapped_get2, 7), 3256 }; 3257 3258 MockRead spdy_reads[] = { 3259 CreateMockRead(*conn_resp1, 1, ASYNC), 3260 CreateMockRead(*wrapped_get_resp1, 3, ASYNC), 3261 CreateMockRead(*wrapped_body1, 4, ASYNC), 3262 CreateMockRead(*conn_resp2, 6, ASYNC), 3263 CreateMockRead(*wrapped_get_resp2, 8, ASYNC), 3264 CreateMockRead(*wrapped_body2, 9, ASYNC), 3265 MockRead(ASYNC, 0, 10), 3266 }; 3267 3268 DeterministicSocketData spdy_data( 3269 spdy_reads, arraysize(spdy_reads), 3270 spdy_writes, arraysize(spdy_writes)); 3271 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3272 3273 SSLSocketDataProvider ssl(ASYNC, OK); 3274 ssl.SetNextProto(GetParam()); 3275 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3276 SSLSocketDataProvider ssl2(ASYNC, OK); 3277 ssl2.was_npn_negotiated = false; 3278 ssl2.protocol_negotiated = kProtoUnknown; 3279 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 3280 SSLSocketDataProvider ssl3(ASYNC, OK); 3281 ssl3.was_npn_negotiated = false; 3282 ssl3.protocol_negotiated = kProtoUnknown; 3283 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3); 3284 3285 TestCompletionCallback callback; 3286 3287 scoped_ptr<HttpTransaction> trans( 3288 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3289 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3290 EXPECT_EQ(ERR_IO_PENDING, rv); 3291 // The first connect and request, each of their responses, and the body. 3292 spdy_data.RunFor(5); 3293 3294 rv = callback.WaitForResult(); 3295 EXPECT_EQ(OK, rv); 3296 3297 LoadTimingInfo load_timing_info; 3298 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3299 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3300 3301 const HttpResponseInfo* response = trans->GetResponseInfo(); 3302 ASSERT_TRUE(response != NULL); 3303 ASSERT_TRUE(response->headers.get() != NULL); 3304 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3305 3306 std::string response_data; 3307 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3308 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); 3309 3310 scoped_ptr<HttpTransaction> trans2( 3311 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3312 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3313 EXPECT_EQ(ERR_IO_PENDING, rv); 3314 3315 // The second connect and request, each of their responses, and the body. 3316 spdy_data.RunFor(5); 3317 rv = callback.WaitForResult(); 3318 EXPECT_EQ(OK, rv); 3319 3320 LoadTimingInfo load_timing_info2; 3321 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3322 // Even though the SPDY connection is reused, a new tunnelled connection has 3323 // to be created, so the socket's load timing looks like a fresh connection. 3324 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES); 3325 3326 // The requests should have different IDs, since they each are using their own 3327 // separate stream. 3328 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3329 3330 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback())); 3331} 3332 3333// Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY 3334// HTTPS Proxy to the same server. 3335TEST_P(HttpNetworkTransactionTest, 3336 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) { 3337 // Configure against https proxy server "proxy:70". 3338 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3339 "https://proxy:70")); 3340 CapturingBoundNetLog log; 3341 session_deps_.net_log = log.bound().net_log(); 3342 scoped_refptr<HttpNetworkSession> session( 3343 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3344 3345 HttpRequestInfo request1; 3346 request1.method = "GET"; 3347 request1.url = GURL("https://www.google.com/"); 3348 request1.load_flags = 0; 3349 3350 HttpRequestInfo request2; 3351 request2.method = "GET"; 3352 request2.url = GURL("https://www.google.com/2"); 3353 request2.load_flags = 0; 3354 3355 // CONNECT to www.google.com:443 via SPDY. 3356 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3357 LOWEST)); 3358 scoped_ptr<SpdyFrame> conn_resp1( 3359 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3360 3361 // Fetch https://www.google.com/ via HTTP. 3362 const char get1[] = "GET / HTTP/1.1\r\n" 3363 "Host: www.google.com\r\n" 3364 "Connection: keep-alive\r\n\r\n"; 3365 scoped_ptr<SpdyFrame> wrapped_get1( 3366 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false)); 3367 const char resp1[] = "HTTP/1.1 200 OK\r\n" 3368 "Content-Length: 1\r\n\r\n"; 3369 scoped_ptr<SpdyFrame> wrapped_get_resp1( 3370 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false)); 3371 scoped_ptr<SpdyFrame> wrapped_body1( 3372 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false)); 3373 scoped_ptr<SpdyFrame> window_update( 3374 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size())); 3375 3376 // Fetch https://www.google.com/2 via HTTP. 3377 const char get2[] = "GET /2 HTTP/1.1\r\n" 3378 "Host: www.google.com\r\n" 3379 "Connection: keep-alive\r\n\r\n"; 3380 scoped_ptr<SpdyFrame> wrapped_get2( 3381 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false)); 3382 const char resp2[] = "HTTP/1.1 200 OK\r\n" 3383 "Content-Length: 2\r\n\r\n"; 3384 scoped_ptr<SpdyFrame> wrapped_get_resp2( 3385 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false)); 3386 scoped_ptr<SpdyFrame> wrapped_body2( 3387 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false)); 3388 3389 MockWrite spdy_writes[] = { 3390 CreateMockWrite(*connect1, 0), 3391 CreateMockWrite(*wrapped_get1, 2), 3392 CreateMockWrite(*wrapped_get2, 5), 3393 }; 3394 3395 MockRead spdy_reads[] = { 3396 CreateMockRead(*conn_resp1, 1, ASYNC), 3397 CreateMockRead(*wrapped_get_resp1, 3, ASYNC), 3398 CreateMockRead(*wrapped_body1, 4, ASYNC), 3399 CreateMockRead(*wrapped_get_resp2, 6, ASYNC), 3400 CreateMockRead(*wrapped_body2, 7, ASYNC), 3401 MockRead(ASYNC, 0, 8), 3402 }; 3403 3404 DeterministicSocketData spdy_data( 3405 spdy_reads, arraysize(spdy_reads), 3406 spdy_writes, arraysize(spdy_writes)); 3407 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3408 3409 SSLSocketDataProvider ssl(ASYNC, OK); 3410 ssl.SetNextProto(GetParam()); 3411 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3412 SSLSocketDataProvider ssl2(ASYNC, OK); 3413 ssl2.was_npn_negotiated = false; 3414 ssl2.protocol_negotiated = kProtoUnknown; 3415 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 3416 3417 TestCompletionCallback callback; 3418 3419 scoped_ptr<HttpTransaction> trans( 3420 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3421 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3422 EXPECT_EQ(ERR_IO_PENDING, rv); 3423 // The first connect and request, each of their responses, and the body. 3424 spdy_data.RunFor(5); 3425 3426 rv = callback.WaitForResult(); 3427 EXPECT_EQ(OK, rv); 3428 3429 LoadTimingInfo load_timing_info; 3430 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3431 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3432 3433 const HttpResponseInfo* response = trans->GetResponseInfo(); 3434 ASSERT_TRUE(response != NULL); 3435 ASSERT_TRUE(response->headers.get() != NULL); 3436 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3437 3438 std::string response_data; 3439 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3440 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); 3441 trans.reset(); 3442 3443 scoped_ptr<HttpTransaction> trans2( 3444 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3445 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3446 EXPECT_EQ(ERR_IO_PENDING, rv); 3447 3448 // The second request, response, and body. There should not be a second 3449 // connect. 3450 spdy_data.RunFor(3); 3451 rv = callback.WaitForResult(); 3452 EXPECT_EQ(OK, rv); 3453 3454 LoadTimingInfo load_timing_info2; 3455 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3456 TestLoadTimingReused(load_timing_info2); 3457 3458 // The requests should have the same ID. 3459 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3460 3461 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback())); 3462} 3463 3464// Test load timing in the case of of two HTTP requests through a SPDY HTTPS 3465// Proxy to different servers. 3466TEST_P(HttpNetworkTransactionTest, 3467 HttpsProxySpdyLoadTimingTwoHttpRequests) { 3468 // Configure against https proxy server "proxy:70". 3469 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3470 "https://proxy:70")); 3471 CapturingBoundNetLog log; 3472 session_deps_.net_log = log.bound().net_log(); 3473 scoped_refptr<HttpNetworkSession> session( 3474 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3475 3476 HttpRequestInfo request1; 3477 request1.method = "GET"; 3478 request1.url = GURL("http://www.google.com/"); 3479 request1.load_flags = 0; 3480 3481 HttpRequestInfo request2; 3482 request2.method = "GET"; 3483 request2.url = GURL("http://news.google.com/"); 3484 request2.load_flags = 0; 3485 3486 // http://www.google.com/ 3487 scoped_ptr<SpdyHeaderBlock> headers( 3488 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/")); 3489 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame( 3490 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 3491 scoped_ptr<SpdyFrame> get_resp1( 3492 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3493 scoped_ptr<SpdyFrame> body1( 3494 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true)); 3495 3496 // http://news.google.com/ 3497 scoped_ptr<SpdyHeaderBlock> headers2( 3498 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/")); 3499 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame( 3500 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 3501 scoped_ptr<SpdyFrame> get_resp2( 3502 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3503 scoped_ptr<SpdyFrame> body2( 3504 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true)); 3505 3506 MockWrite spdy_writes[] = { 3507 CreateMockWrite(*get1, 0), 3508 CreateMockWrite(*get2, 3), 3509 }; 3510 3511 MockRead spdy_reads[] = { 3512 CreateMockRead(*get_resp1, 1, ASYNC), 3513 CreateMockRead(*body1, 2, ASYNC), 3514 CreateMockRead(*get_resp2, 4, ASYNC), 3515 CreateMockRead(*body2, 5, ASYNC), 3516 MockRead(ASYNC, 0, 6), 3517 }; 3518 3519 DeterministicSocketData spdy_data( 3520 spdy_reads, arraysize(spdy_reads), 3521 spdy_writes, arraysize(spdy_writes)); 3522 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3523 3524 SSLSocketDataProvider ssl(ASYNC, OK); 3525 ssl.SetNextProto(GetParam()); 3526 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3527 3528 TestCompletionCallback callback; 3529 3530 scoped_ptr<HttpTransaction> trans( 3531 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3532 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3533 EXPECT_EQ(ERR_IO_PENDING, rv); 3534 spdy_data.RunFor(2); 3535 3536 rv = callback.WaitForResult(); 3537 EXPECT_EQ(OK, rv); 3538 3539 LoadTimingInfo load_timing_info; 3540 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3541 TestLoadTimingNotReused(load_timing_info, 3542 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3543 3544 const HttpResponseInfo* response = trans->GetResponseInfo(); 3545 ASSERT_TRUE(response != NULL); 3546 ASSERT_TRUE(response->headers.get() != NULL); 3547 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3548 3549 std::string response_data; 3550 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3551 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback())); 3552 spdy_data.RunFor(1); 3553 EXPECT_EQ(1, callback.WaitForResult()); 3554 // Delete the first request, so the second one can reuse the socket. 3555 trans.reset(); 3556 3557 scoped_ptr<HttpTransaction> trans2( 3558 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3559 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3560 EXPECT_EQ(ERR_IO_PENDING, rv); 3561 3562 spdy_data.RunFor(2); 3563 rv = callback.WaitForResult(); 3564 EXPECT_EQ(OK, rv); 3565 3566 LoadTimingInfo load_timing_info2; 3567 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3568 TestLoadTimingReused(load_timing_info2); 3569 3570 // The requests should have the same ID. 3571 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3572 3573 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback())); 3574 spdy_data.RunFor(1); 3575 EXPECT_EQ(2, callback.WaitForResult()); 3576} 3577 3578// Test the challenge-response-retry sequence through an HTTPS Proxy 3579TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) { 3580 HttpRequestInfo request; 3581 request.method = "GET"; 3582 request.url = GURL("http://www.google.com/"); 3583 // when the no authentication data flag is set. 3584 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 3585 3586 // Configure against https proxy server "myproxy:70". 3587 session_deps_.proxy_service.reset( 3588 ProxyService::CreateFixed("https://myproxy:70")); 3589 CapturingBoundNetLog log; 3590 session_deps_.net_log = log.bound().net_log(); 3591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3592 3593 // Since we have proxy, should use full url 3594 MockWrite data_writes1[] = { 3595 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3596 "Host: www.google.com\r\n" 3597 "Proxy-Connection: keep-alive\r\n\r\n"), 3598 3599 // After calling trans->RestartWithAuth(), this is the request we should 3600 // be issuing -- the final header line contains the credentials. 3601 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3602 "Host: www.google.com\r\n" 3603 "Proxy-Connection: keep-alive\r\n" 3604 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3605 }; 3606 3607 // The proxy responds to the GET with a 407, using a persistent 3608 // connection. 3609 MockRead data_reads1[] = { 3610 // No credentials. 3611 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 3612 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3613 MockRead("Proxy-Connection: keep-alive\r\n"), 3614 MockRead("Content-Length: 0\r\n\r\n"), 3615 3616 MockRead("HTTP/1.1 200 OK\r\n"), 3617 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3618 MockRead("Content-Length: 100\r\n\r\n"), 3619 MockRead(SYNCHRONOUS, OK), 3620 }; 3621 3622 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3623 data_writes1, arraysize(data_writes1)); 3624 session_deps_.socket_factory->AddSocketDataProvider(&data1); 3625 SSLSocketDataProvider ssl(ASYNC, OK); 3626 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3627 3628 TestCompletionCallback callback1; 3629 3630 scoped_ptr<HttpTransaction> trans( 3631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3632 3633 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3634 EXPECT_EQ(ERR_IO_PENDING, rv); 3635 3636 rv = callback1.WaitForResult(); 3637 EXPECT_EQ(OK, rv); 3638 3639 LoadTimingInfo load_timing_info; 3640 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3641 TestLoadTimingNotReused(load_timing_info, 3642 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3643 3644 const HttpResponseInfo* response = trans->GetResponseInfo(); 3645 ASSERT_TRUE(response != NULL); 3646 ASSERT_FALSE(response->headers.get() == NULL); 3647 EXPECT_EQ(407, response->headers->response_code()); 3648 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 3649 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 3650 3651 TestCompletionCallback callback2; 3652 3653 rv = trans->RestartWithAuth( 3654 AuthCredentials(kFoo, kBar), callback2.callback()); 3655 EXPECT_EQ(ERR_IO_PENDING, rv); 3656 3657 rv = callback2.WaitForResult(); 3658 EXPECT_EQ(OK, rv); 3659 3660 load_timing_info = LoadTimingInfo(); 3661 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3662 // Retrying with HTTP AUTH is considered to be reusing a socket. 3663 TestLoadTimingReused(load_timing_info); 3664 3665 response = trans->GetResponseInfo(); 3666 ASSERT_TRUE(response != NULL); 3667 3668 EXPECT_TRUE(response->headers->IsKeepAlive()); 3669 EXPECT_EQ(200, response->headers->response_code()); 3670 EXPECT_EQ(100, response->headers->GetContentLength()); 3671 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 3672 3673 // The password prompt info should not be set. 3674 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3675} 3676 3677void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( 3678 const MockRead& status, int expected_status) { 3679 HttpRequestInfo request; 3680 request.method = "GET"; 3681 request.url = GURL("https://www.google.com/"); 3682 request.load_flags = 0; 3683 3684 // Configure against proxy server "myproxy:70". 3685 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 3686 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3687 3688 // Since we have proxy, should try to establish tunnel. 3689 MockWrite data_writes[] = { 3690 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 3691 "Host: www.google.com\r\n" 3692 "Proxy-Connection: keep-alive\r\n\r\n"), 3693 }; 3694 3695 MockRead data_reads[] = { 3696 status, 3697 MockRead("Content-Length: 10\r\n\r\n"), 3698 // No response body because the test stops reading here. 3699 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 3700 }; 3701 3702 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 3703 data_writes, arraysize(data_writes)); 3704 session_deps_.socket_factory->AddSocketDataProvider(&data); 3705 3706 TestCompletionCallback callback; 3707 3708 scoped_ptr<HttpTransaction> trans( 3709 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3710 3711 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 3712 EXPECT_EQ(ERR_IO_PENDING, rv); 3713 3714 rv = callback.WaitForResult(); 3715 EXPECT_EQ(expected_status, rv); 3716} 3717 3718void HttpNetworkTransactionTest::ConnectStatusHelper( 3719 const MockRead& status) { 3720 ConnectStatusHelperWithExpectedStatus( 3721 status, ERR_TUNNEL_CONNECTION_FAILED); 3722} 3723 3724TEST_P(HttpNetworkTransactionTest, ConnectStatus100) { 3725 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n")); 3726} 3727 3728TEST_P(HttpNetworkTransactionTest, ConnectStatus101) { 3729 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n")); 3730} 3731 3732TEST_P(HttpNetworkTransactionTest, ConnectStatus201) { 3733 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n")); 3734} 3735 3736TEST_P(HttpNetworkTransactionTest, ConnectStatus202) { 3737 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n")); 3738} 3739 3740TEST_P(HttpNetworkTransactionTest, ConnectStatus203) { 3741 ConnectStatusHelper( 3742 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n")); 3743} 3744 3745TEST_P(HttpNetworkTransactionTest, ConnectStatus204) { 3746 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n")); 3747} 3748 3749TEST_P(HttpNetworkTransactionTest, ConnectStatus205) { 3750 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n")); 3751} 3752 3753TEST_P(HttpNetworkTransactionTest, ConnectStatus206) { 3754 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n")); 3755} 3756 3757TEST_P(HttpNetworkTransactionTest, ConnectStatus300) { 3758 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n")); 3759} 3760 3761TEST_P(HttpNetworkTransactionTest, ConnectStatus301) { 3762 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n")); 3763} 3764 3765TEST_P(HttpNetworkTransactionTest, ConnectStatus302) { 3766 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n")); 3767} 3768 3769TEST_P(HttpNetworkTransactionTest, ConnectStatus303) { 3770 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n")); 3771} 3772 3773TEST_P(HttpNetworkTransactionTest, ConnectStatus304) { 3774 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n")); 3775} 3776 3777TEST_P(HttpNetworkTransactionTest, ConnectStatus305) { 3778 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n")); 3779} 3780 3781TEST_P(HttpNetworkTransactionTest, ConnectStatus306) { 3782 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n")); 3783} 3784 3785TEST_P(HttpNetworkTransactionTest, ConnectStatus307) { 3786 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n")); 3787} 3788 3789TEST_P(HttpNetworkTransactionTest, ConnectStatus400) { 3790 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n")); 3791} 3792 3793TEST_P(HttpNetworkTransactionTest, ConnectStatus401) { 3794 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n")); 3795} 3796 3797TEST_P(HttpNetworkTransactionTest, ConnectStatus402) { 3798 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n")); 3799} 3800 3801TEST_P(HttpNetworkTransactionTest, ConnectStatus403) { 3802 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n")); 3803} 3804 3805TEST_P(HttpNetworkTransactionTest, ConnectStatus404) { 3806 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n")); 3807} 3808 3809TEST_P(HttpNetworkTransactionTest, ConnectStatus405) { 3810 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n")); 3811} 3812 3813TEST_P(HttpNetworkTransactionTest, ConnectStatus406) { 3814 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n")); 3815} 3816 3817TEST_P(HttpNetworkTransactionTest, ConnectStatus407) { 3818 ConnectStatusHelperWithExpectedStatus( 3819 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 3820 ERR_PROXY_AUTH_UNSUPPORTED); 3821} 3822 3823TEST_P(HttpNetworkTransactionTest, ConnectStatus408) { 3824 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n")); 3825} 3826 3827TEST_P(HttpNetworkTransactionTest, ConnectStatus409) { 3828 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n")); 3829} 3830 3831TEST_P(HttpNetworkTransactionTest, ConnectStatus410) { 3832 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n")); 3833} 3834 3835TEST_P(HttpNetworkTransactionTest, ConnectStatus411) { 3836 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n")); 3837} 3838 3839TEST_P(HttpNetworkTransactionTest, ConnectStatus412) { 3840 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n")); 3841} 3842 3843TEST_P(HttpNetworkTransactionTest, ConnectStatus413) { 3844 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n")); 3845} 3846 3847TEST_P(HttpNetworkTransactionTest, ConnectStatus414) { 3848 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n")); 3849} 3850 3851TEST_P(HttpNetworkTransactionTest, ConnectStatus415) { 3852 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n")); 3853} 3854 3855TEST_P(HttpNetworkTransactionTest, ConnectStatus416) { 3856 ConnectStatusHelper( 3857 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n")); 3858} 3859 3860TEST_P(HttpNetworkTransactionTest, ConnectStatus417) { 3861 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n")); 3862} 3863 3864TEST_P(HttpNetworkTransactionTest, ConnectStatus500) { 3865 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n")); 3866} 3867 3868TEST_P(HttpNetworkTransactionTest, ConnectStatus501) { 3869 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n")); 3870} 3871 3872TEST_P(HttpNetworkTransactionTest, ConnectStatus502) { 3873 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n")); 3874} 3875 3876TEST_P(HttpNetworkTransactionTest, ConnectStatus503) { 3877 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n")); 3878} 3879 3880TEST_P(HttpNetworkTransactionTest, ConnectStatus504) { 3881 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n")); 3882} 3883 3884TEST_P(HttpNetworkTransactionTest, ConnectStatus505) { 3885 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n")); 3886} 3887 3888// Test the flow when both the proxy server AND origin server require 3889// authentication. Again, this uses basic auth for both since that is 3890// the simplest to mock. 3891TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { 3892 HttpRequestInfo request; 3893 request.method = "GET"; 3894 request.url = GURL("http://www.google.com/"); 3895 request.load_flags = 0; 3896 3897 // Configure against proxy server "myproxy:70". 3898 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 3899 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3900 3901 scoped_ptr<HttpTransaction> trans( 3902 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 3903 3904 MockWrite data_writes1[] = { 3905 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3906 "Host: www.google.com\r\n" 3907 "Proxy-Connection: keep-alive\r\n\r\n"), 3908 }; 3909 3910 MockRead data_reads1[] = { 3911 MockRead("HTTP/1.0 407 Unauthorized\r\n"), 3912 // Give a couple authenticate options (only the middle one is actually 3913 // supported). 3914 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed. 3915 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3916 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 3917 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3918 // Large content-length -- won't matter, as connection will be reset. 3919 MockRead("Content-Length: 10000\r\n\r\n"), 3920 MockRead(SYNCHRONOUS, ERR_FAILED), 3921 }; 3922 3923 // After calling trans->RestartWithAuth() the first time, this is the 3924 // request we should be issuing -- the final header line contains the 3925 // proxy's credentials. 3926 MockWrite data_writes2[] = { 3927 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3928 "Host: www.google.com\r\n" 3929 "Proxy-Connection: keep-alive\r\n" 3930 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3931 }; 3932 3933 // Now the proxy server lets the request pass through to origin server. 3934 // The origin server responds with a 401. 3935 MockRead data_reads2[] = { 3936 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 3937 // Note: We are using the same realm-name as the proxy server. This is 3938 // completely valid, as realms are unique across hosts. 3939 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3940 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3941 MockRead("Content-Length: 2000\r\n\r\n"), 3942 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached. 3943 }; 3944 3945 // After calling trans->RestartWithAuth() the second time, we should send 3946 // the credentials for both the proxy and origin server. 3947 MockWrite data_writes3[] = { 3948 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3949 "Host: www.google.com\r\n" 3950 "Proxy-Connection: keep-alive\r\n" 3951 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n" 3952 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 3953 }; 3954 3955 // Lastly we get the desired content. 3956 MockRead data_reads3[] = { 3957 MockRead("HTTP/1.0 200 OK\r\n"), 3958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3959 MockRead("Content-Length: 100\r\n\r\n"), 3960 MockRead(SYNCHRONOUS, OK), 3961 }; 3962 3963 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3964 data_writes1, arraysize(data_writes1)); 3965 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 3966 data_writes2, arraysize(data_writes2)); 3967 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 3968 data_writes3, arraysize(data_writes3)); 3969 session_deps_.socket_factory->AddSocketDataProvider(&data1); 3970 session_deps_.socket_factory->AddSocketDataProvider(&data2); 3971 session_deps_.socket_factory->AddSocketDataProvider(&data3); 3972 3973 TestCompletionCallback callback1; 3974 3975 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 3976 EXPECT_EQ(ERR_IO_PENDING, rv); 3977 3978 rv = callback1.WaitForResult(); 3979 EXPECT_EQ(OK, rv); 3980 3981 const HttpResponseInfo* response = trans->GetResponseInfo(); 3982 ASSERT_TRUE(response != NULL); 3983 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 3984 3985 TestCompletionCallback callback2; 3986 3987 rv = trans->RestartWithAuth( 3988 AuthCredentials(kFoo, kBar), callback2.callback()); 3989 EXPECT_EQ(ERR_IO_PENDING, rv); 3990 3991 rv = callback2.WaitForResult(); 3992 EXPECT_EQ(OK, rv); 3993 3994 response = trans->GetResponseInfo(); 3995 ASSERT_TRUE(response != NULL); 3996 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 3997 3998 TestCompletionCallback callback3; 3999 4000 rv = trans->RestartWithAuth( 4001 AuthCredentials(kFoo2, kBar2), callback3.callback()); 4002 EXPECT_EQ(ERR_IO_PENDING, rv); 4003 4004 rv = callback3.WaitForResult(); 4005 EXPECT_EQ(OK, rv); 4006 4007 response = trans->GetResponseInfo(); 4008 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4009 EXPECT_EQ(100, response->headers->GetContentLength()); 4010} 4011 4012// For the NTLM implementation using SSPI, we skip the NTLM tests since we 4013// can't hook into its internals to cause it to generate predictable NTLM 4014// authorization headers. 4015#if defined(NTLM_PORTABLE) 4016// The NTLM authentication unit tests were generated by capturing the HTTP 4017// requests and responses using Fiddler 2 and inspecting the generated random 4018// bytes in the debugger. 4019 4020// Enter the correct password and authenticate successfully. 4021TEST_P(HttpNetworkTransactionTest, NTLMAuth1) { 4022 HttpRequestInfo request; 4023 request.method = "GET"; 4024 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 4025 4026 // Ensure load is not disrupted by flags which suppress behaviour specific 4027 // to other auth schemes. 4028 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; 4029 4030 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1, 4031 MockGetHostName); 4032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4033 4034 MockWrite data_writes1[] = { 4035 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4036 "Host: 172.22.68.17\r\n" 4037 "Connection: keep-alive\r\n\r\n"), 4038 }; 4039 4040 MockRead data_reads1[] = { 4041 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4042 // Negotiate and NTLM are often requested together. However, we only want 4043 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 4044 // the header that requests Negotiate for this test. 4045 MockRead("WWW-Authenticate: NTLM\r\n"), 4046 MockRead("Connection: close\r\n"), 4047 MockRead("Content-Length: 42\r\n"), 4048 MockRead("Content-Type: text/html\r\n\r\n"), 4049 // Missing content -- won't matter, as connection will be reset. 4050 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4051 }; 4052 4053 MockWrite data_writes2[] = { 4054 // After restarting with a null identity, this is the 4055 // request we should be issuing -- the final header line contains a Type 4056 // 1 message. 4057 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4058 "Host: 172.22.68.17\r\n" 4059 "Connection: keep-alive\r\n" 4060 "Authorization: NTLM " 4061 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4062 4063 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4064 // (the credentials for the origin server). The second request continues 4065 // on the same connection. 4066 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4067 "Host: 172.22.68.17\r\n" 4068 "Connection: keep-alive\r\n" 4069 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4070 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4071 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW" 4072 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX" 4073 "ahlhx5I=\r\n\r\n"), 4074 }; 4075 4076 MockRead data_reads2[] = { 4077 // The origin server responds with a Type 2 message. 4078 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4079 MockRead("WWW-Authenticate: NTLM " 4080 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo" 4081 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4082 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4083 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4084 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4085 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4086 "BtAAAAAAA=\r\n"), 4087 MockRead("Content-Length: 42\r\n"), 4088 MockRead("Content-Type: text/html\r\n\r\n"), 4089 MockRead("You are not authorized to view this page\r\n"), 4090 4091 // Lastly we get the desired content. 4092 MockRead("HTTP/1.1 200 OK\r\n"), 4093 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 4094 MockRead("Content-Length: 13\r\n\r\n"), 4095 MockRead("Please Login\r\n"), 4096 MockRead(SYNCHRONOUS, OK), 4097 }; 4098 4099 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4100 data_writes1, arraysize(data_writes1)); 4101 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4102 data_writes2, arraysize(data_writes2)); 4103 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4104 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4105 4106 TestCompletionCallback callback1; 4107 4108 scoped_ptr<HttpTransaction> trans( 4109 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4110 4111 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4112 EXPECT_EQ(ERR_IO_PENDING, rv); 4113 4114 rv = callback1.WaitForResult(); 4115 EXPECT_EQ(OK, rv); 4116 4117 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4118 4119 const HttpResponseInfo* response = trans->GetResponseInfo(); 4120 ASSERT_FALSE(response == NULL); 4121 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4122 4123 TestCompletionCallback callback2; 4124 4125 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM), 4126 callback2.callback()); 4127 EXPECT_EQ(ERR_IO_PENDING, rv); 4128 4129 rv = callback2.WaitForResult(); 4130 EXPECT_EQ(OK, rv); 4131 4132 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4133 4134 response = trans->GetResponseInfo(); 4135 ASSERT_TRUE(response != NULL); 4136 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4137 4138 TestCompletionCallback callback3; 4139 4140 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback()); 4141 EXPECT_EQ(ERR_IO_PENDING, rv); 4142 4143 rv = callback3.WaitForResult(); 4144 EXPECT_EQ(OK, rv); 4145 4146 response = trans->GetResponseInfo(); 4147 ASSERT_TRUE(response != NULL); 4148 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4149 EXPECT_EQ(13, response->headers->GetContentLength()); 4150} 4151 4152// Enter a wrong password, and then the correct one. 4153TEST_P(HttpNetworkTransactionTest, NTLMAuth2) { 4154 HttpRequestInfo request; 4155 request.method = "GET"; 4156 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 4157 request.load_flags = 0; 4158 4159 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2, 4160 MockGetHostName); 4161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4162 4163 MockWrite data_writes1[] = { 4164 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4165 "Host: 172.22.68.17\r\n" 4166 "Connection: keep-alive\r\n\r\n"), 4167 }; 4168 4169 MockRead data_reads1[] = { 4170 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4171 // Negotiate and NTLM are often requested together. However, we only want 4172 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 4173 // the header that requests Negotiate for this test. 4174 MockRead("WWW-Authenticate: NTLM\r\n"), 4175 MockRead("Connection: close\r\n"), 4176 MockRead("Content-Length: 42\r\n"), 4177 MockRead("Content-Type: text/html\r\n\r\n"), 4178 // Missing content -- won't matter, as connection will be reset. 4179 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4180 }; 4181 4182 MockWrite data_writes2[] = { 4183 // After restarting with a null identity, this is the 4184 // request we should be issuing -- the final header line contains a Type 4185 // 1 message. 4186 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4187 "Host: 172.22.68.17\r\n" 4188 "Connection: keep-alive\r\n" 4189 "Authorization: NTLM " 4190 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4191 4192 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4193 // (the credentials for the origin server). The second request continues 4194 // on the same connection. 4195 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4196 "Host: 172.22.68.17\r\n" 4197 "Connection: keep-alive\r\n" 4198 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4199 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4200 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY" 4201 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj" 4202 "4Ww7b7E=\r\n\r\n"), 4203 }; 4204 4205 MockRead data_reads2[] = { 4206 // The origin server responds with a Type 2 message. 4207 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4208 MockRead("WWW-Authenticate: NTLM " 4209 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo" 4210 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4211 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4212 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4213 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4214 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4215 "BtAAAAAAA=\r\n"), 4216 MockRead("Content-Length: 42\r\n"), 4217 MockRead("Content-Type: text/html\r\n\r\n"), 4218 MockRead("You are not authorized to view this page\r\n"), 4219 4220 // Wrong password. 4221 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4222 MockRead("WWW-Authenticate: NTLM\r\n"), 4223 MockRead("Connection: close\r\n"), 4224 MockRead("Content-Length: 42\r\n"), 4225 MockRead("Content-Type: text/html\r\n\r\n"), 4226 // Missing content -- won't matter, as connection will be reset. 4227 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4228 }; 4229 4230 MockWrite data_writes3[] = { 4231 // After restarting with a null identity, this is the 4232 // request we should be issuing -- the final header line contains a Type 4233 // 1 message. 4234 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4235 "Host: 172.22.68.17\r\n" 4236 "Connection: keep-alive\r\n" 4237 "Authorization: NTLM " 4238 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4239 4240 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4241 // (the credentials for the origin server). The second request continues 4242 // on the same connection. 4243 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4244 "Host: 172.22.68.17\r\n" 4245 "Connection: keep-alive\r\n" 4246 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4247 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4248 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54" 4249 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI" 4250 "+4MUm7c=\r\n\r\n"), 4251 }; 4252 4253 MockRead data_reads3[] = { 4254 // The origin server responds with a Type 2 message. 4255 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4256 MockRead("WWW-Authenticate: NTLM " 4257 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo" 4258 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4259 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4260 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4261 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4262 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4263 "BtAAAAAAA=\r\n"), 4264 MockRead("Content-Length: 42\r\n"), 4265 MockRead("Content-Type: text/html\r\n\r\n"), 4266 MockRead("You are not authorized to view this page\r\n"), 4267 4268 // Lastly we get the desired content. 4269 MockRead("HTTP/1.1 200 OK\r\n"), 4270 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 4271 MockRead("Content-Length: 13\r\n\r\n"), 4272 MockRead("Please Login\r\n"), 4273 MockRead(SYNCHRONOUS, OK), 4274 }; 4275 4276 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4277 data_writes1, arraysize(data_writes1)); 4278 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4279 data_writes2, arraysize(data_writes2)); 4280 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4281 data_writes3, arraysize(data_writes3)); 4282 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4283 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4284 session_deps_.socket_factory->AddSocketDataProvider(&data3); 4285 4286 TestCompletionCallback callback1; 4287 4288 scoped_ptr<HttpTransaction> trans( 4289 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4290 4291 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4292 EXPECT_EQ(ERR_IO_PENDING, rv); 4293 4294 rv = callback1.WaitForResult(); 4295 EXPECT_EQ(OK, rv); 4296 4297 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4298 4299 const HttpResponseInfo* response = trans->GetResponseInfo(); 4300 ASSERT_TRUE(response != NULL); 4301 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4302 4303 TestCompletionCallback callback2; 4304 4305 // Enter the wrong password. 4306 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword), 4307 callback2.callback()); 4308 EXPECT_EQ(ERR_IO_PENDING, rv); 4309 4310 rv = callback2.WaitForResult(); 4311 EXPECT_EQ(OK, rv); 4312 4313 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4314 TestCompletionCallback callback3; 4315 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback()); 4316 EXPECT_EQ(ERR_IO_PENDING, rv); 4317 rv = callback3.WaitForResult(); 4318 EXPECT_EQ(OK, rv); 4319 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4320 4321 response = trans->GetResponseInfo(); 4322 ASSERT_FALSE(response == NULL); 4323 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4324 4325 TestCompletionCallback callback4; 4326 4327 // Now enter the right password. 4328 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM), 4329 callback4.callback()); 4330 EXPECT_EQ(ERR_IO_PENDING, rv); 4331 4332 rv = callback4.WaitForResult(); 4333 EXPECT_EQ(OK, rv); 4334 4335 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4336 4337 TestCompletionCallback callback5; 4338 4339 // One more roundtrip 4340 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback()); 4341 EXPECT_EQ(ERR_IO_PENDING, rv); 4342 4343 rv = callback5.WaitForResult(); 4344 EXPECT_EQ(OK, rv); 4345 4346 response = trans->GetResponseInfo(); 4347 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4348 EXPECT_EQ(13, response->headers->GetContentLength()); 4349} 4350#endif // NTLM_PORTABLE 4351 4352// Test reading a server response which has only headers, and no body. 4353// After some maximum number of bytes is consumed, the transaction should 4354// fail with ERR_RESPONSE_HEADERS_TOO_BIG. 4355TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) { 4356 HttpRequestInfo request; 4357 request.method = "GET"; 4358 request.url = GURL("http://www.google.com/"); 4359 request.load_flags = 0; 4360 4361 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4362 scoped_ptr<HttpTransaction> trans( 4363 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 4364 4365 // Respond with 300 kb of headers (we should fail after 256 kb). 4366 std::string large_headers_string; 4367 FillLargeHeadersString(&large_headers_string, 300 * 1024); 4368 4369 MockRead data_reads[] = { 4370 MockRead("HTTP/1.0 200 OK\r\n"), 4371 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()), 4372 MockRead("\r\nBODY"), 4373 MockRead(SYNCHRONOUS, OK), 4374 }; 4375 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4376 session_deps_.socket_factory->AddSocketDataProvider(&data); 4377 4378 TestCompletionCallback callback; 4379 4380 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4381 EXPECT_EQ(ERR_IO_PENDING, rv); 4382 4383 rv = callback.WaitForResult(); 4384 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv); 4385 4386 const HttpResponseInfo* response = trans->GetResponseInfo(); 4387 EXPECT_TRUE(response == NULL); 4388} 4389 4390// Make sure that we don't try to reuse a TCPClientSocket when failing to 4391// establish tunnel. 4392// http://code.google.com/p/chromium/issues/detail?id=3772 4393TEST_P(HttpNetworkTransactionTest, 4394 DontRecycleTransportSocketForSSLTunnel) { 4395 HttpRequestInfo request; 4396 request.method = "GET"; 4397 request.url = GURL("https://www.google.com/"); 4398 request.load_flags = 0; 4399 4400 // Configure against proxy server "myproxy:70". 4401 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 4402 4403 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4404 4405 scoped_ptr<HttpTransaction> trans( 4406 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4407 4408 // Since we have proxy, should try to establish tunnel. 4409 MockWrite data_writes1[] = { 4410 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4411 "Host: www.google.com\r\n" 4412 "Proxy-Connection: keep-alive\r\n\r\n"), 4413 }; 4414 4415 // The proxy responds to the connect with a 404, using a persistent 4416 // connection. Usually a proxy would return 501 (not implemented), 4417 // or 200 (tunnel established). 4418 MockRead data_reads1[] = { 4419 MockRead("HTTP/1.1 404 Not Found\r\n"), 4420 MockRead("Content-Length: 10\r\n\r\n"), 4421 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 4422 }; 4423 4424 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4425 data_writes1, arraysize(data_writes1)); 4426 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4427 4428 TestCompletionCallback callback1; 4429 4430 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4431 EXPECT_EQ(ERR_IO_PENDING, rv); 4432 4433 rv = callback1.WaitForResult(); 4434 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 4435 4436 const HttpResponseInfo* response = trans->GetResponseInfo(); 4437 EXPECT_TRUE(response == NULL); 4438 4439 // Empty the current queue. This is necessary because idle sockets are 4440 // added to the connection pool asynchronously with a PostTask. 4441 base::MessageLoop::current()->RunUntilIdle(); 4442 4443 // We now check to make sure the TCPClientSocket was not added back to 4444 // the pool. 4445 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4446 trans.reset(); 4447 base::MessageLoop::current()->RunUntilIdle(); 4448 // Make sure that the socket didn't get recycled after calling the destructor. 4449 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4450} 4451 4452// Make sure that we recycle a socket after reading all of the response body. 4453TEST_P(HttpNetworkTransactionTest, RecycleSocket) { 4454 HttpRequestInfo request; 4455 request.method = "GET"; 4456 request.url = GURL("http://www.google.com/"); 4457 request.load_flags = 0; 4458 4459 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4460 4461 scoped_ptr<HttpTransaction> trans( 4462 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4463 4464 MockRead data_reads[] = { 4465 // A part of the response body is received with the response headers. 4466 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"), 4467 // The rest of the response body is received in two parts. 4468 MockRead("lo"), 4469 MockRead(" world"), 4470 MockRead("junk"), // Should not be read!! 4471 MockRead(SYNCHRONOUS, OK), 4472 }; 4473 4474 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4475 session_deps_.socket_factory->AddSocketDataProvider(&data); 4476 4477 TestCompletionCallback callback; 4478 4479 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4480 EXPECT_EQ(ERR_IO_PENDING, rv); 4481 4482 rv = callback.WaitForResult(); 4483 EXPECT_EQ(OK, rv); 4484 4485 const HttpResponseInfo* response = trans->GetResponseInfo(); 4486 ASSERT_TRUE(response != NULL); 4487 4488 EXPECT_TRUE(response->headers.get() != NULL); 4489 std::string status_line = response->headers->GetStatusLine(); 4490 EXPECT_EQ("HTTP/1.1 200 OK", status_line); 4491 4492 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4493 4494 std::string response_data; 4495 rv = ReadTransaction(trans.get(), &response_data); 4496 EXPECT_EQ(OK, rv); 4497 EXPECT_EQ("hello world", response_data); 4498 4499 // Empty the current queue. This is necessary because idle sockets are 4500 // added to the connection pool asynchronously with a PostTask. 4501 base::MessageLoop::current()->RunUntilIdle(); 4502 4503 // We now check to make sure the socket was added back to the pool. 4504 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get())); 4505} 4506 4507// Make sure that we recycle a SSL socket after reading all of the response 4508// body. 4509TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) { 4510 HttpRequestInfo request; 4511 request.method = "GET"; 4512 request.url = GURL("https://www.google.com/"); 4513 request.load_flags = 0; 4514 4515 MockWrite data_writes[] = { 4516 MockWrite("GET / HTTP/1.1\r\n" 4517 "Host: www.google.com\r\n" 4518 "Connection: keep-alive\r\n\r\n"), 4519 }; 4520 4521 MockRead data_reads[] = { 4522 MockRead("HTTP/1.1 200 OK\r\n"), 4523 MockRead("Content-Length: 11\r\n\r\n"), 4524 MockRead("hello world"), 4525 MockRead(SYNCHRONOUS, OK), 4526 }; 4527 4528 SSLSocketDataProvider ssl(ASYNC, OK); 4529 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 4530 4531 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4532 data_writes, arraysize(data_writes)); 4533 session_deps_.socket_factory->AddSocketDataProvider(&data); 4534 4535 TestCompletionCallback callback; 4536 4537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4538 scoped_ptr<HttpTransaction> trans( 4539 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4540 4541 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4542 4543 EXPECT_EQ(ERR_IO_PENDING, rv); 4544 EXPECT_EQ(OK, callback.WaitForResult()); 4545 4546 const HttpResponseInfo* response = trans->GetResponseInfo(); 4547 ASSERT_TRUE(response != NULL); 4548 ASSERT_TRUE(response->headers.get() != NULL); 4549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4550 4551 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4552 4553 std::string response_data; 4554 rv = ReadTransaction(trans.get(), &response_data); 4555 EXPECT_EQ(OK, rv); 4556 EXPECT_EQ("hello world", response_data); 4557 4558 // Empty the current queue. This is necessary because idle sockets are 4559 // added to the connection pool asynchronously with a PostTask. 4560 base::MessageLoop::current()->RunUntilIdle(); 4561 4562 // We now check to make sure the socket was added back to the pool. 4563 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4564} 4565 4566// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it 4567// from the pool and make sure that we recover okay. 4568TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) { 4569 HttpRequestInfo request; 4570 request.method = "GET"; 4571 request.url = GURL("https://www.google.com/"); 4572 request.load_flags = 0; 4573 4574 MockWrite data_writes[] = { 4575 MockWrite("GET / HTTP/1.1\r\n" 4576 "Host: www.google.com\r\n" 4577 "Connection: keep-alive\r\n\r\n"), 4578 MockWrite("GET / HTTP/1.1\r\n" 4579 "Host: www.google.com\r\n" 4580 "Connection: keep-alive\r\n\r\n"), 4581 }; 4582 4583 MockRead data_reads[] = { 4584 MockRead("HTTP/1.1 200 OK\r\n"), 4585 MockRead("Content-Length: 11\r\n\r\n"), 4586 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 4587 MockRead("hello world"), 4588 MockRead(ASYNC, 0, 0) // EOF 4589 }; 4590 4591 SSLSocketDataProvider ssl(ASYNC, OK); 4592 SSLSocketDataProvider ssl2(ASYNC, OK); 4593 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 4594 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 4595 4596 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4597 data_writes, arraysize(data_writes)); 4598 StaticSocketDataProvider data2(data_reads, arraysize(data_reads), 4599 data_writes, arraysize(data_writes)); 4600 session_deps_.socket_factory->AddSocketDataProvider(&data); 4601 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4602 4603 TestCompletionCallback callback; 4604 4605 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4606 scoped_ptr<HttpTransaction> trans( 4607 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4608 4609 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4610 4611 EXPECT_EQ(ERR_IO_PENDING, rv); 4612 EXPECT_EQ(OK, callback.WaitForResult()); 4613 4614 const HttpResponseInfo* response = trans->GetResponseInfo(); 4615 ASSERT_TRUE(response != NULL); 4616 ASSERT_TRUE(response->headers.get() != NULL); 4617 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4618 4619 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4620 4621 std::string response_data; 4622 rv = ReadTransaction(trans.get(), &response_data); 4623 EXPECT_EQ(OK, rv); 4624 EXPECT_EQ("hello world", response_data); 4625 4626 // Empty the current queue. This is necessary because idle sockets are 4627 // added to the connection pool asynchronously with a PostTask. 4628 base::MessageLoop::current()->RunUntilIdle(); 4629 4630 // We now check to make sure the socket was added back to the pool. 4631 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4632 4633 // Now start the second transaction, which should reuse the previous socket. 4634 4635 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4636 4637 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4638 4639 EXPECT_EQ(ERR_IO_PENDING, rv); 4640 EXPECT_EQ(OK, callback.WaitForResult()); 4641 4642 response = trans->GetResponseInfo(); 4643 ASSERT_TRUE(response != NULL); 4644 ASSERT_TRUE(response->headers.get() != NULL); 4645 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4646 4647 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4648 4649 rv = ReadTransaction(trans.get(), &response_data); 4650 EXPECT_EQ(OK, rv); 4651 EXPECT_EQ("hello world", response_data); 4652 4653 // Empty the current queue. This is necessary because idle sockets are 4654 // added to the connection pool asynchronously with a PostTask. 4655 base::MessageLoop::current()->RunUntilIdle(); 4656 4657 // We now check to make sure the socket was added back to the pool. 4658 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4659} 4660 4661// Make sure that we recycle a socket after a zero-length response. 4662// http://crbug.com/9880 4663TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { 4664 HttpRequestInfo request; 4665 request.method = "GET"; 4666 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&" 4667 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&" 4668 "e=17259,18167,19592,19773,19981,20133,20173,20233&" 4669 "rt=prt.2642,ol.2649,xjs.2951"); 4670 request.load_flags = 0; 4671 4672 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4673 4674 scoped_ptr<HttpTransaction> trans( 4675 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4676 4677 MockRead data_reads[] = { 4678 MockRead("HTTP/1.1 204 No Content\r\n" 4679 "Content-Length: 0\r\n" 4680 "Content-Type: text/html\r\n\r\n"), 4681 MockRead("junk"), // Should not be read!! 4682 MockRead(SYNCHRONOUS, OK), 4683 }; 4684 4685 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4686 session_deps_.socket_factory->AddSocketDataProvider(&data); 4687 4688 TestCompletionCallback callback; 4689 4690 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4691 EXPECT_EQ(ERR_IO_PENDING, rv); 4692 4693 rv = callback.WaitForResult(); 4694 EXPECT_EQ(OK, rv); 4695 4696 const HttpResponseInfo* response = trans->GetResponseInfo(); 4697 ASSERT_TRUE(response != NULL); 4698 4699 EXPECT_TRUE(response->headers.get() != NULL); 4700 std::string status_line = response->headers->GetStatusLine(); 4701 EXPECT_EQ("HTTP/1.1 204 No Content", status_line); 4702 4703 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4704 4705 std::string response_data; 4706 rv = ReadTransaction(trans.get(), &response_data); 4707 EXPECT_EQ(OK, rv); 4708 EXPECT_EQ("", response_data); 4709 4710 // Empty the current queue. This is necessary because idle sockets are 4711 // added to the connection pool asynchronously with a PostTask. 4712 base::MessageLoop::current()->RunUntilIdle(); 4713 4714 // We now check to make sure the socket was added back to the pool. 4715 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get())); 4716} 4717 4718TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { 4719 ScopedVector<UploadElementReader> element_readers; 4720 element_readers.push_back(new UploadBytesElementReader("foo", 3)); 4721 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 4722 4723 HttpRequestInfo request[2]; 4724 // Transaction 1: a GET request that succeeds. The socket is recycled 4725 // after use. 4726 request[0].method = "GET"; 4727 request[0].url = GURL("http://www.google.com/"); 4728 request[0].load_flags = 0; 4729 // Transaction 2: a POST request. Reuses the socket kept alive from 4730 // transaction 1. The first attempts fails when writing the POST data. 4731 // This causes the transaction to retry with a new socket. The second 4732 // attempt succeeds. 4733 request[1].method = "POST"; 4734 request[1].url = GURL("http://www.google.com/login.cgi"); 4735 request[1].upload_data_stream = &upload_data_stream; 4736 request[1].load_flags = 0; 4737 4738 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4739 4740 // The first socket is used for transaction 1 and the first attempt of 4741 // transaction 2. 4742 4743 // The response of transaction 1. 4744 MockRead data_reads1[] = { 4745 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"), 4746 MockRead("hello world"), 4747 MockRead(SYNCHRONOUS, OK), 4748 }; 4749 // The mock write results of transaction 1 and the first attempt of 4750 // transaction 2. 4751 MockWrite data_writes1[] = { 4752 MockWrite(SYNCHRONOUS, 64), // GET 4753 MockWrite(SYNCHRONOUS, 93), // POST 4754 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data 4755 }; 4756 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4757 data_writes1, arraysize(data_writes1)); 4758 4759 // The second socket is used for the second attempt of transaction 2. 4760 4761 // The response of transaction 2. 4762 MockRead data_reads2[] = { 4763 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"), 4764 MockRead("welcome"), 4765 MockRead(SYNCHRONOUS, OK), 4766 }; 4767 // The mock write results of the second attempt of transaction 2. 4768 MockWrite data_writes2[] = { 4769 MockWrite(SYNCHRONOUS, 93), // POST 4770 MockWrite(SYNCHRONOUS, 3), // POST data 4771 }; 4772 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4773 data_writes2, arraysize(data_writes2)); 4774 4775 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4776 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4777 4778 const char* kExpectedResponseData[] = { 4779 "hello world", "welcome" 4780 }; 4781 4782 for (int i = 0; i < 2; ++i) { 4783 scoped_ptr<HttpTransaction> trans( 4784 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4785 4786 TestCompletionCallback callback; 4787 4788 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog()); 4789 EXPECT_EQ(ERR_IO_PENDING, rv); 4790 4791 rv = callback.WaitForResult(); 4792 EXPECT_EQ(OK, rv); 4793 4794 const HttpResponseInfo* response = trans->GetResponseInfo(); 4795 ASSERT_TRUE(response != NULL); 4796 4797 EXPECT_TRUE(response->headers.get() != NULL); 4798 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4799 4800 std::string response_data; 4801 rv = ReadTransaction(trans.get(), &response_data); 4802 EXPECT_EQ(OK, rv); 4803 EXPECT_EQ(kExpectedResponseData[i], response_data); 4804 } 4805} 4806 4807// Test the request-challenge-retry sequence for basic auth when there is 4808// an identity in the URL. The request should be sent as normal, but when 4809// it fails the identity from the URL is used to answer the challenge. 4810TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) { 4811 HttpRequestInfo request; 4812 request.method = "GET"; 4813 request.url = GURL("http://foo:b@r@www.google.com/"); 4814 request.load_flags = LOAD_NORMAL; 4815 4816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4817 scoped_ptr<HttpTransaction> trans( 4818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 4819 4820 // The password contains an escaped character -- for this test to pass it 4821 // will need to be unescaped by HttpNetworkTransaction. 4822 EXPECT_EQ("b%40r", request.url.password()); 4823 4824 MockWrite data_writes1[] = { 4825 MockWrite("GET / HTTP/1.1\r\n" 4826 "Host: www.google.com\r\n" 4827 "Connection: keep-alive\r\n\r\n"), 4828 }; 4829 4830 MockRead data_reads1[] = { 4831 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4832 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4833 MockRead("Content-Length: 10\r\n\r\n"), 4834 MockRead(SYNCHRONOUS, ERR_FAILED), 4835 }; 4836 4837 // After the challenge above, the transaction will be restarted using the 4838 // identity from the url (foo, b@r) to answer the challenge. 4839 MockWrite data_writes2[] = { 4840 MockWrite("GET / HTTP/1.1\r\n" 4841 "Host: www.google.com\r\n" 4842 "Connection: keep-alive\r\n" 4843 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"), 4844 }; 4845 4846 MockRead data_reads2[] = { 4847 MockRead("HTTP/1.0 200 OK\r\n"), 4848 MockRead("Content-Length: 100\r\n\r\n"), 4849 MockRead(SYNCHRONOUS, OK), 4850 }; 4851 4852 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4853 data_writes1, arraysize(data_writes1)); 4854 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4855 data_writes2, arraysize(data_writes2)); 4856 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4857 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4858 4859 TestCompletionCallback callback1; 4860 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4861 EXPECT_EQ(ERR_IO_PENDING, rv); 4862 rv = callback1.WaitForResult(); 4863 EXPECT_EQ(OK, rv); 4864 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4865 4866 TestCompletionCallback callback2; 4867 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 4868 EXPECT_EQ(ERR_IO_PENDING, rv); 4869 rv = callback2.WaitForResult(); 4870 EXPECT_EQ(OK, rv); 4871 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4872 4873 const HttpResponseInfo* response = trans->GetResponseInfo(); 4874 ASSERT_TRUE(response != NULL); 4875 4876 // There is no challenge info, since the identity in URL worked. 4877 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4878 4879 EXPECT_EQ(100, response->headers->GetContentLength()); 4880 4881 // Empty the current queue. 4882 base::MessageLoop::current()->RunUntilIdle(); 4883} 4884 4885// Test the request-challenge-retry sequence for basic auth when there is an 4886// incorrect identity in the URL. The identity from the URL should be used only 4887// once. 4888TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) { 4889 HttpRequestInfo request; 4890 request.method = "GET"; 4891 // Note: the URL has a username:password in it. The password "baz" is 4892 // wrong (should be "bar"). 4893 request.url = GURL("http://foo:baz@www.google.com/"); 4894 4895 request.load_flags = LOAD_NORMAL; 4896 4897 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4898 scoped_ptr<HttpTransaction> trans( 4899 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 4900 4901 MockWrite data_writes1[] = { 4902 MockWrite("GET / HTTP/1.1\r\n" 4903 "Host: www.google.com\r\n" 4904 "Connection: keep-alive\r\n\r\n"), 4905 }; 4906 4907 MockRead data_reads1[] = { 4908 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4909 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4910 MockRead("Content-Length: 10\r\n\r\n"), 4911 MockRead(SYNCHRONOUS, ERR_FAILED), 4912 }; 4913 4914 // After the challenge above, the transaction will be restarted using the 4915 // identity from the url (foo, baz) to answer the challenge. 4916 MockWrite data_writes2[] = { 4917 MockWrite("GET / HTTP/1.1\r\n" 4918 "Host: www.google.com\r\n" 4919 "Connection: keep-alive\r\n" 4920 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 4921 }; 4922 4923 MockRead data_reads2[] = { 4924 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4925 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4926 MockRead("Content-Length: 10\r\n\r\n"), 4927 MockRead(SYNCHRONOUS, ERR_FAILED), 4928 }; 4929 4930 // After the challenge above, the transaction will be restarted using the 4931 // identity supplied by the user (foo, bar) to answer the challenge. 4932 MockWrite data_writes3[] = { 4933 MockWrite("GET / HTTP/1.1\r\n" 4934 "Host: www.google.com\r\n" 4935 "Connection: keep-alive\r\n" 4936 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 4937 }; 4938 4939 MockRead data_reads3[] = { 4940 MockRead("HTTP/1.0 200 OK\r\n"), 4941 MockRead("Content-Length: 100\r\n\r\n"), 4942 MockRead(SYNCHRONOUS, OK), 4943 }; 4944 4945 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4946 data_writes1, arraysize(data_writes1)); 4947 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4948 data_writes2, arraysize(data_writes2)); 4949 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4950 data_writes3, arraysize(data_writes3)); 4951 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4952 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4953 session_deps_.socket_factory->AddSocketDataProvider(&data3); 4954 4955 TestCompletionCallback callback1; 4956 4957 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4958 EXPECT_EQ(ERR_IO_PENDING, rv); 4959 4960 rv = callback1.WaitForResult(); 4961 EXPECT_EQ(OK, rv); 4962 4963 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4964 TestCompletionCallback callback2; 4965 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 4966 EXPECT_EQ(ERR_IO_PENDING, rv); 4967 rv = callback2.WaitForResult(); 4968 EXPECT_EQ(OK, rv); 4969 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4970 4971 const HttpResponseInfo* response = trans->GetResponseInfo(); 4972 ASSERT_TRUE(response != NULL); 4973 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 4974 4975 TestCompletionCallback callback3; 4976 rv = trans->RestartWithAuth( 4977 AuthCredentials(kFoo, kBar), callback3.callback()); 4978 EXPECT_EQ(ERR_IO_PENDING, rv); 4979 rv = callback3.WaitForResult(); 4980 EXPECT_EQ(OK, rv); 4981 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4982 4983 response = trans->GetResponseInfo(); 4984 ASSERT_TRUE(response != NULL); 4985 4986 // There is no challenge info, since the identity worked. 4987 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4988 4989 EXPECT_EQ(100, response->headers->GetContentLength()); 4990 4991 // Empty the current queue. 4992 base::MessageLoop::current()->RunUntilIdle(); 4993} 4994 4995 4996// Test the request-challenge-retry sequence for basic auth when there is a 4997// correct identity in the URL, but its use is being suppressed. The identity 4998// from the URL should never be used. 4999TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) { 5000 HttpRequestInfo request; 5001 request.method = "GET"; 5002 request.url = GURL("http://foo:bar@www.google.com/"); 5003 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; 5004 5005 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5006 scoped_ptr<HttpTransaction> trans( 5007 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5008 5009 MockWrite data_writes1[] = { 5010 MockWrite("GET / HTTP/1.1\r\n" 5011 "Host: www.google.com\r\n" 5012 "Connection: keep-alive\r\n\r\n"), 5013 }; 5014 5015 MockRead data_reads1[] = { 5016 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5017 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5018 MockRead("Content-Length: 10\r\n\r\n"), 5019 MockRead(SYNCHRONOUS, ERR_FAILED), 5020 }; 5021 5022 // After the challenge above, the transaction will be restarted using the 5023 // identity supplied by the user, not the one in the URL, to answer the 5024 // challenge. 5025 MockWrite data_writes3[] = { 5026 MockWrite("GET / HTTP/1.1\r\n" 5027 "Host: www.google.com\r\n" 5028 "Connection: keep-alive\r\n" 5029 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5030 }; 5031 5032 MockRead data_reads3[] = { 5033 MockRead("HTTP/1.0 200 OK\r\n"), 5034 MockRead("Content-Length: 100\r\n\r\n"), 5035 MockRead(SYNCHRONOUS, OK), 5036 }; 5037 5038 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5039 data_writes1, arraysize(data_writes1)); 5040 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 5041 data_writes3, arraysize(data_writes3)); 5042 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5043 session_deps_.socket_factory->AddSocketDataProvider(&data3); 5044 5045 TestCompletionCallback callback1; 5046 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5047 EXPECT_EQ(ERR_IO_PENDING, rv); 5048 rv = callback1.WaitForResult(); 5049 EXPECT_EQ(OK, rv); 5050 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5051 5052 const HttpResponseInfo* response = trans->GetResponseInfo(); 5053 ASSERT_TRUE(response != NULL); 5054 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5055 5056 TestCompletionCallback callback3; 5057 rv = trans->RestartWithAuth( 5058 AuthCredentials(kFoo, kBar), callback3.callback()); 5059 EXPECT_EQ(ERR_IO_PENDING, rv); 5060 rv = callback3.WaitForResult(); 5061 EXPECT_EQ(OK, rv); 5062 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5063 5064 response = trans->GetResponseInfo(); 5065 ASSERT_TRUE(response != NULL); 5066 5067 // There is no challenge info, since the identity worked. 5068 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5069 EXPECT_EQ(100, response->headers->GetContentLength()); 5070 5071 // Empty the current queue. 5072 base::MessageLoop::current()->RunUntilIdle(); 5073} 5074 5075// Test that previously tried username/passwords for a realm get re-used. 5076TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) { 5077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5078 5079 // Transaction 1: authenticate (foo, bar) on MyRealm1 5080 { 5081 HttpRequestInfo request; 5082 request.method = "GET"; 5083 request.url = GURL("http://www.google.com/x/y/z"); 5084 request.load_flags = 0; 5085 5086 scoped_ptr<HttpTransaction> trans( 5087 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5088 5089 MockWrite data_writes1[] = { 5090 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5091 "Host: www.google.com\r\n" 5092 "Connection: keep-alive\r\n\r\n"), 5093 }; 5094 5095 MockRead data_reads1[] = { 5096 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5097 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5098 MockRead("Content-Length: 10000\r\n\r\n"), 5099 MockRead(SYNCHRONOUS, ERR_FAILED), 5100 }; 5101 5102 // Resend with authorization (username=foo, password=bar) 5103 MockWrite data_writes2[] = { 5104 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5105 "Host: www.google.com\r\n" 5106 "Connection: keep-alive\r\n" 5107 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5108 }; 5109 5110 // Sever accepts the authorization. 5111 MockRead data_reads2[] = { 5112 MockRead("HTTP/1.0 200 OK\r\n"), 5113 MockRead("Content-Length: 100\r\n\r\n"), 5114 MockRead(SYNCHRONOUS, OK), 5115 }; 5116 5117 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5118 data_writes1, arraysize(data_writes1)); 5119 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5120 data_writes2, arraysize(data_writes2)); 5121 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5122 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5123 5124 TestCompletionCallback callback1; 5125 5126 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5127 EXPECT_EQ(ERR_IO_PENDING, rv); 5128 5129 rv = callback1.WaitForResult(); 5130 EXPECT_EQ(OK, rv); 5131 5132 const HttpResponseInfo* response = trans->GetResponseInfo(); 5133 ASSERT_TRUE(response != NULL); 5134 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5135 5136 TestCompletionCallback callback2; 5137 5138 rv = trans->RestartWithAuth( 5139 AuthCredentials(kFoo, kBar), callback2.callback()); 5140 EXPECT_EQ(ERR_IO_PENDING, rv); 5141 5142 rv = callback2.WaitForResult(); 5143 EXPECT_EQ(OK, rv); 5144 5145 response = trans->GetResponseInfo(); 5146 ASSERT_TRUE(response != NULL); 5147 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5148 EXPECT_EQ(100, response->headers->GetContentLength()); 5149 } 5150 5151 // ------------------------------------------------------------------------ 5152 5153 // Transaction 2: authenticate (foo2, bar2) on MyRealm2 5154 { 5155 HttpRequestInfo request; 5156 request.method = "GET"; 5157 // Note that Transaction 1 was at /x/y/z, so this is in the same 5158 // protection space as MyRealm1. 5159 request.url = GURL("http://www.google.com/x/y/a/b"); 5160 request.load_flags = 0; 5161 5162 scoped_ptr<HttpTransaction> trans( 5163 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5164 5165 MockWrite data_writes1[] = { 5166 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5167 "Host: www.google.com\r\n" 5168 "Connection: keep-alive\r\n" 5169 // Send preemptive authorization for MyRealm1 5170 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5171 }; 5172 5173 // The server didn't like the preemptive authorization, and 5174 // challenges us for a different realm (MyRealm2). 5175 MockRead data_reads1[] = { 5176 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5177 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"), 5178 MockRead("Content-Length: 10000\r\n\r\n"), 5179 MockRead(SYNCHRONOUS, ERR_FAILED), 5180 }; 5181 5182 // Resend with authorization for MyRealm2 (username=foo2, password=bar2) 5183 MockWrite data_writes2[] = { 5184 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5185 "Host: www.google.com\r\n" 5186 "Connection: keep-alive\r\n" 5187 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 5188 }; 5189 5190 // Sever accepts the authorization. 5191 MockRead data_reads2[] = { 5192 MockRead("HTTP/1.0 200 OK\r\n"), 5193 MockRead("Content-Length: 100\r\n\r\n"), 5194 MockRead(SYNCHRONOUS, OK), 5195 }; 5196 5197 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5198 data_writes1, arraysize(data_writes1)); 5199 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5200 data_writes2, arraysize(data_writes2)); 5201 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5202 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5203 5204 TestCompletionCallback callback1; 5205 5206 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5207 EXPECT_EQ(ERR_IO_PENDING, rv); 5208 5209 rv = callback1.WaitForResult(); 5210 EXPECT_EQ(OK, rv); 5211 5212 const HttpResponseInfo* response = trans->GetResponseInfo(); 5213 ASSERT_TRUE(response != NULL); 5214 ASSERT_TRUE(response->auth_challenge.get()); 5215 EXPECT_FALSE(response->auth_challenge->is_proxy); 5216 EXPECT_EQ("www.google.com:80", 5217 response->auth_challenge->challenger.ToString()); 5218 EXPECT_EQ("MyRealm2", response->auth_challenge->realm); 5219 EXPECT_EQ("basic", response->auth_challenge->scheme); 5220 5221 TestCompletionCallback callback2; 5222 5223 rv = trans->RestartWithAuth( 5224 AuthCredentials(kFoo2, kBar2), callback2.callback()); 5225 EXPECT_EQ(ERR_IO_PENDING, rv); 5226 5227 rv = callback2.WaitForResult(); 5228 EXPECT_EQ(OK, rv); 5229 5230 response = trans->GetResponseInfo(); 5231 ASSERT_TRUE(response != NULL); 5232 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5233 EXPECT_EQ(100, response->headers->GetContentLength()); 5234 } 5235 5236 // ------------------------------------------------------------------------ 5237 5238 // Transaction 3: Resend a request in MyRealm's protection space -- 5239 // succeed with preemptive authorization. 5240 { 5241 HttpRequestInfo request; 5242 request.method = "GET"; 5243 request.url = GURL("http://www.google.com/x/y/z2"); 5244 request.load_flags = 0; 5245 5246 scoped_ptr<HttpTransaction> trans( 5247 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5248 5249 MockWrite data_writes1[] = { 5250 MockWrite("GET /x/y/z2 HTTP/1.1\r\n" 5251 "Host: www.google.com\r\n" 5252 "Connection: keep-alive\r\n" 5253 // The authorization for MyRealm1 gets sent preemptively 5254 // (since the url is in the same protection space) 5255 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5256 }; 5257 5258 // Sever accepts the preemptive authorization 5259 MockRead data_reads1[] = { 5260 MockRead("HTTP/1.0 200 OK\r\n"), 5261 MockRead("Content-Length: 100\r\n\r\n"), 5262 MockRead(SYNCHRONOUS, OK), 5263 }; 5264 5265 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5266 data_writes1, arraysize(data_writes1)); 5267 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5268 5269 TestCompletionCallback callback1; 5270 5271 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5272 EXPECT_EQ(ERR_IO_PENDING, rv); 5273 5274 rv = callback1.WaitForResult(); 5275 EXPECT_EQ(OK, rv); 5276 5277 const HttpResponseInfo* response = trans->GetResponseInfo(); 5278 ASSERT_TRUE(response != NULL); 5279 5280 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5281 EXPECT_EQ(100, response->headers->GetContentLength()); 5282 } 5283 5284 // ------------------------------------------------------------------------ 5285 5286 // Transaction 4: request another URL in MyRealm (however the 5287 // url is not known to belong to the protection space, so no pre-auth). 5288 { 5289 HttpRequestInfo request; 5290 request.method = "GET"; 5291 request.url = GURL("http://www.google.com/x/1"); 5292 request.load_flags = 0; 5293 5294 scoped_ptr<HttpTransaction> trans( 5295 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5296 5297 MockWrite data_writes1[] = { 5298 MockWrite("GET /x/1 HTTP/1.1\r\n" 5299 "Host: www.google.com\r\n" 5300 "Connection: keep-alive\r\n\r\n"), 5301 }; 5302 5303 MockRead data_reads1[] = { 5304 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5305 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5306 MockRead("Content-Length: 10000\r\n\r\n"), 5307 MockRead(SYNCHRONOUS, ERR_FAILED), 5308 }; 5309 5310 // Resend with authorization from MyRealm's cache. 5311 MockWrite data_writes2[] = { 5312 MockWrite("GET /x/1 HTTP/1.1\r\n" 5313 "Host: www.google.com\r\n" 5314 "Connection: keep-alive\r\n" 5315 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5316 }; 5317 5318 // Sever accepts the authorization. 5319 MockRead data_reads2[] = { 5320 MockRead("HTTP/1.0 200 OK\r\n"), 5321 MockRead("Content-Length: 100\r\n\r\n"), 5322 MockRead(SYNCHRONOUS, OK), 5323 }; 5324 5325 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5326 data_writes1, arraysize(data_writes1)); 5327 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5328 data_writes2, arraysize(data_writes2)); 5329 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5330 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5331 5332 TestCompletionCallback callback1; 5333 5334 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5335 EXPECT_EQ(ERR_IO_PENDING, rv); 5336 5337 rv = callback1.WaitForResult(); 5338 EXPECT_EQ(OK, rv); 5339 5340 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5341 TestCompletionCallback callback2; 5342 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5343 EXPECT_EQ(ERR_IO_PENDING, rv); 5344 rv = callback2.WaitForResult(); 5345 EXPECT_EQ(OK, rv); 5346 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5347 5348 const HttpResponseInfo* response = trans->GetResponseInfo(); 5349 ASSERT_TRUE(response != NULL); 5350 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5351 EXPECT_EQ(100, response->headers->GetContentLength()); 5352 } 5353 5354 // ------------------------------------------------------------------------ 5355 5356 // Transaction 5: request a URL in MyRealm, but the server rejects the 5357 // cached identity. Should invalidate and re-prompt. 5358 { 5359 HttpRequestInfo request; 5360 request.method = "GET"; 5361 request.url = GURL("http://www.google.com/p/q/t"); 5362 request.load_flags = 0; 5363 5364 scoped_ptr<HttpTransaction> trans( 5365 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5366 5367 MockWrite data_writes1[] = { 5368 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5369 "Host: www.google.com\r\n" 5370 "Connection: keep-alive\r\n\r\n"), 5371 }; 5372 5373 MockRead data_reads1[] = { 5374 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5375 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5376 MockRead("Content-Length: 10000\r\n\r\n"), 5377 MockRead(SYNCHRONOUS, ERR_FAILED), 5378 }; 5379 5380 // Resend with authorization from cache for MyRealm. 5381 MockWrite data_writes2[] = { 5382 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5383 "Host: www.google.com\r\n" 5384 "Connection: keep-alive\r\n" 5385 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5386 }; 5387 5388 // Sever rejects the authorization. 5389 MockRead data_reads2[] = { 5390 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5391 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5392 MockRead("Content-Length: 10000\r\n\r\n"), 5393 MockRead(SYNCHRONOUS, ERR_FAILED), 5394 }; 5395 5396 // At this point we should prompt for new credentials for MyRealm. 5397 // Restart with username=foo3, password=foo4. 5398 MockWrite data_writes3[] = { 5399 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5400 "Host: www.google.com\r\n" 5401 "Connection: keep-alive\r\n" 5402 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"), 5403 }; 5404 5405 // Sever accepts the authorization. 5406 MockRead data_reads3[] = { 5407 MockRead("HTTP/1.0 200 OK\r\n"), 5408 MockRead("Content-Length: 100\r\n\r\n"), 5409 MockRead(SYNCHRONOUS, OK), 5410 }; 5411 5412 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5413 data_writes1, arraysize(data_writes1)); 5414 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5415 data_writes2, arraysize(data_writes2)); 5416 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 5417 data_writes3, arraysize(data_writes3)); 5418 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5419 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5420 session_deps_.socket_factory->AddSocketDataProvider(&data3); 5421 5422 TestCompletionCallback callback1; 5423 5424 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5425 EXPECT_EQ(ERR_IO_PENDING, rv); 5426 5427 rv = callback1.WaitForResult(); 5428 EXPECT_EQ(OK, rv); 5429 5430 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5431 TestCompletionCallback callback2; 5432 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5433 EXPECT_EQ(ERR_IO_PENDING, rv); 5434 rv = callback2.WaitForResult(); 5435 EXPECT_EQ(OK, rv); 5436 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5437 5438 const HttpResponseInfo* response = trans->GetResponseInfo(); 5439 ASSERT_TRUE(response != NULL); 5440 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5441 5442 TestCompletionCallback callback3; 5443 5444 rv = trans->RestartWithAuth( 5445 AuthCredentials(kFoo3, kBar3), callback3.callback()); 5446 EXPECT_EQ(ERR_IO_PENDING, rv); 5447 5448 rv = callback3.WaitForResult(); 5449 EXPECT_EQ(OK, rv); 5450 5451 response = trans->GetResponseInfo(); 5452 ASSERT_TRUE(response != NULL); 5453 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5454 EXPECT_EQ(100, response->headers->GetContentLength()); 5455 } 5456} 5457 5458// Tests that nonce count increments when multiple auth attempts 5459// are started with the same nonce. 5460TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) { 5461 HttpAuthHandlerDigest::Factory* digest_factory = 5462 new HttpAuthHandlerDigest::Factory(); 5463 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator = 5464 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef"); 5465 digest_factory->set_nonce_generator(nonce_generator); 5466 session_deps_.http_auth_handler_factory.reset(digest_factory); 5467 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5468 5469 // Transaction 1: authenticate (foo, bar) on MyRealm1 5470 { 5471 HttpRequestInfo request; 5472 request.method = "GET"; 5473 request.url = GURL("http://www.google.com/x/y/z"); 5474 request.load_flags = 0; 5475 5476 scoped_ptr<HttpTransaction> trans( 5477 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5478 5479 MockWrite data_writes1[] = { 5480 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5481 "Host: www.google.com\r\n" 5482 "Connection: keep-alive\r\n\r\n"), 5483 }; 5484 5485 MockRead data_reads1[] = { 5486 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5487 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", " 5488 "algorithm=MD5, qop=\"auth\"\r\n\r\n"), 5489 MockRead(SYNCHRONOUS, OK), 5490 }; 5491 5492 // Resend with authorization (username=foo, password=bar) 5493 MockWrite data_writes2[] = { 5494 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5495 "Host: www.google.com\r\n" 5496 "Connection: keep-alive\r\n" 5497 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 5498 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, " 5499 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, " 5500 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"), 5501 }; 5502 5503 // Sever accepts the authorization. 5504 MockRead data_reads2[] = { 5505 MockRead("HTTP/1.0 200 OK\r\n"), 5506 MockRead(SYNCHRONOUS, OK), 5507 }; 5508 5509 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5510 data_writes1, arraysize(data_writes1)); 5511 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5512 data_writes2, arraysize(data_writes2)); 5513 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5514 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5515 5516 TestCompletionCallback callback1; 5517 5518 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5519 EXPECT_EQ(ERR_IO_PENDING, rv); 5520 5521 rv = callback1.WaitForResult(); 5522 EXPECT_EQ(OK, rv); 5523 5524 const HttpResponseInfo* response = trans->GetResponseInfo(); 5525 ASSERT_TRUE(response != NULL); 5526 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get())); 5527 5528 TestCompletionCallback callback2; 5529 5530 rv = trans->RestartWithAuth( 5531 AuthCredentials(kFoo, kBar), callback2.callback()); 5532 EXPECT_EQ(ERR_IO_PENDING, rv); 5533 5534 rv = callback2.WaitForResult(); 5535 EXPECT_EQ(OK, rv); 5536 5537 response = trans->GetResponseInfo(); 5538 ASSERT_TRUE(response != NULL); 5539 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5540 } 5541 5542 // ------------------------------------------------------------------------ 5543 5544 // Transaction 2: Request another resource in digestive's protection space. 5545 // This will preemptively add an Authorization header which should have an 5546 // "nc" value of 2 (as compared to 1 in the first use. 5547 { 5548 HttpRequestInfo request; 5549 request.method = "GET"; 5550 // Note that Transaction 1 was at /x/y/z, so this is in the same 5551 // protection space as digest. 5552 request.url = GURL("http://www.google.com/x/y/a/b"); 5553 request.load_flags = 0; 5554 5555 scoped_ptr<HttpTransaction> trans( 5556 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5557 5558 MockWrite data_writes1[] = { 5559 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5560 "Host: www.google.com\r\n" 5561 "Connection: keep-alive\r\n" 5562 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 5563 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, " 5564 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, " 5565 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"), 5566 }; 5567 5568 // Sever accepts the authorization. 5569 MockRead data_reads1[] = { 5570 MockRead("HTTP/1.0 200 OK\r\n"), 5571 MockRead("Content-Length: 100\r\n\r\n"), 5572 MockRead(SYNCHRONOUS, OK), 5573 }; 5574 5575 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5576 data_writes1, arraysize(data_writes1)); 5577 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5578 5579 TestCompletionCallback callback1; 5580 5581 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5582 EXPECT_EQ(ERR_IO_PENDING, rv); 5583 5584 rv = callback1.WaitForResult(); 5585 EXPECT_EQ(OK, rv); 5586 5587 const HttpResponseInfo* response = trans->GetResponseInfo(); 5588 ASSERT_TRUE(response != NULL); 5589 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5590 } 5591} 5592 5593// Test the ResetStateForRestart() private method. 5594TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) { 5595 // Create a transaction (the dependencies aren't important). 5596 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5597 scoped_ptr<HttpNetworkTransaction> trans( 5598 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5599 5600 // Setup some state (which we expect ResetStateForRestart() will clear). 5601 trans->read_buf_ = new IOBuffer(15); 5602 trans->read_buf_len_ = 15; 5603 trans->request_headers_.SetHeader("Authorization", "NTLM"); 5604 5605 // Setup state in response_ 5606 HttpResponseInfo* response = &trans->response_; 5607 response->auth_challenge = new AuthChallengeInfo(); 5608 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical. 5609 response->response_time = base::Time::Now(); 5610 response->was_cached = true; // (Wouldn't ever actually be true...) 5611 5612 { // Setup state for response_.vary_data 5613 HttpRequestInfo request; 5614 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n"); 5615 std::replace(temp.begin(), temp.end(), '\n', '\0'); 5616 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp)); 5617 request.extra_headers.SetHeader("Foo", "1"); 5618 request.extra_headers.SetHeader("bar", "23"); 5619 EXPECT_TRUE(response->vary_data.Init(request, *headers.get())); 5620 } 5621 5622 // Cause the above state to be reset. 5623 trans->ResetStateForRestart(); 5624 5625 // Verify that the state that needed to be reset, has been reset. 5626 EXPECT_TRUE(trans->read_buf_.get() == NULL); 5627 EXPECT_EQ(0, trans->read_buf_len_); 5628 EXPECT_TRUE(trans->request_headers_.IsEmpty()); 5629 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5630 EXPECT_TRUE(response->headers.get() == NULL); 5631 EXPECT_FALSE(response->was_cached); 5632 EXPECT_EQ(0U, response->ssl_info.cert_status); 5633 EXPECT_FALSE(response->vary_data.is_valid()); 5634} 5635 5636// Test HTTPS connections to a site with a bad certificate 5637TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) { 5638 HttpRequestInfo request; 5639 request.method = "GET"; 5640 request.url = GURL("https://www.google.com/"); 5641 request.load_flags = 0; 5642 5643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5644 scoped_ptr<HttpTransaction> trans( 5645 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5646 5647 MockWrite data_writes[] = { 5648 MockWrite("GET / HTTP/1.1\r\n" 5649 "Host: www.google.com\r\n" 5650 "Connection: keep-alive\r\n\r\n"), 5651 }; 5652 5653 MockRead data_reads[] = { 5654 MockRead("HTTP/1.0 200 OK\r\n"), 5655 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5656 MockRead("Content-Length: 100\r\n\r\n"), 5657 MockRead(SYNCHRONOUS, OK), 5658 }; 5659 5660 StaticSocketDataProvider ssl_bad_certificate; 5661 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5662 data_writes, arraysize(data_writes)); 5663 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 5664 SSLSocketDataProvider ssl(ASYNC, OK); 5665 5666 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 5667 session_deps_.socket_factory->AddSocketDataProvider(&data); 5668 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 5669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 5670 5671 TestCompletionCallback callback; 5672 5673 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5674 EXPECT_EQ(ERR_IO_PENDING, rv); 5675 5676 rv = callback.WaitForResult(); 5677 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 5678 5679 rv = trans->RestartIgnoringLastError(callback.callback()); 5680 EXPECT_EQ(ERR_IO_PENDING, rv); 5681 5682 rv = callback.WaitForResult(); 5683 EXPECT_EQ(OK, rv); 5684 5685 const HttpResponseInfo* response = trans->GetResponseInfo(); 5686 5687 ASSERT_TRUE(response != NULL); 5688 EXPECT_EQ(100, response->headers->GetContentLength()); 5689} 5690 5691// Test HTTPS connections to a site with a bad certificate, going through a 5692// proxy 5693TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { 5694 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 5695 5696 HttpRequestInfo request; 5697 request.method = "GET"; 5698 request.url = GURL("https://www.google.com/"); 5699 request.load_flags = 0; 5700 5701 MockWrite proxy_writes[] = { 5702 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5703 "Host: www.google.com\r\n" 5704 "Proxy-Connection: keep-alive\r\n\r\n"), 5705 }; 5706 5707 MockRead proxy_reads[] = { 5708 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5709 MockRead(SYNCHRONOUS, OK) 5710 }; 5711 5712 MockWrite data_writes[] = { 5713 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5714 "Host: www.google.com\r\n" 5715 "Proxy-Connection: keep-alive\r\n\r\n"), 5716 MockWrite("GET / HTTP/1.1\r\n" 5717 "Host: www.google.com\r\n" 5718 "Connection: keep-alive\r\n\r\n"), 5719 }; 5720 5721 MockRead data_reads[] = { 5722 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5723 MockRead("HTTP/1.0 200 OK\r\n"), 5724 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5725 MockRead("Content-Length: 100\r\n\r\n"), 5726 MockRead(SYNCHRONOUS, OK), 5727 }; 5728 5729 StaticSocketDataProvider ssl_bad_certificate( 5730 proxy_reads, arraysize(proxy_reads), 5731 proxy_writes, arraysize(proxy_writes)); 5732 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5733 data_writes, arraysize(data_writes)); 5734 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 5735 SSLSocketDataProvider ssl(ASYNC, OK); 5736 5737 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 5738 session_deps_.socket_factory->AddSocketDataProvider(&data); 5739 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 5740 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 5741 5742 TestCompletionCallback callback; 5743 5744 for (int i = 0; i < 2; i++) { 5745 session_deps_.socket_factory->ResetNextMockIndexes(); 5746 5747 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5748 scoped_ptr<HttpTransaction> trans( 5749 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5750 5751 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5752 EXPECT_EQ(ERR_IO_PENDING, rv); 5753 5754 rv = callback.WaitForResult(); 5755 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 5756 5757 rv = trans->RestartIgnoringLastError(callback.callback()); 5758 EXPECT_EQ(ERR_IO_PENDING, rv); 5759 5760 rv = callback.WaitForResult(); 5761 EXPECT_EQ(OK, rv); 5762 5763 const HttpResponseInfo* response = trans->GetResponseInfo(); 5764 5765 ASSERT_TRUE(response != NULL); 5766 EXPECT_EQ(100, response->headers->GetContentLength()); 5767 } 5768} 5769 5770 5771// Test HTTPS connections to a site, going through an HTTPS proxy 5772TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { 5773 session_deps_.proxy_service.reset( 5774 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 5775 CapturingNetLog net_log; 5776 session_deps_.net_log = &net_log; 5777 5778 HttpRequestInfo request; 5779 request.method = "GET"; 5780 request.url = GURL("https://www.google.com/"); 5781 request.load_flags = 0; 5782 5783 MockWrite data_writes[] = { 5784 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5785 "Host: www.google.com\r\n" 5786 "Proxy-Connection: keep-alive\r\n\r\n"), 5787 MockWrite("GET / HTTP/1.1\r\n" 5788 "Host: www.google.com\r\n" 5789 "Connection: keep-alive\r\n\r\n"), 5790 }; 5791 5792 MockRead data_reads[] = { 5793 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5794 MockRead("HTTP/1.1 200 OK\r\n"), 5795 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5796 MockRead("Content-Length: 100\r\n\r\n"), 5797 MockRead(SYNCHRONOUS, OK), 5798 }; 5799 5800 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5801 data_writes, arraysize(data_writes)); 5802 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5803 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel 5804 5805 session_deps_.socket_factory->AddSocketDataProvider(&data); 5806 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5807 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl); 5808 5809 TestCompletionCallback callback; 5810 5811 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5812 scoped_ptr<HttpTransaction> trans( 5813 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5814 5815 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5816 EXPECT_EQ(ERR_IO_PENDING, rv); 5817 5818 rv = callback.WaitForResult(); 5819 EXPECT_EQ(OK, rv); 5820 const HttpResponseInfo* response = trans->GetResponseInfo(); 5821 5822 ASSERT_TRUE(response != NULL); 5823 5824 EXPECT_TRUE(response->headers->IsKeepAlive()); 5825 EXPECT_EQ(200, response->headers->response_code()); 5826 EXPECT_EQ(100, response->headers->GetContentLength()); 5827 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 5828 5829 LoadTimingInfo load_timing_info; 5830 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 5831 TestLoadTimingNotReusedWithPac(load_timing_info, 5832 CONNECT_TIMING_HAS_SSL_TIMES); 5833} 5834 5835// Test an HTTPS Proxy's ability to redirect a CONNECT request 5836TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { 5837 session_deps_.proxy_service.reset( 5838 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 5839 CapturingNetLog net_log; 5840 session_deps_.net_log = &net_log; 5841 5842 HttpRequestInfo request; 5843 request.method = "GET"; 5844 request.url = GURL("https://www.google.com/"); 5845 request.load_flags = 0; 5846 5847 MockWrite data_writes[] = { 5848 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5849 "Host: www.google.com\r\n" 5850 "Proxy-Connection: keep-alive\r\n\r\n"), 5851 }; 5852 5853 MockRead data_reads[] = { 5854 MockRead("HTTP/1.1 302 Redirect\r\n"), 5855 MockRead("Location: http://login.example.com/\r\n"), 5856 MockRead("Content-Length: 0\r\n\r\n"), 5857 MockRead(SYNCHRONOUS, OK), 5858 }; 5859 5860 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5861 data_writes, arraysize(data_writes)); 5862 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5863 5864 session_deps_.socket_factory->AddSocketDataProvider(&data); 5865 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5866 5867 TestCompletionCallback callback; 5868 5869 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5870 scoped_ptr<HttpTransaction> trans( 5871 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5872 5873 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5874 EXPECT_EQ(ERR_IO_PENDING, rv); 5875 5876 rv = callback.WaitForResult(); 5877 EXPECT_EQ(OK, rv); 5878 const HttpResponseInfo* response = trans->GetResponseInfo(); 5879 5880 ASSERT_TRUE(response != NULL); 5881 5882 EXPECT_EQ(302, response->headers->response_code()); 5883 std::string url; 5884 EXPECT_TRUE(response->headers->IsRedirect(&url)); 5885 EXPECT_EQ("http://login.example.com/", url); 5886 5887 // In the case of redirects from proxies, HttpNetworkTransaction returns 5888 // timing for the proxy connection instead of the connection to the host, 5889 // and no send / receive times. 5890 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse. 5891 LoadTimingInfo load_timing_info; 5892 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 5893 5894 EXPECT_FALSE(load_timing_info.socket_reused); 5895 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 5896 5897 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 5898 EXPECT_LE(load_timing_info.proxy_resolve_start, 5899 load_timing_info.proxy_resolve_end); 5900 EXPECT_LE(load_timing_info.proxy_resolve_end, 5901 load_timing_info.connect_timing.connect_start); 5902 ExpectConnectTimingHasTimes( 5903 load_timing_info.connect_timing, 5904 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES); 5905 5906 EXPECT_TRUE(load_timing_info.send_start.is_null()); 5907 EXPECT_TRUE(load_timing_info.send_end.is_null()); 5908 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 5909} 5910 5911// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request 5912TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { 5913 session_deps_.proxy_service.reset( 5914 ProxyService::CreateFixed("https://proxy:70")); 5915 5916 HttpRequestInfo request; 5917 request.method = "GET"; 5918 request.url = GURL("https://www.google.com/"); 5919 request.load_flags = 0; 5920 5921 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 5922 LOWEST)); 5923 scoped_ptr<SpdyFrame> goaway( 5924 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 5925 MockWrite data_writes[] = { 5926 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), 5927 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS), 5928 }; 5929 5930 static const char* const kExtraHeaders[] = { 5931 "location", 5932 "http://login.example.com/", 5933 }; 5934 scoped_ptr<SpdyFrame> resp( 5935 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders, 5936 arraysize(kExtraHeaders)/2, 1)); 5937 MockRead data_reads[] = { 5938 CreateMockRead(*resp.get(), 1, SYNCHRONOUS), 5939 MockRead(ASYNC, 0, 2), // EOF 5940 }; 5941 5942 DelayedSocketData data( 5943 1, // wait for one write to finish before reading. 5944 data_reads, arraysize(data_reads), 5945 data_writes, arraysize(data_writes)); 5946 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 5947 proxy_ssl.SetNextProto(GetParam()); 5948 5949 session_deps_.socket_factory->AddSocketDataProvider(&data); 5950 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 5951 5952 TestCompletionCallback callback; 5953 5954 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5955 scoped_ptr<HttpTransaction> trans( 5956 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5957 5958 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5959 EXPECT_EQ(ERR_IO_PENDING, rv); 5960 5961 rv = callback.WaitForResult(); 5962 EXPECT_EQ(OK, rv); 5963 const HttpResponseInfo* response = trans->GetResponseInfo(); 5964 5965 ASSERT_TRUE(response != NULL); 5966 5967 EXPECT_EQ(302, response->headers->response_code()); 5968 std::string url; 5969 EXPECT_TRUE(response->headers->IsRedirect(&url)); 5970 EXPECT_EQ("http://login.example.com/", url); 5971} 5972 5973// Test that an HTTPS proxy's response to a CONNECT request is filtered. 5974TEST_P(HttpNetworkTransactionTest, 5975 ErrorResponseToHttpsConnectViaHttpsProxy) { 5976 session_deps_.proxy_service.reset( 5977 ProxyService::CreateFixed("https://proxy:70")); 5978 5979 HttpRequestInfo request; 5980 request.method = "GET"; 5981 request.url = GURL("https://www.google.com/"); 5982 request.load_flags = 0; 5983 5984 MockWrite data_writes[] = { 5985 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5986 "Host: www.google.com\r\n" 5987 "Proxy-Connection: keep-alive\r\n\r\n"), 5988 }; 5989 5990 MockRead data_reads[] = { 5991 MockRead("HTTP/1.1 404 Not Found\r\n"), 5992 MockRead("Content-Length: 23\r\n\r\n"), 5993 MockRead("The host does not exist"), 5994 MockRead(SYNCHRONOUS, OK), 5995 }; 5996 5997 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5998 data_writes, arraysize(data_writes)); 5999 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6000 6001 session_deps_.socket_factory->AddSocketDataProvider(&data); 6002 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6003 6004 TestCompletionCallback callback; 6005 6006 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6007 scoped_ptr<HttpTransaction> trans( 6008 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6009 6010 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6011 EXPECT_EQ(ERR_IO_PENDING, rv); 6012 6013 rv = callback.WaitForResult(); 6014 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 6015 6016 // TODO(ttuttle): Anything else to check here? 6017} 6018 6019// Test that a SPDY proxy's response to a CONNECT request is filtered. 6020TEST_P(HttpNetworkTransactionTest, 6021 ErrorResponseToHttpsConnectViaSpdyProxy) { 6022 session_deps_.proxy_service.reset( 6023 ProxyService::CreateFixed("https://proxy:70")); 6024 6025 HttpRequestInfo request; 6026 request.method = "GET"; 6027 request.url = GURL("https://www.google.com/"); 6028 request.load_flags = 0; 6029 6030 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 6031 LOWEST)); 6032 scoped_ptr<SpdyFrame> rst( 6033 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 6034 MockWrite data_writes[] = { 6035 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), 6036 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS), 6037 }; 6038 6039 static const char* const kExtraHeaders[] = { 6040 "location", 6041 "http://login.example.com/", 6042 }; 6043 scoped_ptr<SpdyFrame> resp( 6044 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders, 6045 arraysize(kExtraHeaders)/2, 1)); 6046 scoped_ptr<SpdyFrame> body( 6047 spdy_util_.ConstructSpdyBodyFrame( 6048 1, "The host does not exist", 23, true)); 6049 MockRead data_reads[] = { 6050 CreateMockRead(*resp.get(), 1, SYNCHRONOUS), 6051 CreateMockRead(*body.get(), 2, SYNCHRONOUS), 6052 MockRead(ASYNC, 0, 4), // EOF 6053 }; 6054 6055 DelayedSocketData data( 6056 1, // wait for one write to finish before reading. 6057 data_reads, arraysize(data_reads), 6058 data_writes, arraysize(data_writes)); 6059 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6060 proxy_ssl.SetNextProto(GetParam()); 6061 6062 session_deps_.socket_factory->AddSocketDataProvider(&data); 6063 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6064 6065 TestCompletionCallback callback; 6066 6067 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6068 scoped_ptr<HttpTransaction> trans( 6069 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6070 6071 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6072 EXPECT_EQ(ERR_IO_PENDING, rv); 6073 6074 rv = callback.WaitForResult(); 6075 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 6076 6077 // TODO(ttuttle): Anything else to check here? 6078} 6079 6080// Test the request-challenge-retry sequence for basic auth, through 6081// a SPDY proxy over a single SPDY session. 6082TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) { 6083 HttpRequestInfo request; 6084 request.method = "GET"; 6085 request.url = GURL("https://www.google.com/"); 6086 // when the no authentication data flag is set. 6087 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 6088 6089 // Configure against https proxy server "myproxy:70". 6090 session_deps_.proxy_service.reset( 6091 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); 6092 CapturingBoundNetLog log; 6093 session_deps_.net_log = log.bound().net_log(); 6094 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6095 6096 // Since we have proxy, should try to establish tunnel. 6097 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 6098 LOWEST)); 6099 scoped_ptr<SpdyFrame> rst( 6100 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 6101 6102 // After calling trans->RestartWithAuth(), this is the request we should 6103 // be issuing -- the final header line contains the credentials. 6104 const char* const kAuthCredentials[] = { 6105 "proxy-authorization", "Basic Zm9vOmJhcg==", 6106 }; 6107 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect( 6108 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST)); 6109 // fetch https://www.google.com/ via HTTP 6110 const char get[] = "GET / HTTP/1.1\r\n" 6111 "Host: www.google.com\r\n" 6112 "Connection: keep-alive\r\n\r\n"; 6113 scoped_ptr<SpdyFrame> wrapped_get( 6114 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false)); 6115 6116 MockWrite spdy_writes[] = { 6117 CreateMockWrite(*req, 1, ASYNC), 6118 CreateMockWrite(*rst, 4, ASYNC), 6119 CreateMockWrite(*connect2, 5), 6120 CreateMockWrite(*wrapped_get, 8), 6121 }; 6122 6123 // The proxy responds to the connect with a 407, using a persistent 6124 // connection. 6125 const char* const kAuthChallenge[] = { 6126 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required", 6127 spdy_util_.GetVersionKey(), "HTTP/1.1", 6128 "proxy-authenticate", "Basic realm=\"MyRealm1\"", 6129 }; 6130 6131 scoped_ptr<SpdyFrame> conn_auth_resp( 6132 spdy_util_.ConstructSpdyControlFrame(NULL, 6133 0, 6134 false, 6135 1, 6136 LOWEST, 6137 SYN_REPLY, 6138 CONTROL_FLAG_NONE, 6139 kAuthChallenge, 6140 arraysize(kAuthChallenge), 6141 0)); 6142 6143 scoped_ptr<SpdyFrame> conn_resp( 6144 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 6145 const char resp[] = "HTTP/1.1 200 OK\r\n" 6146 "Content-Length: 5\r\n\r\n"; 6147 6148 scoped_ptr<SpdyFrame> wrapped_get_resp( 6149 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false)); 6150 scoped_ptr<SpdyFrame> wrapped_body( 6151 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false)); 6152 MockRead spdy_reads[] = { 6153 CreateMockRead(*conn_auth_resp, 2, ASYNC), 6154 CreateMockRead(*conn_resp, 6, ASYNC), 6155 CreateMockRead(*wrapped_get_resp, 9, ASYNC), 6156 CreateMockRead(*wrapped_body, 10, ASYNC), 6157 MockRead(ASYNC, OK, 11), // EOF. May or may not be read. 6158 }; 6159 6160 OrderedSocketData spdy_data( 6161 spdy_reads, arraysize(spdy_reads), 6162 spdy_writes, arraysize(spdy_writes)); 6163 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6164 // Negotiate SPDY to the proxy 6165 SSLSocketDataProvider proxy(ASYNC, OK); 6166 proxy.SetNextProto(GetParam()); 6167 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6168 // Vanilla SSL to the server 6169 SSLSocketDataProvider server(ASYNC, OK); 6170 session_deps_.socket_factory->AddSSLSocketDataProvider(&server); 6171 6172 TestCompletionCallback callback1; 6173 6174 scoped_ptr<HttpTransaction> trans( 6175 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6176 6177 int rv = trans->Start(&request, callback1.callback(), log.bound()); 6178 EXPECT_EQ(ERR_IO_PENDING, rv); 6179 6180 rv = callback1.WaitForResult(); 6181 EXPECT_EQ(OK, rv); 6182 net::CapturingNetLog::CapturedEntryList entries; 6183 log.GetEntries(&entries); 6184 size_t pos = ExpectLogContainsSomewhere( 6185 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 6186 NetLog::PHASE_NONE); 6187 ExpectLogContainsSomewhere( 6188 entries, pos, 6189 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 6190 NetLog::PHASE_NONE); 6191 6192 const HttpResponseInfo* response = trans->GetResponseInfo(); 6193 ASSERT_TRUE(response != NULL); 6194 ASSERT_FALSE(response->headers.get() == NULL); 6195 EXPECT_EQ(407, response->headers->response_code()); 6196 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6197 EXPECT_TRUE(response->auth_challenge.get() != NULL); 6198 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 6199 6200 TestCompletionCallback callback2; 6201 6202 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), 6203 callback2.callback()); 6204 EXPECT_EQ(ERR_IO_PENDING, rv); 6205 6206 rv = callback2.WaitForResult(); 6207 EXPECT_EQ(OK, rv); 6208 6209 response = trans->GetResponseInfo(); 6210 ASSERT_TRUE(response != NULL); 6211 6212 EXPECT_TRUE(response->headers->IsKeepAlive()); 6213 EXPECT_EQ(200, response->headers->response_code()); 6214 EXPECT_EQ(5, response->headers->GetContentLength()); 6215 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6216 6217 // The password prompt info should not be set. 6218 EXPECT_TRUE(response->auth_challenge.get() == NULL); 6219 6220 LoadTimingInfo load_timing_info; 6221 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6222 TestLoadTimingNotReusedWithPac(load_timing_info, 6223 CONNECT_TIMING_HAS_SSL_TIMES); 6224 6225 trans.reset(); 6226 session->CloseAllConnections(); 6227} 6228 6229// Test that an explicitly trusted SPDY proxy can push a resource from an 6230// origin that is different from that of its associated resource. 6231TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) { 6232 HttpRequestInfo request; 6233 HttpRequestInfo push_request; 6234 6235 request.method = "GET"; 6236 request.url = GURL("http://www.google.com/"); 6237 push_request.method = "GET"; 6238 push_request.url = GURL("http://www.another-origin.com/foo.dat"); 6239 6240 // Configure against https proxy server "myproxy:70". 6241 session_deps_.proxy_service.reset( 6242 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); 6243 CapturingBoundNetLog log; 6244 session_deps_.net_log = log.bound().net_log(); 6245 6246 // Enable cross-origin push. 6247 session_deps_.trusted_spdy_proxy = "myproxy:70"; 6248 6249 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6250 6251 scoped_ptr<SpdyFrame> stream1_syn( 6252 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 6253 6254 MockWrite spdy_writes[] = { 6255 CreateMockWrite(*stream1_syn, 1, ASYNC), 6256 }; 6257 6258 scoped_ptr<SpdyFrame> 6259 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 6260 6261 scoped_ptr<SpdyFrame> 6262 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6263 6264 scoped_ptr<SpdyFrame> 6265 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 6266 0, 6267 2, 6268 1, 6269 "http://www.another-origin.com/foo.dat")); 6270 const char kPushedData[] = "pushed"; 6271 scoped_ptr<SpdyFrame> stream2_body( 6272 spdy_util_.ConstructSpdyBodyFrame( 6273 2, kPushedData, strlen(kPushedData), true)); 6274 6275 MockRead spdy_reads[] = { 6276 CreateMockRead(*stream1_reply, 2, ASYNC), 6277 CreateMockRead(*stream2_syn, 3, ASYNC), 6278 CreateMockRead(*stream1_body, 4, ASYNC), 6279 CreateMockRead(*stream2_body, 5, ASYNC), 6280 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 6281 }; 6282 6283 OrderedSocketData spdy_data( 6284 spdy_reads, arraysize(spdy_reads), 6285 spdy_writes, arraysize(spdy_writes)); 6286 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6287 // Negotiate SPDY to the proxy 6288 SSLSocketDataProvider proxy(ASYNC, OK); 6289 proxy.SetNextProto(GetParam()); 6290 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6291 6292 scoped_ptr<HttpTransaction> trans( 6293 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6294 TestCompletionCallback callback; 6295 int rv = trans->Start(&request, callback.callback(), log.bound()); 6296 EXPECT_EQ(ERR_IO_PENDING, rv); 6297 6298 rv = callback.WaitForResult(); 6299 EXPECT_EQ(OK, rv); 6300 const HttpResponseInfo* response = trans->GetResponseInfo(); 6301 6302 scoped_ptr<HttpTransaction> push_trans( 6303 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6304 rv = push_trans->Start(&push_request, callback.callback(), log.bound()); 6305 EXPECT_EQ(ERR_IO_PENDING, rv); 6306 6307 rv = callback.WaitForResult(); 6308 EXPECT_EQ(OK, rv); 6309 const HttpResponseInfo* push_response = push_trans->GetResponseInfo(); 6310 6311 ASSERT_TRUE(response != NULL); 6312 EXPECT_TRUE(response->headers->IsKeepAlive()); 6313 6314 EXPECT_EQ(200, response->headers->response_code()); 6315 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6316 6317 std::string response_data; 6318 rv = ReadTransaction(trans.get(), &response_data); 6319 EXPECT_EQ(OK, rv); 6320 EXPECT_EQ("hello!", response_data); 6321 6322 LoadTimingInfo load_timing_info; 6323 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6324 TestLoadTimingNotReusedWithPac(load_timing_info, 6325 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6326 6327 // Verify the pushed stream. 6328 EXPECT_TRUE(push_response->headers.get() != NULL); 6329 EXPECT_EQ(200, push_response->headers->response_code()); 6330 6331 rv = ReadTransaction(push_trans.get(), &response_data); 6332 EXPECT_EQ(OK, rv); 6333 EXPECT_EQ("pushed", response_data); 6334 6335 LoadTimingInfo push_load_timing_info; 6336 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info)); 6337 TestLoadTimingReusedWithPac(push_load_timing_info); 6338 // The transactions should share a socket ID, despite being for different 6339 // origins. 6340 EXPECT_EQ(load_timing_info.socket_log_id, 6341 push_load_timing_info.socket_log_id); 6342 6343 trans.reset(); 6344 push_trans.reset(); 6345 session->CloseAllConnections(); 6346} 6347 6348// Test that an explicitly trusted SPDY proxy cannot push HTTPS content. 6349TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) { 6350 HttpRequestInfo request; 6351 6352 request.method = "GET"; 6353 request.url = GURL("http://www.google.com/"); 6354 6355 // Configure against https proxy server "myproxy:70". 6356 session_deps_.proxy_service.reset( 6357 ProxyService::CreateFixed("https://myproxy:70")); 6358 CapturingBoundNetLog log; 6359 session_deps_.net_log = log.bound().net_log(); 6360 6361 // Enable cross-origin push. 6362 session_deps_.trusted_spdy_proxy = "myproxy:70"; 6363 6364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6365 6366 scoped_ptr<SpdyFrame> stream1_syn( 6367 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 6368 6369 scoped_ptr<SpdyFrame> push_rst( 6370 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 6371 6372 MockWrite spdy_writes[] = { 6373 CreateMockWrite(*stream1_syn, 1, ASYNC), 6374 CreateMockWrite(*push_rst, 4), 6375 }; 6376 6377 scoped_ptr<SpdyFrame> 6378 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 6379 6380 scoped_ptr<SpdyFrame> 6381 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6382 6383 scoped_ptr<SpdyFrame> 6384 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 6385 0, 6386 2, 6387 1, 6388 "https://www.another-origin.com/foo.dat")); 6389 6390 MockRead spdy_reads[] = { 6391 CreateMockRead(*stream1_reply, 2, ASYNC), 6392 CreateMockRead(*stream2_syn, 3, ASYNC), 6393 CreateMockRead(*stream1_body, 5, ASYNC), 6394 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 6395 }; 6396 6397 OrderedSocketData spdy_data( 6398 spdy_reads, arraysize(spdy_reads), 6399 spdy_writes, arraysize(spdy_writes)); 6400 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6401 // Negotiate SPDY to the proxy 6402 SSLSocketDataProvider proxy(ASYNC, OK); 6403 proxy.SetNextProto(GetParam()); 6404 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6405 6406 scoped_ptr<HttpTransaction> trans( 6407 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6408 TestCompletionCallback callback; 6409 int rv = trans->Start(&request, callback.callback(), log.bound()); 6410 EXPECT_EQ(ERR_IO_PENDING, rv); 6411 6412 rv = callback.WaitForResult(); 6413 EXPECT_EQ(OK, rv); 6414 const HttpResponseInfo* response = trans->GetResponseInfo(); 6415 6416 ASSERT_TRUE(response != NULL); 6417 EXPECT_TRUE(response->headers->IsKeepAlive()); 6418 6419 EXPECT_EQ(200, response->headers->response_code()); 6420 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6421 6422 std::string response_data; 6423 rv = ReadTransaction(trans.get(), &response_data); 6424 EXPECT_EQ(OK, rv); 6425 EXPECT_EQ("hello!", response_data); 6426 6427 trans.reset(); 6428 session->CloseAllConnections(); 6429} 6430 6431// Test HTTPS connections to a site with a bad certificate, going through an 6432// HTTPS proxy 6433TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { 6434 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 6435 "https://proxy:70")); 6436 6437 HttpRequestInfo request; 6438 request.method = "GET"; 6439 request.url = GURL("https://www.google.com/"); 6440 request.load_flags = 0; 6441 6442 // Attempt to fetch the URL from a server with a bad cert 6443 MockWrite bad_cert_writes[] = { 6444 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6445 "Host: www.google.com\r\n" 6446 "Proxy-Connection: keep-alive\r\n\r\n"), 6447 }; 6448 6449 MockRead bad_cert_reads[] = { 6450 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6451 MockRead(SYNCHRONOUS, OK) 6452 }; 6453 6454 // Attempt to fetch the URL with a good cert 6455 MockWrite good_data_writes[] = { 6456 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6457 "Host: www.google.com\r\n" 6458 "Proxy-Connection: keep-alive\r\n\r\n"), 6459 MockWrite("GET / HTTP/1.1\r\n" 6460 "Host: www.google.com\r\n" 6461 "Connection: keep-alive\r\n\r\n"), 6462 }; 6463 6464 MockRead good_cert_reads[] = { 6465 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6466 MockRead("HTTP/1.0 200 OK\r\n"), 6467 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6468 MockRead("Content-Length: 100\r\n\r\n"), 6469 MockRead(SYNCHRONOUS, OK), 6470 }; 6471 6472 StaticSocketDataProvider ssl_bad_certificate( 6473 bad_cert_reads, arraysize(bad_cert_reads), 6474 bad_cert_writes, arraysize(bad_cert_writes)); 6475 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads), 6476 good_data_writes, arraysize(good_data_writes)); 6477 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 6478 SSLSocketDataProvider ssl(ASYNC, OK); 6479 6480 // SSL to the proxy, then CONNECT request, then SSL with bad certificate 6481 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6482 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 6483 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 6484 6485 // SSL to the proxy, then CONNECT request, then valid SSL certificate 6486 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6487 session_deps_.socket_factory->AddSocketDataProvider(&data); 6488 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6489 6490 TestCompletionCallback callback; 6491 6492 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6493 scoped_ptr<HttpTransaction> trans( 6494 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6495 6496 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6497 EXPECT_EQ(ERR_IO_PENDING, rv); 6498 6499 rv = callback.WaitForResult(); 6500 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 6501 6502 rv = trans->RestartIgnoringLastError(callback.callback()); 6503 EXPECT_EQ(ERR_IO_PENDING, rv); 6504 6505 rv = callback.WaitForResult(); 6506 EXPECT_EQ(OK, rv); 6507 6508 const HttpResponseInfo* response = trans->GetResponseInfo(); 6509 6510 ASSERT_TRUE(response != NULL); 6511 EXPECT_EQ(100, response->headers->GetContentLength()); 6512} 6513 6514TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) { 6515 HttpRequestInfo request; 6516 request.method = "GET"; 6517 request.url = GURL("http://www.google.com/"); 6518 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 6519 "Chromium Ultra Awesome X Edition"); 6520 6521 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6522 scoped_ptr<HttpTransaction> trans( 6523 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6524 6525 MockWrite data_writes[] = { 6526 MockWrite("GET / HTTP/1.1\r\n" 6527 "Host: www.google.com\r\n" 6528 "Connection: keep-alive\r\n" 6529 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 6530 }; 6531 6532 // Lastly, the server responds with the actual content. 6533 MockRead data_reads[] = { 6534 MockRead("HTTP/1.0 200 OK\r\n"), 6535 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6536 MockRead("Content-Length: 100\r\n\r\n"), 6537 MockRead(SYNCHRONOUS, OK), 6538 }; 6539 6540 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6541 data_writes, arraysize(data_writes)); 6542 session_deps_.socket_factory->AddSocketDataProvider(&data); 6543 6544 TestCompletionCallback callback; 6545 6546 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6547 EXPECT_EQ(ERR_IO_PENDING, rv); 6548 6549 rv = callback.WaitForResult(); 6550 EXPECT_EQ(OK, rv); 6551} 6552 6553TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) { 6554 HttpRequestInfo request; 6555 request.method = "GET"; 6556 request.url = GURL("https://www.google.com/"); 6557 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 6558 "Chromium Ultra Awesome X Edition"); 6559 6560 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 6561 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6562 scoped_ptr<HttpTransaction> trans( 6563 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6564 6565 MockWrite data_writes[] = { 6566 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6567 "Host: www.google.com\r\n" 6568 "Proxy-Connection: keep-alive\r\n" 6569 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 6570 }; 6571 MockRead data_reads[] = { 6572 // Return an error, so the transaction stops here (this test isn't 6573 // interested in the rest). 6574 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 6575 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 6576 MockRead("Proxy-Connection: close\r\n\r\n"), 6577 }; 6578 6579 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6580 data_writes, arraysize(data_writes)); 6581 session_deps_.socket_factory->AddSocketDataProvider(&data); 6582 6583 TestCompletionCallback callback; 6584 6585 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6586 EXPECT_EQ(ERR_IO_PENDING, rv); 6587 6588 rv = callback.WaitForResult(); 6589 EXPECT_EQ(OK, rv); 6590} 6591 6592TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) { 6593 HttpRequestInfo request; 6594 request.method = "GET"; 6595 request.url = GURL("http://www.google.com/"); 6596 request.load_flags = 0; 6597 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer, 6598 "http://the.previous.site.com/"); 6599 6600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6601 scoped_ptr<HttpTransaction> trans( 6602 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6603 6604 MockWrite data_writes[] = { 6605 MockWrite("GET / HTTP/1.1\r\n" 6606 "Host: www.google.com\r\n" 6607 "Connection: keep-alive\r\n" 6608 "Referer: http://the.previous.site.com/\r\n\r\n"), 6609 }; 6610 6611 // Lastly, the server responds with the actual content. 6612 MockRead data_reads[] = { 6613 MockRead("HTTP/1.0 200 OK\r\n"), 6614 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6615 MockRead("Content-Length: 100\r\n\r\n"), 6616 MockRead(SYNCHRONOUS, OK), 6617 }; 6618 6619 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6620 data_writes, arraysize(data_writes)); 6621 session_deps_.socket_factory->AddSocketDataProvider(&data); 6622 6623 TestCompletionCallback callback; 6624 6625 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6626 EXPECT_EQ(ERR_IO_PENDING, rv); 6627 6628 rv = callback.WaitForResult(); 6629 EXPECT_EQ(OK, rv); 6630} 6631 6632TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) { 6633 HttpRequestInfo request; 6634 request.method = "POST"; 6635 request.url = GURL("http://www.google.com/"); 6636 6637 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6638 scoped_ptr<HttpTransaction> trans( 6639 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6640 6641 MockWrite data_writes[] = { 6642 MockWrite("POST / HTTP/1.1\r\n" 6643 "Host: www.google.com\r\n" 6644 "Connection: keep-alive\r\n" 6645 "Content-Length: 0\r\n\r\n"), 6646 }; 6647 6648 // Lastly, the server responds with the actual content. 6649 MockRead data_reads[] = { 6650 MockRead("HTTP/1.0 200 OK\r\n"), 6651 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6652 MockRead("Content-Length: 100\r\n\r\n"), 6653 MockRead(SYNCHRONOUS, OK), 6654 }; 6655 6656 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6657 data_writes, arraysize(data_writes)); 6658 session_deps_.socket_factory->AddSocketDataProvider(&data); 6659 6660 TestCompletionCallback callback; 6661 6662 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6663 EXPECT_EQ(ERR_IO_PENDING, rv); 6664 6665 rv = callback.WaitForResult(); 6666 EXPECT_EQ(OK, rv); 6667} 6668 6669TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) { 6670 HttpRequestInfo request; 6671 request.method = "PUT"; 6672 request.url = GURL("http://www.google.com/"); 6673 6674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6675 scoped_ptr<HttpTransaction> trans( 6676 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6677 6678 MockWrite data_writes[] = { 6679 MockWrite("PUT / HTTP/1.1\r\n" 6680 "Host: www.google.com\r\n" 6681 "Connection: keep-alive\r\n" 6682 "Content-Length: 0\r\n\r\n"), 6683 }; 6684 6685 // Lastly, the server responds with the actual content. 6686 MockRead data_reads[] = { 6687 MockRead("HTTP/1.0 200 OK\r\n"), 6688 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6689 MockRead("Content-Length: 100\r\n\r\n"), 6690 MockRead(SYNCHRONOUS, OK), 6691 }; 6692 6693 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6694 data_writes, arraysize(data_writes)); 6695 session_deps_.socket_factory->AddSocketDataProvider(&data); 6696 6697 TestCompletionCallback callback; 6698 6699 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6700 EXPECT_EQ(ERR_IO_PENDING, rv); 6701 6702 rv = callback.WaitForResult(); 6703 EXPECT_EQ(OK, rv); 6704} 6705 6706TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) { 6707 HttpRequestInfo request; 6708 request.method = "HEAD"; 6709 request.url = GURL("http://www.google.com/"); 6710 6711 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6712 scoped_ptr<HttpTransaction> trans( 6713 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6714 6715 MockWrite data_writes[] = { 6716 MockWrite("HEAD / HTTP/1.1\r\n" 6717 "Host: www.google.com\r\n" 6718 "Connection: keep-alive\r\n" 6719 "Content-Length: 0\r\n\r\n"), 6720 }; 6721 6722 // Lastly, the server responds with the actual content. 6723 MockRead data_reads[] = { 6724 MockRead("HTTP/1.0 200 OK\r\n"), 6725 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6726 MockRead("Content-Length: 100\r\n\r\n"), 6727 MockRead(SYNCHRONOUS, OK), 6728 }; 6729 6730 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6731 data_writes, arraysize(data_writes)); 6732 session_deps_.socket_factory->AddSocketDataProvider(&data); 6733 6734 TestCompletionCallback callback; 6735 6736 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6737 EXPECT_EQ(ERR_IO_PENDING, rv); 6738 6739 rv = callback.WaitForResult(); 6740 EXPECT_EQ(OK, rv); 6741} 6742 6743TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) { 6744 HttpRequestInfo request; 6745 request.method = "GET"; 6746 request.url = GURL("http://www.google.com/"); 6747 request.load_flags = LOAD_BYPASS_CACHE; 6748 6749 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6750 scoped_ptr<HttpTransaction> trans( 6751 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6752 6753 MockWrite data_writes[] = { 6754 MockWrite("GET / HTTP/1.1\r\n" 6755 "Host: www.google.com\r\n" 6756 "Connection: keep-alive\r\n" 6757 "Pragma: no-cache\r\n" 6758 "Cache-Control: no-cache\r\n\r\n"), 6759 }; 6760 6761 // Lastly, the server responds with the actual content. 6762 MockRead data_reads[] = { 6763 MockRead("HTTP/1.0 200 OK\r\n"), 6764 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6765 MockRead("Content-Length: 100\r\n\r\n"), 6766 MockRead(SYNCHRONOUS, OK), 6767 }; 6768 6769 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6770 data_writes, arraysize(data_writes)); 6771 session_deps_.socket_factory->AddSocketDataProvider(&data); 6772 6773 TestCompletionCallback callback; 6774 6775 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6776 EXPECT_EQ(ERR_IO_PENDING, rv); 6777 6778 rv = callback.WaitForResult(); 6779 EXPECT_EQ(OK, rv); 6780} 6781 6782TEST_P(HttpNetworkTransactionTest, 6783 BuildRequest_CacheControlValidateCache) { 6784 HttpRequestInfo request; 6785 request.method = "GET"; 6786 request.url = GURL("http://www.google.com/"); 6787 request.load_flags = LOAD_VALIDATE_CACHE; 6788 6789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6790 scoped_ptr<HttpTransaction> trans( 6791 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6792 6793 MockWrite data_writes[] = { 6794 MockWrite("GET / HTTP/1.1\r\n" 6795 "Host: www.google.com\r\n" 6796 "Connection: keep-alive\r\n" 6797 "Cache-Control: max-age=0\r\n\r\n"), 6798 }; 6799 6800 // Lastly, the server responds with the actual content. 6801 MockRead data_reads[] = { 6802 MockRead("HTTP/1.0 200 OK\r\n"), 6803 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6804 MockRead("Content-Length: 100\r\n\r\n"), 6805 MockRead(SYNCHRONOUS, OK), 6806 }; 6807 6808 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6809 data_writes, arraysize(data_writes)); 6810 session_deps_.socket_factory->AddSocketDataProvider(&data); 6811 6812 TestCompletionCallback callback; 6813 6814 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6815 EXPECT_EQ(ERR_IO_PENDING, rv); 6816 6817 rv = callback.WaitForResult(); 6818 EXPECT_EQ(OK, rv); 6819} 6820 6821TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) { 6822 HttpRequestInfo request; 6823 request.method = "GET"; 6824 request.url = GURL("http://www.google.com/"); 6825 request.extra_headers.SetHeader("FooHeader", "Bar"); 6826 6827 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6828 scoped_ptr<HttpTransaction> trans( 6829 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6830 6831 MockWrite data_writes[] = { 6832 MockWrite("GET / HTTP/1.1\r\n" 6833 "Host: www.google.com\r\n" 6834 "Connection: keep-alive\r\n" 6835 "FooHeader: Bar\r\n\r\n"), 6836 }; 6837 6838 // Lastly, the server responds with the actual content. 6839 MockRead data_reads[] = { 6840 MockRead("HTTP/1.0 200 OK\r\n"), 6841 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6842 MockRead("Content-Length: 100\r\n\r\n"), 6843 MockRead(SYNCHRONOUS, OK), 6844 }; 6845 6846 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6847 data_writes, arraysize(data_writes)); 6848 session_deps_.socket_factory->AddSocketDataProvider(&data); 6849 6850 TestCompletionCallback callback; 6851 6852 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6853 EXPECT_EQ(ERR_IO_PENDING, rv); 6854 6855 rv = callback.WaitForResult(); 6856 EXPECT_EQ(OK, rv); 6857} 6858 6859TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) { 6860 HttpRequestInfo request; 6861 request.method = "GET"; 6862 request.url = GURL("http://www.google.com/"); 6863 request.extra_headers.SetHeader("referer", "www.foo.com"); 6864 request.extra_headers.SetHeader("hEllo", "Kitty"); 6865 request.extra_headers.SetHeader("FoO", "bar"); 6866 6867 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6868 scoped_ptr<HttpTransaction> trans( 6869 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6870 6871 MockWrite data_writes[] = { 6872 MockWrite("GET / HTTP/1.1\r\n" 6873 "Host: www.google.com\r\n" 6874 "Connection: keep-alive\r\n" 6875 "referer: www.foo.com\r\n" 6876 "hEllo: Kitty\r\n" 6877 "FoO: bar\r\n\r\n"), 6878 }; 6879 6880 // Lastly, the server responds with the actual content. 6881 MockRead data_reads[] = { 6882 MockRead("HTTP/1.0 200 OK\r\n"), 6883 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6884 MockRead("Content-Length: 100\r\n\r\n"), 6885 MockRead(SYNCHRONOUS, OK), 6886 }; 6887 6888 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6889 data_writes, arraysize(data_writes)); 6890 session_deps_.socket_factory->AddSocketDataProvider(&data); 6891 6892 TestCompletionCallback callback; 6893 6894 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6895 EXPECT_EQ(ERR_IO_PENDING, rv); 6896 6897 rv = callback.WaitForResult(); 6898 EXPECT_EQ(OK, rv); 6899} 6900 6901TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) { 6902 HttpRequestInfo request; 6903 request.method = "GET"; 6904 request.url = GURL("http://www.google.com/"); 6905 request.load_flags = 0; 6906 6907 session_deps_.proxy_service.reset( 6908 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080")); 6909 CapturingNetLog net_log; 6910 session_deps_.net_log = &net_log; 6911 6912 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6913 scoped_ptr<HttpTransaction> trans( 6914 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6915 6916 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; 6917 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 6918 6919 MockWrite data_writes[] = { 6920 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)), 6921 MockWrite("GET / HTTP/1.1\r\n" 6922 "Host: www.google.com\r\n" 6923 "Connection: keep-alive\r\n\r\n") 6924 }; 6925 6926 MockRead data_reads[] = { 6927 MockRead(ASYNC, read_buffer, arraysize(read_buffer)), 6928 MockRead("HTTP/1.0 200 OK\r\n"), 6929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6930 MockRead("Payload"), 6931 MockRead(SYNCHRONOUS, OK) 6932 }; 6933 6934 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6935 data_writes, arraysize(data_writes)); 6936 session_deps_.socket_factory->AddSocketDataProvider(&data); 6937 6938 TestCompletionCallback callback; 6939 6940 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6941 EXPECT_EQ(ERR_IO_PENDING, rv); 6942 6943 rv = callback.WaitForResult(); 6944 EXPECT_EQ(OK, rv); 6945 6946 const HttpResponseInfo* response = trans->GetResponseInfo(); 6947 ASSERT_TRUE(response != NULL); 6948 6949 LoadTimingInfo load_timing_info; 6950 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6951 TestLoadTimingNotReusedWithPac(load_timing_info, 6952 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6953 6954 std::string response_text; 6955 rv = ReadTransaction(trans.get(), &response_text); 6956 EXPECT_EQ(OK, rv); 6957 EXPECT_EQ("Payload", response_text); 6958} 6959 6960TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) { 6961 HttpRequestInfo request; 6962 request.method = "GET"; 6963 request.url = GURL("https://www.google.com/"); 6964 request.load_flags = 0; 6965 6966 session_deps_.proxy_service.reset( 6967 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080")); 6968 CapturingNetLog net_log; 6969 session_deps_.net_log = &net_log; 6970 6971 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6972 scoped_ptr<HttpTransaction> trans( 6973 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6974 6975 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 }; 6976 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 6977 6978 MockWrite data_writes[] = { 6979 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer), 6980 arraysize(write_buffer)), 6981 MockWrite("GET / HTTP/1.1\r\n" 6982 "Host: www.google.com\r\n" 6983 "Connection: keep-alive\r\n\r\n") 6984 }; 6985 6986 MockRead data_reads[] = { 6987 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer), 6988 arraysize(read_buffer)), 6989 MockRead("HTTP/1.0 200 OK\r\n"), 6990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 6991 MockRead("Payload"), 6992 MockRead(SYNCHRONOUS, OK) 6993 }; 6994 6995 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6996 data_writes, arraysize(data_writes)); 6997 session_deps_.socket_factory->AddSocketDataProvider(&data); 6998 6999 SSLSocketDataProvider ssl(ASYNC, OK); 7000 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 7001 7002 TestCompletionCallback callback; 7003 7004 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7005 EXPECT_EQ(ERR_IO_PENDING, rv); 7006 7007 rv = callback.WaitForResult(); 7008 EXPECT_EQ(OK, rv); 7009 7010 LoadTimingInfo load_timing_info; 7011 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 7012 TestLoadTimingNotReusedWithPac(load_timing_info, 7013 CONNECT_TIMING_HAS_SSL_TIMES); 7014 7015 const HttpResponseInfo* response = trans->GetResponseInfo(); 7016 ASSERT_TRUE(response != NULL); 7017 7018 std::string response_text; 7019 rv = ReadTransaction(trans.get(), &response_text); 7020 EXPECT_EQ(OK, rv); 7021 EXPECT_EQ("Payload", response_text); 7022} 7023 7024TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) { 7025 HttpRequestInfo request; 7026 request.method = "GET"; 7027 request.url = GURL("http://www.google.com/"); 7028 request.load_flags = 0; 7029 7030 session_deps_.proxy_service.reset( 7031 ProxyService::CreateFixed("socks4://myproxy:1080")); 7032 CapturingNetLog net_log; 7033 session_deps_.net_log = &net_log; 7034 7035 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7036 scoped_ptr<HttpTransaction> trans( 7037 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7038 7039 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 }; 7040 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 }; 7041 7042 MockWrite data_writes[] = { 7043 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)), 7044 MockWrite("GET / HTTP/1.1\r\n" 7045 "Host: www.google.com\r\n" 7046 "Connection: keep-alive\r\n\r\n") 7047 }; 7048 7049 MockRead data_reads[] = { 7050 MockRead(ASYNC, read_buffer, arraysize(read_buffer)), 7051 MockRead("HTTP/1.0 200 OK\r\n"), 7052 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 7053 MockRead("Payload"), 7054 MockRead(SYNCHRONOUS, OK) 7055 }; 7056 7057 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7058 data_writes, arraysize(data_writes)); 7059 session_deps_.socket_factory->AddSocketDataProvider(&data); 7060 7061 TestCompletionCallback callback; 7062 7063 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7064 EXPECT_EQ(ERR_IO_PENDING, rv); 7065 7066 rv = callback.WaitForResult(); 7067 EXPECT_EQ(OK, rv); 7068 7069 const HttpResponseInfo* response = trans->GetResponseInfo(); 7070 ASSERT_TRUE(response != NULL); 7071 7072 LoadTimingInfo load_timing_info; 7073 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 7074 TestLoadTimingNotReused(load_timing_info, 7075 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 7076 7077 std::string response_text; 7078 rv = ReadTransaction(trans.get(), &response_text); 7079 EXPECT_EQ(OK, rv); 7080 EXPECT_EQ("Payload", response_text); 7081} 7082 7083TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) { 7084 HttpRequestInfo request; 7085 request.method = "GET"; 7086 request.url = GURL("http://www.google.com/"); 7087 request.load_flags = 0; 7088 7089 session_deps_.proxy_service.reset( 7090 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080")); 7091 CapturingNetLog net_log; 7092 session_deps_.net_log = &net_log; 7093 7094 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7095 scoped_ptr<HttpTransaction> trans( 7096 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7097 7098 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; 7099 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; 7100 const char kSOCKS5OkRequest[] = { 7101 0x05, // Version 7102 0x01, // Command (CONNECT) 7103 0x00, // Reserved. 7104 0x03, // Address type (DOMAINNAME). 7105 0x0E, // Length of domain (14) 7106 // Domain string: 7107 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', 7108 0x00, 0x50, // 16-bit port (80) 7109 }; 7110 const char kSOCKS5OkResponse[] = 7111 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 }; 7112 7113 MockWrite data_writes[] = { 7114 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), 7115 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)), 7116 MockWrite("GET / HTTP/1.1\r\n" 7117 "Host: www.google.com\r\n" 7118 "Connection: keep-alive\r\n\r\n") 7119 }; 7120 7121 MockRead data_reads[] = { 7122 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), 7123 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), 7124 MockRead("HTTP/1.0 200 OK\r\n"), 7125 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 7126 MockRead("Payload"), 7127 MockRead(SYNCHRONOUS, OK) 7128 }; 7129 7130 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7131 data_writes, arraysize(data_writes)); 7132 session_deps_.socket_factory->AddSocketDataProvider(&data); 7133 7134 TestCompletionCallback callback; 7135 7136 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7137 EXPECT_EQ(ERR_IO_PENDING, rv); 7138 7139 rv = callback.WaitForResult(); 7140 EXPECT_EQ(OK, rv); 7141 7142 const HttpResponseInfo* response = trans->GetResponseInfo(); 7143 ASSERT_TRUE(response != NULL); 7144 7145 LoadTimingInfo load_timing_info; 7146 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 7147 TestLoadTimingNotReusedWithPac(load_timing_info, 7148 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 7149 7150 std::string response_text; 7151 rv = ReadTransaction(trans.get(), &response_text); 7152 EXPECT_EQ(OK, rv); 7153 EXPECT_EQ("Payload", response_text); 7154} 7155 7156TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) { 7157 HttpRequestInfo request; 7158 request.method = "GET"; 7159 request.url = GURL("https://www.google.com/"); 7160 request.load_flags = 0; 7161 7162 session_deps_.proxy_service.reset( 7163 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080")); 7164 CapturingNetLog net_log; 7165 session_deps_.net_log = &net_log; 7166 7167 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7168 scoped_ptr<HttpTransaction> trans( 7169 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7170 7171 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; 7172 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; 7173 const unsigned char kSOCKS5OkRequest[] = { 7174 0x05, // Version 7175 0x01, // Command (CONNECT) 7176 0x00, // Reserved. 7177 0x03, // Address type (DOMAINNAME). 7178 0x0E, // Length of domain (14) 7179 // Domain string: 7180 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', 7181 0x01, 0xBB, // 16-bit port (443) 7182 }; 7183 7184 const char kSOCKS5OkResponse[] = 7185 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 }; 7186 7187 MockWrite data_writes[] = { 7188 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), 7189 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest), 7190 arraysize(kSOCKS5OkRequest)), 7191 MockWrite("GET / HTTP/1.1\r\n" 7192 "Host: www.google.com\r\n" 7193 "Connection: keep-alive\r\n\r\n") 7194 }; 7195 7196 MockRead data_reads[] = { 7197 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), 7198 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), 7199 MockRead("HTTP/1.0 200 OK\r\n"), 7200 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"), 7201 MockRead("Payload"), 7202 MockRead(SYNCHRONOUS, OK) 7203 }; 7204 7205 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7206 data_writes, arraysize(data_writes)); 7207 session_deps_.socket_factory->AddSocketDataProvider(&data); 7208 7209 SSLSocketDataProvider ssl(ASYNC, OK); 7210 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 7211 7212 TestCompletionCallback callback; 7213 7214 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7215 EXPECT_EQ(ERR_IO_PENDING, rv); 7216 7217 rv = callback.WaitForResult(); 7218 EXPECT_EQ(OK, rv); 7219 7220 const HttpResponseInfo* response = trans->GetResponseInfo(); 7221 ASSERT_TRUE(response != NULL); 7222 7223 LoadTimingInfo load_timing_info; 7224 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 7225 TestLoadTimingNotReusedWithPac(load_timing_info, 7226 CONNECT_TIMING_HAS_SSL_TIMES); 7227 7228 std::string response_text; 7229 rv = ReadTransaction(trans.get(), &response_text); 7230 EXPECT_EQ(OK, rv); 7231 EXPECT_EQ("Payload", response_text); 7232} 7233 7234namespace { 7235 7236// Tests that for connection endpoints the group names are correctly set. 7237 7238struct GroupNameTest { 7239 std::string proxy_server; 7240 std::string url; 7241 std::string expected_group_name; 7242 bool ssl; 7243}; 7244 7245scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests( 7246 NextProto next_proto, 7247 SpdySessionDependencies* session_deps_) { 7248 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_)); 7249 7250 base::WeakPtr<HttpServerProperties> http_server_properties = 7251 session->http_server_properties(); 7252 http_server_properties->SetAlternateProtocol( 7253 HostPortPair("host.with.alternate", 80), 443, 7254 AlternateProtocolFromNextProto(next_proto)); 7255 7256 return session; 7257} 7258 7259int GroupNameTransactionHelper( 7260 const std::string& url, 7261 const scoped_refptr<HttpNetworkSession>& session) { 7262 HttpRequestInfo request; 7263 request.method = "GET"; 7264 request.url = GURL(url); 7265 request.load_flags = 0; 7266 7267 scoped_ptr<HttpTransaction> trans( 7268 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7269 7270 TestCompletionCallback callback; 7271 7272 // We do not complete this request, the dtor will clean the transaction up. 7273 return trans->Start(&request, callback.callback(), BoundNetLog()); 7274} 7275 7276} // namespace 7277 7278TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) { 7279 const GroupNameTest tests[] = { 7280 { 7281 "", // unused 7282 "http://www.google.com/direct", 7283 "www.google.com:80", 7284 false, 7285 }, 7286 { 7287 "", // unused 7288 "http://[2001:1418:13:1::25]/direct", 7289 "[2001:1418:13:1::25]:80", 7290 false, 7291 }, 7292 7293 // SSL Tests 7294 { 7295 "", // unused 7296 "https://www.google.com/direct_ssl", 7297 "ssl/www.google.com:443", 7298 true, 7299 }, 7300 { 7301 "", // unused 7302 "https://[2001:1418:13:1::25]/direct", 7303 "ssl/[2001:1418:13:1::25]:443", 7304 true, 7305 }, 7306 { 7307 "", // unused 7308 "http://host.with.alternate/direct", 7309 "ssl/host.with.alternate:443", 7310 true, 7311 }, 7312 }; 7313 7314 HttpStreamFactory::set_use_alternate_protocols(true); 7315 7316 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 7317 session_deps_.proxy_service.reset( 7318 ProxyService::CreateFixed(tests[i].proxy_server)); 7319 scoped_refptr<HttpNetworkSession> session( 7320 SetupSessionForGroupNameTests(GetParam(), &session_deps_)); 7321 7322 HttpNetworkSessionPeer peer(session); 7323 CaptureGroupNameTransportSocketPool* transport_conn_pool = 7324 new CaptureGroupNameTransportSocketPool(NULL, NULL); 7325 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 7326 new CaptureGroupNameSSLSocketPool(NULL, NULL); 7327 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( 7328 new MockClientSocketPoolManager); 7329 mock_pool_manager->SetTransportSocketPool(transport_conn_pool); 7330 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool); 7331 peer.SetClientSocketPoolManager( 7332 mock_pool_manager.PassAs<ClientSocketPoolManager>()); 7333 7334 EXPECT_EQ(ERR_IO_PENDING, 7335 GroupNameTransactionHelper(tests[i].url, session)); 7336 if (tests[i].ssl) 7337 EXPECT_EQ(tests[i].expected_group_name, 7338 ssl_conn_pool->last_group_name_received()); 7339 else 7340 EXPECT_EQ(tests[i].expected_group_name, 7341 transport_conn_pool->last_group_name_received()); 7342 } 7343 7344} 7345 7346TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) { 7347 const GroupNameTest tests[] = { 7348 { 7349 "http_proxy", 7350 "http://www.google.com/http_proxy_normal", 7351 "www.google.com:80", 7352 false, 7353 }, 7354 7355 // SSL Tests 7356 { 7357 "http_proxy", 7358 "https://www.google.com/http_connect_ssl", 7359 "ssl/www.google.com:443", 7360 true, 7361 }, 7362 7363 { 7364 "http_proxy", 7365 "http://host.with.alternate/direct", 7366 "ssl/host.with.alternate:443", 7367 true, 7368 }, 7369 7370 { 7371 "http_proxy", 7372 "ftp://ftp.google.com/http_proxy_normal", 7373 "ftp/ftp.google.com:21", 7374 false, 7375 }, 7376 }; 7377 7378 HttpStreamFactory::set_use_alternate_protocols(true); 7379 7380 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 7381 session_deps_.proxy_service.reset( 7382 ProxyService::CreateFixed(tests[i].proxy_server)); 7383 scoped_refptr<HttpNetworkSession> session( 7384 SetupSessionForGroupNameTests(GetParam(), &session_deps_)); 7385 7386 HttpNetworkSessionPeer peer(session); 7387 7388 HostPortPair proxy_host("http_proxy", 80); 7389 CaptureGroupNameHttpProxySocketPool* http_proxy_pool = 7390 new CaptureGroupNameHttpProxySocketPool(NULL, NULL); 7391 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 7392 new CaptureGroupNameSSLSocketPool(NULL, NULL); 7393 7394 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( 7395 new MockClientSocketPoolManager); 7396 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool); 7397 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); 7398 peer.SetClientSocketPoolManager( 7399 mock_pool_manager.PassAs<ClientSocketPoolManager>()); 7400 7401 EXPECT_EQ(ERR_IO_PENDING, 7402 GroupNameTransactionHelper(tests[i].url, session)); 7403 if (tests[i].ssl) 7404 EXPECT_EQ(tests[i].expected_group_name, 7405 ssl_conn_pool->last_group_name_received()); 7406 else 7407 EXPECT_EQ(tests[i].expected_group_name, 7408 http_proxy_pool->last_group_name_received()); 7409 } 7410} 7411 7412TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) { 7413 const GroupNameTest tests[] = { 7414 { 7415 "socks4://socks_proxy:1080", 7416 "http://www.google.com/socks4_direct", 7417 "socks4/www.google.com:80", 7418 false, 7419 }, 7420 { 7421 "socks5://socks_proxy:1080", 7422 "http://www.google.com/socks5_direct", 7423 "socks5/www.google.com:80", 7424 false, 7425 }, 7426 7427 // SSL Tests 7428 { 7429 "socks4://socks_proxy:1080", 7430 "https://www.google.com/socks4_ssl", 7431 "socks4/ssl/www.google.com:443", 7432 true, 7433 }, 7434 { 7435 "socks5://socks_proxy:1080", 7436 "https://www.google.com/socks5_ssl", 7437 "socks5/ssl/www.google.com:443", 7438 true, 7439 }, 7440 7441 { 7442 "socks4://socks_proxy:1080", 7443 "http://host.with.alternate/direct", 7444 "socks4/ssl/host.with.alternate:443", 7445 true, 7446 }, 7447 }; 7448 7449 HttpStreamFactory::set_use_alternate_protocols(true); 7450 7451 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 7452 session_deps_.proxy_service.reset( 7453 ProxyService::CreateFixed(tests[i].proxy_server)); 7454 scoped_refptr<HttpNetworkSession> session( 7455 SetupSessionForGroupNameTests(GetParam(), &session_deps_)); 7456 7457 HttpNetworkSessionPeer peer(session); 7458 7459 HostPortPair proxy_host("socks_proxy", 1080); 7460 CaptureGroupNameSOCKSSocketPool* socks_conn_pool = 7461 new CaptureGroupNameSOCKSSocketPool(NULL, NULL); 7462 CaptureGroupNameSSLSocketPool* ssl_conn_pool = 7463 new CaptureGroupNameSSLSocketPool(NULL, NULL); 7464 7465 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( 7466 new MockClientSocketPoolManager); 7467 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool); 7468 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool); 7469 peer.SetClientSocketPoolManager( 7470 mock_pool_manager.PassAs<ClientSocketPoolManager>()); 7471 7472 scoped_ptr<HttpTransaction> trans( 7473 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7474 7475 EXPECT_EQ(ERR_IO_PENDING, 7476 GroupNameTransactionHelper(tests[i].url, session)); 7477 if (tests[i].ssl) 7478 EXPECT_EQ(tests[i].expected_group_name, 7479 ssl_conn_pool->last_group_name_received()); 7480 else 7481 EXPECT_EQ(tests[i].expected_group_name, 7482 socks_conn_pool->last_group_name_received()); 7483 } 7484} 7485 7486TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) { 7487 HttpRequestInfo request; 7488 request.method = "GET"; 7489 request.url = GURL("http://www.google.com/"); 7490 7491 session_deps_.proxy_service.reset( 7492 ProxyService::CreateFixed("myproxy:70;foobar:80")); 7493 7494 // This simulates failure resolving all hostnames; that means we will fail 7495 // connecting to both proxies (myproxy:70 and foobar:80). 7496 session_deps_.host_resolver->rules()->AddSimulatedFailure("*"); 7497 7498 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7499 scoped_ptr<HttpTransaction> trans( 7500 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7501 7502 TestCompletionCallback callback; 7503 7504 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7505 EXPECT_EQ(ERR_IO_PENDING, rv); 7506 7507 rv = callback.WaitForResult(); 7508 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv); 7509} 7510 7511// Base test to make sure that when the load flags for a request specify to 7512// bypass the cache, the DNS cache is not used. 7513void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper( 7514 int load_flags) { 7515 // Issue a request, asking to bypass the cache(s). 7516 HttpRequestInfo request; 7517 request.method = "GET"; 7518 request.load_flags = load_flags; 7519 request.url = GURL("http://www.google.com/"); 7520 7521 // Select a host resolver that does caching. 7522 session_deps_.host_resolver.reset(new MockCachingHostResolver); 7523 7524 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7525 scoped_ptr<HttpTransaction> trans( 7526 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7527 7528 // Warm up the host cache so it has an entry for "www.google.com". 7529 AddressList addrlist; 7530 TestCompletionCallback callback; 7531 int rv = session_deps_.host_resolver->Resolve( 7532 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 7533 DEFAULT_PRIORITY, 7534 &addrlist, 7535 callback.callback(), 7536 NULL, 7537 BoundNetLog()); 7538 EXPECT_EQ(ERR_IO_PENDING, rv); 7539 rv = callback.WaitForResult(); 7540 EXPECT_EQ(OK, rv); 7541 7542 // Verify that it was added to host cache, by doing a subsequent async lookup 7543 // and confirming it completes synchronously. 7544 rv = session_deps_.host_resolver->Resolve( 7545 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), 7546 DEFAULT_PRIORITY, 7547 &addrlist, 7548 callback.callback(), 7549 NULL, 7550 BoundNetLog()); 7551 ASSERT_EQ(OK, rv); 7552 7553 // Inject a failure the next time that "www.google.com" is resolved. This way 7554 // we can tell if the next lookup hit the cache, or the "network". 7555 // (cache --> success, "network" --> failure). 7556 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com"); 7557 7558 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the 7559 // first read -- this won't be reached as the host resolution will fail first. 7560 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) }; 7561 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7562 session_deps_.socket_factory->AddSocketDataProvider(&data); 7563 7564 // Run the request. 7565 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7566 ASSERT_EQ(ERR_IO_PENDING, rv); 7567 rv = callback.WaitForResult(); 7568 7569 // If we bypassed the cache, we would have gotten a failure while resolving 7570 // "www.google.com". 7571 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); 7572} 7573 7574// There are multiple load flags that should trigger the host cache bypass. 7575// Test each in isolation: 7576TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) { 7577 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE); 7578} 7579 7580TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) { 7581 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE); 7582} 7583 7584TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) { 7585 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE); 7586} 7587 7588// Make sure we can handle an error when writing the request. 7589TEST_P(HttpNetworkTransactionTest, RequestWriteError) { 7590 HttpRequestInfo request; 7591 request.method = "GET"; 7592 request.url = GURL("http://www.foo.com/"); 7593 request.load_flags = 0; 7594 7595 MockWrite write_failure[] = { 7596 MockWrite(ASYNC, ERR_CONNECTION_RESET), 7597 }; 7598 StaticSocketDataProvider data(NULL, 0, 7599 write_failure, arraysize(write_failure)); 7600 session_deps_.socket_factory->AddSocketDataProvider(&data); 7601 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7602 7603 TestCompletionCallback callback; 7604 7605 scoped_ptr<HttpTransaction> trans( 7606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7607 7608 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7609 EXPECT_EQ(ERR_IO_PENDING, rv); 7610 7611 rv = callback.WaitForResult(); 7612 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 7613} 7614 7615// Check that a connection closed after the start of the headers finishes ok. 7616TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { 7617 HttpRequestInfo request; 7618 request.method = "GET"; 7619 request.url = GURL("http://www.foo.com/"); 7620 request.load_flags = 0; 7621 7622 MockRead data_reads[] = { 7623 MockRead("HTTP/1."), 7624 MockRead(SYNCHRONOUS, OK), 7625 }; 7626 7627 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7628 session_deps_.socket_factory->AddSocketDataProvider(&data); 7629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7630 7631 TestCompletionCallback callback; 7632 7633 scoped_ptr<HttpTransaction> trans( 7634 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7635 7636 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7637 EXPECT_EQ(ERR_IO_PENDING, rv); 7638 7639 rv = callback.WaitForResult(); 7640 EXPECT_EQ(OK, rv); 7641 7642 const HttpResponseInfo* response = trans->GetResponseInfo(); 7643 ASSERT_TRUE(response != NULL); 7644 7645 EXPECT_TRUE(response->headers.get() != NULL); 7646 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7647 7648 std::string response_data; 7649 rv = ReadTransaction(trans.get(), &response_data); 7650 EXPECT_EQ(OK, rv); 7651 EXPECT_EQ("", response_data); 7652} 7653 7654// Make sure that a dropped connection while draining the body for auth 7655// restart does the right thing. 7656TEST_P(HttpNetworkTransactionTest, DrainResetOK) { 7657 HttpRequestInfo request; 7658 request.method = "GET"; 7659 request.url = GURL("http://www.google.com/"); 7660 request.load_flags = 0; 7661 7662 MockWrite data_writes1[] = { 7663 MockWrite("GET / HTTP/1.1\r\n" 7664 "Host: www.google.com\r\n" 7665 "Connection: keep-alive\r\n\r\n"), 7666 }; 7667 7668 MockRead data_reads1[] = { 7669 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 7670 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 7671 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7672 MockRead("Content-Length: 14\r\n\r\n"), 7673 MockRead("Unauth"), 7674 MockRead(ASYNC, ERR_CONNECTION_RESET), 7675 }; 7676 7677 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 7678 data_writes1, arraysize(data_writes1)); 7679 session_deps_.socket_factory->AddSocketDataProvider(&data1); 7680 7681 // After calling trans->RestartWithAuth(), this is the request we should 7682 // be issuing -- the final header line contains the credentials. 7683 MockWrite data_writes2[] = { 7684 MockWrite("GET / HTTP/1.1\r\n" 7685 "Host: www.google.com\r\n" 7686 "Connection: keep-alive\r\n" 7687 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 7688 }; 7689 7690 // Lastly, the server responds with the actual content. 7691 MockRead data_reads2[] = { 7692 MockRead("HTTP/1.1 200 OK\r\n"), 7693 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7694 MockRead("Content-Length: 100\r\n\r\n"), 7695 MockRead(SYNCHRONOUS, OK), 7696 }; 7697 7698 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 7699 data_writes2, arraysize(data_writes2)); 7700 session_deps_.socket_factory->AddSocketDataProvider(&data2); 7701 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7702 7703 TestCompletionCallback callback1; 7704 7705 scoped_ptr<HttpTransaction> trans( 7706 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 7707 7708 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 7709 EXPECT_EQ(ERR_IO_PENDING, rv); 7710 7711 rv = callback1.WaitForResult(); 7712 EXPECT_EQ(OK, rv); 7713 7714 const HttpResponseInfo* response = trans->GetResponseInfo(); 7715 ASSERT_TRUE(response != NULL); 7716 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 7717 7718 TestCompletionCallback callback2; 7719 7720 rv = trans->RestartWithAuth( 7721 AuthCredentials(kFoo, kBar), callback2.callback()); 7722 EXPECT_EQ(ERR_IO_PENDING, rv); 7723 7724 rv = callback2.WaitForResult(); 7725 EXPECT_EQ(OK, rv); 7726 7727 response = trans->GetResponseInfo(); 7728 ASSERT_TRUE(response != NULL); 7729 EXPECT_TRUE(response->auth_challenge.get() == NULL); 7730 EXPECT_EQ(100, response->headers->GetContentLength()); 7731} 7732 7733// Test HTTPS connections going through a proxy that sends extra data. 7734TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) { 7735 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 7736 7737 HttpRequestInfo request; 7738 request.method = "GET"; 7739 request.url = GURL("https://www.google.com/"); 7740 request.load_flags = 0; 7741 7742 MockRead proxy_reads[] = { 7743 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"), 7744 MockRead(SYNCHRONOUS, OK) 7745 }; 7746 7747 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0); 7748 SSLSocketDataProvider ssl(ASYNC, OK); 7749 7750 session_deps_.socket_factory->AddSocketDataProvider(&data); 7751 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 7752 7753 TestCompletionCallback callback; 7754 7755 session_deps_.socket_factory->ResetNextMockIndexes(); 7756 7757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7758 scoped_ptr<HttpTransaction> trans( 7759 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7760 7761 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7762 EXPECT_EQ(ERR_IO_PENDING, rv); 7763 7764 rv = callback.WaitForResult(); 7765 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 7766} 7767 7768TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) { 7769 HttpRequestInfo request; 7770 request.method = "GET"; 7771 request.url = GURL("http://www.google.com/"); 7772 request.load_flags = 0; 7773 7774 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7775 scoped_ptr<HttpTransaction> trans( 7776 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7777 7778 MockRead data_reads[] = { 7779 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"), 7780 MockRead(SYNCHRONOUS, OK), 7781 }; 7782 7783 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7784 session_deps_.socket_factory->AddSocketDataProvider(&data); 7785 7786 TestCompletionCallback callback; 7787 7788 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7789 EXPECT_EQ(ERR_IO_PENDING, rv); 7790 7791 EXPECT_EQ(OK, callback.WaitForResult()); 7792 7793 const HttpResponseInfo* response = trans->GetResponseInfo(); 7794 ASSERT_TRUE(response != NULL); 7795 7796 EXPECT_TRUE(response->headers.get() != NULL); 7797 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7798 7799 std::string response_data; 7800 rv = ReadTransaction(trans.get(), &response_data); 7801 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 7802} 7803 7804TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) { 7805 base::FilePath temp_file_path; 7806 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path)); 7807 const uint64 kFakeSize = 100000; // file is actually blank 7808 UploadFileElementReader::ScopedOverridingContentLengthForTests 7809 overriding_content_length(kFakeSize); 7810 7811 ScopedVector<UploadElementReader> element_readers; 7812 element_readers.push_back( 7813 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 7814 temp_file_path, 7815 0, 7816 kuint64max, 7817 base::Time())); 7818 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 7819 7820 HttpRequestInfo request; 7821 request.method = "POST"; 7822 request.url = GURL("http://www.google.com/upload"); 7823 request.upload_data_stream = &upload_data_stream; 7824 request.load_flags = 0; 7825 7826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7827 scoped_ptr<HttpTransaction> trans( 7828 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7829 7830 MockRead data_reads[] = { 7831 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 7832 MockRead("hello world"), 7833 MockRead(SYNCHRONOUS, OK), 7834 }; 7835 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 7836 session_deps_.socket_factory->AddSocketDataProvider(&data); 7837 7838 TestCompletionCallback callback; 7839 7840 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7841 EXPECT_EQ(ERR_IO_PENDING, rv); 7842 7843 rv = callback.WaitForResult(); 7844 EXPECT_EQ(OK, rv); 7845 7846 const HttpResponseInfo* response = trans->GetResponseInfo(); 7847 ASSERT_TRUE(response != NULL); 7848 7849 EXPECT_TRUE(response->headers.get() != NULL); 7850 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 7851 7852 std::string response_data; 7853 rv = ReadTransaction(trans.get(), &response_data); 7854 EXPECT_EQ(OK, rv); 7855 EXPECT_EQ("hello world", response_data); 7856 7857 base::DeleteFile(temp_file_path, false); 7858} 7859 7860TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) { 7861 base::FilePath temp_file; 7862 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file)); 7863 std::string temp_file_content("Unreadable file."); 7864 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(), 7865 temp_file_content.length())); 7866 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file)); 7867 7868 ScopedVector<UploadElementReader> element_readers; 7869 element_readers.push_back( 7870 new UploadFileElementReader(base::MessageLoopProxy::current().get(), 7871 temp_file, 7872 0, 7873 kuint64max, 7874 base::Time())); 7875 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 7876 7877 HttpRequestInfo request; 7878 request.method = "POST"; 7879 request.url = GURL("http://www.google.com/upload"); 7880 request.upload_data_stream = &upload_data_stream; 7881 request.load_flags = 0; 7882 7883 // If we try to upload an unreadable file, the transaction should fail. 7884 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7885 scoped_ptr<HttpTransaction> trans( 7886 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7887 7888 StaticSocketDataProvider data(NULL, 0, NULL, 0); 7889 session_deps_.socket_factory->AddSocketDataProvider(&data); 7890 7891 TestCompletionCallback callback; 7892 7893 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7894 EXPECT_EQ(ERR_IO_PENDING, rv); 7895 7896 rv = callback.WaitForResult(); 7897 EXPECT_EQ(ERR_ACCESS_DENIED, rv); 7898 7899 const HttpResponseInfo* response = trans->GetResponseInfo(); 7900 EXPECT_FALSE(response); 7901 7902 base::DeleteFile(temp_file, false); 7903} 7904 7905TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) { 7906 class FakeUploadElementReader : public UploadElementReader { 7907 public: 7908 FakeUploadElementReader() {} 7909 virtual ~FakeUploadElementReader() {} 7910 7911 const CompletionCallback& callback() const { return callback_; } 7912 7913 // UploadElementReader overrides: 7914 virtual int Init(const CompletionCallback& callback) OVERRIDE { 7915 callback_ = callback; 7916 return ERR_IO_PENDING; 7917 } 7918 virtual uint64 GetContentLength() const OVERRIDE { return 0; } 7919 virtual uint64 BytesRemaining() const OVERRIDE { return 0; } 7920 virtual int Read(IOBuffer* buf, 7921 int buf_length, 7922 const CompletionCallback& callback) OVERRIDE { 7923 return ERR_FAILED; 7924 } 7925 7926 private: 7927 CompletionCallback callback_; 7928 }; 7929 7930 FakeUploadElementReader* fake_reader = new FakeUploadElementReader; 7931 ScopedVector<UploadElementReader> element_readers; 7932 element_readers.push_back(fake_reader); 7933 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 7934 7935 HttpRequestInfo request; 7936 request.method = "POST"; 7937 request.url = GURL("http://www.google.com/upload"); 7938 request.upload_data_stream = &upload_data_stream; 7939 request.load_flags = 0; 7940 7941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7942 scoped_ptr<HttpTransaction> trans( 7943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7944 7945 StaticSocketDataProvider data; 7946 session_deps_.socket_factory->AddSocketDataProvider(&data); 7947 7948 TestCompletionCallback callback; 7949 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7950 EXPECT_EQ(ERR_IO_PENDING, rv); 7951 base::MessageLoop::current()->RunUntilIdle(); 7952 7953 // Transaction is pending on request body initialization. 7954 ASSERT_FALSE(fake_reader->callback().is_null()); 7955 7956 // Return Init()'s result after the transaction gets destroyed. 7957 trans.reset(); 7958 fake_reader->callback().Run(OK); // Should not crash. 7959} 7960 7961// Tests that changes to Auth realms are treated like auth rejections. 7962TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) { 7963 7964 HttpRequestInfo request; 7965 request.method = "GET"; 7966 request.url = GURL("http://www.google.com/"); 7967 request.load_flags = 0; 7968 7969 // First transaction will request a resource and receive a Basic challenge 7970 // with realm="first_realm". 7971 MockWrite data_writes1[] = { 7972 MockWrite("GET / HTTP/1.1\r\n" 7973 "Host: www.google.com\r\n" 7974 "Connection: keep-alive\r\n" 7975 "\r\n"), 7976 }; 7977 MockRead data_reads1[] = { 7978 MockRead("HTTP/1.1 401 Unauthorized\r\n" 7979 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n" 7980 "\r\n"), 7981 }; 7982 7983 // After calling trans->RestartWithAuth(), provide an Authentication header 7984 // for first_realm. The server will reject and provide a challenge with 7985 // second_realm. 7986 MockWrite data_writes2[] = { 7987 MockWrite("GET / HTTP/1.1\r\n" 7988 "Host: www.google.com\r\n" 7989 "Connection: keep-alive\r\n" 7990 "Authorization: Basic Zmlyc3Q6YmF6\r\n" 7991 "\r\n"), 7992 }; 7993 MockRead data_reads2[] = { 7994 MockRead("HTTP/1.1 401 Unauthorized\r\n" 7995 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n" 7996 "\r\n"), 7997 }; 7998 7999 // This again fails, and goes back to first_realm. Make sure that the 8000 // entry is removed from cache. 8001 MockWrite data_writes3[] = { 8002 MockWrite("GET / HTTP/1.1\r\n" 8003 "Host: www.google.com\r\n" 8004 "Connection: keep-alive\r\n" 8005 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n" 8006 "\r\n"), 8007 }; 8008 MockRead data_reads3[] = { 8009 MockRead("HTTP/1.1 401 Unauthorized\r\n" 8010 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n" 8011 "\r\n"), 8012 }; 8013 8014 // Try one last time (with the correct password) and get the resource. 8015 MockWrite data_writes4[] = { 8016 MockWrite("GET / HTTP/1.1\r\n" 8017 "Host: www.google.com\r\n" 8018 "Connection: keep-alive\r\n" 8019 "Authorization: Basic Zmlyc3Q6YmFy\r\n" 8020 "\r\n"), 8021 }; 8022 MockRead data_reads4[] = { 8023 MockRead("HTTP/1.1 200 OK\r\n" 8024 "Content-Type: text/html; charset=iso-8859-1\r\n" 8025 "Content-Length: 5\r\n" 8026 "\r\n" 8027 "hello"), 8028 }; 8029 8030 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 8031 data_writes1, arraysize(data_writes1)); 8032 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 8033 data_writes2, arraysize(data_writes2)); 8034 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 8035 data_writes3, arraysize(data_writes3)); 8036 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4), 8037 data_writes4, arraysize(data_writes4)); 8038 session_deps_.socket_factory->AddSocketDataProvider(&data1); 8039 session_deps_.socket_factory->AddSocketDataProvider(&data2); 8040 session_deps_.socket_factory->AddSocketDataProvider(&data3); 8041 session_deps_.socket_factory->AddSocketDataProvider(&data4); 8042 8043 TestCompletionCallback callback1; 8044 8045 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8046 scoped_ptr<HttpTransaction> trans( 8047 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 8048 8049 // Issue the first request with Authorize headers. There should be a 8050 // password prompt for first_realm waiting to be filled in after the 8051 // transaction completes. 8052 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 8053 EXPECT_EQ(ERR_IO_PENDING, rv); 8054 rv = callback1.WaitForResult(); 8055 EXPECT_EQ(OK, rv); 8056 const HttpResponseInfo* response = trans->GetResponseInfo(); 8057 ASSERT_TRUE(response != NULL); 8058 const AuthChallengeInfo* challenge = response->auth_challenge.get(); 8059 ASSERT_FALSE(challenge == NULL); 8060 EXPECT_FALSE(challenge->is_proxy); 8061 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString()); 8062 EXPECT_EQ("first_realm", challenge->realm); 8063 EXPECT_EQ("basic", challenge->scheme); 8064 8065 // Issue the second request with an incorrect password. There should be a 8066 // password prompt for second_realm waiting to be filled in after the 8067 // transaction completes. 8068 TestCompletionCallback callback2; 8069 rv = trans->RestartWithAuth( 8070 AuthCredentials(kFirst, kBaz), callback2.callback()); 8071 EXPECT_EQ(ERR_IO_PENDING, rv); 8072 rv = callback2.WaitForResult(); 8073 EXPECT_EQ(OK, rv); 8074 response = trans->GetResponseInfo(); 8075 ASSERT_TRUE(response != NULL); 8076 challenge = response->auth_challenge.get(); 8077 ASSERT_FALSE(challenge == NULL); 8078 EXPECT_FALSE(challenge->is_proxy); 8079 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString()); 8080 EXPECT_EQ("second_realm", challenge->realm); 8081 EXPECT_EQ("basic", challenge->scheme); 8082 8083 // Issue the third request with another incorrect password. There should be 8084 // a password prompt for first_realm waiting to be filled in. If the password 8085 // prompt is not present, it indicates that the HttpAuthCacheEntry for 8086 // first_realm was not correctly removed. 8087 TestCompletionCallback callback3; 8088 rv = trans->RestartWithAuth( 8089 AuthCredentials(kSecond, kFou), callback3.callback()); 8090 EXPECT_EQ(ERR_IO_PENDING, rv); 8091 rv = callback3.WaitForResult(); 8092 EXPECT_EQ(OK, rv); 8093 response = trans->GetResponseInfo(); 8094 ASSERT_TRUE(response != NULL); 8095 challenge = response->auth_challenge.get(); 8096 ASSERT_FALSE(challenge == NULL); 8097 EXPECT_FALSE(challenge->is_proxy); 8098 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString()); 8099 EXPECT_EQ("first_realm", challenge->realm); 8100 EXPECT_EQ("basic", challenge->scheme); 8101 8102 // Issue the fourth request with the correct password and username. 8103 TestCompletionCallback callback4; 8104 rv = trans->RestartWithAuth( 8105 AuthCredentials(kFirst, kBar), callback4.callback()); 8106 EXPECT_EQ(ERR_IO_PENDING, rv); 8107 rv = callback4.WaitForResult(); 8108 EXPECT_EQ(OK, rv); 8109 response = trans->GetResponseInfo(); 8110 ASSERT_TRUE(response != NULL); 8111 EXPECT_TRUE(response->auth_challenge.get() == NULL); 8112} 8113 8114TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) { 8115 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8116 HttpStreamFactory::set_use_alternate_protocols(true); 8117 8118 std::string alternate_protocol_http_header = 8119 GetAlternateProtocolHttpHeader(); 8120 8121 MockRead data_reads[] = { 8122 MockRead("HTTP/1.1 200 OK\r\n"), 8123 MockRead(alternate_protocol_http_header.c_str()), 8124 MockRead("hello world"), 8125 MockRead(SYNCHRONOUS, OK), 8126 }; 8127 8128 HttpRequestInfo request; 8129 request.method = "GET"; 8130 request.url = GURL("http://www.google.com/"); 8131 request.load_flags = 0; 8132 8133 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 8134 8135 session_deps_.socket_factory->AddSocketDataProvider(&data); 8136 8137 TestCompletionCallback callback; 8138 8139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8140 scoped_ptr<HttpTransaction> trans( 8141 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8142 8143 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8144 EXPECT_EQ(ERR_IO_PENDING, rv); 8145 8146 HostPortPair http_host_port_pair("www.google.com", 80); 8147 const HttpServerProperties& http_server_properties = 8148 *session->http_server_properties(); 8149 EXPECT_FALSE( 8150 http_server_properties.HasAlternateProtocol(http_host_port_pair)); 8151 8152 EXPECT_EQ(OK, callback.WaitForResult()); 8153 8154 const HttpResponseInfo* response = trans->GetResponseInfo(); 8155 ASSERT_TRUE(response != NULL); 8156 ASSERT_TRUE(response->headers.get() != NULL); 8157 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8158 EXPECT_FALSE(response->was_fetched_via_spdy); 8159 EXPECT_FALSE(response->was_npn_negotiated); 8160 8161 std::string response_data; 8162 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8163 EXPECT_EQ("hello world", response_data); 8164 8165 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair)); 8166 const PortAlternateProtocolPair alternate = 8167 http_server_properties.GetAlternateProtocol(http_host_port_pair); 8168 PortAlternateProtocolPair expected_alternate; 8169 expected_alternate.port = 443; 8170 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam()); 8171 EXPECT_TRUE(expected_alternate.Equals(alternate)); 8172} 8173 8174TEST_P(HttpNetworkTransactionTest, 8175 MarkBrokenAlternateProtocolAndFallback) { 8176 HttpStreamFactory::set_use_alternate_protocols(true); 8177 8178 HttpRequestInfo request; 8179 request.method = "GET"; 8180 request.url = GURL("http://www.google.com/"); 8181 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 // Port must be < 1024, or the header will be ignored (since initial port was 8202 // port 80 (another restricted port). 8203 http_server_properties->SetAlternateProtocol( 8204 HostPortPair::FromURL(request.url), 8205 666 /* port is ignored by MockConnect anyway */, 8206 AlternateProtocolFromNextProto(GetParam())); 8207 8208 scoped_ptr<HttpTransaction> trans( 8209 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8210 TestCompletionCallback callback; 8211 8212 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8213 EXPECT_EQ(ERR_IO_PENDING, rv); 8214 EXPECT_EQ(OK, callback.WaitForResult()); 8215 8216 const HttpResponseInfo* response = trans->GetResponseInfo(); 8217 ASSERT_TRUE(response != NULL); 8218 ASSERT_TRUE(response->headers.get() != NULL); 8219 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8220 8221 std::string response_data; 8222 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8223 EXPECT_EQ("hello world", response_data); 8224 8225 ASSERT_TRUE(http_server_properties->HasAlternateProtocol( 8226 HostPortPair::FromURL(request.url))); 8227 const PortAlternateProtocolPair alternate = 8228 http_server_properties->GetAlternateProtocol( 8229 HostPortPair::FromURL(request.url)); 8230 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol); 8231} 8232 8233TEST_P(HttpNetworkTransactionTest, 8234 AlternateProtocolPortRestrictedBlocked) { 8235 // Ensure that we're not allowed to redirect traffic via an alternate 8236 // protocol to an unrestricted (port >= 1024) when the original traffic was 8237 // on a restricted port (port < 1024). Ensure that we can redirect in all 8238 // other cases. 8239 HttpStreamFactory::set_use_alternate_protocols(true); 8240 8241 HttpRequestInfo restricted_port_request; 8242 restricted_port_request.method = "GET"; 8243 restricted_port_request.url = GURL("http://www.google.com:1023/"); 8244 restricted_port_request.load_flags = 0; 8245 8246 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8247 StaticSocketDataProvider first_data; 8248 first_data.set_connect_data(mock_connect); 8249 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8250 8251 MockRead data_reads[] = { 8252 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8253 MockRead("hello world"), 8254 MockRead(ASYNC, OK), 8255 }; 8256 StaticSocketDataProvider second_data( 8257 data_reads, arraysize(data_reads), NULL, 0); 8258 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8259 8260 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8261 8262 base::WeakPtr<HttpServerProperties> http_server_properties = 8263 session->http_server_properties(); 8264 const int kUnrestrictedAlternatePort = 1024; 8265 http_server_properties->SetAlternateProtocol( 8266 HostPortPair::FromURL(restricted_port_request.url), 8267 kUnrestrictedAlternatePort, 8268 AlternateProtocolFromNextProto(GetParam())); 8269 8270 scoped_ptr<HttpTransaction> trans( 8271 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8272 TestCompletionCallback callback; 8273 8274 int rv = trans->Start( 8275 &restricted_port_request, 8276 callback.callback(), BoundNetLog()); 8277 EXPECT_EQ(ERR_IO_PENDING, rv); 8278 // Invalid change to unrestricted port should fail. 8279 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult()); 8280} 8281 8282TEST_P(HttpNetworkTransactionTest, 8283 AlternateProtocolPortRestrictedPermitted) { 8284 // Ensure that we're allowed to redirect traffic via an alternate 8285 // protocol to an unrestricted (port >= 1024) when the original traffic was 8286 // on a restricted port (port < 1024) if we set 8287 // enable_user_alternate_protocol_ports. 8288 8289 HttpStreamFactory::set_use_alternate_protocols(true); 8290 session_deps_.enable_user_alternate_protocol_ports = true; 8291 8292 HttpRequestInfo restricted_port_request; 8293 restricted_port_request.method = "GET"; 8294 restricted_port_request.url = GURL("http://www.google.com:1023/"); 8295 restricted_port_request.load_flags = 0; 8296 8297 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8298 StaticSocketDataProvider first_data; 8299 first_data.set_connect_data(mock_connect); 8300 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8301 8302 MockRead data_reads[] = { 8303 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8304 MockRead("hello world"), 8305 MockRead(ASYNC, OK), 8306 }; 8307 StaticSocketDataProvider second_data( 8308 data_reads, arraysize(data_reads), NULL, 0); 8309 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8310 8311 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8312 8313 base::WeakPtr<HttpServerProperties> http_server_properties = 8314 session->http_server_properties(); 8315 const int kUnrestrictedAlternatePort = 1024; 8316 http_server_properties->SetAlternateProtocol( 8317 HostPortPair::FromURL(restricted_port_request.url), 8318 kUnrestrictedAlternatePort, 8319 AlternateProtocolFromNextProto(GetParam())); 8320 8321 scoped_ptr<HttpTransaction> trans( 8322 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8323 TestCompletionCallback callback; 8324 8325 EXPECT_EQ(ERR_IO_PENDING, trans->Start( 8326 &restricted_port_request, 8327 callback.callback(), BoundNetLog())); 8328 // Change to unrestricted port should succeed. 8329 EXPECT_EQ(OK, callback.WaitForResult()); 8330} 8331 8332TEST_P(HttpNetworkTransactionTest, 8333 AlternateProtocolPortRestrictedAllowed) { 8334 // Ensure that we're not allowed to redirect traffic via an alternate 8335 // protocol to an unrestricted (port >= 1024) when the original traffic was 8336 // on a restricted port (port < 1024). Ensure that we can redirect in all 8337 // other cases. 8338 HttpStreamFactory::set_use_alternate_protocols(true); 8339 8340 HttpRequestInfo restricted_port_request; 8341 restricted_port_request.method = "GET"; 8342 restricted_port_request.url = GURL("http://www.google.com:1023/"); 8343 restricted_port_request.load_flags = 0; 8344 8345 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8346 StaticSocketDataProvider first_data; 8347 first_data.set_connect_data(mock_connect); 8348 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8349 8350 MockRead data_reads[] = { 8351 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8352 MockRead("hello world"), 8353 MockRead(ASYNC, OK), 8354 }; 8355 StaticSocketDataProvider second_data( 8356 data_reads, arraysize(data_reads), NULL, 0); 8357 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8358 8359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8360 8361 base::WeakPtr<HttpServerProperties> http_server_properties = 8362 session->http_server_properties(); 8363 const int kRestrictedAlternatePort = 80; 8364 http_server_properties->SetAlternateProtocol( 8365 HostPortPair::FromURL(restricted_port_request.url), 8366 kRestrictedAlternatePort, 8367 AlternateProtocolFromNextProto(GetParam())); 8368 8369 scoped_ptr<HttpTransaction> trans( 8370 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8371 TestCompletionCallback callback; 8372 8373 int rv = trans->Start( 8374 &restricted_port_request, 8375 callback.callback(), BoundNetLog()); 8376 EXPECT_EQ(ERR_IO_PENDING, rv); 8377 // Valid change to restricted port should pass. 8378 EXPECT_EQ(OK, callback.WaitForResult()); 8379} 8380 8381TEST_P(HttpNetworkTransactionTest, 8382 AlternateProtocolPortUnrestrictedAllowed1) { 8383 // Ensure that we're not allowed to redirect traffic via an alternate 8384 // protocol to an unrestricted (port >= 1024) when the original traffic was 8385 // on a restricted port (port < 1024). Ensure that we can redirect in all 8386 // other cases. 8387 HttpStreamFactory::set_use_alternate_protocols(true); 8388 8389 HttpRequestInfo unrestricted_port_request; 8390 unrestricted_port_request.method = "GET"; 8391 unrestricted_port_request.url = GURL("http://www.google.com:1024/"); 8392 unrestricted_port_request.load_flags = 0; 8393 8394 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8395 StaticSocketDataProvider first_data; 8396 first_data.set_connect_data(mock_connect); 8397 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8398 8399 MockRead data_reads[] = { 8400 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8401 MockRead("hello world"), 8402 MockRead(ASYNC, OK), 8403 }; 8404 StaticSocketDataProvider second_data( 8405 data_reads, arraysize(data_reads), NULL, 0); 8406 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8407 8408 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8409 8410 base::WeakPtr<HttpServerProperties> http_server_properties = 8411 session->http_server_properties(); 8412 const int kRestrictedAlternatePort = 80; 8413 http_server_properties->SetAlternateProtocol( 8414 HostPortPair::FromURL(unrestricted_port_request.url), 8415 kRestrictedAlternatePort, 8416 AlternateProtocolFromNextProto(GetParam())); 8417 8418 scoped_ptr<HttpTransaction> trans( 8419 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8420 TestCompletionCallback callback; 8421 8422 int rv = trans->Start( 8423 &unrestricted_port_request, callback.callback(), BoundNetLog()); 8424 EXPECT_EQ(ERR_IO_PENDING, rv); 8425 // Valid change to restricted port should pass. 8426 EXPECT_EQ(OK, callback.WaitForResult()); 8427} 8428 8429TEST_P(HttpNetworkTransactionTest, 8430 AlternateProtocolPortUnrestrictedAllowed2) { 8431 // Ensure that we're not allowed to redirect traffic via an alternate 8432 // protocol to an unrestricted (port >= 1024) when the original traffic was 8433 // on a restricted port (port < 1024). Ensure that we can redirect in all 8434 // other cases. 8435 HttpStreamFactory::set_use_alternate_protocols(true); 8436 8437 HttpRequestInfo unrestricted_port_request; 8438 unrestricted_port_request.method = "GET"; 8439 unrestricted_port_request.url = GURL("http://www.google.com:1024/"); 8440 unrestricted_port_request.load_flags = 0; 8441 8442 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 8443 StaticSocketDataProvider first_data; 8444 first_data.set_connect_data(mock_connect); 8445 session_deps_.socket_factory->AddSocketDataProvider(&first_data); 8446 8447 MockRead data_reads[] = { 8448 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8449 MockRead("hello world"), 8450 MockRead(ASYNC, OK), 8451 }; 8452 StaticSocketDataProvider second_data( 8453 data_reads, arraysize(data_reads), NULL, 0); 8454 session_deps_.socket_factory->AddSocketDataProvider(&second_data); 8455 8456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8457 8458 base::WeakPtr<HttpServerProperties> http_server_properties = 8459 session->http_server_properties(); 8460 const int kUnrestrictedAlternatePort = 1024; 8461 http_server_properties->SetAlternateProtocol( 8462 HostPortPair::FromURL(unrestricted_port_request.url), 8463 kUnrestrictedAlternatePort, 8464 AlternateProtocolFromNextProto(GetParam())); 8465 8466 scoped_ptr<HttpTransaction> trans( 8467 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8468 TestCompletionCallback callback; 8469 8470 int rv = trans->Start( 8471 &unrestricted_port_request, callback.callback(), BoundNetLog()); 8472 EXPECT_EQ(ERR_IO_PENDING, rv); 8473 // Valid change to an unrestricted port should pass. 8474 EXPECT_EQ(OK, callback.WaitForResult()); 8475} 8476 8477TEST_P(HttpNetworkTransactionTest, 8478 AlternateProtocolUnsafeBlocked) { 8479 // Ensure that we're not allowed to redirect traffic via an alternate 8480 // protocol to an unsafe port, and that we resume the second 8481 // HttpStreamFactoryImpl::Job once the alternate protocol request fails. 8482 HttpStreamFactory::set_use_alternate_protocols(true); 8483 8484 HttpRequestInfo request; 8485 request.method = "GET"; 8486 request.url = GURL("http://www.google.com/"); 8487 request.load_flags = 0; 8488 8489 // The alternate protocol request will error out before we attempt to connect, 8490 // so only the standard HTTP request will try to connect. 8491 MockRead data_reads[] = { 8492 MockRead("HTTP/1.1 200 OK\r\n\r\n"), 8493 MockRead("hello world"), 8494 MockRead(ASYNC, OK), 8495 }; 8496 StaticSocketDataProvider data( 8497 data_reads, arraysize(data_reads), NULL, 0); 8498 session_deps_.socket_factory->AddSocketDataProvider(&data); 8499 8500 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8501 8502 base::WeakPtr<HttpServerProperties> http_server_properties = 8503 session->http_server_properties(); 8504 const int kUnsafePort = 7; 8505 http_server_properties->SetAlternateProtocol( 8506 HostPortPair::FromURL(request.url), 8507 kUnsafePort, 8508 AlternateProtocolFromNextProto(GetParam())); 8509 8510 scoped_ptr<HttpTransaction> trans( 8511 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8512 TestCompletionCallback callback; 8513 8514 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8515 EXPECT_EQ(ERR_IO_PENDING, rv); 8516 // The HTTP request should succeed. 8517 EXPECT_EQ(OK, callback.WaitForResult()); 8518 8519 // Disable alternate protocol before the asserts. 8520 HttpStreamFactory::set_use_alternate_protocols(false); 8521 8522 const HttpResponseInfo* response = trans->GetResponseInfo(); 8523 ASSERT_TRUE(response != NULL); 8524 ASSERT_TRUE(response->headers.get() != NULL); 8525 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8526 8527 std::string response_data; 8528 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8529 EXPECT_EQ("hello world", response_data); 8530} 8531 8532TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { 8533 HttpStreamFactory::set_use_alternate_protocols(true); 8534 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8535 8536 HttpRequestInfo request; 8537 request.method = "GET"; 8538 request.url = GURL("http://www.google.com/"); 8539 request.load_flags = 0; 8540 8541 std::string alternate_protocol_http_header = 8542 GetAlternateProtocolHttpHeader(); 8543 8544 MockRead data_reads[] = { 8545 MockRead("HTTP/1.1 200 OK\r\n"), 8546 MockRead(alternate_protocol_http_header.c_str()), 8547 MockRead("hello world"), 8548 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8549 MockRead(ASYNC, OK) 8550 }; 8551 8552 StaticSocketDataProvider first_transaction( 8553 data_reads, arraysize(data_reads), NULL, 0); 8554 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8555 8556 SSLSocketDataProvider ssl(ASYNC, OK); 8557 ssl.SetNextProto(GetParam()); 8558 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8559 8560 scoped_ptr<SpdyFrame> req( 8561 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8562 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 8563 8564 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8565 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8566 MockRead spdy_reads[] = { 8567 CreateMockRead(*resp), 8568 CreateMockRead(*data), 8569 MockRead(ASYNC, 0, 0), 8570 }; 8571 8572 DelayedSocketData spdy_data( 8573 1, // wait for one write to finish before reading. 8574 spdy_reads, arraysize(spdy_reads), 8575 spdy_writes, arraysize(spdy_writes)); 8576 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8577 8578 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8579 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 8580 NULL, 0, NULL, 0); 8581 hanging_non_alternate_protocol_socket.set_connect_data( 8582 never_finishing_connect); 8583 session_deps_.socket_factory->AddSocketDataProvider( 8584 &hanging_non_alternate_protocol_socket); 8585 8586 TestCompletionCallback callback; 8587 8588 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8589 scoped_ptr<HttpTransaction> trans( 8590 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8591 8592 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8593 EXPECT_EQ(ERR_IO_PENDING, rv); 8594 EXPECT_EQ(OK, callback.WaitForResult()); 8595 8596 const HttpResponseInfo* response = trans->GetResponseInfo(); 8597 ASSERT_TRUE(response != NULL); 8598 ASSERT_TRUE(response->headers.get() != NULL); 8599 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8600 8601 std::string response_data; 8602 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8603 EXPECT_EQ("hello world", response_data); 8604 8605 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8606 8607 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8608 EXPECT_EQ(ERR_IO_PENDING, rv); 8609 EXPECT_EQ(OK, callback.WaitForResult()); 8610 8611 response = trans->GetResponseInfo(); 8612 ASSERT_TRUE(response != NULL); 8613 ASSERT_TRUE(response->headers.get() != NULL); 8614 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8615 EXPECT_TRUE(response->was_fetched_via_spdy); 8616 EXPECT_TRUE(response->was_npn_negotiated); 8617 8618 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8619 EXPECT_EQ("hello!", response_data); 8620} 8621 8622TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { 8623 HttpStreamFactory::set_use_alternate_protocols(true); 8624 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8625 8626 HttpRequestInfo request; 8627 request.method = "GET"; 8628 request.url = GURL("http://www.google.com/"); 8629 request.load_flags = 0; 8630 8631 std::string alternate_protocol_http_header = 8632 GetAlternateProtocolHttpHeader(); 8633 8634 MockRead data_reads[] = { 8635 MockRead("HTTP/1.1 200 OK\r\n"), 8636 MockRead(alternate_protocol_http_header.c_str()), 8637 MockRead("hello world"), 8638 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8639 MockRead(ASYNC, OK), 8640 }; 8641 8642 StaticSocketDataProvider first_transaction( 8643 data_reads, arraysize(data_reads), NULL, 0); 8644 // Socket 1 is the HTTP transaction with the Alternate-Protocol header. 8645 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8646 8647 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8648 StaticSocketDataProvider hanging_socket( 8649 NULL, 0, NULL, 0); 8650 hanging_socket.set_connect_data(never_finishing_connect); 8651 // Socket 2 and 3 are the hanging Alternate-Protocol and 8652 // non-Alternate-Protocol jobs from the 2nd transaction. 8653 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); 8654 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); 8655 8656 SSLSocketDataProvider ssl(ASYNC, OK); 8657 ssl.SetNextProto(GetParam()); 8658 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8659 8660 scoped_ptr<SpdyFrame> req1( 8661 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8662 scoped_ptr<SpdyFrame> req2( 8663 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); 8664 MockWrite spdy_writes[] = { 8665 CreateMockWrite(*req1), 8666 CreateMockWrite(*req2), 8667 }; 8668 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8669 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8670 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 8671 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 8672 MockRead spdy_reads[] = { 8673 CreateMockRead(*resp1), 8674 CreateMockRead(*data1), 8675 CreateMockRead(*resp2), 8676 CreateMockRead(*data2), 8677 MockRead(ASYNC, 0, 0), 8678 }; 8679 8680 DelayedSocketData spdy_data( 8681 2, // wait for writes to finish before reading. 8682 spdy_reads, arraysize(spdy_reads), 8683 spdy_writes, arraysize(spdy_writes)); 8684 // Socket 4 is the successful Alternate-Protocol for transaction 3. 8685 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8686 8687 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3. 8688 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); 8689 8690 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8691 TestCompletionCallback callback1; 8692 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 8693 8694 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog()); 8695 EXPECT_EQ(ERR_IO_PENDING, rv); 8696 EXPECT_EQ(OK, callback1.WaitForResult()); 8697 8698 const HttpResponseInfo* response = trans1.GetResponseInfo(); 8699 ASSERT_TRUE(response != NULL); 8700 ASSERT_TRUE(response->headers.get() != NULL); 8701 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8702 8703 std::string response_data; 8704 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 8705 EXPECT_EQ("hello world", response_data); 8706 8707 TestCompletionCallback callback2; 8708 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 8709 rv = trans2.Start(&request, callback2.callback(), BoundNetLog()); 8710 EXPECT_EQ(ERR_IO_PENDING, rv); 8711 8712 TestCompletionCallback callback3; 8713 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get()); 8714 rv = trans3.Start(&request, callback3.callback(), BoundNetLog()); 8715 EXPECT_EQ(ERR_IO_PENDING, rv); 8716 8717 EXPECT_EQ(OK, callback2.WaitForResult()); 8718 EXPECT_EQ(OK, callback3.WaitForResult()); 8719 8720 response = trans2.GetResponseInfo(); 8721 ASSERT_TRUE(response != NULL); 8722 ASSERT_TRUE(response->headers.get() != NULL); 8723 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8724 EXPECT_TRUE(response->was_fetched_via_spdy); 8725 EXPECT_TRUE(response->was_npn_negotiated); 8726 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 8727 EXPECT_EQ("hello!", response_data); 8728 8729 response = trans3.GetResponseInfo(); 8730 ASSERT_TRUE(response != NULL); 8731 ASSERT_TRUE(response->headers.get() != NULL); 8732 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8733 EXPECT_TRUE(response->was_fetched_via_spdy); 8734 EXPECT_TRUE(response->was_npn_negotiated); 8735 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data)); 8736 EXPECT_EQ("hello!", response_data); 8737} 8738 8739TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) { 8740 HttpStreamFactory::set_use_alternate_protocols(true); 8741 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8742 8743 HttpRequestInfo request; 8744 request.method = "GET"; 8745 request.url = GURL("http://www.google.com/"); 8746 request.load_flags = 0; 8747 8748 std::string alternate_protocol_http_header = 8749 GetAlternateProtocolHttpHeader(); 8750 8751 MockRead data_reads[] = { 8752 MockRead("HTTP/1.1 200 OK\r\n"), 8753 MockRead(alternate_protocol_http_header.c_str()), 8754 MockRead("hello world"), 8755 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8756 MockRead(ASYNC, OK), 8757 }; 8758 8759 StaticSocketDataProvider first_transaction( 8760 data_reads, arraysize(data_reads), NULL, 0); 8761 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8762 8763 SSLSocketDataProvider ssl(ASYNC, OK); 8764 ssl.SetNextProto(GetParam()); 8765 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8766 8767 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8768 StaticSocketDataProvider hanging_alternate_protocol_socket( 8769 NULL, 0, NULL, 0); 8770 hanging_alternate_protocol_socket.set_connect_data( 8771 never_finishing_connect); 8772 session_deps_.socket_factory->AddSocketDataProvider( 8773 &hanging_alternate_protocol_socket); 8774 8775 // 2nd request is just a copy of the first one, over HTTP again. 8776 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8777 8778 TestCompletionCallback callback; 8779 8780 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8781 scoped_ptr<HttpTransaction> trans( 8782 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8783 8784 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8785 EXPECT_EQ(ERR_IO_PENDING, rv); 8786 EXPECT_EQ(OK, callback.WaitForResult()); 8787 8788 const HttpResponseInfo* response = trans->GetResponseInfo(); 8789 ASSERT_TRUE(response != NULL); 8790 ASSERT_TRUE(response->headers.get() != NULL); 8791 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8792 8793 std::string response_data; 8794 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8795 EXPECT_EQ("hello world", response_data); 8796 8797 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8798 8799 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8800 EXPECT_EQ(ERR_IO_PENDING, rv); 8801 EXPECT_EQ(OK, callback.WaitForResult()); 8802 8803 response = trans->GetResponseInfo(); 8804 ASSERT_TRUE(response != NULL); 8805 ASSERT_TRUE(response->headers.get() != NULL); 8806 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8807 EXPECT_FALSE(response->was_fetched_via_spdy); 8808 EXPECT_FALSE(response->was_npn_negotiated); 8809 8810 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8811 EXPECT_EQ("hello world", response_data); 8812} 8813 8814class CapturingProxyResolver : public ProxyResolver { 8815 public: 8816 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {} 8817 virtual ~CapturingProxyResolver() {} 8818 8819 virtual int GetProxyForURL(const GURL& url, 8820 ProxyInfo* results, 8821 const CompletionCallback& callback, 8822 RequestHandle* request, 8823 const BoundNetLog& net_log) OVERRIDE { 8824 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP, 8825 HostPortPair("myproxy", 80)); 8826 results->UseProxyServer(proxy_server); 8827 resolved_.push_back(url); 8828 return OK; 8829 } 8830 8831 virtual void CancelRequest(RequestHandle request) OVERRIDE { 8832 NOTREACHED(); 8833 } 8834 8835 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE { 8836 NOTREACHED(); 8837 return LOAD_STATE_IDLE; 8838 } 8839 8840 virtual void CancelSetPacScript() OVERRIDE { 8841 NOTREACHED(); 8842 } 8843 8844 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&, 8845 const CompletionCallback& /*callback*/) OVERRIDE { 8846 return OK; 8847 } 8848 8849 const std::vector<GURL>& resolved() const { return resolved_; } 8850 8851 private: 8852 std::vector<GURL> resolved_; 8853 8854 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver); 8855}; 8856 8857TEST_P(HttpNetworkTransactionTest, 8858 UseAlternateProtocolForTunneledNpnSpdy) { 8859 HttpStreamFactory::set_use_alternate_protocols(true); 8860 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8861 8862 ProxyConfig proxy_config; 8863 proxy_config.set_auto_detect(true); 8864 proxy_config.set_pac_url(GURL("http://fooproxyurl")); 8865 8866 CapturingProxyResolver* capturing_proxy_resolver = 8867 new CapturingProxyResolver(); 8868 session_deps_.proxy_service.reset(new ProxyService( 8869 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver, 8870 NULL)); 8871 CapturingNetLog net_log; 8872 session_deps_.net_log = &net_log; 8873 8874 HttpRequestInfo request; 8875 request.method = "GET"; 8876 request.url = GURL("http://www.google.com/"); 8877 request.load_flags = 0; 8878 8879 std::string alternate_protocol_http_header = 8880 GetAlternateProtocolHttpHeader(); 8881 8882 MockRead data_reads[] = { 8883 MockRead("HTTP/1.1 200 OK\r\n"), 8884 MockRead(alternate_protocol_http_header.c_str()), 8885 MockRead("hello world"), 8886 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 8887 MockRead(ASYNC, OK), 8888 }; 8889 8890 StaticSocketDataProvider first_transaction( 8891 data_reads, arraysize(data_reads), NULL, 0); 8892 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 8893 8894 SSLSocketDataProvider ssl(ASYNC, OK); 8895 ssl.SetNextProto(GetParam()); 8896 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 8897 8898 scoped_ptr<SpdyFrame> req( 8899 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 8900 MockWrite spdy_writes[] = { 8901 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 8902 "Host: www.google.com\r\n" 8903 "Proxy-Connection: keep-alive\r\n\r\n"), // 0 8904 CreateMockWrite(*req), // 3 8905 }; 8906 8907 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; 8908 8909 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 8910 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 8911 MockRead spdy_reads[] = { 8912 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1 8913 CreateMockRead(*resp.get(), 4), // 2, 4 8914 CreateMockRead(*data.get(), 4), // 5 8915 MockRead(ASYNC, 0, 0, 4), // 6 8916 }; 8917 8918 OrderedSocketData spdy_data( 8919 spdy_reads, arraysize(spdy_reads), 8920 spdy_writes, arraysize(spdy_writes)); 8921 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 8922 8923 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 8924 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 8925 NULL, 0, NULL, 0); 8926 hanging_non_alternate_protocol_socket.set_connect_data( 8927 never_finishing_connect); 8928 session_deps_.socket_factory->AddSocketDataProvider( 8929 &hanging_non_alternate_protocol_socket); 8930 8931 TestCompletionCallback callback; 8932 8933 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 8934 scoped_ptr<HttpTransaction> trans( 8935 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8936 8937 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8938 EXPECT_EQ(ERR_IO_PENDING, rv); 8939 EXPECT_EQ(OK, callback.WaitForResult()); 8940 8941 const HttpResponseInfo* response = trans->GetResponseInfo(); 8942 ASSERT_TRUE(response != NULL); 8943 ASSERT_TRUE(response->headers.get() != NULL); 8944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8945 EXPECT_FALSE(response->was_fetched_via_spdy); 8946 EXPECT_FALSE(response->was_npn_negotiated); 8947 8948 std::string response_data; 8949 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8950 EXPECT_EQ("hello world", response_data); 8951 8952 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 8953 8954 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 8955 EXPECT_EQ(ERR_IO_PENDING, rv); 8956 EXPECT_EQ(OK, callback.WaitForResult()); 8957 8958 response = trans->GetResponseInfo(); 8959 ASSERT_TRUE(response != NULL); 8960 ASSERT_TRUE(response->headers.get() != NULL); 8961 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 8962 EXPECT_TRUE(response->was_fetched_via_spdy); 8963 EXPECT_TRUE(response->was_npn_negotiated); 8964 8965 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 8966 EXPECT_EQ("hello!", response_data); 8967 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size()); 8968 EXPECT_EQ("http://www.google.com/", 8969 capturing_proxy_resolver->resolved()[0].spec()); 8970 EXPECT_EQ("https://www.google.com/", 8971 capturing_proxy_resolver->resolved()[1].spec()); 8972 8973 LoadTimingInfo load_timing_info; 8974 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 8975 TestLoadTimingNotReusedWithPac(load_timing_info, 8976 CONNECT_TIMING_HAS_SSL_TIMES); 8977} 8978 8979TEST_P(HttpNetworkTransactionTest, 8980 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) { 8981 HttpStreamFactory::set_use_alternate_protocols(true); 8982 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 8983 8984 HttpRequestInfo request; 8985 request.method = "GET"; 8986 request.url = GURL("http://www.google.com/"); 8987 request.load_flags = 0; 8988 8989 std::string alternate_protocol_http_header = 8990 GetAlternateProtocolHttpHeader(); 8991 8992 MockRead data_reads[] = { 8993 MockRead("HTTP/1.1 200 OK\r\n"), 8994 MockRead(alternate_protocol_http_header.c_str()), 8995 MockRead("hello world"), 8996 MockRead(ASYNC, OK), 8997 }; 8998 8999 StaticSocketDataProvider first_transaction( 9000 data_reads, arraysize(data_reads), NULL, 0); 9001 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); 9002 9003 SSLSocketDataProvider ssl(ASYNC, OK); 9004 ssl.SetNextProto(GetParam()); 9005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9006 9007 scoped_ptr<SpdyFrame> req( 9008 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 9009 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 9010 9011 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 9012 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 9013 MockRead spdy_reads[] = { 9014 CreateMockRead(*resp), 9015 CreateMockRead(*data), 9016 MockRead(ASYNC, 0, 0), 9017 }; 9018 9019 DelayedSocketData spdy_data( 9020 1, // wait for one write to finish before reading. 9021 spdy_reads, arraysize(spdy_reads), 9022 spdy_writes, arraysize(spdy_writes)); 9023 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 9024 9025 TestCompletionCallback callback; 9026 9027 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9028 9029 scoped_ptr<HttpTransaction> trans( 9030 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9031 9032 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9033 EXPECT_EQ(ERR_IO_PENDING, rv); 9034 EXPECT_EQ(OK, callback.WaitForResult()); 9035 9036 const HttpResponseInfo* response = trans->GetResponseInfo(); 9037 ASSERT_TRUE(response != NULL); 9038 ASSERT_TRUE(response->headers.get() != NULL); 9039 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 9040 9041 std::string response_data; 9042 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 9043 EXPECT_EQ("hello world", response_data); 9044 9045 // Set up an initial SpdySession in the pool to reuse. 9046 HostPortPair host_port_pair("www.google.com", 443); 9047 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), 9048 kPrivacyModeDisabled); 9049 base::WeakPtr<SpdySession> spdy_session = 9050 CreateSecureSpdySession(session, key, BoundNetLog()); 9051 9052 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9053 9054 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9055 EXPECT_EQ(ERR_IO_PENDING, rv); 9056 EXPECT_EQ(OK, callback.WaitForResult()); 9057 9058 response = trans->GetResponseInfo(); 9059 ASSERT_TRUE(response != NULL); 9060 ASSERT_TRUE(response->headers.get() != NULL); 9061 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 9062 EXPECT_TRUE(response->was_fetched_via_spdy); 9063 EXPECT_TRUE(response->was_npn_negotiated); 9064 9065 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 9066 EXPECT_EQ("hello!", response_data); 9067} 9068 9069// GenerateAuthToken is a mighty big test. 9070// It tests all permutation of GenerateAuthToken behavior: 9071// - Synchronous and Asynchronous completion. 9072// - OK or error on completion. 9073// - Direct connection, non-authenticating proxy, and authenticating proxy. 9074// - HTTP or HTTPS backend (to include proxy tunneling). 9075// - Non-authenticating and authenticating backend. 9076// 9077// In all, there are 44 reasonable permuations (for example, if there are 9078// problems generating an auth token for an authenticating proxy, we don't 9079// need to test all permutations of the backend server). 9080// 9081// The test proceeds by going over each of the configuration cases, and 9082// potentially running up to three rounds in each of the tests. The TestConfig 9083// specifies both the configuration for the test as well as the expectations 9084// for the results. 9085TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { 9086 static const char kServer[] = "http://www.example.com"; 9087 static const char kSecureServer[] = "https://www.example.com"; 9088 static const char kProxy[] = "myproxy:70"; 9089 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS; 9090 9091 enum AuthTiming { 9092 AUTH_NONE, 9093 AUTH_SYNC, 9094 AUTH_ASYNC, 9095 }; 9096 9097 const MockWrite kGet( 9098 "GET / HTTP/1.1\r\n" 9099 "Host: www.example.com\r\n" 9100 "Connection: keep-alive\r\n\r\n"); 9101 const MockWrite kGetProxy( 9102 "GET http://www.example.com/ HTTP/1.1\r\n" 9103 "Host: www.example.com\r\n" 9104 "Proxy-Connection: keep-alive\r\n\r\n"); 9105 const MockWrite kGetAuth( 9106 "GET / HTTP/1.1\r\n" 9107 "Host: www.example.com\r\n" 9108 "Connection: keep-alive\r\n" 9109 "Authorization: auth_token\r\n\r\n"); 9110 const MockWrite kGetProxyAuth( 9111 "GET http://www.example.com/ HTTP/1.1\r\n" 9112 "Host: www.example.com\r\n" 9113 "Proxy-Connection: keep-alive\r\n" 9114 "Proxy-Authorization: auth_token\r\n\r\n"); 9115 const MockWrite kGetAuthThroughProxy( 9116 "GET http://www.example.com/ HTTP/1.1\r\n" 9117 "Host: www.example.com\r\n" 9118 "Proxy-Connection: keep-alive\r\n" 9119 "Authorization: auth_token\r\n\r\n"); 9120 const MockWrite kGetAuthWithProxyAuth( 9121 "GET http://www.example.com/ HTTP/1.1\r\n" 9122 "Host: www.example.com\r\n" 9123 "Proxy-Connection: keep-alive\r\n" 9124 "Proxy-Authorization: auth_token\r\n" 9125 "Authorization: auth_token\r\n\r\n"); 9126 const MockWrite kConnect( 9127 "CONNECT www.example.com:443 HTTP/1.1\r\n" 9128 "Host: www.example.com\r\n" 9129 "Proxy-Connection: keep-alive\r\n\r\n"); 9130 const MockWrite kConnectProxyAuth( 9131 "CONNECT www.example.com:443 HTTP/1.1\r\n" 9132 "Host: www.example.com\r\n" 9133 "Proxy-Connection: keep-alive\r\n" 9134 "Proxy-Authorization: auth_token\r\n\r\n"); 9135 9136 const MockRead kSuccess( 9137 "HTTP/1.1 200 OK\r\n" 9138 "Content-Type: text/html; charset=iso-8859-1\r\n" 9139 "Content-Length: 3\r\n\r\n" 9140 "Yes"); 9141 const MockRead kFailure( 9142 "Should not be called."); 9143 const MockRead kServerChallenge( 9144 "HTTP/1.1 401 Unauthorized\r\n" 9145 "WWW-Authenticate: Mock realm=server\r\n" 9146 "Content-Type: text/html; charset=iso-8859-1\r\n" 9147 "Content-Length: 14\r\n\r\n" 9148 "Unauthorized\r\n"); 9149 const MockRead kProxyChallenge( 9150 "HTTP/1.1 407 Unauthorized\r\n" 9151 "Proxy-Authenticate: Mock realm=proxy\r\n" 9152 "Proxy-Connection: close\r\n" 9153 "Content-Type: text/html; charset=iso-8859-1\r\n" 9154 "Content-Length: 14\r\n\r\n" 9155 "Unauthorized\r\n"); 9156 const MockRead kProxyConnected( 9157 "HTTP/1.1 200 Connection Established\r\n\r\n"); 9158 9159 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with 9160 // no constructors, but the C++ compiler on Windows warns about 9161 // unspecified data in compound literals. So, moved to using constructors, 9162 // and TestRound's created with the default constructor should not be used. 9163 struct TestRound { 9164 TestRound() 9165 : expected_rv(ERR_UNEXPECTED), 9166 extra_write(NULL), 9167 extra_read(NULL) { 9168 } 9169 TestRound(const MockWrite& write_arg, const MockRead& read_arg, 9170 int expected_rv_arg) 9171 : write(write_arg), 9172 read(read_arg), 9173 expected_rv(expected_rv_arg), 9174 extra_write(NULL), 9175 extra_read(NULL) { 9176 } 9177 TestRound(const MockWrite& write_arg, const MockRead& read_arg, 9178 int expected_rv_arg, const MockWrite* extra_write_arg, 9179 const MockRead* extra_read_arg) 9180 : write(write_arg), 9181 read(read_arg), 9182 expected_rv(expected_rv_arg), 9183 extra_write(extra_write_arg), 9184 extra_read(extra_read_arg) { 9185 } 9186 MockWrite write; 9187 MockRead read; 9188 int expected_rv; 9189 const MockWrite* extra_write; 9190 const MockRead* extra_read; 9191 }; 9192 9193 static const int kNoSSL = 500; 9194 9195 struct TestConfig { 9196 const char* proxy_url; 9197 AuthTiming proxy_auth_timing; 9198 int proxy_auth_rv; 9199 const char* server_url; 9200 AuthTiming server_auth_timing; 9201 int server_auth_rv; 9202 int num_auth_rounds; 9203 int first_ssl_round; 9204 TestRound rounds[3]; 9205 } test_configs[] = { 9206 // Non-authenticating HTTP server with a direct connection. 9207 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL, 9208 { TestRound(kGet, kSuccess, OK)}}, 9209 // Authenticating HTTP server with a direct connection. 9210 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL, 9211 { TestRound(kGet, kServerChallenge, OK), 9212 TestRound(kGetAuth, kSuccess, OK)}}, 9213 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL, 9214 { TestRound(kGet, kServerChallenge, OK), 9215 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9216 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL, 9217 { TestRound(kGet, kServerChallenge, OK), 9218 TestRound(kGetAuth, kSuccess, OK)}}, 9219 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL, 9220 { TestRound(kGet, kServerChallenge, OK), 9221 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9222 // Non-authenticating HTTP server through a non-authenticating proxy. 9223 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL, 9224 { TestRound(kGetProxy, kSuccess, OK)}}, 9225 // Authenticating HTTP server through a non-authenticating proxy. 9226 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL, 9227 { TestRound(kGetProxy, kServerChallenge, OK), 9228 TestRound(kGetAuthThroughProxy, kSuccess, OK)}}, 9229 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL, 9230 { TestRound(kGetProxy, kServerChallenge, OK), 9231 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}}, 9232 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL, 9233 { TestRound(kGetProxy, kServerChallenge, OK), 9234 TestRound(kGetAuthThroughProxy, kSuccess, OK)}}, 9235 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL, 9236 { TestRound(kGetProxy, kServerChallenge, OK), 9237 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}}, 9238 // Non-authenticating HTTP server through an authenticating proxy. 9239 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL, 9240 { TestRound(kGetProxy, kProxyChallenge, OK), 9241 TestRound(kGetProxyAuth, kSuccess, OK)}}, 9242 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL, 9243 { TestRound(kGetProxy, kProxyChallenge, OK), 9244 TestRound(kGetProxyAuth, kFailure, kAuthErr)}}, 9245 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL, 9246 { TestRound(kGetProxy, kProxyChallenge, OK), 9247 TestRound(kGetProxyAuth, kSuccess, OK)}}, 9248 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL, 9249 { TestRound(kGetProxy, kProxyChallenge, OK), 9250 TestRound(kGetProxyAuth, kFailure, kAuthErr)}}, 9251 // Authenticating HTTP server through an authenticating proxy. 9252 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL, 9253 { TestRound(kGetProxy, kProxyChallenge, OK), 9254 TestRound(kGetProxyAuth, kServerChallenge, OK), 9255 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9256 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL, 9257 { TestRound(kGetProxy, kProxyChallenge, OK), 9258 TestRound(kGetProxyAuth, kServerChallenge, OK), 9259 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9260 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL, 9261 { TestRound(kGetProxy, kProxyChallenge, OK), 9262 TestRound(kGetProxyAuth, kServerChallenge, OK), 9263 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9264 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL, 9265 { TestRound(kGetProxy, kProxyChallenge, OK), 9266 TestRound(kGetProxyAuth, kServerChallenge, OK), 9267 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9268 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL, 9269 { TestRound(kGetProxy, kProxyChallenge, OK), 9270 TestRound(kGetProxyAuth, kServerChallenge, OK), 9271 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9272 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL, 9273 { TestRound(kGetProxy, kProxyChallenge, OK), 9274 TestRound(kGetProxyAuth, kServerChallenge, OK), 9275 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9276 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL, 9277 { TestRound(kGetProxy, kProxyChallenge, OK), 9278 TestRound(kGetProxyAuth, kServerChallenge, OK), 9279 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}}, 9280 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL, 9281 { TestRound(kGetProxy, kProxyChallenge, OK), 9282 TestRound(kGetProxyAuth, kServerChallenge, OK), 9283 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}}, 9284 // Non-authenticating HTTPS server with a direct connection. 9285 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0, 9286 { TestRound(kGet, kSuccess, OK)}}, 9287 // Authenticating HTTPS server with a direct connection. 9288 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0, 9289 { TestRound(kGet, kServerChallenge, OK), 9290 TestRound(kGetAuth, kSuccess, OK)}}, 9291 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0, 9292 { TestRound(kGet, kServerChallenge, OK), 9293 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9294 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0, 9295 { TestRound(kGet, kServerChallenge, OK), 9296 TestRound(kGetAuth, kSuccess, OK)}}, 9297 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0, 9298 { TestRound(kGet, kServerChallenge, OK), 9299 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9300 // Non-authenticating HTTPS server with a non-authenticating proxy. 9301 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0, 9302 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}}, 9303 // Authenticating HTTPS server through a non-authenticating proxy. 9304 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0, 9305 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9306 TestRound(kGetAuth, kSuccess, OK)}}, 9307 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0, 9308 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9309 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9310 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0, 9311 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9312 TestRound(kGetAuth, kSuccess, OK)}}, 9313 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0, 9314 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge), 9315 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9316 // Non-Authenticating HTTPS server through an authenticating proxy. 9317 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1, 9318 { TestRound(kConnect, kProxyChallenge, OK), 9319 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}}, 9320 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL, 9321 { TestRound(kConnect, kProxyChallenge, OK), 9322 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}}, 9323 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1, 9324 { TestRound(kConnect, kProxyChallenge, OK), 9325 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}}, 9326 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL, 9327 { TestRound(kConnect, kProxyChallenge, OK), 9328 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}}, 9329 // Authenticating HTTPS server through an authenticating proxy. 9330 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1, 9331 { TestRound(kConnect, kProxyChallenge, OK), 9332 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9333 &kGet, &kServerChallenge), 9334 TestRound(kGetAuth, kSuccess, OK)}}, 9335 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1, 9336 { TestRound(kConnect, kProxyChallenge, OK), 9337 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9338 &kGet, &kServerChallenge), 9339 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9340 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1, 9341 { TestRound(kConnect, kProxyChallenge, OK), 9342 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9343 &kGet, &kServerChallenge), 9344 TestRound(kGetAuth, kSuccess, OK)}}, 9345 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1, 9346 { TestRound(kConnect, kProxyChallenge, OK), 9347 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9348 &kGet, &kServerChallenge), 9349 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9350 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1, 9351 { TestRound(kConnect, kProxyChallenge, OK), 9352 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9353 &kGet, &kServerChallenge), 9354 TestRound(kGetAuth, kSuccess, OK)}}, 9355 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1, 9356 { TestRound(kConnect, kProxyChallenge, OK), 9357 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9358 &kGet, &kServerChallenge), 9359 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9360 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1, 9361 { TestRound(kConnect, kProxyChallenge, OK), 9362 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9363 &kGet, &kServerChallenge), 9364 TestRound(kGetAuth, kSuccess, OK)}}, 9365 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1, 9366 { TestRound(kConnect, kProxyChallenge, OK), 9367 TestRound(kConnectProxyAuth, kProxyConnected, OK, 9368 &kGet, &kServerChallenge), 9369 TestRound(kGetAuth, kFailure, kAuthErr)}}, 9370 }; 9371 9372 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) { 9373 HttpAuthHandlerMock::Factory* auth_factory( 9374 new HttpAuthHandlerMock::Factory()); 9375 session_deps_.http_auth_handler_factory.reset(auth_factory); 9376 const TestConfig& test_config = test_configs[i]; 9377 9378 // Set up authentication handlers as necessary. 9379 if (test_config.proxy_auth_timing != AUTH_NONE) { 9380 for (int n = 0; n < 2; n++) { 9381 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 9382 std::string auth_challenge = "Mock realm=proxy"; 9383 GURL origin(test_config.proxy_url); 9384 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 9385 auth_challenge.end()); 9386 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY, 9387 origin, BoundNetLog()); 9388 auth_handler->SetGenerateExpectation( 9389 test_config.proxy_auth_timing == AUTH_ASYNC, 9390 test_config.proxy_auth_rv); 9391 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY); 9392 } 9393 } 9394 if (test_config.server_auth_timing != AUTH_NONE) { 9395 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 9396 std::string auth_challenge = "Mock realm=server"; 9397 GURL origin(test_config.server_url); 9398 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 9399 auth_challenge.end()); 9400 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, 9401 origin, BoundNetLog()); 9402 auth_handler->SetGenerateExpectation( 9403 test_config.server_auth_timing == AUTH_ASYNC, 9404 test_config.server_auth_rv); 9405 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER); 9406 } 9407 if (test_config.proxy_url) { 9408 session_deps_.proxy_service.reset( 9409 ProxyService::CreateFixed(test_config.proxy_url)); 9410 } else { 9411 session_deps_.proxy_service.reset(ProxyService::CreateDirect()); 9412 } 9413 9414 HttpRequestInfo request; 9415 request.method = "GET"; 9416 request.url = GURL(test_config.server_url); 9417 request.load_flags = 0; 9418 9419 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9420 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session); 9421 9422 for (int round = 0; round < test_config.num_auth_rounds; ++round) { 9423 const TestRound& read_write_round = test_config.rounds[round]; 9424 9425 // Set up expected reads and writes. 9426 MockRead reads[2]; 9427 reads[0] = read_write_round.read; 9428 size_t length_reads = 1; 9429 if (read_write_round.extra_read) { 9430 reads[1] = *read_write_round.extra_read; 9431 length_reads = 2; 9432 } 9433 9434 MockWrite writes[2]; 9435 writes[0] = read_write_round.write; 9436 size_t length_writes = 1; 9437 if (read_write_round.extra_write) { 9438 writes[1] = *read_write_round.extra_write; 9439 length_writes = 2; 9440 } 9441 StaticSocketDataProvider data_provider( 9442 reads, length_reads, writes, length_writes); 9443 session_deps_.socket_factory->AddSocketDataProvider(&data_provider); 9444 9445 // Add an SSL sequence if necessary. 9446 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK); 9447 if (round >= test_config.first_ssl_round) 9448 session_deps_.socket_factory->AddSSLSocketDataProvider( 9449 &ssl_socket_data_provider); 9450 9451 // Start or restart the transaction. 9452 TestCompletionCallback callback; 9453 int rv; 9454 if (round == 0) { 9455 rv = trans.Start(&request, callback.callback(), BoundNetLog()); 9456 } else { 9457 rv = trans.RestartWithAuth( 9458 AuthCredentials(kFoo, kBar), callback.callback()); 9459 } 9460 if (rv == ERR_IO_PENDING) 9461 rv = callback.WaitForResult(); 9462 9463 // Compare results with expected data. 9464 EXPECT_EQ(read_write_round.expected_rv, rv); 9465 const HttpResponseInfo* response = trans.GetResponseInfo(); 9466 if (read_write_round.expected_rv == OK) { 9467 ASSERT_TRUE(response != NULL); 9468 } else { 9469 EXPECT_TRUE(response == NULL); 9470 EXPECT_EQ(round + 1, test_config.num_auth_rounds); 9471 continue; 9472 } 9473 if (round + 1 < test_config.num_auth_rounds) { 9474 EXPECT_FALSE(response->auth_challenge.get() == NULL); 9475 } else { 9476 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9477 } 9478 } 9479 } 9480} 9481 9482TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) { 9483 // Do multi-round authentication and make sure it works correctly. 9484 HttpAuthHandlerMock::Factory* auth_factory( 9485 new HttpAuthHandlerMock::Factory()); 9486 session_deps_.http_auth_handler_factory.reset(auth_factory); 9487 session_deps_.proxy_service.reset(ProxyService::CreateDirect()); 9488 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1"); 9489 session_deps_.host_resolver->set_synchronous_mode(true); 9490 9491 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock()); 9492 auth_handler->set_connection_based(true); 9493 std::string auth_challenge = "Mock realm=server"; 9494 GURL origin("http://www.example.com"); 9495 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(), 9496 auth_challenge.end()); 9497 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, 9498 origin, BoundNetLog()); 9499 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER); 9500 9501 int rv = OK; 9502 const HttpResponseInfo* response = NULL; 9503 HttpRequestInfo request; 9504 request.method = "GET"; 9505 request.url = origin; 9506 request.load_flags = 0; 9507 9508 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9509 9510 // Use a TCP Socket Pool with only one connection per group. This is used 9511 // to validate that the TCP socket is not released to the pool between 9512 // each round of multi-round authentication. 9513 HttpNetworkSessionPeer session_peer(session); 9514 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP"); 9515 TransportClientSocketPool* transport_pool = new TransportClientSocketPool( 9516 50, // Max sockets for pool 9517 1, // Max sockets per group 9518 &transport_pool_histograms, 9519 session_deps_.host_resolver.get(), 9520 session_deps_.socket_factory.get(), 9521 session_deps_.net_log); 9522 scoped_ptr<MockClientSocketPoolManager> mock_pool_manager( 9523 new MockClientSocketPoolManager); 9524 mock_pool_manager->SetTransportSocketPool(transport_pool); 9525 session_peer.SetClientSocketPoolManager( 9526 mock_pool_manager.PassAs<ClientSocketPoolManager>()); 9527 9528 scoped_ptr<HttpTransaction> trans( 9529 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9530 TestCompletionCallback callback; 9531 9532 const MockWrite kGet( 9533 "GET / HTTP/1.1\r\n" 9534 "Host: www.example.com\r\n" 9535 "Connection: keep-alive\r\n\r\n"); 9536 const MockWrite kGetAuth( 9537 "GET / HTTP/1.1\r\n" 9538 "Host: www.example.com\r\n" 9539 "Connection: keep-alive\r\n" 9540 "Authorization: auth_token\r\n\r\n"); 9541 9542 const MockRead kServerChallenge( 9543 "HTTP/1.1 401 Unauthorized\r\n" 9544 "WWW-Authenticate: Mock realm=server\r\n" 9545 "Content-Type: text/html; charset=iso-8859-1\r\n" 9546 "Content-Length: 14\r\n\r\n" 9547 "Unauthorized\r\n"); 9548 const MockRead kSuccess( 9549 "HTTP/1.1 200 OK\r\n" 9550 "Content-Type: text/html; charset=iso-8859-1\r\n" 9551 "Content-Length: 3\r\n\r\n" 9552 "Yes"); 9553 9554 MockWrite writes[] = { 9555 // First round 9556 kGet, 9557 // Second round 9558 kGetAuth, 9559 // Third round 9560 kGetAuth, 9561 // Fourth round 9562 kGetAuth, 9563 // Competing request 9564 kGet, 9565 }; 9566 MockRead reads[] = { 9567 // First round 9568 kServerChallenge, 9569 // Second round 9570 kServerChallenge, 9571 // Third round 9572 kServerChallenge, 9573 // Fourth round 9574 kSuccess, 9575 // Competing response 9576 kSuccess, 9577 }; 9578 StaticSocketDataProvider data_provider(reads, arraysize(reads), 9579 writes, arraysize(writes)); 9580 session_deps_.socket_factory->AddSocketDataProvider(&data_provider); 9581 9582 const char* const kSocketGroup = "www.example.com:80"; 9583 9584 // First round of authentication. 9585 auth_handler->SetGenerateExpectation(false, OK); 9586 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9587 if (rv == ERR_IO_PENDING) 9588 rv = callback.WaitForResult(); 9589 EXPECT_EQ(OK, rv); 9590 response = trans->GetResponseInfo(); 9591 ASSERT_TRUE(response != NULL); 9592 EXPECT_FALSE(response->auth_challenge.get() == NULL); 9593 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9594 9595 // In between rounds, another request comes in for the same domain. 9596 // It should not be able to grab the TCP socket that trans has already 9597 // claimed. 9598 scoped_ptr<HttpTransaction> trans_compete( 9599 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9600 TestCompletionCallback callback_compete; 9601 rv = trans_compete->Start( 9602 &request, callback_compete.callback(), BoundNetLog()); 9603 EXPECT_EQ(ERR_IO_PENDING, rv); 9604 // callback_compete.WaitForResult at this point would stall forever, 9605 // since the HttpNetworkTransaction does not release the request back to 9606 // the pool until after authentication completes. 9607 9608 // Second round of authentication. 9609 auth_handler->SetGenerateExpectation(false, OK); 9610 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback()); 9611 if (rv == ERR_IO_PENDING) 9612 rv = callback.WaitForResult(); 9613 EXPECT_EQ(OK, rv); 9614 response = trans->GetResponseInfo(); 9615 ASSERT_TRUE(response != NULL); 9616 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9617 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9618 9619 // Third round of authentication. 9620 auth_handler->SetGenerateExpectation(false, OK); 9621 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback()); 9622 if (rv == ERR_IO_PENDING) 9623 rv = callback.WaitForResult(); 9624 EXPECT_EQ(OK, rv); 9625 response = trans->GetResponseInfo(); 9626 ASSERT_TRUE(response != NULL); 9627 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9628 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9629 9630 // Fourth round of authentication, which completes successfully. 9631 auth_handler->SetGenerateExpectation(false, OK); 9632 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback()); 9633 if (rv == ERR_IO_PENDING) 9634 rv = callback.WaitForResult(); 9635 EXPECT_EQ(OK, rv); 9636 response = trans->GetResponseInfo(); 9637 ASSERT_TRUE(response != NULL); 9638 EXPECT_TRUE(response->auth_challenge.get() == NULL); 9639 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9640 9641 // Read the body since the fourth round was successful. This will also 9642 // release the socket back to the pool. 9643 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50)); 9644 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 9645 if (rv == ERR_IO_PENDING) 9646 rv = callback.WaitForResult(); 9647 EXPECT_EQ(3, rv); 9648 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 9649 EXPECT_EQ(0, rv); 9650 // There are still 0 idle sockets, since the trans_compete transaction 9651 // will be handed it immediately after trans releases it to the group. 9652 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9653 9654 // The competing request can now finish. Wait for the headers and then 9655 // read the body. 9656 rv = callback_compete.WaitForResult(); 9657 EXPECT_EQ(OK, rv); 9658 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback()); 9659 if (rv == ERR_IO_PENDING) 9660 rv = callback.WaitForResult(); 9661 EXPECT_EQ(3, rv); 9662 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback()); 9663 EXPECT_EQ(0, rv); 9664 9665 // Finally, the socket is released to the group. 9666 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup)); 9667} 9668 9669// This tests the case that a request is issued via http instead of spdy after 9670// npn is negotiated. 9671TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) { 9672 HttpStreamFactory::set_use_alternate_protocols(true); 9673 std::vector<NextProto> next_protos; 9674 next_protos.push_back(kProtoHTTP11); 9675 HttpStreamFactory::SetNextProtos(next_protos); 9676 HttpRequestInfo request; 9677 request.method = "GET"; 9678 request.url = GURL("https://www.google.com/"); 9679 request.load_flags = 0; 9680 9681 MockWrite data_writes[] = { 9682 MockWrite("GET / HTTP/1.1\r\n" 9683 "Host: www.google.com\r\n" 9684 "Connection: keep-alive\r\n\r\n"), 9685 }; 9686 9687 std::string alternate_protocol_http_header = 9688 GetAlternateProtocolHttpHeader(); 9689 9690 MockRead data_reads[] = { 9691 MockRead("HTTP/1.1 200 OK\r\n"), 9692 MockRead(alternate_protocol_http_header.c_str()), 9693 MockRead("hello world"), 9694 MockRead(SYNCHRONOUS, OK), 9695 }; 9696 9697 SSLSocketDataProvider ssl(ASYNC, OK); 9698 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; 9699 ssl.next_proto = "http/1.1"; 9700 ssl.protocol_negotiated = kProtoHTTP11; 9701 9702 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9703 9704 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 9705 data_writes, arraysize(data_writes)); 9706 session_deps_.socket_factory->AddSocketDataProvider(&data); 9707 9708 TestCompletionCallback callback; 9709 9710 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9711 scoped_ptr<HttpTransaction> trans( 9712 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9713 9714 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9715 9716 EXPECT_EQ(ERR_IO_PENDING, rv); 9717 EXPECT_EQ(OK, callback.WaitForResult()); 9718 9719 const HttpResponseInfo* response = trans->GetResponseInfo(); 9720 ASSERT_TRUE(response != NULL); 9721 ASSERT_TRUE(response->headers.get() != NULL); 9722 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 9723 9724 std::string response_data; 9725 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 9726 EXPECT_EQ("hello world", response_data); 9727 9728 EXPECT_FALSE(response->was_fetched_via_spdy); 9729 EXPECT_TRUE(response->was_npn_negotiated); 9730} 9731 9732TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) { 9733 // Simulate the SSL handshake completing with an NPN negotiation 9734 // followed by an immediate server closing of the socket. 9735 // Fix crash: http://crbug.com/46369 9736 HttpStreamFactory::set_use_alternate_protocols(true); 9737 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 9738 9739 HttpRequestInfo request; 9740 request.method = "GET"; 9741 request.url = GURL("https://www.google.com/"); 9742 request.load_flags = 0; 9743 9744 SSLSocketDataProvider ssl(ASYNC, OK); 9745 ssl.SetNextProto(GetParam()); 9746 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9747 9748 scoped_ptr<SpdyFrame> req( 9749 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 9750 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 9751 9752 MockRead spdy_reads[] = { 9753 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately. 9754 }; 9755 9756 DelayedSocketData spdy_data( 9757 0, // don't wait in this case, immediate hangup. 9758 spdy_reads, arraysize(spdy_reads), 9759 spdy_writes, arraysize(spdy_writes)); 9760 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 9761 9762 TestCompletionCallback callback; 9763 9764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9765 scoped_ptr<HttpTransaction> trans( 9766 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9767 9768 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 9769 EXPECT_EQ(ERR_IO_PENDING, rv); 9770 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult()); 9771} 9772 9773// A subclass of HttpAuthHandlerMock that records the request URL when 9774// it gets it. This is needed since the auth handler may get destroyed 9775// before we get a chance to query it. 9776class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock { 9777 public: 9778 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {} 9779 9780 virtual ~UrlRecordingHttpAuthHandlerMock() {} 9781 9782 protected: 9783 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials, 9784 const HttpRequestInfo* request, 9785 const CompletionCallback& callback, 9786 std::string* auth_token) OVERRIDE { 9787 *url_ = request->url; 9788 return HttpAuthHandlerMock::GenerateAuthTokenImpl( 9789 credentials, request, callback, auth_token); 9790 } 9791 9792 private: 9793 GURL* url_; 9794}; 9795 9796TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { 9797 // This test ensures that the URL passed into the proxy is upgraded 9798 // to https when doing an Alternate Protocol upgrade. 9799 HttpStreamFactory::set_use_alternate_protocols(true); 9800 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 9801 9802 session_deps_.proxy_service.reset( 9803 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 9804 CapturingNetLog net_log; 9805 session_deps_.net_log = &net_log; 9806 GURL request_url; 9807 { 9808 HttpAuthHandlerMock::Factory* auth_factory = 9809 new HttpAuthHandlerMock::Factory(); 9810 UrlRecordingHttpAuthHandlerMock* auth_handler = 9811 new UrlRecordingHttpAuthHandlerMock(&request_url); 9812 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY); 9813 auth_factory->set_do_init_from_challenge(true); 9814 session_deps_.http_auth_handler_factory.reset(auth_factory); 9815 } 9816 9817 HttpRequestInfo request; 9818 request.method = "GET"; 9819 request.url = GURL("http://www.google.com"); 9820 request.load_flags = 0; 9821 9822 // First round goes unauthenticated through the proxy. 9823 MockWrite data_writes_1[] = { 9824 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 9825 "Host: www.google.com\r\n" 9826 "Proxy-Connection: keep-alive\r\n" 9827 "\r\n"), 9828 }; 9829 MockRead data_reads_1[] = { 9830 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 9831 MockRead("HTTP/1.1 200 OK\r\n" 9832 "Alternate-Protocol: 443:npn-spdy/2\r\n" 9833 "Proxy-Connection: close\r\n" 9834 "\r\n"), 9835 }; 9836 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1), 9837 data_writes_1, arraysize(data_writes_1)); 9838 9839 // Second round tries to tunnel to www.google.com due to the 9840 // Alternate-Protocol announcement in the first round. It fails due 9841 // to a proxy authentication challenge. 9842 // After the failure, a tunnel is established to www.google.com using 9843 // Proxy-Authorization headers. There is then a SPDY request round. 9844 // 9845 // NOTE: Despite the "Proxy-Connection: Close", these are done on the 9846 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket 9847 // does a Disconnect and Connect on the same socket, rather than trying 9848 // to obtain a new one. 9849 // 9850 // NOTE: Originally, the proxy response to the second CONNECT request 9851 // simply returned another 407 so the unit test could skip the SSL connection 9852 // establishment and SPDY framing issues. Alas, the 9853 // retry-http-when-alternate-protocol fails logic kicks in, which was more 9854 // complicated to set up expectations for than the SPDY session. 9855 9856 scoped_ptr<SpdyFrame> req( 9857 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 9858 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 9859 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 9860 9861 MockWrite data_writes_2[] = { 9862 // First connection attempt without Proxy-Authorization. 9863 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 9864 "Host: www.google.com\r\n" 9865 "Proxy-Connection: keep-alive\r\n" 9866 "\r\n"), 9867 9868 // Second connection attempt with Proxy-Authorization. 9869 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 9870 "Host: www.google.com\r\n" 9871 "Proxy-Connection: keep-alive\r\n" 9872 "Proxy-Authorization: auth_token\r\n" 9873 "\r\n"), 9874 9875 // SPDY request 9876 CreateMockWrite(*req), 9877 }; 9878 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n" 9879 "Proxy-Authenticate: Mock\r\n" 9880 "Proxy-Connection: close\r\n" 9881 "\r\n"); 9882 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; 9883 MockRead data_reads_2[] = { 9884 // First connection attempt fails 9885 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1), 9886 MockRead(ASYNC, kRejectConnectResponse, 9887 arraysize(kRejectConnectResponse) - 1, 1), 9888 9889 // Second connection attempt passes 9890 MockRead(ASYNC, kAcceptConnectResponse, 9891 arraysize(kAcceptConnectResponse) -1, 4), 9892 9893 // SPDY response 9894 CreateMockRead(*resp.get(), 6), 9895 CreateMockRead(*data.get(), 6), 9896 MockRead(ASYNC, 0, 0, 6), 9897 }; 9898 OrderedSocketData data_2( 9899 data_reads_2, arraysize(data_reads_2), 9900 data_writes_2, arraysize(data_writes_2)); 9901 9902 SSLSocketDataProvider ssl(ASYNC, OK); 9903 ssl.SetNextProto(GetParam()); 9904 9905 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); 9906 StaticSocketDataProvider hanging_non_alternate_protocol_socket( 9907 NULL, 0, NULL, 0); 9908 hanging_non_alternate_protocol_socket.set_connect_data( 9909 never_finishing_connect); 9910 9911 session_deps_.socket_factory->AddSocketDataProvider(&data_1); 9912 session_deps_.socket_factory->AddSocketDataProvider(&data_2); 9913 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 9914 session_deps_.socket_factory->AddSocketDataProvider( 9915 &hanging_non_alternate_protocol_socket); 9916 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9917 9918 // First round should work and provide the Alternate-Protocol state. 9919 TestCompletionCallback callback_1; 9920 scoped_ptr<HttpTransaction> trans_1( 9921 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9922 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog()); 9923 EXPECT_EQ(ERR_IO_PENDING, rv); 9924 EXPECT_EQ(OK, callback_1.WaitForResult()); 9925 9926 // Second round should attempt a tunnel connect and get an auth challenge. 9927 TestCompletionCallback callback_2; 9928 scoped_ptr<HttpTransaction> trans_2( 9929 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 9930 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog()); 9931 EXPECT_EQ(ERR_IO_PENDING, rv); 9932 EXPECT_EQ(OK, callback_2.WaitForResult()); 9933 const HttpResponseInfo* response = trans_2->GetResponseInfo(); 9934 ASSERT_TRUE(response != NULL); 9935 ASSERT_FALSE(response->auth_challenge.get() == NULL); 9936 9937 // Restart with auth. Tunnel should work and response received. 9938 TestCompletionCallback callback_3; 9939 rv = trans_2->RestartWithAuth( 9940 AuthCredentials(kFoo, kBar), callback_3.callback()); 9941 EXPECT_EQ(ERR_IO_PENDING, rv); 9942 EXPECT_EQ(OK, callback_3.WaitForResult()); 9943 9944 // After all that work, these two lines (or actually, just the scheme) are 9945 // what this test is all about. Make sure it happens correctly. 9946 EXPECT_EQ("https", request_url.scheme()); 9947 EXPECT_EQ("www.google.com", request_url.host()); 9948 9949 LoadTimingInfo load_timing_info; 9950 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info)); 9951 TestLoadTimingNotReusedWithPac(load_timing_info, 9952 CONNECT_TIMING_HAS_SSL_TIMES); 9953} 9954 9955// Test that if we cancel the transaction as the connection is completing, that 9956// everything tears down correctly. 9957TEST_P(HttpNetworkTransactionTest, SimpleCancel) { 9958 // Setup everything about the connection to complete synchronously, so that 9959 // after calling HttpNetworkTransaction::Start, the only thing we're waiting 9960 // for is the callback from the HttpStreamRequest. 9961 // Then cancel the transaction. 9962 // Verify that we don't crash. 9963 MockConnect mock_connect(SYNCHRONOUS, OK); 9964 MockRead data_reads[] = { 9965 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"), 9966 MockRead(SYNCHRONOUS, "hello world"), 9967 MockRead(SYNCHRONOUS, OK), 9968 }; 9969 9970 HttpRequestInfo request; 9971 request.method = "GET"; 9972 request.url = GURL("http://www.google.com/"); 9973 request.load_flags = 0; 9974 9975 session_deps_.host_resolver->set_synchronous_mode(true); 9976 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 9977 scoped_ptr<HttpTransaction> trans( 9978 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 9979 9980 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 9981 data.set_connect_data(mock_connect); 9982 session_deps_.socket_factory->AddSocketDataProvider(&data); 9983 9984 TestCompletionCallback callback; 9985 9986 CapturingBoundNetLog log; 9987 int rv = trans->Start(&request, callback.callback(), log.bound()); 9988 EXPECT_EQ(ERR_IO_PENDING, rv); 9989 trans.reset(); // Cancel the transaction here. 9990 9991 base::MessageLoop::current()->RunUntilIdle(); 9992} 9993 9994// Test a basic GET request through a proxy. 9995TEST_P(HttpNetworkTransactionTest, ProxyGet) { 9996 session_deps_.proxy_service.reset( 9997 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 9998 CapturingBoundNetLog log; 9999 session_deps_.net_log = log.bound().net_log(); 10000 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10001 10002 HttpRequestInfo request; 10003 request.method = "GET"; 10004 request.url = GURL("http://www.google.com/"); 10005 10006 MockWrite data_writes1[] = { 10007 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 10008 "Host: www.google.com\r\n" 10009 "Proxy-Connection: keep-alive\r\n\r\n"), 10010 }; 10011 10012 MockRead data_reads1[] = { 10013 MockRead("HTTP/1.1 200 OK\r\n"), 10014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 10015 MockRead("Content-Length: 100\r\n\r\n"), 10016 MockRead(SYNCHRONOUS, OK), 10017 }; 10018 10019 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 10020 data_writes1, arraysize(data_writes1)); 10021 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10022 10023 TestCompletionCallback callback1; 10024 10025 scoped_ptr<HttpTransaction> trans( 10026 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10027 10028 int rv = trans->Start(&request, callback1.callback(), log.bound()); 10029 EXPECT_EQ(ERR_IO_PENDING, rv); 10030 10031 rv = callback1.WaitForResult(); 10032 EXPECT_EQ(OK, rv); 10033 10034 const HttpResponseInfo* response = trans->GetResponseInfo(); 10035 ASSERT_TRUE(response != NULL); 10036 10037 EXPECT_TRUE(response->headers->IsKeepAlive()); 10038 EXPECT_EQ(200, response->headers->response_code()); 10039 EXPECT_EQ(100, response->headers->GetContentLength()); 10040 EXPECT_TRUE(response->was_fetched_via_proxy); 10041 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 10042 10043 LoadTimingInfo load_timing_info; 10044 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 10045 TestLoadTimingNotReusedWithPac(load_timing_info, 10046 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 10047} 10048 10049// Test a basic HTTPS GET request through a proxy. 10050TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) { 10051 session_deps_.proxy_service.reset( 10052 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 10053 CapturingBoundNetLog log; 10054 session_deps_.net_log = log.bound().net_log(); 10055 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10056 10057 HttpRequestInfo request; 10058 request.method = "GET"; 10059 request.url = GURL("https://www.google.com/"); 10060 10061 // Since we have proxy, should try to establish tunnel. 10062 MockWrite data_writes1[] = { 10063 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 10064 "Host: www.google.com\r\n" 10065 "Proxy-Connection: keep-alive\r\n\r\n"), 10066 10067 MockWrite("GET / HTTP/1.1\r\n" 10068 "Host: www.google.com\r\n" 10069 "Connection: keep-alive\r\n\r\n"), 10070 }; 10071 10072 MockRead data_reads1[] = { 10073 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 10074 10075 MockRead("HTTP/1.1 200 OK\r\n"), 10076 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 10077 MockRead("Content-Length: 100\r\n\r\n"), 10078 MockRead(SYNCHRONOUS, OK), 10079 }; 10080 10081 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 10082 data_writes1, arraysize(data_writes1)); 10083 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10084 SSLSocketDataProvider ssl(ASYNC, OK); 10085 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10086 10087 TestCompletionCallback callback1; 10088 10089 scoped_ptr<HttpTransaction> trans( 10090 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10091 10092 int rv = trans->Start(&request, callback1.callback(), log.bound()); 10093 EXPECT_EQ(ERR_IO_PENDING, rv); 10094 10095 rv = callback1.WaitForResult(); 10096 EXPECT_EQ(OK, rv); 10097 net::CapturingNetLog::CapturedEntryList entries; 10098 log.GetEntries(&entries); 10099 size_t pos = ExpectLogContainsSomewhere( 10100 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 10101 NetLog::PHASE_NONE); 10102 ExpectLogContainsSomewhere( 10103 entries, pos, 10104 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 10105 NetLog::PHASE_NONE); 10106 10107 const HttpResponseInfo* response = trans->GetResponseInfo(); 10108 ASSERT_TRUE(response != NULL); 10109 10110 EXPECT_TRUE(response->headers->IsKeepAlive()); 10111 EXPECT_EQ(200, response->headers->response_code()); 10112 EXPECT_EQ(100, response->headers->GetContentLength()); 10113 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 10114 EXPECT_TRUE(response->was_fetched_via_proxy); 10115 10116 LoadTimingInfo load_timing_info; 10117 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 10118 TestLoadTimingNotReusedWithPac(load_timing_info, 10119 CONNECT_TIMING_HAS_SSL_TIMES); 10120} 10121 10122// Test a basic HTTPS GET request through a proxy, but the server hangs up 10123// while establishing the tunnel. 10124TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) { 10125 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 10126 CapturingBoundNetLog log; 10127 session_deps_.net_log = log.bound().net_log(); 10128 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10129 10130 HttpRequestInfo request; 10131 request.method = "GET"; 10132 request.url = GURL("https://www.google.com/"); 10133 10134 // Since we have proxy, should try to establish tunnel. 10135 MockWrite data_writes1[] = { 10136 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 10137 "Host: www.google.com\r\n" 10138 "Proxy-Connection: keep-alive\r\n\r\n"), 10139 10140 MockWrite("GET / HTTP/1.1\r\n" 10141 "Host: www.google.com\r\n" 10142 "Connection: keep-alive\r\n\r\n"), 10143 }; 10144 10145 MockRead data_reads1[] = { 10146 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 10147 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 10148 MockRead(ASYNC, 0, 0), // EOF 10149 }; 10150 10151 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 10152 data_writes1, arraysize(data_writes1)); 10153 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10154 SSLSocketDataProvider ssl(ASYNC, OK); 10155 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10156 10157 TestCompletionCallback callback1; 10158 10159 scoped_ptr<HttpTransaction> trans( 10160 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10161 10162 int rv = trans->Start(&request, callback1.callback(), log.bound()); 10163 EXPECT_EQ(ERR_IO_PENDING, rv); 10164 10165 rv = callback1.WaitForResult(); 10166 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 10167 net::CapturingNetLog::CapturedEntryList entries; 10168 log.GetEntries(&entries); 10169 size_t pos = ExpectLogContainsSomewhere( 10170 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 10171 NetLog::PHASE_NONE); 10172 ExpectLogContainsSomewhere( 10173 entries, pos, 10174 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 10175 NetLog::PHASE_NONE); 10176} 10177 10178// Test for crbug.com/55424. 10179TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) { 10180 scoped_ptr<SpdyFrame> req( 10181 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10182 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 10183 10184 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10185 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 10186 MockRead spdy_reads[] = { 10187 CreateMockRead(*resp), 10188 CreateMockRead(*data), 10189 MockRead(ASYNC, 0, 0), 10190 }; 10191 10192 DelayedSocketData spdy_data( 10193 1, // wait for one write to finish before reading. 10194 spdy_reads, arraysize(spdy_reads), 10195 spdy_writes, arraysize(spdy_writes)); 10196 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10197 10198 SSLSocketDataProvider ssl(ASYNC, OK); 10199 ssl.SetNextProto(GetParam()); 10200 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10201 10202 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10203 10204 // Set up an initial SpdySession in the pool to reuse. 10205 HostPortPair host_port_pair("www.google.com", 443); 10206 SpdySessionKey key(host_port_pair, ProxyServer::Direct(), 10207 kPrivacyModeDisabled); 10208 base::WeakPtr<SpdySession> spdy_session = 10209 CreateInsecureSpdySession(session, key, BoundNetLog()); 10210 10211 HttpRequestInfo request; 10212 request.method = "GET"; 10213 request.url = GURL("https://www.google.com/"); 10214 request.load_flags = 0; 10215 10216 // This is the important line that marks this as a preconnect. 10217 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED; 10218 10219 scoped_ptr<HttpTransaction> trans( 10220 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10221 10222 TestCompletionCallback callback; 10223 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 10224 EXPECT_EQ(ERR_IO_PENDING, rv); 10225 EXPECT_EQ(OK, callback.WaitForResult()); 10226} 10227 10228// Given a net error, cause that error to be returned from the first Write() 10229// call and verify that the HttpTransaction fails with that error. 10230void HttpNetworkTransactionTest::CheckErrorIsPassedBack( 10231 int error, IoMode mode) { 10232 net::HttpRequestInfo request_info; 10233 request_info.url = GURL("https://www.example.com/"); 10234 request_info.method = "GET"; 10235 request_info.load_flags = net::LOAD_NORMAL; 10236 10237 SSLSocketDataProvider ssl_data(mode, OK); 10238 net::MockWrite data_writes[] = { 10239 net::MockWrite(mode, error), 10240 }; 10241 net::StaticSocketDataProvider data(NULL, 0, 10242 data_writes, arraysize(data_writes)); 10243 session_deps_.socket_factory->AddSocketDataProvider(&data); 10244 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data); 10245 10246 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10247 scoped_ptr<HttpTransaction> trans( 10248 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10249 10250 TestCompletionCallback callback; 10251 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); 10252 if (rv == net::ERR_IO_PENDING) 10253 rv = callback.WaitForResult(); 10254 ASSERT_EQ(error, rv); 10255} 10256 10257TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) { 10258 // Just check a grab bag of cert errors. 10259 static const int kErrors[] = { 10260 ERR_CERT_COMMON_NAME_INVALID, 10261 ERR_CERT_AUTHORITY_INVALID, 10262 ERR_CERT_DATE_INVALID, 10263 }; 10264 for (size_t i = 0; i < arraysize(kErrors); i++) { 10265 CheckErrorIsPassedBack(kErrors[i], ASYNC); 10266 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS); 10267 } 10268} 10269 10270// Ensure that a client certificate is removed from the SSL client auth 10271// cache when: 10272// 1) No proxy is involved. 10273// 2) TLS False Start is disabled. 10274// 3) The initial TLS handshake requests a client certificate. 10275// 4) The client supplies an invalid/unacceptable certificate. 10276TEST_P(HttpNetworkTransactionTest, 10277 ClientAuthCertCache_Direct_NoFalseStart) { 10278 net::HttpRequestInfo request_info; 10279 request_info.url = GURL("https://www.example.com/"); 10280 request_info.method = "GET"; 10281 request_info.load_flags = net::LOAD_NORMAL; 10282 10283 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 10284 cert_request->host_and_port = HostPortPair("www.example.com", 443); 10285 10286 // [ssl_]data1 contains the data for the first SSL handshake. When a 10287 // CertificateRequest is received for the first time, the handshake will 10288 // be aborted to allow the caller to provide a certificate. 10289 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 10290 ssl_data1.cert_request_info = cert_request.get(); 10291 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); 10292 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 10293 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10294 10295 // [ssl_]data2 contains the data for the second SSL handshake. When TLS 10296 // False Start is not being used, the result of the SSL handshake will be 10297 // returned as part of the SSLClientSocket::Connect() call. This test 10298 // matches the result of a server sending a handshake_failure alert, 10299 // rather than a Finished message, because it requires a client 10300 // certificate and none was supplied. 10301 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10302 ssl_data2.cert_request_info = cert_request.get(); 10303 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); 10304 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); 10305 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10306 10307 // [ssl_]data3 contains the data for the third SSL handshake. When a 10308 // connection to a server fails during an SSL handshake, 10309 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous 10310 // connection was attempted with TLSv1.1. This is transparent to the caller 10311 // of the HttpNetworkTransaction. Because this test failure is due to 10312 // requiring a client certificate, this fallback handshake should also 10313 // fail. 10314 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10315 ssl_data3.cert_request_info = cert_request.get(); 10316 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); 10317 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); 10318 session_deps_.socket_factory->AddSocketDataProvider(&data3); 10319 10320 // [ssl_]data4 contains the data for the fourth SSL handshake. When a 10321 // connection to a server fails during an SSL handshake, 10322 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous 10323 // connection was attempted with TLSv1. This is transparent to the caller 10324 // of the HttpNetworkTransaction. Because this test failure is due to 10325 // requiring a client certificate, this fallback handshake should also 10326 // fail. 10327 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10328 ssl_data4.cert_request_info = cert_request.get(); 10329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); 10330 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0); 10331 session_deps_.socket_factory->AddSocketDataProvider(&data4); 10332 10333 // Need one more if TLSv1.2 is enabled. 10334 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10335 ssl_data5.cert_request_info = cert_request.get(); 10336 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); 10337 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0); 10338 session_deps_.socket_factory->AddSocketDataProvider(&data5); 10339 10340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10341 scoped_ptr<HttpTransaction> trans( 10342 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10343 10344 // Begin the SSL handshake with the peer. This consumes ssl_data1. 10345 TestCompletionCallback callback; 10346 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); 10347 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10348 10349 // Complete the SSL handshake, which should abort due to requiring a 10350 // client certificate. 10351 rv = callback.WaitForResult(); 10352 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 10353 10354 // Indicate that no certificate should be supplied. From the perspective 10355 // of SSLClientCertCache, NULL is just as meaningful as a real 10356 // certificate, so this is the same as supply a 10357 // legitimate-but-unacceptable certificate. 10358 rv = trans->RestartWithCertificate(NULL, callback.callback()); 10359 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10360 10361 // Ensure the certificate was added to the client auth cache before 10362 // allowing the connection to continue restarting. 10363 scoped_refptr<X509Certificate> client_cert; 10364 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup( 10365 HostPortPair("www.example.com", 443), &client_cert)); 10366 ASSERT_EQ(NULL, client_cert.get()); 10367 10368 // Restart the handshake. This will consume ssl_data2, which fails, and 10369 // then consume ssl_data3 and ssl_data4, both of which should also fail. 10370 // The result code is checked against what ssl_data4 should return. 10371 rv = callback.WaitForResult(); 10372 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 10373 10374 // Ensure that the client certificate is removed from the cache on a 10375 // handshake failure. 10376 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( 10377 HostPortPair("www.example.com", 443), &client_cert)); 10378} 10379 10380// Ensure that a client certificate is removed from the SSL client auth 10381// cache when: 10382// 1) No proxy is involved. 10383// 2) TLS False Start is enabled. 10384// 3) The initial TLS handshake requests a client certificate. 10385// 4) The client supplies an invalid/unacceptable certificate. 10386TEST_P(HttpNetworkTransactionTest, 10387 ClientAuthCertCache_Direct_FalseStart) { 10388 net::HttpRequestInfo request_info; 10389 request_info.url = GURL("https://www.example.com/"); 10390 request_info.method = "GET"; 10391 request_info.load_flags = net::LOAD_NORMAL; 10392 10393 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 10394 cert_request->host_and_port = HostPortPair("www.example.com", 443); 10395 10396 // When TLS False Start is used, SSLClientSocket::Connect() calls will 10397 // return successfully after reading up to the peer's Certificate message. 10398 // This is to allow the caller to call SSLClientSocket::Write(), which can 10399 // enqueue application data to be sent in the same packet as the 10400 // ChangeCipherSpec and Finished messages. 10401 // The actual handshake will be finished when SSLClientSocket::Read() is 10402 // called, which expects to process the peer's ChangeCipherSpec and 10403 // Finished messages. If there was an error negotiating with the peer, 10404 // such as due to the peer requiring a client certificate when none was 10405 // supplied, the alert sent by the peer won't be processed until Read() is 10406 // called. 10407 10408 // Like the non-False Start case, when a client certificate is requested by 10409 // the peer, the handshake is aborted during the Connect() call. 10410 // [ssl_]data1 represents the initial SSL handshake with the peer. 10411 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 10412 ssl_data1.cert_request_info = cert_request.get(); 10413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); 10414 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 10415 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10416 10417 // When a client certificate is supplied, Connect() will not be aborted 10418 // when the peer requests the certificate. Instead, the handshake will 10419 // artificially succeed, allowing the caller to write the HTTP request to 10420 // the socket. The handshake messages are not processed until Read() is 10421 // called, which then detects that the handshake was aborted, due to the 10422 // peer sending a handshake_failure because it requires a client 10423 // certificate. 10424 SSLSocketDataProvider ssl_data2(ASYNC, net::OK); 10425 ssl_data2.cert_request_info = cert_request.get(); 10426 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); 10427 net::MockRead data2_reads[] = { 10428 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR), 10429 }; 10430 net::StaticSocketDataProvider data2( 10431 data2_reads, arraysize(data2_reads), NULL, 0); 10432 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10433 10434 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is 10435 // the data for the SSL handshake once the TLSv1.1 connection falls back to 10436 // TLSv1. It has the same behaviour as [ssl_]data2. 10437 SSLSocketDataProvider ssl_data3(ASYNC, net::OK); 10438 ssl_data3.cert_request_info = cert_request.get(); 10439 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); 10440 net::StaticSocketDataProvider data3( 10441 data2_reads, arraysize(data2_reads), NULL, 0); 10442 session_deps_.socket_factory->AddSocketDataProvider(&data3); 10443 10444 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection 10445 // falls back to SSLv3. It has the same behaviour as [ssl_]data2. 10446 SSLSocketDataProvider ssl_data4(ASYNC, net::OK); 10447 ssl_data4.cert_request_info = cert_request.get(); 10448 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); 10449 net::StaticSocketDataProvider data4( 10450 data2_reads, arraysize(data2_reads), NULL, 0); 10451 session_deps_.socket_factory->AddSocketDataProvider(&data4); 10452 10453 // Need one more if TLSv1.2 is enabled. 10454 SSLSocketDataProvider ssl_data5(ASYNC, net::OK); 10455 ssl_data5.cert_request_info = cert_request.get(); 10456 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); 10457 net::StaticSocketDataProvider data5( 10458 data2_reads, arraysize(data2_reads), NULL, 0); 10459 session_deps_.socket_factory->AddSocketDataProvider(&data5); 10460 10461 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10462 scoped_ptr<HttpTransaction> trans( 10463 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10464 10465 // Begin the initial SSL handshake. 10466 TestCompletionCallback callback; 10467 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); 10468 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10469 10470 // Complete the SSL handshake, which should abort due to requiring a 10471 // client certificate. 10472 rv = callback.WaitForResult(); 10473 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 10474 10475 // Indicate that no certificate should be supplied. From the perspective 10476 // of SSLClientCertCache, NULL is just as meaningful as a real 10477 // certificate, so this is the same as supply a 10478 // legitimate-but-unacceptable certificate. 10479 rv = trans->RestartWithCertificate(NULL, callback.callback()); 10480 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10481 10482 // Ensure the certificate was added to the client auth cache before 10483 // allowing the connection to continue restarting. 10484 scoped_refptr<X509Certificate> client_cert; 10485 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup( 10486 HostPortPair("www.example.com", 443), &client_cert)); 10487 ASSERT_EQ(NULL, client_cert.get()); 10488 10489 // Restart the handshake. This will consume ssl_data2, which fails, and 10490 // then consume ssl_data3 and ssl_data4, both of which should also fail. 10491 // The result code is checked against what ssl_data4 should return. 10492 rv = callback.WaitForResult(); 10493 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); 10494 10495 // Ensure that the client certificate is removed from the cache on a 10496 // handshake failure. 10497 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( 10498 HostPortPair("www.example.com", 443), &client_cert)); 10499} 10500 10501// Ensure that a client certificate is removed from the SSL client auth 10502// cache when: 10503// 1) An HTTPS proxy is involved. 10504// 3) The HTTPS proxy requests a client certificate. 10505// 4) The client supplies an invalid/unacceptable certificate for the 10506// proxy. 10507// The test is repeated twice, first for connecting to an HTTPS endpoint, 10508// then for connecting to an HTTP endpoint. 10509TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) { 10510 session_deps_.proxy_service.reset( 10511 ProxyService::CreateFixed("https://proxy:70")); 10512 CapturingBoundNetLog log; 10513 session_deps_.net_log = log.bound().net_log(); 10514 10515 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); 10516 cert_request->host_and_port = HostPortPair("proxy", 70); 10517 10518 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of 10519 // [ssl_]data[1-3]. Rather than represending the endpoint 10520 // (www.example.com:443), they represent failures with the HTTPS proxy 10521 // (proxy:70). 10522 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); 10523 ssl_data1.cert_request_info = cert_request.get(); 10524 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); 10525 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); 10526 session_deps_.socket_factory->AddSocketDataProvider(&data1); 10527 10528 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10529 ssl_data2.cert_request_info = cert_request.get(); 10530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); 10531 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); 10532 session_deps_.socket_factory->AddSocketDataProvider(&data2); 10533 10534 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3. 10535#if 0 10536 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); 10537 ssl_data3.cert_request_info = cert_request.get(); 10538 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); 10539 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); 10540 session_deps_.socket_factory->AddSocketDataProvider(&data3); 10541#endif 10542 10543 net::HttpRequestInfo requests[2]; 10544 requests[0].url = GURL("https://www.example.com/"); 10545 requests[0].method = "GET"; 10546 requests[0].load_flags = net::LOAD_NORMAL; 10547 10548 requests[1].url = GURL("http://www.example.com/"); 10549 requests[1].method = "GET"; 10550 requests[1].load_flags = net::LOAD_NORMAL; 10551 10552 for (size_t i = 0; i < arraysize(requests); ++i) { 10553 session_deps_.socket_factory->ResetNextMockIndexes(); 10554 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10555 scoped_ptr<HttpNetworkTransaction> trans( 10556 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 10557 10558 // Begin the SSL handshake with the proxy. 10559 TestCompletionCallback callback; 10560 int rv = trans->Start( 10561 &requests[i], callback.callback(), net::BoundNetLog()); 10562 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10563 10564 // Complete the SSL handshake, which should abort due to requiring a 10565 // client certificate. 10566 rv = callback.WaitForResult(); 10567 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); 10568 10569 // Indicate that no certificate should be supplied. From the perspective 10570 // of SSLClientCertCache, NULL is just as meaningful as a real 10571 // certificate, so this is the same as supply a 10572 // legitimate-but-unacceptable certificate. 10573 rv = trans->RestartWithCertificate(NULL, callback.callback()); 10574 ASSERT_EQ(net::ERR_IO_PENDING, rv); 10575 10576 // Ensure the certificate was added to the client auth cache before 10577 // allowing the connection to continue restarting. 10578 scoped_refptr<X509Certificate> client_cert; 10579 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup( 10580 HostPortPair("proxy", 70), &client_cert)); 10581 ASSERT_EQ(NULL, client_cert.get()); 10582 // Ensure the certificate was NOT cached for the endpoint. This only 10583 // applies to HTTPS requests, but is fine to check for HTTP requests. 10584 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( 10585 HostPortPair("www.example.com", 443), &client_cert)); 10586 10587 // Restart the handshake. This will consume ssl_data2, which fails, and 10588 // then consume ssl_data3, which should also fail. The result code is 10589 // checked against what ssl_data3 should return. 10590 rv = callback.WaitForResult(); 10591 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv); 10592 10593 // Now that the new handshake has failed, ensure that the client 10594 // certificate was removed from the client auth cache. 10595 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( 10596 HostPortPair("proxy", 70), &client_cert)); 10597 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup( 10598 HostPortPair("www.example.com", 443), &client_cert)); 10599 } 10600} 10601 10602// Unlike TEST/TEST_F, which are macros that expand to further macros, 10603// TEST_P is a macro that expands directly to code that stringizes the 10604// arguments. As a result, macros passed as parameters (such as prefix 10605// or test_case_name) will not be expanded by the preprocessor. To 10606// work around this, indirect the macro for TEST_P, so that the 10607// pre-processor will expand macros such as MAYBE_test_name before 10608// instantiating the test. 10609#define WRAPPED_TEST_P(test_case_name, test_name) \ 10610 TEST_P(test_case_name, test_name) 10611 10612// Times out on Win7 dbg(2) bot. http://crbug.com/124776 10613#if defined(OS_WIN) 10614#define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling 10615#else 10616#define MAYBE_UseIPConnectionPooling UseIPConnectionPooling 10617#endif 10618WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) { 10619 HttpStreamFactory::set_use_alternate_protocols(true); 10620 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 10621 10622 // Set up a special HttpNetworkSession with a MockCachingHostResolver. 10623 session_deps_.host_resolver.reset(new MockCachingHostResolver()); 10624 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10625 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); 10626 pool_peer.DisableDomainAuthenticationVerification(); 10627 10628 SSLSocketDataProvider ssl(ASYNC, OK); 10629 ssl.SetNextProto(GetParam()); 10630 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10631 10632 scoped_ptr<SpdyFrame> host1_req( 10633 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10634 scoped_ptr<SpdyFrame> host2_req( 10635 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST)); 10636 MockWrite spdy_writes[] = { 10637 CreateMockWrite(*host1_req, 1), 10638 CreateMockWrite(*host2_req, 4), 10639 }; 10640 scoped_ptr<SpdyFrame> host1_resp( 10641 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10642 scoped_ptr<SpdyFrame> host1_resp_body( 10643 spdy_util_.ConstructSpdyBodyFrame(1, true)); 10644 scoped_ptr<SpdyFrame> host2_resp( 10645 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10646 scoped_ptr<SpdyFrame> host2_resp_body( 10647 spdy_util_.ConstructSpdyBodyFrame(3, true)); 10648 MockRead spdy_reads[] = { 10649 CreateMockRead(*host1_resp, 2), 10650 CreateMockRead(*host1_resp_body, 3), 10651 CreateMockRead(*host2_resp, 5), 10652 CreateMockRead(*host2_resp_body, 6), 10653 MockRead(ASYNC, 0, 7), 10654 }; 10655 10656 IPAddressNumber ip; 10657 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); 10658 IPEndPoint peer_addr = IPEndPoint(ip, 443); 10659 MockConnect connect(ASYNC, OK, peer_addr); 10660 OrderedSocketData spdy_data( 10661 connect, 10662 spdy_reads, arraysize(spdy_reads), 10663 spdy_writes, arraysize(spdy_writes)); 10664 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10665 10666 TestCompletionCallback callback; 10667 HttpRequestInfo request1; 10668 request1.method = "GET"; 10669 request1.url = GURL("https://www.google.com/"); 10670 request1.load_flags = 0; 10671 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 10672 10673 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); 10674 EXPECT_EQ(ERR_IO_PENDING, rv); 10675 EXPECT_EQ(OK, callback.WaitForResult()); 10676 10677 const HttpResponseInfo* response = trans1.GetResponseInfo(); 10678 ASSERT_TRUE(response != NULL); 10679 ASSERT_TRUE(response->headers.get() != NULL); 10680 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10681 10682 std::string response_data; 10683 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 10684 EXPECT_EQ("hello!", response_data); 10685 10686 // Preload www.gmail.com into HostCache. 10687 HostPortPair host_port("www.gmail.com", 443); 10688 HostResolver::RequestInfo resolve_info(host_port); 10689 AddressList ignored; 10690 rv = session_deps_.host_resolver->Resolve(resolve_info, 10691 DEFAULT_PRIORITY, 10692 &ignored, 10693 callback.callback(), 10694 NULL, 10695 BoundNetLog()); 10696 EXPECT_EQ(ERR_IO_PENDING, rv); 10697 rv = callback.WaitForResult(); 10698 EXPECT_EQ(OK, rv); 10699 10700 HttpRequestInfo request2; 10701 request2.method = "GET"; 10702 request2.url = GURL("https://www.gmail.com/"); 10703 request2.load_flags = 0; 10704 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 10705 10706 rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); 10707 EXPECT_EQ(ERR_IO_PENDING, rv); 10708 EXPECT_EQ(OK, callback.WaitForResult()); 10709 10710 response = trans2.GetResponseInfo(); 10711 ASSERT_TRUE(response != NULL); 10712 ASSERT_TRUE(response->headers.get() != NULL); 10713 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10714 EXPECT_TRUE(response->was_fetched_via_spdy); 10715 EXPECT_TRUE(response->was_npn_negotiated); 10716 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 10717 EXPECT_EQ("hello!", response_data); 10718} 10719#undef MAYBE_UseIPConnectionPooling 10720 10721TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) { 10722 HttpStreamFactory::set_use_alternate_protocols(true); 10723 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 10724 10725 // Set up a special HttpNetworkSession with a MockCachingHostResolver. 10726 session_deps_.host_resolver.reset(new MockCachingHostResolver()); 10727 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10728 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); 10729 pool_peer.DisableDomainAuthenticationVerification(); 10730 10731 SSLSocketDataProvider ssl(ASYNC, OK); 10732 ssl.SetNextProto(GetParam()); 10733 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10734 10735 scoped_ptr<SpdyFrame> host1_req( 10736 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10737 scoped_ptr<SpdyFrame> host2_req( 10738 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST)); 10739 MockWrite spdy_writes[] = { 10740 CreateMockWrite(*host1_req, 1), 10741 CreateMockWrite(*host2_req, 4), 10742 }; 10743 scoped_ptr<SpdyFrame> host1_resp( 10744 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10745 scoped_ptr<SpdyFrame> host1_resp_body( 10746 spdy_util_.ConstructSpdyBodyFrame(1, true)); 10747 scoped_ptr<SpdyFrame> host2_resp( 10748 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10749 scoped_ptr<SpdyFrame> host2_resp_body( 10750 spdy_util_.ConstructSpdyBodyFrame(3, true)); 10751 MockRead spdy_reads[] = { 10752 CreateMockRead(*host1_resp, 2), 10753 CreateMockRead(*host1_resp_body, 3), 10754 CreateMockRead(*host2_resp, 5), 10755 CreateMockRead(*host2_resp_body, 6), 10756 MockRead(ASYNC, 0, 7), 10757 }; 10758 10759 IPAddressNumber ip; 10760 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); 10761 IPEndPoint peer_addr = IPEndPoint(ip, 443); 10762 MockConnect connect(ASYNC, OK, peer_addr); 10763 OrderedSocketData spdy_data( 10764 connect, 10765 spdy_reads, arraysize(spdy_reads), 10766 spdy_writes, arraysize(spdy_writes)); 10767 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10768 10769 TestCompletionCallback callback; 10770 HttpRequestInfo request1; 10771 request1.method = "GET"; 10772 request1.url = GURL("https://www.google.com/"); 10773 request1.load_flags = 0; 10774 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 10775 10776 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); 10777 EXPECT_EQ(ERR_IO_PENDING, rv); 10778 EXPECT_EQ(OK, callback.WaitForResult()); 10779 10780 const HttpResponseInfo* response = trans1.GetResponseInfo(); 10781 ASSERT_TRUE(response != NULL); 10782 ASSERT_TRUE(response->headers.get() != NULL); 10783 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10784 10785 std::string response_data; 10786 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 10787 EXPECT_EQ("hello!", response_data); 10788 10789 HttpRequestInfo request2; 10790 request2.method = "GET"; 10791 request2.url = GURL("https://www.gmail.com/"); 10792 request2.load_flags = 0; 10793 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 10794 10795 rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); 10796 EXPECT_EQ(ERR_IO_PENDING, rv); 10797 EXPECT_EQ(OK, callback.WaitForResult()); 10798 10799 response = trans2.GetResponseInfo(); 10800 ASSERT_TRUE(response != NULL); 10801 ASSERT_TRUE(response->headers.get() != NULL); 10802 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10803 EXPECT_TRUE(response->was_fetched_via_spdy); 10804 EXPECT_TRUE(response->was_npn_negotiated); 10805 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 10806 EXPECT_EQ("hello!", response_data); 10807} 10808 10809class OneTimeCachingHostResolver : public net::HostResolver { 10810 public: 10811 explicit OneTimeCachingHostResolver(const HostPortPair& host_port) 10812 : host_port_(host_port) {} 10813 virtual ~OneTimeCachingHostResolver() {} 10814 10815 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); } 10816 10817 // HostResolver methods: 10818 virtual int Resolve(const RequestInfo& info, 10819 RequestPriority priority, 10820 AddressList* addresses, 10821 const CompletionCallback& callback, 10822 RequestHandle* out_req, 10823 const BoundNetLog& net_log) OVERRIDE { 10824 return host_resolver_.Resolve( 10825 info, priority, addresses, callback, out_req, net_log); 10826 } 10827 10828 virtual int ResolveFromCache(const RequestInfo& info, 10829 AddressList* addresses, 10830 const BoundNetLog& net_log) OVERRIDE { 10831 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log); 10832 if (rv == OK && info.host_port_pair().Equals(host_port_)) 10833 host_resolver_.GetHostCache()->clear(); 10834 return rv; 10835 } 10836 10837 virtual void CancelRequest(RequestHandle req) OVERRIDE { 10838 host_resolver_.CancelRequest(req); 10839 } 10840 10841 MockCachingHostResolver* GetMockHostResolver() { 10842 return &host_resolver_; 10843 } 10844 10845 private: 10846 MockCachingHostResolver host_resolver_; 10847 const HostPortPair host_port_; 10848}; 10849 10850// Times out on Win7 dbg(2) bot. http://crbug.com/124776 10851#if defined(OS_WIN) 10852#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \ 10853 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration 10854#else 10855#define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \ 10856 UseIPConnectionPoolingWithHostCacheExpiration 10857#endif 10858WRAPPED_TEST_P(HttpNetworkTransactionTest, 10859 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) { 10860// Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_ 10861// prefix doesn't work with parametrized tests). 10862#if defined(OS_WIN) 10863 return; 10864#endif 10865 10866 HttpStreamFactory::set_use_alternate_protocols(true); 10867 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 10868 10869 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver. 10870 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443)); 10871 HttpNetworkSession::Params params = 10872 SpdySessionDependencies::CreateSessionParams(&session_deps_); 10873 params.host_resolver = &host_resolver; 10874 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 10875 SpdySessionPoolPeer pool_peer(session->spdy_session_pool()); 10876 pool_peer.DisableDomainAuthenticationVerification(); 10877 10878 SSLSocketDataProvider ssl(ASYNC, OK); 10879 ssl.SetNextProto(GetParam()); 10880 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 10881 10882 scoped_ptr<SpdyFrame> host1_req( 10883 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST)); 10884 scoped_ptr<SpdyFrame> host2_req( 10885 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST)); 10886 MockWrite spdy_writes[] = { 10887 CreateMockWrite(*host1_req, 1), 10888 CreateMockWrite(*host2_req, 4), 10889 }; 10890 scoped_ptr<SpdyFrame> host1_resp( 10891 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 10892 scoped_ptr<SpdyFrame> host1_resp_body( 10893 spdy_util_.ConstructSpdyBodyFrame(1, true)); 10894 scoped_ptr<SpdyFrame> host2_resp( 10895 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 10896 scoped_ptr<SpdyFrame> host2_resp_body( 10897 spdy_util_.ConstructSpdyBodyFrame(3, true)); 10898 MockRead spdy_reads[] = { 10899 CreateMockRead(*host1_resp, 2), 10900 CreateMockRead(*host1_resp_body, 3), 10901 CreateMockRead(*host2_resp, 5), 10902 CreateMockRead(*host2_resp_body, 6), 10903 MockRead(ASYNC, 0, 7), 10904 }; 10905 10906 IPAddressNumber ip; 10907 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip)); 10908 IPEndPoint peer_addr = IPEndPoint(ip, 443); 10909 MockConnect connect(ASYNC, OK, peer_addr); 10910 OrderedSocketData spdy_data( 10911 connect, 10912 spdy_reads, arraysize(spdy_reads), 10913 spdy_writes, arraysize(spdy_writes)); 10914 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 10915 10916 TestCompletionCallback callback; 10917 HttpRequestInfo request1; 10918 request1.method = "GET"; 10919 request1.url = GURL("https://www.google.com/"); 10920 request1.load_flags = 0; 10921 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); 10922 10923 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog()); 10924 EXPECT_EQ(ERR_IO_PENDING, rv); 10925 EXPECT_EQ(OK, callback.WaitForResult()); 10926 10927 const HttpResponseInfo* response = trans1.GetResponseInfo(); 10928 ASSERT_TRUE(response != NULL); 10929 ASSERT_TRUE(response->headers.get() != NULL); 10930 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10931 10932 std::string response_data; 10933 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data)); 10934 EXPECT_EQ("hello!", response_data); 10935 10936 // Preload cache entries into HostCache. 10937 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443)); 10938 AddressList ignored; 10939 rv = host_resolver.Resolve(resolve_info, 10940 DEFAULT_PRIORITY, 10941 &ignored, 10942 callback.callback(), 10943 NULL, 10944 BoundNetLog()); 10945 EXPECT_EQ(ERR_IO_PENDING, rv); 10946 rv = callback.WaitForResult(); 10947 EXPECT_EQ(OK, rv); 10948 10949 HttpRequestInfo request2; 10950 request2.method = "GET"; 10951 request2.url = GURL("https://www.gmail.com/"); 10952 request2.load_flags = 0; 10953 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get()); 10954 10955 rv = trans2.Start(&request2, callback.callback(), BoundNetLog()); 10956 EXPECT_EQ(ERR_IO_PENDING, rv); 10957 EXPECT_EQ(OK, callback.WaitForResult()); 10958 10959 response = trans2.GetResponseInfo(); 10960 ASSERT_TRUE(response != NULL); 10961 ASSERT_TRUE(response->headers.get() != NULL); 10962 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 10963 EXPECT_TRUE(response->was_fetched_via_spdy); 10964 EXPECT_TRUE(response->was_npn_negotiated); 10965 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data)); 10966 EXPECT_EQ("hello!", response_data); 10967} 10968#undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration 10969 10970TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) { 10971 MockRead data_reads1[] = { 10972 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION), 10973 }; 10974 MockRead data_reads2[] = { 10975 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 10976 MockRead("hello world"), 10977 MockRead(SYNCHRONOUS, OK), 10978 }; 10979 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0); 10980 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0); 10981 StaticSocketDataProvider* data[] = { &data1, &data2 }; 10982 10983 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data)); 10984 10985 EXPECT_EQ(OK, out.rv); 10986 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 10987 EXPECT_EQ("hello world", out.response_data); 10988} 10989 10990TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) { 10991 MockWrite data_writes1[] = { 10992 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION), 10993 }; 10994 MockWrite data_writes2[] = { 10995 MockWrite("GET / HTTP/1.1\r\n" 10996 "Host: www.google.com\r\n" 10997 "Connection: keep-alive\r\n\r\n"), 10998 }; 10999 MockRead data_reads2[] = { 11000 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 11001 MockRead("hello world"), 11002 MockRead(SYNCHRONOUS, OK), 11003 }; 11004 StaticSocketDataProvider data1(NULL, 0, 11005 data_writes1, arraysize(data_writes1)); 11006 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 11007 data_writes2, arraysize(data_writes2)); 11008 StaticSocketDataProvider* data[] = { &data1, &data2 }; 11009 11010 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data)); 11011 11012 EXPECT_EQ(OK, out.rv); 11013 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 11014 EXPECT_EQ("hello world", out.response_data); 11015} 11016 11017TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) { 11018 const std::string https_url = "https://www.google.com/"; 11019 const std::string http_url = "http://www.google.com:443/"; 11020 11021 // SPDY GET for HTTPS URL 11022 scoped_ptr<SpdyFrame> req1( 11023 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST)); 11024 11025 MockWrite writes1[] = { 11026 CreateMockWrite(*req1, 0), 11027 }; 11028 11029 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11030 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11031 MockRead reads1[] = { 11032 CreateMockRead(*resp1, 1), 11033 CreateMockRead(*body1, 2), 11034 MockRead(ASYNC, ERR_IO_PENDING, 3) 11035 }; 11036 11037 DelayedSocketData data1( 11038 1, reads1, arraysize(reads1), 11039 writes1, arraysize(writes1)); 11040 MockConnect connect_data1(ASYNC, OK); 11041 data1.set_connect_data(connect_data1); 11042 11043 // HTTP GET for the HTTP URL 11044 MockWrite writes2[] = { 11045 MockWrite(ASYNC, 4, 11046 "GET / HTTP/1.1\r\n" 11047 "Host: www.google.com:443\r\n" 11048 "Connection: keep-alive\r\n\r\n"), 11049 }; 11050 11051 MockRead reads2[] = { 11052 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 11053 MockRead(ASYNC, 6, "hello"), 11054 MockRead(ASYNC, 7, OK), 11055 }; 11056 11057 DelayedSocketData data2( 11058 1, reads2, arraysize(reads2), 11059 writes2, arraysize(writes2)); 11060 11061 SSLSocketDataProvider ssl(ASYNC, OK); 11062 ssl.SetNextProto(GetParam()); 11063 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 11064 session_deps_.socket_factory->AddSocketDataProvider(&data1); 11065 session_deps_.socket_factory->AddSocketDataProvider(&data2); 11066 11067 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11068 11069 // Start the first transaction to set up the SpdySession 11070 HttpRequestInfo request1; 11071 request1.method = "GET"; 11072 request1.url = GURL(https_url); 11073 request1.load_flags = 0; 11074 HttpNetworkTransaction trans1(LOWEST, session.get()); 11075 TestCompletionCallback callback1; 11076 EXPECT_EQ(ERR_IO_PENDING, 11077 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11078 base::MessageLoop::current()->RunUntilIdle(); 11079 11080 EXPECT_EQ(OK, callback1.WaitForResult()); 11081 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 11082 11083 // Now, start the HTTP request 11084 HttpRequestInfo request2; 11085 request2.method = "GET"; 11086 request2.url = GURL(http_url); 11087 request2.load_flags = 0; 11088 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11089 TestCompletionCallback callback2; 11090 EXPECT_EQ(ERR_IO_PENDING, 11091 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11092 base::MessageLoop::current()->RunUntilIdle(); 11093 11094 EXPECT_EQ(OK, callback2.WaitForResult()); 11095 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11096} 11097 11098TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) { 11099 const std::string https_url = "https://www.google.com/"; 11100 const std::string http_url = "http://www.google.com:443/"; 11101 11102 // SPDY GET for HTTPS URL (through CONNECT tunnel) 11103 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 11104 LOWEST)); 11105 scoped_ptr<SpdyFrame> req1( 11106 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST)); 11107 11108 // SPDY GET for HTTP URL (through the proxy, but not the tunnel) 11109 scoped_ptr<SpdyFrame> wrapped_req1( 11110 spdy_util_.ConstructWrappedSpdyFrame(req1, 1)); 11111 const char* const headers[] = { 11112 spdy_util_.GetMethodKey(), "GET", 11113 spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/", 11114 spdy_util_.GetHostKey(), "www.google.com:443", 11115 spdy_util_.GetSchemeKey(), "http", 11116 spdy_util_.GetVersionKey(), "HTTP/1.1" 11117 }; 11118 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame( 11119 NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN, 11120 headers, arraysize(headers), 0)); 11121 11122 MockWrite writes1[] = { 11123 CreateMockWrite(*connect, 0), 11124 CreateMockWrite(*wrapped_req1, 2), 11125 CreateMockWrite(*req2, 5), 11126 }; 11127 11128 scoped_ptr<SpdyFrame> conn_resp( 11129 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11130 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11131 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11132 scoped_ptr<SpdyFrame> wrapped_resp1( 11133 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1)); 11134 scoped_ptr<SpdyFrame> wrapped_body1( 11135 spdy_util_.ConstructWrappedSpdyFrame(body1, 1)); 11136 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 11137 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 11138 MockRead reads1[] = { 11139 CreateMockRead(*conn_resp, 1), 11140 CreateMockRead(*wrapped_resp1, 3), 11141 CreateMockRead(*wrapped_body1, 4), 11142 CreateMockRead(*resp2, 6), 11143 CreateMockRead(*body2, 7), 11144 MockRead(ASYNC, ERR_IO_PENDING, 8) 11145 }; 11146 11147 DeterministicSocketData data1(reads1, arraysize(reads1), 11148 writes1, arraysize(writes1)); 11149 MockConnect connect_data1(ASYNC, OK); 11150 data1.set_connect_data(connect_data1); 11151 11152 session_deps_.proxy_service.reset( 11153 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 11154 CapturingNetLog log; 11155 session_deps_.net_log = &log; 11156 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy 11157 ssl1.SetNextProto(GetParam()); 11158 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); 11159 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server 11160 ssl2.SetNextProto(GetParam()); 11161 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 11162 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1); 11163 11164 scoped_refptr<HttpNetworkSession> session( 11165 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 11166 11167 // Start the first transaction to set up the SpdySession 11168 HttpRequestInfo request1; 11169 request1.method = "GET"; 11170 request1.url = GURL(https_url); 11171 request1.load_flags = 0; 11172 HttpNetworkTransaction trans1(LOWEST, session.get()); 11173 TestCompletionCallback callback1; 11174 EXPECT_EQ(ERR_IO_PENDING, 11175 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11176 base::MessageLoop::current()->RunUntilIdle(); 11177 data1.RunFor(4); 11178 11179 EXPECT_EQ(OK, callback1.WaitForResult()); 11180 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 11181 11182 LoadTimingInfo load_timing_info1; 11183 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1)); 11184 TestLoadTimingNotReusedWithPac(load_timing_info1, 11185 CONNECT_TIMING_HAS_SSL_TIMES); 11186 11187 // Now, start the HTTP request 11188 HttpRequestInfo request2; 11189 request2.method = "GET"; 11190 request2.url = GURL(http_url); 11191 request2.load_flags = 0; 11192 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11193 TestCompletionCallback callback2; 11194 EXPECT_EQ(ERR_IO_PENDING, 11195 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11196 base::MessageLoop::current()->RunUntilIdle(); 11197 data1.RunFor(3); 11198 11199 EXPECT_EQ(OK, callback2.WaitForResult()); 11200 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11201 11202 LoadTimingInfo load_timing_info2; 11203 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2)); 11204 // The established SPDY sessions is considered reused by the HTTP request. 11205 TestLoadTimingReusedWithPac(load_timing_info2); 11206 // HTTP requests over a SPDY session should have a different connection 11207 // socket_log_id than requests over a tunnel. 11208 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 11209} 11210 11211TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) { 11212 HttpStreamFactory::set_force_spdy_always(true); 11213 const std::string https_url = "https://www.google.com/"; 11214 const std::string http_url = "http://www.google.com:443/"; 11215 11216 // SPDY GET for HTTPS URL 11217 scoped_ptr<SpdyFrame> req1( 11218 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST)); 11219 // SPDY GET for the HTTP URL 11220 scoped_ptr<SpdyFrame> req2( 11221 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM)); 11222 11223 MockWrite writes[] = { 11224 CreateMockWrite(*req1, 1), 11225 CreateMockWrite(*req2, 4), 11226 }; 11227 11228 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11229 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11230 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 11231 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true)); 11232 MockRead reads[] = { 11233 CreateMockRead(*resp1, 2), 11234 CreateMockRead(*body1, 3), 11235 CreateMockRead(*resp2, 5), 11236 CreateMockRead(*body2, 6), 11237 MockRead(ASYNC, ERR_IO_PENDING, 7) 11238 }; 11239 11240 OrderedSocketData data(reads, arraysize(reads), 11241 writes, arraysize(writes)); 11242 11243 SSLSocketDataProvider ssl(ASYNC, OK); 11244 ssl.SetNextProto(GetParam()); 11245 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 11246 session_deps_.socket_factory->AddSocketDataProvider(&data); 11247 11248 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11249 11250 // Start the first transaction to set up the SpdySession 11251 HttpRequestInfo request1; 11252 request1.method = "GET"; 11253 request1.url = GURL(https_url); 11254 request1.load_flags = 0; 11255 HttpNetworkTransaction trans1(LOWEST, session.get()); 11256 TestCompletionCallback callback1; 11257 EXPECT_EQ(ERR_IO_PENDING, 11258 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11259 base::MessageLoop::current()->RunUntilIdle(); 11260 11261 EXPECT_EQ(OK, callback1.WaitForResult()); 11262 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 11263 11264 // Now, start the HTTP request 11265 HttpRequestInfo request2; 11266 request2.method = "GET"; 11267 request2.url = GURL(http_url); 11268 request2.load_flags = 0; 11269 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11270 TestCompletionCallback callback2; 11271 EXPECT_EQ(ERR_IO_PENDING, 11272 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11273 base::MessageLoop::current()->RunUntilIdle(); 11274 11275 EXPECT_EQ(OK, callback2.WaitForResult()); 11276 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11277} 11278 11279// Test that in the case where we have a SPDY session to a SPDY proxy 11280// that we do not pool other origins that resolve to the same IP when 11281// the certificate does not match the new origin. 11282// http://crbug.com/134690 11283TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) { 11284 const std::string url1 = "http://www.google.com/"; 11285 const std::string url2 = "https://mail.google.com/"; 11286 const std::string ip_addr = "1.2.3.4"; 11287 11288 // SPDY GET for HTTP URL (through SPDY proxy) 11289 scoped_ptr<SpdyHeaderBlock> headers( 11290 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/")); 11291 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame( 11292 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 11293 11294 MockWrite writes1[] = { 11295 CreateMockWrite(*req1, 0), 11296 }; 11297 11298 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11299 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11300 MockRead reads1[] = { 11301 CreateMockRead(*resp1, 1), 11302 CreateMockRead(*body1, 2), 11303 MockRead(ASYNC, OK, 3) // EOF 11304 }; 11305 11306 scoped_ptr<DeterministicSocketData> data1( 11307 new DeterministicSocketData(reads1, arraysize(reads1), 11308 writes1, arraysize(writes1))); 11309 IPAddressNumber ip; 11310 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip)); 11311 IPEndPoint peer_addr = IPEndPoint(ip, 443); 11312 MockConnect connect_data1(ASYNC, OK, peer_addr); 11313 data1->set_connect_data(connect_data1); 11314 11315 // SPDY GET for HTTPS URL (direct) 11316 scoped_ptr<SpdyFrame> req2( 11317 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM)); 11318 11319 MockWrite writes2[] = { 11320 CreateMockWrite(*req2, 0), 11321 }; 11322 11323 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11324 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11325 MockRead reads2[] = { 11326 CreateMockRead(*resp2, 1), 11327 CreateMockRead(*body2, 2), 11328 MockRead(ASYNC, OK, 3) // EOF 11329 }; 11330 11331 scoped_ptr<DeterministicSocketData> data2( 11332 new DeterministicSocketData(reads2, arraysize(reads2), 11333 writes2, arraysize(writes2))); 11334 MockConnect connect_data2(ASYNC, OK); 11335 data2->set_connect_data(connect_data2); 11336 11337 // Set up a proxy config that sends HTTP requests to a proxy, and 11338 // all others direct. 11339 ProxyConfig proxy_config; 11340 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443"); 11341 CapturingProxyResolver* capturing_proxy_resolver = 11342 new CapturingProxyResolver(); 11343 session_deps_.proxy_service.reset(new ProxyService( 11344 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver, 11345 NULL)); 11346 11347 // Load a valid cert. Note, that this does not need to 11348 // be valid for proxy because the MockSSLClientSocket does 11349 // not actually verify it. But SpdySession will use this 11350 // to see if it is valid for the new origin 11351 base::FilePath certs_dir = GetTestCertsDirectory(); 11352 scoped_refptr<X509Certificate> server_cert( 11353 ImportCertFromFile(certs_dir, "ok_cert.pem")); 11354 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert); 11355 11356 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy 11357 ssl1.SetNextProto(GetParam()); 11358 ssl1.cert = server_cert; 11359 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); 11360 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11361 data1.get()); 11362 11363 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server 11364 ssl2.SetNextProto(GetParam()); 11365 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 11366 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11367 data2.get()); 11368 11369 session_deps_.host_resolver.reset(new MockCachingHostResolver()); 11370 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr); 11371 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr); 11372 11373 scoped_refptr<HttpNetworkSession> session( 11374 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 11375 11376 // Start the first transaction to set up the SpdySession 11377 HttpRequestInfo request1; 11378 request1.method = "GET"; 11379 request1.url = GURL(url1); 11380 request1.load_flags = 0; 11381 HttpNetworkTransaction trans1(LOWEST, session.get()); 11382 TestCompletionCallback callback1; 11383 ASSERT_EQ(ERR_IO_PENDING, 11384 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11385 data1->RunFor(3); 11386 11387 ASSERT_TRUE(callback1.have_result()); 11388 EXPECT_EQ(OK, callback1.WaitForResult()); 11389 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy); 11390 11391 // Now, start the HTTP request 11392 HttpRequestInfo request2; 11393 request2.method = "GET"; 11394 request2.url = GURL(url2); 11395 request2.load_flags = 0; 11396 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11397 TestCompletionCallback callback2; 11398 EXPECT_EQ(ERR_IO_PENDING, 11399 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11400 base::MessageLoop::current()->RunUntilIdle(); 11401 data2->RunFor(3); 11402 11403 ASSERT_TRUE(callback2.have_result()); 11404 EXPECT_EQ(OK, callback2.WaitForResult()); 11405 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11406} 11407 11408// Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED 11409// error) in SPDY session, removes the socket from pool and closes the SPDY 11410// session. Verify that new url's from the same HttpNetworkSession (and a new 11411// SpdySession) do work. http://crbug.com/224701 11412TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) { 11413 const std::string https_url = "https://www.google.com/"; 11414 11415 MockRead reads1[] = { 11416 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0) 11417 }; 11418 11419 scoped_ptr<DeterministicSocketData> data1( 11420 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0)); 11421 data1->SetStop(1); 11422 11423 scoped_ptr<SpdyFrame> req2( 11424 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM)); 11425 MockWrite writes2[] = { 11426 CreateMockWrite(*req2, 0), 11427 }; 11428 11429 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11430 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); 11431 MockRead reads2[] = { 11432 CreateMockRead(*resp2, 1), 11433 CreateMockRead(*body2, 2), 11434 MockRead(ASYNC, OK, 3) // EOF 11435 }; 11436 11437 scoped_ptr<DeterministicSocketData> data2( 11438 new DeterministicSocketData(reads2, arraysize(reads2), 11439 writes2, arraysize(writes2))); 11440 11441 SSLSocketDataProvider ssl1(ASYNC, OK); 11442 ssl1.SetNextProto(GetParam()); 11443 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1); 11444 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11445 data1.get()); 11446 11447 SSLSocketDataProvider ssl2(ASYNC, OK); 11448 ssl2.SetNextProto(GetParam()); 11449 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 11450 session_deps_.deterministic_socket_factory->AddSocketDataProvider( 11451 data2.get()); 11452 11453 scoped_refptr<HttpNetworkSession> session( 11454 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 11455 11456 // Start the first transaction to set up the SpdySession and verify that 11457 // connection was closed. 11458 HttpRequestInfo request1; 11459 request1.method = "GET"; 11460 request1.url = GURL(https_url); 11461 request1.load_flags = 0; 11462 HttpNetworkTransaction trans1(MEDIUM, session.get()); 11463 TestCompletionCallback callback1; 11464 EXPECT_EQ(ERR_IO_PENDING, 11465 trans1.Start(&request1, callback1.callback(), BoundNetLog())); 11466 base::MessageLoop::current()->RunUntilIdle(); 11467 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult()); 11468 11469 // Now, start the second request and make sure it succeeds. 11470 HttpRequestInfo request2; 11471 request2.method = "GET"; 11472 request2.url = GURL(https_url); 11473 request2.load_flags = 0; 11474 HttpNetworkTransaction trans2(MEDIUM, session.get()); 11475 TestCompletionCallback callback2; 11476 EXPECT_EQ(ERR_IO_PENDING, 11477 trans2.Start(&request2, callback2.callback(), BoundNetLog())); 11478 base::MessageLoop::current()->RunUntilIdle(); 11479 data2->RunFor(3); 11480 11481 ASSERT_TRUE(callback2.have_result()); 11482 EXPECT_EQ(OK, callback2.WaitForResult()); 11483 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy); 11484} 11485 11486TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) { 11487 HttpStreamFactory::SetNextProtos(SpdyNextProtos()); 11488 ClientSocketPoolManager::set_max_sockets_per_group( 11489 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 11490 ClientSocketPoolManager::set_max_sockets_per_pool( 11491 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 11492 11493 // Use two different hosts with different IPs so they don't get pooled. 11494 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1"); 11495 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2"); 11496 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11497 11498 SSLSocketDataProvider ssl1(ASYNC, OK); 11499 ssl1.SetNextProto(GetParam()); 11500 SSLSocketDataProvider ssl2(ASYNC, OK); 11501 ssl2.SetNextProto(GetParam()); 11502 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1); 11503 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 11504 11505 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet( 11506 "https://www.a.com", false, 1, DEFAULT_PRIORITY)); 11507 MockWrite spdy1_writes[] = { 11508 CreateMockWrite(*host1_req, 1), 11509 }; 11510 scoped_ptr<SpdyFrame> host1_resp( 11511 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11512 scoped_ptr<SpdyFrame> host1_resp_body( 11513 spdy_util_.ConstructSpdyBodyFrame(1, true)); 11514 MockRead spdy1_reads[] = { 11515 CreateMockRead(*host1_resp, 2), 11516 CreateMockRead(*host1_resp_body, 3), 11517 MockRead(ASYNC, ERR_IO_PENDING, 4), 11518 }; 11519 11520 scoped_ptr<OrderedSocketData> spdy1_data( 11521 new OrderedSocketData( 11522 spdy1_reads, arraysize(spdy1_reads), 11523 spdy1_writes, arraysize(spdy1_writes))); 11524 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get()); 11525 11526 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet( 11527 "https://www.b.com", false, 1, DEFAULT_PRIORITY)); 11528 MockWrite spdy2_writes[] = { 11529 CreateMockWrite(*host2_req, 1), 11530 }; 11531 scoped_ptr<SpdyFrame> host2_resp( 11532 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 11533 scoped_ptr<SpdyFrame> host2_resp_body( 11534 spdy_util_.ConstructSpdyBodyFrame(1, true)); 11535 MockRead spdy2_reads[] = { 11536 CreateMockRead(*host2_resp, 2), 11537 CreateMockRead(*host2_resp_body, 3), 11538 MockRead(ASYNC, ERR_IO_PENDING, 4), 11539 }; 11540 11541 scoped_ptr<OrderedSocketData> spdy2_data( 11542 new OrderedSocketData( 11543 spdy2_reads, arraysize(spdy2_reads), 11544 spdy2_writes, arraysize(spdy2_writes))); 11545 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get()); 11546 11547 MockWrite http_write[] = { 11548 MockWrite("GET / HTTP/1.1\r\n" 11549 "Host: www.a.com\r\n" 11550 "Connection: keep-alive\r\n\r\n"), 11551 }; 11552 11553 MockRead http_read[] = { 11554 MockRead("HTTP/1.1 200 OK\r\n"), 11555 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 11556 MockRead("Content-Length: 6\r\n\r\n"), 11557 MockRead("hello!"), 11558 }; 11559 StaticSocketDataProvider http_data(http_read, arraysize(http_read), 11560 http_write, arraysize(http_write)); 11561 session_deps_.socket_factory->AddSocketDataProvider(&http_data); 11562 11563 HostPortPair host_port_pair_a("www.a.com", 443); 11564 SpdySessionKey spdy_session_key_a( 11565 host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled); 11566 EXPECT_FALSE( 11567 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11568 11569 TestCompletionCallback callback; 11570 HttpRequestInfo request1; 11571 request1.method = "GET"; 11572 request1.url = GURL("https://www.a.com/"); 11573 request1.load_flags = 0; 11574 scoped_ptr<HttpNetworkTransaction> trans( 11575 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 11576 11577 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 11578 EXPECT_EQ(ERR_IO_PENDING, rv); 11579 EXPECT_EQ(OK, callback.WaitForResult()); 11580 11581 const HttpResponseInfo* response = trans->GetResponseInfo(); 11582 ASSERT_TRUE(response != NULL); 11583 ASSERT_TRUE(response->headers.get() != NULL); 11584 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 11585 EXPECT_TRUE(response->was_fetched_via_spdy); 11586 EXPECT_TRUE(response->was_npn_negotiated); 11587 11588 std::string response_data; 11589 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 11590 EXPECT_EQ("hello!", response_data); 11591 trans.reset(); 11592 EXPECT_TRUE( 11593 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11594 11595 HostPortPair host_port_pair_b("www.b.com", 443); 11596 SpdySessionKey spdy_session_key_b( 11597 host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled); 11598 EXPECT_FALSE( 11599 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); 11600 HttpRequestInfo request2; 11601 request2.method = "GET"; 11602 request2.url = GURL("https://www.b.com/"); 11603 request2.load_flags = 0; 11604 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 11605 11606 rv = trans->Start(&request2, callback.callback(), BoundNetLog()); 11607 EXPECT_EQ(ERR_IO_PENDING, rv); 11608 EXPECT_EQ(OK, callback.WaitForResult()); 11609 11610 response = trans->GetResponseInfo(); 11611 ASSERT_TRUE(response != NULL); 11612 ASSERT_TRUE(response->headers.get() != NULL); 11613 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 11614 EXPECT_TRUE(response->was_fetched_via_spdy); 11615 EXPECT_TRUE(response->was_npn_negotiated); 11616 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 11617 EXPECT_EQ("hello!", response_data); 11618 EXPECT_FALSE( 11619 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11620 EXPECT_TRUE( 11621 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); 11622 11623 HostPortPair host_port_pair_a1("www.a.com", 80); 11624 SpdySessionKey spdy_session_key_a1( 11625 host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled); 11626 EXPECT_FALSE( 11627 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1)); 11628 HttpRequestInfo request3; 11629 request3.method = "GET"; 11630 request3.url = GURL("http://www.a.com/"); 11631 request3.load_flags = 0; 11632 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 11633 11634 rv = trans->Start(&request3, callback.callback(), BoundNetLog()); 11635 EXPECT_EQ(ERR_IO_PENDING, rv); 11636 EXPECT_EQ(OK, callback.WaitForResult()); 11637 11638 response = trans->GetResponseInfo(); 11639 ASSERT_TRUE(response != NULL); 11640 ASSERT_TRUE(response->headers.get() != NULL); 11641 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 11642 EXPECT_FALSE(response->was_fetched_via_spdy); 11643 EXPECT_FALSE(response->was_npn_negotiated); 11644 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 11645 EXPECT_EQ("hello!", response_data); 11646 EXPECT_FALSE( 11647 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a)); 11648 EXPECT_FALSE( 11649 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b)); 11650} 11651 11652TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) { 11653 HttpRequestInfo request; 11654 request.method = "GET"; 11655 request.url = GURL("http://www.google.com/"); 11656 request.load_flags = 0; 11657 11658 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11659 scoped_ptr<HttpTransaction> trans( 11660 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11661 11662 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED); 11663 StaticSocketDataProvider data; 11664 data.set_connect_data(mock_connect); 11665 session_deps_.socket_factory->AddSocketDataProvider(&data); 11666 11667 TestCompletionCallback callback; 11668 11669 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11670 EXPECT_EQ(ERR_IO_PENDING, rv); 11671 11672 rv = callback.WaitForResult(); 11673 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); 11674 11675 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11676 11677 // We don't care whether this succeeds or fails, but it shouldn't crash. 11678 HttpRequestHeaders request_headers; 11679 trans->GetFullRequestHeaders(&request_headers); 11680} 11681 11682TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { 11683 HttpRequestInfo request; 11684 request.method = "GET"; 11685 request.url = GURL("http://www.google.com/"); 11686 request.load_flags = 0; 11687 11688 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11689 scoped_ptr<HttpTransaction> trans( 11690 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11691 11692 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); 11693 StaticSocketDataProvider data; 11694 data.set_connect_data(mock_connect); 11695 session_deps_.socket_factory->AddSocketDataProvider(&data); 11696 11697 TestCompletionCallback callback; 11698 11699 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11700 EXPECT_EQ(ERR_IO_PENDING, rv); 11701 11702 rv = callback.WaitForResult(); 11703 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); 11704 11705 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11706 11707 // We don't care whether this succeeds or fails, but it shouldn't crash. 11708 HttpRequestHeaders request_headers; 11709 trans->GetFullRequestHeaders(&request_headers); 11710} 11711 11712TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) { 11713 HttpRequestInfo request; 11714 request.method = "GET"; 11715 request.url = GURL("http://www.google.com/"); 11716 request.load_flags = 0; 11717 11718 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11719 scoped_ptr<HttpTransaction> trans( 11720 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11721 11722 MockWrite data_writes[] = { 11723 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET), 11724 }; 11725 MockRead data_reads[] = { 11726 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 11727 }; 11728 11729 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11730 data_writes, arraysize(data_writes)); 11731 session_deps_.socket_factory->AddSocketDataProvider(&data); 11732 11733 TestCompletionCallback callback; 11734 11735 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11736 EXPECT_EQ(ERR_IO_PENDING, rv); 11737 11738 rv = callback.WaitForResult(); 11739 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11740 11741 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11742 11743 HttpRequestHeaders request_headers; 11744 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11745 EXPECT_TRUE(request_headers.HasHeader("Host")); 11746} 11747 11748TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) { 11749 HttpRequestInfo request; 11750 request.method = "GET"; 11751 request.url = GURL("http://www.google.com/"); 11752 request.load_flags = 0; 11753 11754 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11755 scoped_ptr<HttpTransaction> trans( 11756 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11757 11758 MockWrite data_writes[] = { 11759 MockWrite(ASYNC, ERR_CONNECTION_RESET), 11760 }; 11761 MockRead data_reads[] = { 11762 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 11763 }; 11764 11765 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11766 data_writes, arraysize(data_writes)); 11767 session_deps_.socket_factory->AddSocketDataProvider(&data); 11768 11769 TestCompletionCallback callback; 11770 11771 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11772 EXPECT_EQ(ERR_IO_PENDING, rv); 11773 11774 rv = callback.WaitForResult(); 11775 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11776 11777 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11778 11779 HttpRequestHeaders request_headers; 11780 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11781 EXPECT_TRUE(request_headers.HasHeader("Host")); 11782} 11783 11784TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) { 11785 HttpRequestInfo request; 11786 request.method = "GET"; 11787 request.url = GURL("http://www.google.com/"); 11788 request.load_flags = 0; 11789 11790 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11791 scoped_ptr<HttpTransaction> trans( 11792 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11793 11794 MockWrite data_writes[] = { 11795 MockWrite("GET / HTTP/1.1\r\n" 11796 "Host: www.google.com\r\n" 11797 "Connection: keep-alive\r\n\r\n"), 11798 }; 11799 MockRead data_reads[] = { 11800 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET), 11801 }; 11802 11803 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11804 data_writes, arraysize(data_writes)); 11805 session_deps_.socket_factory->AddSocketDataProvider(&data); 11806 11807 TestCompletionCallback callback; 11808 11809 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11810 EXPECT_EQ(ERR_IO_PENDING, rv); 11811 11812 rv = callback.WaitForResult(); 11813 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11814 11815 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11816 11817 HttpRequestHeaders request_headers; 11818 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11819 EXPECT_TRUE(request_headers.HasHeader("Host")); 11820} 11821 11822TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) { 11823 HttpRequestInfo request; 11824 request.method = "GET"; 11825 request.url = GURL("http://www.google.com/"); 11826 request.load_flags = 0; 11827 11828 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11829 scoped_ptr<HttpTransaction> trans( 11830 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11831 11832 MockWrite data_writes[] = { 11833 MockWrite("GET / HTTP/1.1\r\n" 11834 "Host: www.google.com\r\n" 11835 "Connection: keep-alive\r\n\r\n"), 11836 }; 11837 MockRead data_reads[] = { 11838 MockRead(ASYNC, ERR_CONNECTION_RESET), 11839 }; 11840 11841 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11842 data_writes, arraysize(data_writes)); 11843 session_deps_.socket_factory->AddSocketDataProvider(&data); 11844 11845 TestCompletionCallback callback; 11846 11847 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11848 EXPECT_EQ(ERR_IO_PENDING, rv); 11849 11850 rv = callback.WaitForResult(); 11851 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 11852 11853 EXPECT_EQ(NULL, trans->GetResponseInfo()); 11854 11855 HttpRequestHeaders request_headers; 11856 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11857 EXPECT_TRUE(request_headers.HasHeader("Host")); 11858} 11859 11860TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) { 11861 HttpRequestInfo request; 11862 request.method = "GET"; 11863 request.url = GURL("http://www.google.com/"); 11864 request.load_flags = 0; 11865 request.extra_headers.SetHeader("X-Foo", "bar"); 11866 11867 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 11868 scoped_ptr<HttpTransaction> trans( 11869 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 11870 11871 MockWrite data_writes[] = { 11872 MockWrite("GET / HTTP/1.1\r\n" 11873 "Host: www.google.com\r\n" 11874 "Connection: keep-alive\r\n" 11875 "X-Foo: bar\r\n\r\n"), 11876 }; 11877 MockRead data_reads[] = { 11878 MockRead("HTTP/1.1 200 OK\r\n" 11879 "Content-Length: 5\r\n\r\n" 11880 "hello"), 11881 MockRead(ASYNC, ERR_UNEXPECTED), 11882 }; 11883 11884 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 11885 data_writes, arraysize(data_writes)); 11886 session_deps_.socket_factory->AddSocketDataProvider(&data); 11887 11888 TestCompletionCallback callback; 11889 11890 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 11891 EXPECT_EQ(ERR_IO_PENDING, rv); 11892 11893 rv = callback.WaitForResult(); 11894 EXPECT_EQ(OK, rv); 11895 11896 HttpRequestHeaders request_headers; 11897 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 11898 std::string foo; 11899 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo)); 11900 EXPECT_EQ("bar", foo); 11901} 11902 11903namespace { 11904 11905// Fake HttpStreamBase that simply records calls to SetPriority(). 11906class FakeStream : public HttpStreamBase, 11907 public base::SupportsWeakPtr<FakeStream> { 11908 public: 11909 explicit FakeStream(RequestPriority priority) : priority_(priority) {} 11910 virtual ~FakeStream() {} 11911 11912 RequestPriority priority() const { return priority_; } 11913 11914 virtual int InitializeStream(const HttpRequestInfo* request_info, 11915 RequestPriority priority, 11916 const BoundNetLog& net_log, 11917 const CompletionCallback& callback) OVERRIDE { 11918 return ERR_IO_PENDING; 11919 } 11920 11921 virtual int SendRequest(const HttpRequestHeaders& request_headers, 11922 HttpResponseInfo* response, 11923 const CompletionCallback& callback) OVERRIDE { 11924 ADD_FAILURE(); 11925 return ERR_UNEXPECTED; 11926 } 11927 11928 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE { 11929 ADD_FAILURE(); 11930 return ERR_UNEXPECTED; 11931 } 11932 11933 virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE { 11934 ADD_FAILURE(); 11935 return NULL; 11936 } 11937 11938 virtual int ReadResponseBody(IOBuffer* buf, int buf_len, 11939 const CompletionCallback& callback) OVERRIDE { 11940 ADD_FAILURE(); 11941 return ERR_UNEXPECTED; 11942 } 11943 11944 virtual void Close(bool not_reusable) OVERRIDE {} 11945 11946 virtual bool IsResponseBodyComplete() const OVERRIDE { 11947 ADD_FAILURE(); 11948 return false; 11949 } 11950 11951 virtual bool CanFindEndOfResponse() const OVERRIDE { 11952 return false; 11953 } 11954 11955 virtual bool IsConnectionReused() const OVERRIDE { 11956 ADD_FAILURE(); 11957 return false; 11958 } 11959 11960 virtual void SetConnectionReused() OVERRIDE { 11961 ADD_FAILURE(); 11962 } 11963 11964 virtual bool IsConnectionReusable() const OVERRIDE { 11965 ADD_FAILURE(); 11966 return false; 11967 } 11968 11969 virtual int64 GetTotalReceivedBytes() const OVERRIDE { 11970 ADD_FAILURE(); 11971 return 0; 11972 } 11973 11974 virtual bool GetLoadTimingInfo( 11975 LoadTimingInfo* load_timing_info) const OVERRIDE { 11976 ADD_FAILURE(); 11977 return false; 11978 } 11979 11980 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE { 11981 ADD_FAILURE(); 11982 } 11983 11984 virtual void GetSSLCertRequestInfo( 11985 SSLCertRequestInfo* cert_request_info) OVERRIDE { 11986 ADD_FAILURE(); 11987 } 11988 11989 virtual bool IsSpdyHttpStream() const OVERRIDE { 11990 ADD_FAILURE(); 11991 return false; 11992 } 11993 11994 virtual void Drain(HttpNetworkSession* session) OVERRIDE { 11995 ADD_FAILURE(); 11996 } 11997 11998 virtual void SetPriority(RequestPriority priority) OVERRIDE { 11999 priority_ = priority; 12000 } 12001 12002 private: 12003 RequestPriority priority_; 12004 12005 DISALLOW_COPY_AND_ASSIGN(FakeStream); 12006}; 12007 12008// Fake HttpStreamRequest that simply records calls to SetPriority() 12009// and vends FakeStreams with its current priority. 12010class FakeStreamRequest : public HttpStreamRequest, 12011 public base::SupportsWeakPtr<FakeStreamRequest> { 12012 public: 12013 FakeStreamRequest(RequestPriority priority, 12014 HttpStreamRequest::Delegate* delegate) 12015 : priority_(priority), 12016 delegate_(delegate), 12017 websocket_stream_create_helper_(NULL) {} 12018 12019 FakeStreamRequest(RequestPriority priority, 12020 HttpStreamRequest::Delegate* delegate, 12021 WebSocketHandshakeStreamBase::CreateHelper* create_helper) 12022 : priority_(priority), 12023 delegate_(delegate), 12024 websocket_stream_create_helper_(create_helper) {} 12025 12026 virtual ~FakeStreamRequest() {} 12027 12028 RequestPriority priority() const { return priority_; } 12029 12030 const WebSocketHandshakeStreamBase::CreateHelper* 12031 websocket_stream_create_helper() const { 12032 return websocket_stream_create_helper_; 12033 } 12034 12035 // Create a new FakeStream and pass it to the request's 12036 // delegate. Returns a weak pointer to the FakeStream. 12037 base::WeakPtr<FakeStream> FinishStreamRequest() { 12038 FakeStream* fake_stream = new FakeStream(priority_); 12039 // Do this before calling OnStreamReady() as OnStreamReady() may 12040 // immediately delete |fake_stream|. 12041 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr(); 12042 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream); 12043 return weak_stream; 12044 } 12045 12046 virtual int RestartTunnelWithProxyAuth( 12047 const AuthCredentials& credentials) OVERRIDE { 12048 ADD_FAILURE(); 12049 return ERR_UNEXPECTED; 12050 } 12051 12052 virtual LoadState GetLoadState() const OVERRIDE { 12053 ADD_FAILURE(); 12054 return LoadState(); 12055 } 12056 12057 virtual void SetPriority(RequestPriority priority) OVERRIDE { 12058 priority_ = priority; 12059 } 12060 12061 virtual bool was_npn_negotiated() const OVERRIDE { 12062 return false; 12063 } 12064 12065 virtual NextProto protocol_negotiated() const OVERRIDE { 12066 return kProtoUnknown; 12067 } 12068 12069 virtual bool using_spdy() const OVERRIDE { 12070 return false; 12071 } 12072 12073 private: 12074 RequestPriority priority_; 12075 HttpStreamRequest::Delegate* const delegate_; 12076 WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_; 12077 12078 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest); 12079}; 12080 12081// Fake HttpStreamFactory that vends FakeStreamRequests. 12082class FakeStreamFactory : public HttpStreamFactory { 12083 public: 12084 FakeStreamFactory() {} 12085 virtual ~FakeStreamFactory() {} 12086 12087 // Returns a WeakPtr<> to the last HttpStreamRequest returned by 12088 // RequestStream() (which may be NULL if it was destroyed already). 12089 base::WeakPtr<FakeStreamRequest> last_stream_request() { 12090 return last_stream_request_; 12091 } 12092 12093 virtual HttpStreamRequest* RequestStream( 12094 const HttpRequestInfo& info, 12095 RequestPriority priority, 12096 const SSLConfig& server_ssl_config, 12097 const SSLConfig& proxy_ssl_config, 12098 HttpStreamRequest::Delegate* delegate, 12099 const BoundNetLog& net_log) OVERRIDE { 12100 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate); 12101 last_stream_request_ = fake_request->AsWeakPtr(); 12102 return fake_request; 12103 } 12104 12105 virtual HttpStreamRequest* RequestWebSocketHandshakeStream( 12106 const HttpRequestInfo& info, 12107 RequestPriority priority, 12108 const SSLConfig& server_ssl_config, 12109 const SSLConfig& proxy_ssl_config, 12110 HttpStreamRequest::Delegate* delegate, 12111 WebSocketHandshakeStreamBase::CreateHelper* create_helper, 12112 const BoundNetLog& net_log) OVERRIDE { 12113 FakeStreamRequest* fake_request = 12114 new FakeStreamRequest(priority, delegate, create_helper); 12115 last_stream_request_ = fake_request->AsWeakPtr(); 12116 return fake_request; 12117 } 12118 12119 virtual void PreconnectStreams(int num_streams, 12120 const HttpRequestInfo& info, 12121 RequestPriority priority, 12122 const SSLConfig& server_ssl_config, 12123 const SSLConfig& proxy_ssl_config) OVERRIDE { 12124 ADD_FAILURE(); 12125 } 12126 12127 virtual base::Value* PipelineInfoToValue() const OVERRIDE { 12128 ADD_FAILURE(); 12129 return NULL; 12130 } 12131 12132 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE { 12133 ADD_FAILURE(); 12134 return NULL; 12135 } 12136 12137 private: 12138 base::WeakPtr<FakeStreamRequest> last_stream_request_; 12139 12140 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory); 12141}; 12142 12143// TODO(yhirano): Split this class out into a net/websockets file, if it is 12144// worth doing. 12145class FakeWebSocketStreamCreateHelper : 12146 public WebSocketHandshakeStreamBase::CreateHelper { 12147 public: 12148 virtual WebSocketHandshakeStreamBase* CreateBasicStream( 12149 scoped_ptr<ClientSocketHandle> connection, 12150 bool using_proxy) OVERRIDE { 12151 NOTREACHED(); 12152 return NULL; 12153 } 12154 12155 virtual WebSocketHandshakeStreamBase* CreateSpdyStream( 12156 const base::WeakPtr<SpdySession>& session, 12157 bool use_relative_url) OVERRIDE { 12158 NOTREACHED(); 12159 return NULL; 12160 }; 12161 12162 virtual ~FakeWebSocketStreamCreateHelper() {} 12163 12164 virtual scoped_ptr<WebSocketStream> Upgrade() { 12165 NOTREACHED(); 12166 return scoped_ptr<WebSocketStream>(); 12167 } 12168}; 12169 12170} // namespace 12171 12172// Make sure that HttpNetworkTransaction passes on its priority to its 12173// stream request on start. 12174TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) { 12175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 12176 HttpNetworkSessionPeer peer(session); 12177 FakeStreamFactory* fake_factory = new FakeStreamFactory(); 12178 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory)); 12179 12180 HttpNetworkTransaction trans(LOW, session); 12181 12182 ASSERT_TRUE(fake_factory->last_stream_request() == NULL); 12183 12184 HttpRequestInfo request; 12185 TestCompletionCallback callback; 12186 EXPECT_EQ(ERR_IO_PENDING, 12187 trans.Start(&request, callback.callback(), BoundNetLog())); 12188 12189 base::WeakPtr<FakeStreamRequest> fake_request = 12190 fake_factory->last_stream_request(); 12191 ASSERT_TRUE(fake_request != NULL); 12192 EXPECT_EQ(LOW, fake_request->priority()); 12193} 12194 12195// Make sure that HttpNetworkTransaction passes on its priority 12196// updates to its stream request. 12197TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) { 12198 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 12199 HttpNetworkSessionPeer peer(session); 12200 FakeStreamFactory* fake_factory = new FakeStreamFactory(); 12201 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory)); 12202 12203 HttpNetworkTransaction trans(LOW, session); 12204 12205 HttpRequestInfo request; 12206 TestCompletionCallback callback; 12207 EXPECT_EQ(ERR_IO_PENDING, 12208 trans.Start(&request, callback.callback(), BoundNetLog())); 12209 12210 base::WeakPtr<FakeStreamRequest> fake_request = 12211 fake_factory->last_stream_request(); 12212 ASSERT_TRUE(fake_request != NULL); 12213 EXPECT_EQ(LOW, fake_request->priority()); 12214 12215 trans.SetPriority(LOWEST); 12216 ASSERT_TRUE(fake_request != NULL); 12217 EXPECT_EQ(LOWEST, fake_request->priority()); 12218} 12219 12220// Make sure that HttpNetworkTransaction passes on its priority 12221// updates to its stream. 12222TEST_P(HttpNetworkTransactionTest, SetStreamPriority) { 12223 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 12224 HttpNetworkSessionPeer peer(session); 12225 FakeStreamFactory* fake_factory = new FakeStreamFactory(); 12226 peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory)); 12227 12228 HttpNetworkTransaction trans(LOW, session); 12229 12230 HttpRequestInfo request; 12231 TestCompletionCallback callback; 12232 EXPECT_EQ(ERR_IO_PENDING, 12233 trans.Start(&request, callback.callback(), BoundNetLog())); 12234 12235 base::WeakPtr<FakeStreamRequest> fake_request = 12236 fake_factory->last_stream_request(); 12237 ASSERT_TRUE(fake_request != NULL); 12238 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest(); 12239 ASSERT_TRUE(fake_stream != NULL); 12240 EXPECT_EQ(LOW, fake_stream->priority()); 12241 12242 trans.SetPriority(LOWEST); 12243 EXPECT_EQ(LOWEST, fake_stream->priority()); 12244} 12245 12246TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) { 12247 // The same logic needs to be tested for both ws: and wss: schemes, but this 12248 // test is already parameterised on NextProto, so it uses a loop to verify 12249 // that the different schemes work. 12250 std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"}; 12251 for (size_t i = 0; i < arraysize(test_cases); ++i) { 12252 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 12253 HttpNetworkSessionPeer peer(session); 12254 FakeStreamFactory* fake_factory = new FakeStreamFactory(); 12255 FakeWebSocketStreamCreateHelper websocket_stream_create_helper; 12256 peer.SetHttpStreamFactoryForWebSocket( 12257 scoped_ptr<HttpStreamFactory>(fake_factory)); 12258 12259 HttpNetworkTransaction trans(LOW, session); 12260 trans.SetWebSocketHandshakeStreamCreateHelper( 12261 &websocket_stream_create_helper); 12262 12263 HttpRequestInfo request; 12264 TestCompletionCallback callback; 12265 request.method = "GET"; 12266 request.url = GURL(test_cases[i]); 12267 12268 EXPECT_EQ(ERR_IO_PENDING, 12269 trans.Start(&request, callback.callback(), BoundNetLog())); 12270 12271 base::WeakPtr<FakeStreamRequest> fake_request = 12272 fake_factory->last_stream_request(); 12273 ASSERT_TRUE(fake_request != NULL); 12274 EXPECT_EQ(&websocket_stream_create_helper, 12275 fake_request->websocket_stream_create_helper()); 12276 } 12277} 12278 12279// Tests that when a used socket is returned to the SSL socket pool, it's closed 12280// if the transport socket pool is stalled on the global socket limit. 12281TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) { 12282 ClientSocketPoolManager::set_max_sockets_per_group( 12283 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 12284 ClientSocketPoolManager::set_max_sockets_per_pool( 12285 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 12286 12287 // Set up SSL request. 12288 12289 HttpRequestInfo ssl_request; 12290 ssl_request.method = "GET"; 12291 ssl_request.url = GURL("https://www.google.com/"); 12292 12293 MockWrite ssl_writes[] = { 12294 MockWrite("GET / HTTP/1.1\r\n" 12295 "Host: www.google.com\r\n" 12296 "Connection: keep-alive\r\n\r\n"), 12297 }; 12298 MockRead ssl_reads[] = { 12299 MockRead("HTTP/1.1 200 OK\r\n"), 12300 MockRead("Content-Length: 11\r\n\r\n"), 12301 MockRead("hello world"), 12302 MockRead(SYNCHRONOUS, OK), 12303 }; 12304 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads), 12305 ssl_writes, arraysize(ssl_writes)); 12306 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data); 12307 12308 SSLSocketDataProvider ssl(ASYNC, OK); 12309 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 12310 12311 // Set up HTTP request. 12312 12313 HttpRequestInfo http_request; 12314 http_request.method = "GET"; 12315 http_request.url = GURL("http://www.google.com/"); 12316 12317 MockWrite http_writes[] = { 12318 MockWrite("GET / HTTP/1.1\r\n" 12319 "Host: www.google.com\r\n" 12320 "Connection: keep-alive\r\n\r\n"), 12321 }; 12322 MockRead http_reads[] = { 12323 MockRead("HTTP/1.1 200 OK\r\n"), 12324 MockRead("Content-Length: 7\r\n\r\n"), 12325 MockRead("falafel"), 12326 MockRead(SYNCHRONOUS, OK), 12327 }; 12328 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 12329 http_writes, arraysize(http_writes)); 12330 session_deps_.socket_factory->AddSocketDataProvider(&http_data); 12331 12332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 12333 12334 // Start the SSL request. 12335 TestCompletionCallback ssl_callback; 12336 scoped_ptr<HttpTransaction> ssl_trans( 12337 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 12338 ASSERT_EQ(ERR_IO_PENDING, 12339 ssl_trans->Start(&ssl_request, ssl_callback.callback(), 12340 BoundNetLog())); 12341 12342 // Start the HTTP request. Pool should stall. 12343 TestCompletionCallback http_callback; 12344 scoped_ptr<HttpTransaction> http_trans( 12345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 12346 ASSERT_EQ(ERR_IO_PENDING, 12347 http_trans->Start(&http_request, http_callback.callback(), 12348 BoundNetLog())); 12349 EXPECT_TRUE(IsTransportSocketPoolStalled(session)); 12350 12351 // Wait for response from SSL request. 12352 ASSERT_EQ(OK, ssl_callback.WaitForResult()); 12353 std::string response_data; 12354 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data)); 12355 EXPECT_EQ("hello world", response_data); 12356 12357 // The SSL socket should automatically be closed, so the HTTP request can 12358 // start. 12359 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session)); 12360 ASSERT_FALSE(IsTransportSocketPoolStalled(session)); 12361 12362 // The HTTP request can now complete. 12363 ASSERT_EQ(OK, http_callback.WaitForResult()); 12364 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data)); 12365 EXPECT_EQ("falafel", response_data); 12366 12367 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session)); 12368} 12369 12370// Tests that when a SSL connection is established but there's no corresponding 12371// request that needs it, the new socket is closed if the transport socket pool 12372// is stalled on the global socket limit. 12373TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) { 12374 ClientSocketPoolManager::set_max_sockets_per_group( 12375 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 12376 ClientSocketPoolManager::set_max_sockets_per_pool( 12377 HttpNetworkSession::NORMAL_SOCKET_POOL, 1); 12378 12379 // Set up an ssl request. 12380 12381 HttpRequestInfo ssl_request; 12382 ssl_request.method = "GET"; 12383 ssl_request.url = GURL("https://www.foopy.com/"); 12384 12385 // No data will be sent on the SSL socket. 12386 StaticSocketDataProvider ssl_data; 12387 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data); 12388 12389 SSLSocketDataProvider ssl(ASYNC, OK); 12390 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 12391 12392 // Set up HTTP request. 12393 12394 HttpRequestInfo http_request; 12395 http_request.method = "GET"; 12396 http_request.url = GURL("http://www.google.com/"); 12397 12398 MockWrite http_writes[] = { 12399 MockWrite("GET / HTTP/1.1\r\n" 12400 "Host: www.google.com\r\n" 12401 "Connection: keep-alive\r\n\r\n"), 12402 }; 12403 MockRead http_reads[] = { 12404 MockRead("HTTP/1.1 200 OK\r\n"), 12405 MockRead("Content-Length: 7\r\n\r\n"), 12406 MockRead("falafel"), 12407 MockRead(SYNCHRONOUS, OK), 12408 }; 12409 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), 12410 http_writes, arraysize(http_writes)); 12411 session_deps_.socket_factory->AddSocketDataProvider(&http_data); 12412 12413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 12414 12415 // Preconnect an SSL socket. A preconnect is needed because connect jobs are 12416 // cancelled when a normal transaction is cancelled. 12417 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); 12418 net::SSLConfig ssl_config; 12419 session->ssl_config_service()->GetSSLConfig(&ssl_config); 12420 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY, 12421 ssl_config, ssl_config); 12422 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session)); 12423 12424 // Start the HTTP request. Pool should stall. 12425 TestCompletionCallback http_callback; 12426 scoped_ptr<HttpTransaction> http_trans( 12427 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 12428 ASSERT_EQ(ERR_IO_PENDING, 12429 http_trans->Start(&http_request, http_callback.callback(), 12430 BoundNetLog())); 12431 EXPECT_TRUE(IsTransportSocketPoolStalled(session)); 12432 12433 // The SSL connection will automatically be closed once the connection is 12434 // established, to let the HTTP request start. 12435 ASSERT_EQ(OK, http_callback.WaitForResult()); 12436 std::string response_data; 12437 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data)); 12438 EXPECT_EQ("falafel", response_data); 12439 12440 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session)); 12441} 12442 12443} // namespace net 12444