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/run_loop.h" 20 #include "base/strings/string_util.h" 21 #include "base/strings/utf_string_conversions.h" 22 #include "base/test/test_file_util.h" 23 #include "net/base/auth.h" 24 #include "net/base/capturing_net_log.h" 25 #include "net/base/completion_callback.h" 26 #include "net/base/load_timing_info.h" 27 #include "net/base/load_timing_info_test_util.h" 28 #include "net/base/net_log.h" 29 #include "net/base/net_log_unittest.h" 30 #include "net/base/request_priority.h" 31 #include "net/base/test_completion_callback.h" 32 #include "net/base/test_data_directory.h" 33 #include "net/base/upload_bytes_element_reader.h" 34 #include "net/base/upload_data_stream.h" 35 #include "net/base/upload_file_element_reader.h" 36 #include "net/cert/mock_cert_verifier.h" 37 #include "net/dns/host_cache.h" 38 #include "net/dns/mock_host_resolver.h" 39 #include "net/http/http_auth_challenge_tokenizer.h" 40 #include "net/http/http_auth_handler_digest.h" 41 #include "net/http/http_auth_handler_mock.h" 42 #include "net/http/http_auth_handler_ntlm.h" 43 #include "net/http/http_basic_stream.h" 44 #include "net/http/http_network_session.h" 45 #include "net/http/http_network_session_peer.h" 46 #include "net/http/http_server_properties_impl.h" 47 #include "net/http/http_stream.h" 48 #include "net/http/http_stream_factory.h" 49 #include "net/http/http_transaction_test_util.h" 50 #include "net/proxy/proxy_config_service_fixed.h" 51 #include "net/proxy/proxy_info.h" 52 #include "net/proxy/proxy_resolver.h" 53 #include "net/proxy/proxy_service.h" 54 #include "net/socket/client_socket_factory.h" 55 #include "net/socket/client_socket_pool_manager.h" 56 #include "net/socket/mock_client_socket_pool_manager.h" 57 #include "net/socket/next_proto.h" 58 #include "net/socket/socket_test_util.h" 59 #include "net/socket/ssl_client_socket.h" 60 #include "net/spdy/spdy_framer.h" 61 #include "net/spdy/spdy_session.h" 62 #include "net/spdy/spdy_session_pool.h" 63 #include "net/spdy/spdy_test_util_common.h" 64 #include "net/ssl/ssl_cert_request_info.h" 65 #include "net/ssl/ssl_config_service.h" 66 #include "net/ssl/ssl_config_service_defaults.h" 67 #include "net/ssl/ssl_info.h" 68 #include "net/test/cert_test_util.h" 69 #include "net/websockets/websocket_handshake_stream_base.h" 70 #include "testing/gtest/include/gtest/gtest.h" 71 #include "testing/platform_test.h" 72 #include "url/gurl.h" 73 74 using base::ASCIIToUTF16; 75 76 //----------------------------------------------------------------------------- 77 78 namespace { 79 80 const base::string16 kBar(ASCIIToUTF16("bar")); 81 const base::string16 kBar2(ASCIIToUTF16("bar2")); 82 const base::string16 kBar3(ASCIIToUTF16("bar3")); 83 const base::string16 kBaz(ASCIIToUTF16("baz")); 84 const base::string16 kFirst(ASCIIToUTF16("first")); 85 const base::string16 kFoo(ASCIIToUTF16("foo")); 86 const base::string16 kFoo2(ASCIIToUTF16("foo2")); 87 const base::string16 kFoo3(ASCIIToUTF16("foo3")); 88 const base::string16 kFou(ASCIIToUTF16("fou")); 89 const base::string16 kSecond(ASCIIToUTF16("second")); 90 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm")); 91 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword")); 92 93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) { 94 return session->GetTransportSocketPool( 95 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); 96 } 97 98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) { 99 return session->GetSSLSocketPool( 100 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); 101 } 102 103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) { 104 return session->GetTransportSocketPool( 105 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled(); 106 } 107 108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns 109 // a JSONified list of headers as a single string. Uses single quotes instead 110 // of double quotes for easier comparison. Returns false on failure. 111 bool GetHeaders(base::DictionaryValue* params, std::string* headers) { 112 if (!params) 113 return false; 114 base::ListValue* header_list; 115 if (!params->GetList("headers", &header_list)) 116 return false; 117 std::string double_quote_headers; 118 base::JSONWriter::Write(header_list, &double_quote_headers); 119 base::ReplaceChars(double_quote_headers, "\"", "'", headers); 120 return true; 121 } 122 123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is 124 // used. 125 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) { 126 EXPECT_TRUE(load_timing_info.socket_reused); 127 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 128 129 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); 130 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); 131 132 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 133 EXPECT_FALSE(load_timing_info.send_start.is_null()); 134 135 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 136 137 // Set at a higher level. 138 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 139 EXPECT_TRUE(load_timing_info.request_start.is_null()); 140 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 141 } 142 143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is 144 // used. 145 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info, 146 int connect_timing_flags) { 147 EXPECT_FALSE(load_timing_info.socket_reused); 148 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 149 150 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); 151 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); 152 153 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 154 connect_timing_flags); 155 EXPECT_LE(load_timing_info.connect_timing.connect_end, 156 load_timing_info.send_start); 157 158 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 159 160 // Set at a higher level. 161 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 162 EXPECT_TRUE(load_timing_info.request_start.is_null()); 163 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 164 } 165 166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is 167 // used. 168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) { 169 EXPECT_TRUE(load_timing_info.socket_reused); 170 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 171 172 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); 173 174 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 175 EXPECT_LE(load_timing_info.proxy_resolve_start, 176 load_timing_info.proxy_resolve_end); 177 EXPECT_LE(load_timing_info.proxy_resolve_end, 178 load_timing_info.send_start); 179 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 180 181 // Set at a higher level. 182 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 183 EXPECT_TRUE(load_timing_info.request_start.is_null()); 184 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 185 } 186 187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is 188 // used. 189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info, 190 int connect_timing_flags) { 191 EXPECT_FALSE(load_timing_info.socket_reused); 192 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 193 194 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 195 EXPECT_LE(load_timing_info.proxy_resolve_start, 196 load_timing_info.proxy_resolve_end); 197 EXPECT_LE(load_timing_info.proxy_resolve_end, 198 load_timing_info.connect_timing.connect_start); 199 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 200 connect_timing_flags); 201 EXPECT_LE(load_timing_info.connect_timing.connect_end, 202 load_timing_info.send_start); 203 204 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); 205 206 // Set at a higher level. 207 EXPECT_TRUE(load_timing_info.request_start_time.is_null()); 208 EXPECT_TRUE(load_timing_info.request_start.is_null()); 209 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 210 } 211 212 } // namespace 213 214 namespace net { 215 216 namespace { 217 218 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) { 219 return SpdySessionDependencies::SpdyCreateSession(session_deps); 220 } 221 222 } // namespace 223 224 class HttpNetworkTransactionTest 225 : public PlatformTest, 226 public ::testing::WithParamInterface<NextProto> { 227 public: 228 virtual ~HttpNetworkTransactionTest() { 229 // Important to restore the per-pool limit first, since the pool limit must 230 // always be greater than group limit, and the tests reduce both limits. 231 ClientSocketPoolManager::set_max_sockets_per_pool( 232 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_); 233 ClientSocketPoolManager::set_max_sockets_per_group( 234 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_); 235 } 236 237 protected: 238 HttpNetworkTransactionTest() 239 : spdy_util_(GetParam()), 240 session_deps_(GetParam()), 241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group( 242 HttpNetworkSession::NORMAL_SOCKET_POOL)), 243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool( 244 HttpNetworkSession::NORMAL_SOCKET_POOL)) { 245 } 246 247 struct SimpleGetHelperResult { 248 int rv; 249 std::string status_line; 250 std::string response_data; 251 int64 totalReceivedBytes; 252 LoadTimingInfo load_timing_info; 253 }; 254 255 virtual void SetUp() { 256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 257 base::MessageLoop::current()->RunUntilIdle(); 258 } 259 260 virtual void TearDown() { 261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 262 base::MessageLoop::current()->RunUntilIdle(); 263 // Empty the current queue. 264 base::MessageLoop::current()->RunUntilIdle(); 265 PlatformTest::TearDown(); 266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 267 base::MessageLoop::current()->RunUntilIdle(); 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 // Either |write_failure| specifies a write failure or |read_failure| 286 // specifies a read failure when using a reused socket. In either case, the 287 // failure should cause the network transaction to resend the request, and the 288 // other argument should be NULL. 289 void PreconnectErrorResendRequestTest(const MockWrite* write_failure, 290 const MockRead* read_failure, 291 bool use_spdy); 292 293 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[], 294 size_t data_count) { 295 SimpleGetHelperResult out; 296 297 HttpRequestInfo request; 298 request.method = "GET"; 299 request.url = GURL("http://www.google.com/"); 300 request.load_flags = 0; 301 302 CapturingBoundNetLog log; 303 session_deps_.net_log = log.bound().net_log(); 304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 305 scoped_ptr<HttpTransaction> trans( 306 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 307 308 for (size_t i = 0; i < data_count; ++i) { 309 session_deps_.socket_factory->AddSocketDataProvider(data[i]); 310 } 311 312 TestCompletionCallback callback; 313 314 EXPECT_TRUE(log.bound().IsLogging()); 315 int rv = trans->Start(&request, callback.callback(), log.bound()); 316 EXPECT_EQ(ERR_IO_PENDING, rv); 317 318 out.rv = callback.WaitForResult(); 319 320 // Even in the failure cases that use this function, connections are always 321 // successfully established before the error. 322 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info)); 323 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 324 325 if (out.rv != OK) 326 return out; 327 328 const HttpResponseInfo* response = trans->GetResponseInfo(); 329 // Can't use ASSERT_* inside helper functions like this, so 330 // return an error. 331 if (response == NULL || response->headers.get() == NULL) { 332 out.rv = ERR_UNEXPECTED; 333 return out; 334 } 335 out.status_line = response->headers->GetStatusLine(); 336 337 EXPECT_EQ("127.0.0.1", response->socket_address.host()); 338 EXPECT_EQ(80, response->socket_address.port()); 339 340 rv = ReadTransaction(trans.get(), &out.response_data); 341 EXPECT_EQ(OK, rv); 342 343 net::CapturingNetLog::CapturedEntryList entries; 344 log.GetEntries(&entries); 345 size_t pos = ExpectLogContainsSomewhere( 346 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, 347 NetLog::PHASE_NONE); 348 ExpectLogContainsSomewhere( 349 entries, pos, 350 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS, 351 NetLog::PHASE_NONE); 352 353 std::string line; 354 EXPECT_TRUE(entries[pos].GetStringValue("line", &line)); 355 EXPECT_EQ("GET / HTTP/1.1\r\n", line); 356 357 HttpRequestHeaders request_headers; 358 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers)); 359 std::string value; 360 EXPECT_TRUE(request_headers.GetHeader("Host", &value)); 361 EXPECT_EQ("www.google.com", value); 362 EXPECT_TRUE(request_headers.GetHeader("Connection", &value)); 363 EXPECT_EQ("keep-alive", value); 364 365 std::string response_headers; 366 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers)); 367 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']", 368 response_headers); 369 370 out.totalReceivedBytes = trans->GetTotalReceivedBytes(); 371 return out; 372 } 373 374 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[], 375 size_t reads_count) { 376 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0); 377 StaticSocketDataProvider* data[] = { &reads }; 378 return SimpleGetHelperForData(data, 1); 379 } 380 381 int64 ReadsSize(MockRead data_reads[], size_t reads_count) { 382 int64 size = 0; 383 for (size_t i = 0; i < reads_count; ++i) 384 size += data_reads[i].data_len; 385 return size; 386 } 387 388 void ConnectStatusHelperWithExpectedStatus(const MockRead& status, 389 int expected_status); 390 391 void ConnectStatusHelper(const MockRead& status); 392 393 void BypassHostCacheOnRefreshHelper(int load_flags); 394 395 void CheckErrorIsPassedBack(int error, IoMode mode); 396 397 SpdyTestUtil spdy_util_; 398 SpdySessionDependencies session_deps_; 399 400 // Original socket limits. Some tests set these. Safest to always restore 401 // them once each test has been run. 402 int old_max_group_sockets_; 403 int old_max_pool_sockets_; 404 }; 405 406 INSTANTIATE_TEST_CASE_P( 407 NextProto, 408 HttpNetworkTransactionTest, 409 testing::Values(kProtoDeprecatedSPDY2, 410 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4)); 411 412 namespace { 413 414 class BeforeNetworkStartHandler { 415 public: 416 explicit BeforeNetworkStartHandler(bool defer) 417 : defer_on_before_network_start_(defer), 418 observed_before_network_start_(false) {} 419 420 void OnBeforeNetworkStart(bool* defer) { 421 *defer = defer_on_before_network_start_; 422 observed_before_network_start_ = true; 423 } 424 425 bool observed_before_network_start() const { 426 return observed_before_network_start_; 427 } 428 429 private: 430 const bool defer_on_before_network_start_; 431 bool observed_before_network_start_; 432 433 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler); 434 }; 435 436 // Fill |str| with a long header list that consumes >= |size| bytes. 437 void FillLargeHeadersString(std::string* str, int size) { 438 const char* row = 439 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n"; 440 const int sizeof_row = strlen(row); 441 const int num_rows = static_cast<int>( 442 ceil(static_cast<float>(size) / sizeof_row)); 443 const int sizeof_data = num_rows * sizeof_row; 444 DCHECK(sizeof_data >= size); 445 str->reserve(sizeof_data); 446 447 for (int i = 0; i < num_rows; ++i) 448 str->append(row, sizeof_row); 449 } 450 451 // Alternative functions that eliminate randomness and dependency on the local 452 // host name so that the generated NTLM messages are reproducible. 453 void MockGenerateRandom1(uint8* output, size_t n) { 454 static const uint8 bytes[] = { 455 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54 456 }; 457 static size_t current_byte = 0; 458 for (size_t i = 0; i < n; ++i) { 459 output[i] = bytes[current_byte++]; 460 current_byte %= arraysize(bytes); 461 } 462 } 463 464 void MockGenerateRandom2(uint8* output, size_t n) { 465 static const uint8 bytes[] = { 466 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1, 467 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f 468 }; 469 static size_t current_byte = 0; 470 for (size_t i = 0; i < n; ++i) { 471 output[i] = bytes[current_byte++]; 472 current_byte %= arraysize(bytes); 473 } 474 } 475 476 std::string MockGetHostName() { 477 return "WTC-WIN7"; 478 } 479 480 template<typename ParentPool> 481 class CaptureGroupNameSocketPool : public ParentPool { 482 public: 483 CaptureGroupNameSocketPool(HostResolver* host_resolver, 484 CertVerifier* cert_verifier); 485 486 const std::string last_group_name_received() const { 487 return last_group_name_; 488 } 489 490 virtual int RequestSocket(const std::string& group_name, 491 const void* socket_params, 492 RequestPriority priority, 493 ClientSocketHandle* handle, 494 const CompletionCallback& callback, 495 const BoundNetLog& net_log) { 496 last_group_name_ = group_name; 497 return ERR_IO_PENDING; 498 } 499 virtual void CancelRequest(const std::string& group_name, 500 ClientSocketHandle* handle) {} 501 virtual void ReleaseSocket(const std::string& group_name, 502 scoped_ptr<StreamSocket> socket, 503 int id) {} 504 virtual void CloseIdleSockets() {} 505 virtual int IdleSocketCount() const { 506 return 0; 507 } 508 virtual int IdleSocketCountInGroup(const std::string& group_name) const { 509 return 0; 510 } 511 virtual LoadState GetLoadState(const std::string& group_name, 512 const ClientSocketHandle* handle) const { 513 return LOAD_STATE_IDLE; 514 } 515 virtual base::TimeDelta ConnectionTimeout() const { 516 return base::TimeDelta(); 517 } 518 519 private: 520 std::string last_group_name_; 521 }; 522 523 typedef CaptureGroupNameSocketPool<TransportClientSocketPool> 524 CaptureGroupNameTransportSocketPool; 525 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool> 526 CaptureGroupNameHttpProxySocketPool; 527 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool> 528 CaptureGroupNameSOCKSSocketPool; 529 typedef CaptureGroupNameSocketPool<SSLClientSocketPool> 530 CaptureGroupNameSSLSocketPool; 531 532 template<typename ParentPool> 533 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool( 534 HostResolver* host_resolver, 535 CertVerifier* /* cert_verifier */) 536 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {} 537 538 template<> 539 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool( 540 HostResolver* host_resolver, 541 CertVerifier* /* cert_verifier */) 542 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {} 543 544 template <> 545 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool( 546 HostResolver* host_resolver, 547 CertVerifier* cert_verifier) 548 : SSLClientSocketPool(0, 549 0, 550 NULL, 551 host_resolver, 552 cert_verifier, 553 NULL, 554 NULL, 555 NULL, 556 std::string(), 557 NULL, 558 NULL, 559 NULL, 560 NULL, 561 NULL, 562 NULL) {} 563 564 //----------------------------------------------------------------------------- 565 566 // Helper functions for validating that AuthChallengeInfo's are correctly 567 // configured for common cases. 568 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) { 569 if (!auth_challenge) 570 return false; 571 EXPECT_FALSE(auth_challenge->is_proxy); 572 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString()); 573 EXPECT_EQ("MyRealm1", auth_challenge->realm); 574 EXPECT_EQ("basic", auth_challenge->scheme); 575 return true; 576 } 577 578 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) { 579 if (!auth_challenge) 580 return false; 581 EXPECT_TRUE(auth_challenge->is_proxy); 582 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString()); 583 EXPECT_EQ("MyRealm1", auth_challenge->realm); 584 EXPECT_EQ("basic", auth_challenge->scheme); 585 return true; 586 } 587 588 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) { 589 if (!auth_challenge) 590 return false; 591 EXPECT_FALSE(auth_challenge->is_proxy); 592 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString()); 593 EXPECT_EQ("digestive", auth_challenge->realm); 594 EXPECT_EQ("digest", auth_challenge->scheme); 595 return true; 596 } 597 598 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) { 599 if (!auth_challenge) 600 return false; 601 EXPECT_FALSE(auth_challenge->is_proxy); 602 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString()); 603 EXPECT_EQ(std::string(), auth_challenge->realm); 604 EXPECT_EQ("ntlm", auth_challenge->scheme); 605 return true; 606 } 607 608 } // namespace 609 610 TEST_P(HttpNetworkTransactionTest, Basic) { 611 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 612 scoped_ptr<HttpTransaction> trans( 613 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 614 } 615 616 TEST_P(HttpNetworkTransactionTest, SimpleGET) { 617 MockRead data_reads[] = { 618 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 619 MockRead("hello world"), 620 MockRead(SYNCHRONOUS, OK), 621 }; 622 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 623 arraysize(data_reads)); 624 EXPECT_EQ(OK, out.rv); 625 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 626 EXPECT_EQ("hello world", out.response_data); 627 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 628 EXPECT_EQ(reads_size, out.totalReceivedBytes); 629 } 630 631 // Response with no status line. 632 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) { 633 MockRead data_reads[] = { 634 MockRead("hello world"), 635 MockRead(SYNCHRONOUS, OK), 636 }; 637 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 638 arraysize(data_reads)); 639 EXPECT_EQ(OK, out.rv); 640 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 641 EXPECT_EQ("hello world", out.response_data); 642 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 643 EXPECT_EQ(reads_size, out.totalReceivedBytes); 644 } 645 646 // Allow up to 4 bytes of junk to precede status line. 647 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) { 648 MockRead data_reads[] = { 649 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 650 MockRead(SYNCHRONOUS, OK), 651 }; 652 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 653 arraysize(data_reads)); 654 EXPECT_EQ(OK, out.rv); 655 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 656 EXPECT_EQ("DATA", out.response_data); 657 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 658 EXPECT_EQ(reads_size, out.totalReceivedBytes); 659 } 660 661 // Allow up to 4 bytes of junk to precede status line. 662 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) { 663 MockRead data_reads[] = { 664 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 665 MockRead(SYNCHRONOUS, OK), 666 }; 667 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 668 arraysize(data_reads)); 669 EXPECT_EQ(OK, out.rv); 670 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 671 EXPECT_EQ("DATA", out.response_data); 672 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 673 EXPECT_EQ(reads_size, out.totalReceivedBytes); 674 } 675 676 // Beyond 4 bytes of slop and it should fail to find a status line. 677 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) { 678 MockRead data_reads[] = { 679 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"), 680 MockRead(SYNCHRONOUS, OK), 681 }; 682 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 683 arraysize(data_reads)); 684 EXPECT_EQ(OK, out.rv); 685 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 686 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data); 687 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 688 EXPECT_EQ(reads_size, out.totalReceivedBytes); 689 } 690 691 // Same as StatusLineJunk4Bytes, except the read chunks are smaller. 692 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) { 693 MockRead data_reads[] = { 694 MockRead("\n"), 695 MockRead("\n"), 696 MockRead("Q"), 697 MockRead("J"), 698 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"), 699 MockRead(SYNCHRONOUS, OK), 700 }; 701 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 702 arraysize(data_reads)); 703 EXPECT_EQ(OK, out.rv); 704 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); 705 EXPECT_EQ("DATA", out.response_data); 706 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 707 EXPECT_EQ(reads_size, out.totalReceivedBytes); 708 } 709 710 // Close the connection before enough bytes to have a status line. 711 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) { 712 MockRead data_reads[] = { 713 MockRead("HTT"), 714 MockRead(SYNCHRONOUS, OK), 715 }; 716 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 717 arraysize(data_reads)); 718 EXPECT_EQ(OK, out.rv); 719 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); 720 EXPECT_EQ("HTT", out.response_data); 721 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 722 EXPECT_EQ(reads_size, out.totalReceivedBytes); 723 } 724 725 // Simulate a 204 response, lacking a Content-Length header, sent over a 726 // persistent connection. The response should still terminate since a 204 727 // cannot have a response body. 728 TEST_P(HttpNetworkTransactionTest, StopsReading204) { 729 char junk[] = "junk"; 730 MockRead data_reads[] = { 731 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 732 MockRead(junk), // Should not be read!! 733 MockRead(SYNCHRONOUS, OK), 734 }; 735 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 736 arraysize(data_reads)); 737 EXPECT_EQ(OK, out.rv); 738 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line); 739 EXPECT_EQ("", out.response_data); 740 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 741 int64 response_size = reads_size - strlen(junk); 742 EXPECT_EQ(response_size, out.totalReceivedBytes); 743 } 744 745 // A simple request using chunked encoding with some extra data after. 746 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) { 747 std::string final_chunk = "0\r\n\r\n"; 748 std::string extra_data = "HTTP/1.1 200 OK\r\n"; 749 std::string last_read = final_chunk + extra_data; 750 MockRead data_reads[] = { 751 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"), 752 MockRead("5\r\nHello\r\n"), 753 MockRead("1\r\n"), 754 MockRead(" \r\n"), 755 MockRead("5\r\nworld\r\n"), 756 MockRead(last_read.data()), 757 MockRead(SYNCHRONOUS, OK), 758 }; 759 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 760 arraysize(data_reads)); 761 EXPECT_EQ(OK, out.rv); 762 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 763 EXPECT_EQ("Hello world", out.response_data); 764 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 765 int64 response_size = reads_size - extra_data.size(); 766 EXPECT_EQ(response_size, out.totalReceivedBytes); 767 } 768 769 // Next tests deal with http://crbug.com/56344. 770 771 TEST_P(HttpNetworkTransactionTest, 772 MultipleContentLengthHeadersNoTransferEncoding) { 773 MockRead data_reads[] = { 774 MockRead("HTTP/1.1 200 OK\r\n"), 775 MockRead("Content-Length: 10\r\n"), 776 MockRead("Content-Length: 5\r\n\r\n"), 777 }; 778 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 779 arraysize(data_reads)); 780 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 781 } 782 783 TEST_P(HttpNetworkTransactionTest, 784 DuplicateContentLengthHeadersNoTransferEncoding) { 785 MockRead data_reads[] = { 786 MockRead("HTTP/1.1 200 OK\r\n"), 787 MockRead("Content-Length: 5\r\n"), 788 MockRead("Content-Length: 5\r\n\r\n"), 789 MockRead("Hello"), 790 }; 791 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 792 arraysize(data_reads)); 793 EXPECT_EQ(OK, out.rv); 794 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 795 EXPECT_EQ("Hello", out.response_data); 796 } 797 798 TEST_P(HttpNetworkTransactionTest, 799 ComplexContentLengthHeadersNoTransferEncoding) { 800 // More than 2 dupes. 801 { 802 MockRead data_reads[] = { 803 MockRead("HTTP/1.1 200 OK\r\n"), 804 MockRead("Content-Length: 5\r\n"), 805 MockRead("Content-Length: 5\r\n"), 806 MockRead("Content-Length: 5\r\n\r\n"), 807 MockRead("Hello"), 808 }; 809 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 810 arraysize(data_reads)); 811 EXPECT_EQ(OK, out.rv); 812 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 813 EXPECT_EQ("Hello", out.response_data); 814 } 815 // HTTP/1.0 816 { 817 MockRead data_reads[] = { 818 MockRead("HTTP/1.0 200 OK\r\n"), 819 MockRead("Content-Length: 5\r\n"), 820 MockRead("Content-Length: 5\r\n"), 821 MockRead("Content-Length: 5\r\n\r\n"), 822 MockRead("Hello"), 823 }; 824 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 825 arraysize(data_reads)); 826 EXPECT_EQ(OK, out.rv); 827 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); 828 EXPECT_EQ("Hello", out.response_data); 829 } 830 // 2 dupes and one mismatched. 831 { 832 MockRead data_reads[] = { 833 MockRead("HTTP/1.1 200 OK\r\n"), 834 MockRead("Content-Length: 10\r\n"), 835 MockRead("Content-Length: 10\r\n"), 836 MockRead("Content-Length: 5\r\n\r\n"), 837 }; 838 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 839 arraysize(data_reads)); 840 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv); 841 } 842 } 843 844 TEST_P(HttpNetworkTransactionTest, 845 MultipleContentLengthHeadersTransferEncoding) { 846 MockRead data_reads[] = { 847 MockRead("HTTP/1.1 200 OK\r\n"), 848 MockRead("Content-Length: 666\r\n"), 849 MockRead("Content-Length: 1337\r\n"), 850 MockRead("Transfer-Encoding: chunked\r\n\r\n"), 851 MockRead("5\r\nHello\r\n"), 852 MockRead("1\r\n"), 853 MockRead(" \r\n"), 854 MockRead("5\r\nworld\r\n"), 855 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"), 856 MockRead(SYNCHRONOUS, OK), 857 }; 858 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 859 arraysize(data_reads)); 860 EXPECT_EQ(OK, out.rv); 861 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 862 EXPECT_EQ("Hello world", out.response_data); 863 } 864 865 // Next tests deal with http://crbug.com/98895. 866 867 // Checks that a single Content-Disposition header results in no error. 868 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) { 869 MockRead data_reads[] = { 870 MockRead("HTTP/1.1 200 OK\r\n"), 871 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"), 872 MockRead("Content-Length: 5\r\n\r\n"), 873 MockRead("Hello"), 874 }; 875 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 876 arraysize(data_reads)); 877 EXPECT_EQ(OK, out.rv); 878 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 879 EXPECT_EQ("Hello", out.response_data); 880 } 881 882 // Checks that two identical Content-Disposition headers result in no error. 883 TEST_P(HttpNetworkTransactionTest, 884 TwoIdenticalContentDispositionHeaders) { 885 MockRead data_reads[] = { 886 MockRead("HTTP/1.1 200 OK\r\n"), 887 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 888 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 889 MockRead("Content-Length: 5\r\n\r\n"), 890 MockRead("Hello"), 891 }; 892 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 893 arraysize(data_reads)); 894 EXPECT_EQ(OK, out.rv); 895 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); 896 EXPECT_EQ("Hello", out.response_data); 897 } 898 899 // Checks that two distinct Content-Disposition headers result in an error. 900 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) { 901 MockRead data_reads[] = { 902 MockRead("HTTP/1.1 200 OK\r\n"), 903 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"), 904 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"), 905 MockRead("Content-Length: 5\r\n\r\n"), 906 MockRead("Hello"), 907 }; 908 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 909 arraysize(data_reads)); 910 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv); 911 } 912 913 // Checks that two identical Location headers result in no error. 914 // Also tests Location header behavior. 915 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) { 916 MockRead data_reads[] = { 917 MockRead("HTTP/1.1 302 Redirect\r\n"), 918 MockRead("Location: http://good.com/\r\n"), 919 MockRead("Location: http://good.com/\r\n"), 920 MockRead("Content-Length: 0\r\n\r\n"), 921 MockRead(SYNCHRONOUS, OK), 922 }; 923 924 HttpRequestInfo request; 925 request.method = "GET"; 926 request.url = GURL("http://redirect.com/"); 927 request.load_flags = 0; 928 929 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 930 scoped_ptr<HttpTransaction> trans( 931 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 932 933 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 934 session_deps_.socket_factory->AddSocketDataProvider(&data); 935 936 TestCompletionCallback callback; 937 938 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 939 EXPECT_EQ(ERR_IO_PENDING, rv); 940 941 EXPECT_EQ(OK, callback.WaitForResult()); 942 943 const HttpResponseInfo* response = trans->GetResponseInfo(); 944 ASSERT_TRUE(response != NULL && response->headers.get() != NULL); 945 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine()); 946 std::string url; 947 EXPECT_TRUE(response->headers->IsRedirect(&url)); 948 EXPECT_EQ("http://good.com/", url); 949 EXPECT_TRUE(response->proxy_server.IsEmpty()); 950 } 951 952 // Checks that two distinct Location headers result in an error. 953 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) { 954 MockRead data_reads[] = { 955 MockRead("HTTP/1.1 302 Redirect\r\n"), 956 MockRead("Location: http://good.com/\r\n"), 957 MockRead("Location: http://evil.com/\r\n"), 958 MockRead("Content-Length: 0\r\n\r\n"), 959 MockRead(SYNCHRONOUS, OK), 960 }; 961 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 962 arraysize(data_reads)); 963 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv); 964 } 965 966 // Do a request using the HEAD method. Verify that we don't try to read the 967 // message body (since HEAD has none). 968 TEST_P(HttpNetworkTransactionTest, Head) { 969 HttpRequestInfo request; 970 request.method = "HEAD"; 971 request.url = GURL("http://www.google.com/"); 972 request.load_flags = 0; 973 974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 975 scoped_ptr<HttpTransaction> trans( 976 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 977 978 MockWrite data_writes1[] = { 979 MockWrite("HEAD / HTTP/1.1\r\n" 980 "Host: www.google.com\r\n" 981 "Connection: keep-alive\r\n" 982 "Content-Length: 0\r\n\r\n"), 983 }; 984 MockRead data_reads1[] = { 985 MockRead("HTTP/1.1 404 Not Found\r\n"), 986 MockRead("Server: Blah\r\n"), 987 MockRead("Content-Length: 1234\r\n\r\n"), 988 989 // No response body because the test stops reading here. 990 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 991 }; 992 993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 994 data_writes1, arraysize(data_writes1)); 995 session_deps_.socket_factory->AddSocketDataProvider(&data1); 996 997 TestCompletionCallback callback1; 998 999 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1000 EXPECT_EQ(ERR_IO_PENDING, rv); 1001 1002 rv = callback1.WaitForResult(); 1003 EXPECT_EQ(OK, rv); 1004 1005 const HttpResponseInfo* response = trans->GetResponseInfo(); 1006 ASSERT_TRUE(response != NULL); 1007 1008 // Check that the headers got parsed. 1009 EXPECT_TRUE(response->headers.get() != NULL); 1010 EXPECT_EQ(1234, response->headers->GetContentLength()); 1011 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine()); 1012 EXPECT_TRUE(response->proxy_server.IsEmpty()); 1013 1014 std::string server_header; 1015 void* iter = NULL; 1016 bool has_server_header = response->headers->EnumerateHeader( 1017 &iter, "Server", &server_header); 1018 EXPECT_TRUE(has_server_header); 1019 EXPECT_EQ("Blah", server_header); 1020 1021 // Reading should give EOF right away, since there is no message body 1022 // (despite non-zero content-length). 1023 std::string response_data; 1024 rv = ReadTransaction(trans.get(), &response_data); 1025 EXPECT_EQ(OK, rv); 1026 EXPECT_EQ("", response_data); 1027 } 1028 1029 TEST_P(HttpNetworkTransactionTest, ReuseConnection) { 1030 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1031 1032 MockRead data_reads[] = { 1033 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1034 MockRead("hello"), 1035 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1036 MockRead("world"), 1037 MockRead(SYNCHRONOUS, OK), 1038 }; 1039 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1040 session_deps_.socket_factory->AddSocketDataProvider(&data); 1041 1042 const char* const kExpectedResponseData[] = { 1043 "hello", "world" 1044 }; 1045 1046 for (int i = 0; i < 2; ++i) { 1047 HttpRequestInfo request; 1048 request.method = "GET"; 1049 request.url = GURL("http://www.google.com/"); 1050 request.load_flags = 0; 1051 1052 scoped_ptr<HttpTransaction> trans( 1053 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1054 1055 TestCompletionCallback callback; 1056 1057 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1058 EXPECT_EQ(ERR_IO_PENDING, rv); 1059 1060 rv = callback.WaitForResult(); 1061 EXPECT_EQ(OK, rv); 1062 1063 const HttpResponseInfo* response = trans->GetResponseInfo(); 1064 ASSERT_TRUE(response != NULL); 1065 1066 EXPECT_TRUE(response->headers.get() != NULL); 1067 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1068 EXPECT_TRUE(response->proxy_server.IsEmpty()); 1069 1070 std::string response_data; 1071 rv = ReadTransaction(trans.get(), &response_data); 1072 EXPECT_EQ(OK, rv); 1073 EXPECT_EQ(kExpectedResponseData[i], response_data); 1074 } 1075 } 1076 1077 TEST_P(HttpNetworkTransactionTest, Ignores100) { 1078 ScopedVector<UploadElementReader> element_readers; 1079 element_readers.push_back(new UploadBytesElementReader("foo", 3)); 1080 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 1081 1082 HttpRequestInfo request; 1083 request.method = "POST"; 1084 request.url = GURL("http://www.foo.com/"); 1085 request.upload_data_stream = &upload_data_stream; 1086 request.load_flags = 0; 1087 1088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1089 scoped_ptr<HttpTransaction> trans( 1090 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1091 1092 MockRead data_reads[] = { 1093 MockRead("HTTP/1.0 100 Continue\r\n\r\n"), 1094 MockRead("HTTP/1.0 200 OK\r\n\r\n"), 1095 MockRead("hello world"), 1096 MockRead(SYNCHRONOUS, OK), 1097 }; 1098 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1099 session_deps_.socket_factory->AddSocketDataProvider(&data); 1100 1101 TestCompletionCallback callback; 1102 1103 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1104 EXPECT_EQ(ERR_IO_PENDING, rv); 1105 1106 rv = callback.WaitForResult(); 1107 EXPECT_EQ(OK, rv); 1108 1109 const HttpResponseInfo* response = trans->GetResponseInfo(); 1110 ASSERT_TRUE(response != NULL); 1111 1112 EXPECT_TRUE(response->headers.get() != NULL); 1113 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine()); 1114 1115 std::string response_data; 1116 rv = ReadTransaction(trans.get(), &response_data); 1117 EXPECT_EQ(OK, rv); 1118 EXPECT_EQ("hello world", response_data); 1119 } 1120 1121 // This test is almost the same as Ignores100 above, but the response contains 1122 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is 1123 // HTTP/1.1 and the two status headers are read in one read. 1124 TEST_P(HttpNetworkTransactionTest, Ignores1xx) { 1125 HttpRequestInfo request; 1126 request.method = "GET"; 1127 request.url = GURL("http://www.foo.com/"); 1128 request.load_flags = 0; 1129 1130 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1131 scoped_ptr<HttpTransaction> trans( 1132 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1133 1134 MockRead data_reads[] = { 1135 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n" 1136 "HTTP/1.1 200 OK\r\n\r\n"), 1137 MockRead("hello world"), 1138 MockRead(SYNCHRONOUS, OK), 1139 }; 1140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1141 session_deps_.socket_factory->AddSocketDataProvider(&data); 1142 1143 TestCompletionCallback callback; 1144 1145 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1146 EXPECT_EQ(ERR_IO_PENDING, rv); 1147 1148 rv = callback.WaitForResult(); 1149 EXPECT_EQ(OK, rv); 1150 1151 const HttpResponseInfo* response = trans->GetResponseInfo(); 1152 ASSERT_TRUE(response != NULL); 1153 1154 EXPECT_TRUE(response->headers.get() != NULL); 1155 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1156 1157 std::string response_data; 1158 rv = ReadTransaction(trans.get(), &response_data); 1159 EXPECT_EQ(OK, rv); 1160 EXPECT_EQ("hello world", response_data); 1161 } 1162 1163 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) { 1164 HttpRequestInfo request; 1165 request.method = "POST"; 1166 request.url = GURL("http://www.foo.com/"); 1167 request.load_flags = 0; 1168 1169 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1170 scoped_ptr<HttpTransaction> trans( 1171 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1172 1173 MockRead data_reads[] = { 1174 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"), 1175 MockRead(ASYNC, 0), 1176 }; 1177 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1178 session_deps_.socket_factory->AddSocketDataProvider(&data); 1179 1180 TestCompletionCallback callback; 1181 1182 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1183 EXPECT_EQ(ERR_IO_PENDING, rv); 1184 1185 rv = callback.WaitForResult(); 1186 EXPECT_EQ(OK, rv); 1187 1188 std::string response_data; 1189 rv = ReadTransaction(trans.get(), &response_data); 1190 EXPECT_EQ(OK, rv); 1191 EXPECT_EQ("", response_data); 1192 } 1193 1194 TEST_P(HttpNetworkTransactionTest, EmptyResponse) { 1195 HttpRequestInfo request; 1196 request.method = "POST"; 1197 request.url = GURL("http://www.foo.com/"); 1198 request.load_flags = 0; 1199 1200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1201 scoped_ptr<HttpTransaction> trans( 1202 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1203 1204 1205 MockRead data_reads[] = { 1206 MockRead(ASYNC, 0), 1207 }; 1208 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1209 session_deps_.socket_factory->AddSocketDataProvider(&data); 1210 1211 TestCompletionCallback callback; 1212 1213 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1214 EXPECT_EQ(ERR_IO_PENDING, rv); 1215 1216 rv = callback.WaitForResult(); 1217 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); 1218 } 1219 1220 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest( 1221 const MockWrite* write_failure, 1222 const MockRead* read_failure) { 1223 HttpRequestInfo request; 1224 request.method = "GET"; 1225 request.url = GURL("http://www.foo.com/"); 1226 request.load_flags = 0; 1227 1228 CapturingNetLog net_log; 1229 session_deps_.net_log = &net_log; 1230 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1231 1232 // Written data for successfully sending both requests. 1233 MockWrite data1_writes[] = { 1234 MockWrite("GET / HTTP/1.1\r\n" 1235 "Host: www.foo.com\r\n" 1236 "Connection: keep-alive\r\n\r\n"), 1237 MockWrite("GET / HTTP/1.1\r\n" 1238 "Host: www.foo.com\r\n" 1239 "Connection: keep-alive\r\n\r\n") 1240 }; 1241 1242 // Read results for the first request. 1243 MockRead data1_reads[] = { 1244 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1245 MockRead("hello"), 1246 MockRead(ASYNC, OK), 1247 }; 1248 1249 if (write_failure) { 1250 ASSERT_FALSE(read_failure); 1251 data1_writes[1] = *write_failure; 1252 } else { 1253 ASSERT_TRUE(read_failure); 1254 data1_reads[2] = *read_failure; 1255 } 1256 1257 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), 1258 data1_writes, arraysize(data1_writes)); 1259 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1260 1261 MockRead data2_reads[] = { 1262 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1263 MockRead("world"), 1264 MockRead(ASYNC, OK), 1265 }; 1266 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 1267 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1268 1269 const char* kExpectedResponseData[] = { 1270 "hello", "world" 1271 }; 1272 1273 uint32 first_socket_log_id = NetLog::Source::kInvalidId; 1274 for (int i = 0; i < 2; ++i) { 1275 TestCompletionCallback callback; 1276 1277 scoped_ptr<HttpTransaction> trans( 1278 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1279 1280 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1281 EXPECT_EQ(ERR_IO_PENDING, rv); 1282 1283 rv = callback.WaitForResult(); 1284 EXPECT_EQ(OK, rv); 1285 1286 LoadTimingInfo load_timing_info; 1287 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1288 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 1289 if (i == 0) { 1290 first_socket_log_id = load_timing_info.socket_log_id; 1291 } else { 1292 // The second request should be using a new socket. 1293 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id); 1294 } 1295 1296 const HttpResponseInfo* response = trans->GetResponseInfo(); 1297 ASSERT_TRUE(response != NULL); 1298 1299 EXPECT_TRUE(response->headers.get() != NULL); 1300 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1301 1302 std::string response_data; 1303 rv = ReadTransaction(trans.get(), &response_data); 1304 EXPECT_EQ(OK, rv); 1305 EXPECT_EQ(kExpectedResponseData[i], response_data); 1306 } 1307 } 1308 1309 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest( 1310 const MockWrite* write_failure, 1311 const MockRead* read_failure, 1312 bool use_spdy) { 1313 HttpRequestInfo request; 1314 request.method = "GET"; 1315 request.url = GURL("https://www.foo.com/"); 1316 request.load_flags = 0; 1317 1318 CapturingNetLog net_log; 1319 session_deps_.net_log = &net_log; 1320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1321 1322 SSLSocketDataProvider ssl1(ASYNC, OK); 1323 SSLSocketDataProvider ssl2(ASYNC, OK); 1324 if (use_spdy) { 1325 ssl1.SetNextProto(GetParam()); 1326 ssl2.SetNextProto(GetParam()); 1327 } 1328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1); 1329 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 1330 1331 // SPDY versions of the request and response. 1332 scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet( 1333 request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY)); 1334 scoped_ptr<SpdyFrame> spdy_response( 1335 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1336 scoped_ptr<SpdyFrame> spdy_data( 1337 spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true)); 1338 1339 // HTTP/1.1 versions of the request and response. 1340 const char kHttpRequest[] = "GET / HTTP/1.1\r\n" 1341 "Host: www.foo.com\r\n" 1342 "Connection: keep-alive\r\n\r\n"; 1343 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"; 1344 const char kHttpData[] = "hello"; 1345 1346 std::vector<MockRead> data1_reads; 1347 std::vector<MockWrite> data1_writes; 1348 if (write_failure) { 1349 ASSERT_FALSE(read_failure); 1350 data1_writes.push_back(*write_failure); 1351 data1_reads.push_back(MockRead(ASYNC, OK)); 1352 } else { 1353 ASSERT_TRUE(read_failure); 1354 if (use_spdy) { 1355 data1_writes.push_back(CreateMockWrite(*spdy_request)); 1356 } else { 1357 data1_writes.push_back(MockWrite(kHttpRequest)); 1358 } 1359 data1_reads.push_back(*read_failure); 1360 } 1361 1362 StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(), 1363 &data1_writes[0], data1_writes.size()); 1364 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1365 1366 std::vector<MockRead> data2_reads; 1367 std::vector<MockWrite> data2_writes; 1368 1369 if (use_spdy) { 1370 data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC)); 1371 1372 data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC)); 1373 data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC)); 1374 data2_reads.push_back(MockRead(ASYNC, OK, 3)); 1375 } else { 1376 data2_writes.push_back( 1377 MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0)); 1378 1379 data2_reads.push_back( 1380 MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1)); 1381 data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2)); 1382 data2_reads.push_back(MockRead(ASYNC, OK, 3)); 1383 } 1384 OrderedSocketData data2(&data2_reads[0], data2_reads.size(), 1385 &data2_writes[0], data2_writes.size()); 1386 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1387 1388 // Preconnect a socket. 1389 net::SSLConfig ssl_config; 1390 session->ssl_config_service()->GetSSLConfig(&ssl_config); 1391 session->GetNextProtos(&ssl_config.next_protos); 1392 session->http_stream_factory()->PreconnectStreams( 1393 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config); 1394 // Wait for the preconnect to complete. 1395 // TODO(davidben): Some way to wait for an idle socket count might be handy. 1396 base::RunLoop().RunUntilIdle(); 1397 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 1398 1399 // Make the request. 1400 TestCompletionCallback callback; 1401 1402 scoped_ptr<HttpTransaction> trans( 1403 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1404 1405 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1406 EXPECT_EQ(ERR_IO_PENDING, rv); 1407 1408 rv = callback.WaitForResult(); 1409 EXPECT_EQ(OK, rv); 1410 1411 LoadTimingInfo load_timing_info; 1412 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1413 TestLoadTimingNotReused( 1414 load_timing_info, 1415 CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES); 1416 1417 const HttpResponseInfo* response = trans->GetResponseInfo(); 1418 ASSERT_TRUE(response != NULL); 1419 1420 EXPECT_TRUE(response->headers.get() != NULL); 1421 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1422 1423 std::string response_data; 1424 rv = ReadTransaction(trans.get(), &response_data); 1425 EXPECT_EQ(OK, rv); 1426 EXPECT_EQ(kHttpData, response_data); 1427 } 1428 1429 TEST_P(HttpNetworkTransactionTest, 1430 KeepAliveConnectionNotConnectedOnWrite) { 1431 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED); 1432 KeepAliveConnectionResendRequestTest(&write_failure, NULL); 1433 } 1434 1435 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) { 1436 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET); 1437 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1438 } 1439 1440 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) { 1441 MockRead read_failure(SYNCHRONOUS, OK); // EOF 1442 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1443 } 1444 1445 // Make sure that on a 408 response (Request Timeout), the request is retried, 1446 // if the socket was a reused keep alive socket. 1447 TEST_P(HttpNetworkTransactionTest, KeepAlive408) { 1448 MockRead read_failure(SYNCHRONOUS, 1449 "HTTP/1.1 408 Request Timeout\r\n" 1450 "Connection: Keep-Alive\r\n" 1451 "Content-Length: 6\r\n\r\n" 1452 "Pickle"); 1453 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1454 } 1455 1456 TEST_P(HttpNetworkTransactionTest, 1457 PreconnectErrorNotConnectedOnWrite) { 1458 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED); 1459 PreconnectErrorResendRequestTest(&write_failure, NULL, false); 1460 } 1461 1462 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) { 1463 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET); 1464 PreconnectErrorResendRequestTest(NULL, &read_failure, false); 1465 } 1466 1467 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) { 1468 MockRead read_failure(SYNCHRONOUS, OK); // EOF 1469 PreconnectErrorResendRequestTest(NULL, &read_failure, false); 1470 } 1471 1472 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) { 1473 MockRead read_failure(ASYNC, OK); // EOF 1474 PreconnectErrorResendRequestTest(NULL, &read_failure, false); 1475 } 1476 1477 // Make sure that on a 408 response (Request Timeout), the request is retried, 1478 // if the socket was a preconnected (UNUSED_IDLE) socket. 1479 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) { 1480 MockRead read_failure(SYNCHRONOUS, 1481 "HTTP/1.1 408 Request Timeout\r\n" 1482 "Connection: Keep-Alive\r\n" 1483 "Content-Length: 6\r\n\r\n" 1484 "Pickle"); 1485 KeepAliveConnectionResendRequestTest(NULL, &read_failure); 1486 PreconnectErrorResendRequestTest(NULL, &read_failure, false); 1487 } 1488 1489 TEST_P(HttpNetworkTransactionTest, 1490 SpdyPreconnectErrorNotConnectedOnWrite) { 1491 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED); 1492 PreconnectErrorResendRequestTest(&write_failure, NULL, true); 1493 } 1494 1495 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) { 1496 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET); 1497 PreconnectErrorResendRequestTest(NULL, &read_failure, true); 1498 } 1499 1500 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) { 1501 MockRead read_failure(SYNCHRONOUS, OK); // EOF 1502 PreconnectErrorResendRequestTest(NULL, &read_failure, true); 1503 } 1504 1505 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) { 1506 MockRead read_failure(ASYNC, OK); // EOF 1507 PreconnectErrorResendRequestTest(NULL, &read_failure, true); 1508 } 1509 1510 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) { 1511 HttpRequestInfo request; 1512 request.method = "GET"; 1513 request.url = GURL("http://www.google.com/"); 1514 request.load_flags = 0; 1515 1516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1517 scoped_ptr<HttpTransaction> trans( 1518 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1519 1520 MockRead data_reads[] = { 1521 MockRead(ASYNC, ERR_CONNECTION_RESET), 1522 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 1523 MockRead("hello world"), 1524 MockRead(SYNCHRONOUS, OK), 1525 }; 1526 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1527 session_deps_.socket_factory->AddSocketDataProvider(&data); 1528 1529 TestCompletionCallback callback; 1530 1531 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1532 EXPECT_EQ(ERR_IO_PENDING, rv); 1533 1534 rv = callback.WaitForResult(); 1535 EXPECT_EQ(ERR_CONNECTION_RESET, rv); 1536 1537 const HttpResponseInfo* response = trans->GetResponseInfo(); 1538 EXPECT_TRUE(response == NULL); 1539 } 1540 1541 // What do various browsers do when the server closes a non-keepalive 1542 // connection without sending any response header or body? 1543 // 1544 // IE7: error page 1545 // Safari 3.1.2 (Windows): error page 1546 // Firefox 3.0.1: blank page 1547 // Opera 9.52: after five attempts, blank page 1548 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE) 1549 // Us: error page (EMPTY_RESPONSE) 1550 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) { 1551 MockRead data_reads[] = { 1552 MockRead(SYNCHRONOUS, OK), // EOF 1553 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used 1554 MockRead("hello world"), 1555 MockRead(SYNCHRONOUS, OK), 1556 }; 1557 SimpleGetHelperResult out = SimpleGetHelper(data_reads, 1558 arraysize(data_reads)); 1559 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv); 1560 } 1561 1562 // Test that network access can be deferred and resumed. 1563 TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) { 1564 HttpRequestInfo request; 1565 request.method = "GET"; 1566 request.url = GURL("http://www.google.com/"); 1567 request.load_flags = 0; 1568 1569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1570 scoped_ptr<HttpTransaction> trans( 1571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1572 1573 // Defer on OnBeforeNetworkStart. 1574 BeforeNetworkStartHandler net_start_handler(true); // defer 1575 trans->SetBeforeNetworkStartCallback( 1576 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart, 1577 base::Unretained(&net_start_handler))); 1578 1579 MockRead data_reads[] = { 1580 MockRead("HTTP/1.0 200 OK\r\n"), 1581 MockRead("Content-Length: 5\r\n\r\n"), 1582 MockRead("hello"), 1583 MockRead(SYNCHRONOUS, 0), 1584 }; 1585 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1586 session_deps_.socket_factory->AddSocketDataProvider(&data); 1587 1588 TestCompletionCallback callback; 1589 1590 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1591 EXPECT_EQ(ERR_IO_PENDING, rv); 1592 base::MessageLoop::current()->RunUntilIdle(); 1593 1594 // Should have deferred for network start. 1595 EXPECT_TRUE(net_start_handler.observed_before_network_start()); 1596 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState()); 1597 EXPECT_TRUE(trans->GetResponseInfo() == NULL); 1598 1599 trans->ResumeNetworkStart(); 1600 rv = callback.WaitForResult(); 1601 EXPECT_EQ(OK, rv); 1602 EXPECT_TRUE(trans->GetResponseInfo() != NULL); 1603 1604 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1605 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1606 if (rv == ERR_IO_PENDING) 1607 rv = callback.WaitForResult(); 1608 EXPECT_EQ(5, rv); 1609 trans.reset(); 1610 } 1611 1612 // Test that network use can be deferred and canceled. 1613 TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) { 1614 HttpRequestInfo request; 1615 request.method = "GET"; 1616 request.url = GURL("http://www.google.com/"); 1617 request.load_flags = 0; 1618 1619 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1620 scoped_ptr<HttpTransaction> trans( 1621 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1622 1623 // Defer on OnBeforeNetworkStart. 1624 BeforeNetworkStartHandler net_start_handler(true); // defer 1625 trans->SetBeforeNetworkStartCallback( 1626 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart, 1627 base::Unretained(&net_start_handler))); 1628 1629 TestCompletionCallback callback; 1630 1631 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1632 EXPECT_EQ(ERR_IO_PENDING, rv); 1633 base::MessageLoop::current()->RunUntilIdle(); 1634 1635 // Should have deferred for network start. 1636 EXPECT_TRUE(net_start_handler.observed_before_network_start()); 1637 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState()); 1638 EXPECT_TRUE(trans->GetResponseInfo() == NULL); 1639 } 1640 1641 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression 1642 // tests. There was a bug causing HttpNetworkTransaction to hang in the 1643 // destructor in such situations. 1644 // See http://crbug.com/154712 and http://crbug.com/156609. 1645 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) { 1646 HttpRequestInfo request; 1647 request.method = "GET"; 1648 request.url = GURL("http://www.google.com/"); 1649 request.load_flags = 0; 1650 1651 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1652 scoped_ptr<HttpTransaction> trans( 1653 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1654 1655 MockRead data_reads[] = { 1656 MockRead("HTTP/1.0 200 OK\r\n"), 1657 MockRead("Connection: keep-alive\r\n"), 1658 MockRead("Content-Length: 100\r\n\r\n"), 1659 MockRead("hello"), 1660 MockRead(SYNCHRONOUS, 0), 1661 }; 1662 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1663 session_deps_.socket_factory->AddSocketDataProvider(&data); 1664 1665 TestCompletionCallback callback; 1666 1667 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1668 EXPECT_EQ(ERR_IO_PENDING, rv); 1669 1670 rv = callback.WaitForResult(); 1671 EXPECT_EQ(OK, rv); 1672 1673 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1674 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1675 if (rv == ERR_IO_PENDING) 1676 rv = callback.WaitForResult(); 1677 EXPECT_EQ(5, rv); 1678 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1679 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 1680 1681 trans.reset(); 1682 base::MessageLoop::current()->RunUntilIdle(); 1683 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 1684 } 1685 1686 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) { 1687 HttpRequestInfo request; 1688 request.method = "GET"; 1689 request.url = GURL("http://www.google.com/"); 1690 request.load_flags = 0; 1691 1692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1693 scoped_ptr<HttpTransaction> trans( 1694 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1695 1696 MockRead data_reads[] = { 1697 MockRead("HTTP/1.0 200 OK\r\n"), 1698 MockRead("Connection: keep-alive\r\n"), 1699 MockRead("Content-Length: 100\r\n\r\n"), 1700 MockRead(SYNCHRONOUS, 0), 1701 }; 1702 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 1703 session_deps_.socket_factory->AddSocketDataProvider(&data); 1704 1705 TestCompletionCallback callback; 1706 1707 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1708 EXPECT_EQ(ERR_IO_PENDING, rv); 1709 1710 rv = callback.WaitForResult(); 1711 EXPECT_EQ(OK, rv); 1712 1713 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); 1714 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); 1715 if (rv == ERR_IO_PENDING) 1716 rv = callback.WaitForResult(); 1717 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv); 1718 1719 trans.reset(); 1720 base::MessageLoop::current()->RunUntilIdle(); 1721 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 1722 } 1723 1724 // Test that we correctly reuse a keep-alive connection after not explicitly 1725 // reading the body. 1726 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { 1727 HttpRequestInfo request; 1728 request.method = "GET"; 1729 request.url = GURL("http://www.foo.com/"); 1730 request.load_flags = 0; 1731 1732 CapturingNetLog net_log; 1733 session_deps_.net_log = &net_log; 1734 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1735 1736 // Note that because all these reads happen in the same 1737 // StaticSocketDataProvider, it shows that the same socket is being reused for 1738 // all transactions. 1739 MockRead data1_reads[] = { 1740 MockRead("HTTP/1.1 204 No Content\r\n\r\n"), 1741 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"), 1742 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"), 1743 MockRead("HTTP/1.1 302 Found\r\n" 1744 "Content-Length: 0\r\n\r\n"), 1745 MockRead("HTTP/1.1 302 Found\r\n" 1746 "Content-Length: 5\r\n\r\n" 1747 "hello"), 1748 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 1749 "Content-Length: 0\r\n\r\n"), 1750 MockRead("HTTP/1.1 301 Moved Permanently\r\n" 1751 "Content-Length: 5\r\n\r\n" 1752 "hello"), 1753 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), 1754 MockRead("hello"), 1755 }; 1756 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0); 1757 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1758 1759 MockRead data2_reads[] = { 1760 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 1761 }; 1762 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); 1763 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1764 1765 const int kNumUnreadBodies = arraysize(data1_reads) - 2; 1766 std::string response_lines[kNumUnreadBodies]; 1767 1768 uint32 first_socket_log_id = NetLog::Source::kInvalidId; 1769 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) { 1770 TestCompletionCallback callback; 1771 1772 scoped_ptr<HttpTransaction> trans( 1773 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1774 1775 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1776 EXPECT_EQ(ERR_IO_PENDING, rv); 1777 1778 rv = callback.WaitForResult(); 1779 EXPECT_EQ(OK, rv); 1780 1781 LoadTimingInfo load_timing_info; 1782 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 1783 if (i == 0) { 1784 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES); 1785 first_socket_log_id = load_timing_info.socket_log_id; 1786 } else { 1787 TestLoadTimingReused(load_timing_info); 1788 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id); 1789 } 1790 1791 const HttpResponseInfo* response = trans->GetResponseInfo(); 1792 ASSERT_TRUE(response != NULL); 1793 1794 ASSERT_TRUE(response->headers.get() != NULL); 1795 response_lines[i] = response->headers->GetStatusLine(); 1796 1797 // We intentionally don't read the response bodies. 1798 } 1799 1800 const char* const kStatusLines[] = { 1801 "HTTP/1.1 204 No Content", 1802 "HTTP/1.1 205 Reset Content", 1803 "HTTP/1.1 304 Not Modified", 1804 "HTTP/1.1 302 Found", 1805 "HTTP/1.1 302 Found", 1806 "HTTP/1.1 301 Moved Permanently", 1807 "HTTP/1.1 301 Moved Permanently", 1808 }; 1809 1810 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines), 1811 forgot_to_update_kStatusLines); 1812 1813 for (int i = 0; i < kNumUnreadBodies; ++i) 1814 EXPECT_EQ(kStatusLines[i], response_lines[i]); 1815 1816 TestCompletionCallback callback; 1817 scoped_ptr<HttpTransaction> trans( 1818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 1819 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1820 EXPECT_EQ(ERR_IO_PENDING, rv); 1821 rv = callback.WaitForResult(); 1822 EXPECT_EQ(OK, rv); 1823 const HttpResponseInfo* response = trans->GetResponseInfo(); 1824 ASSERT_TRUE(response != NULL); 1825 ASSERT_TRUE(response->headers.get() != NULL); 1826 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 1827 std::string response_data; 1828 rv = ReadTransaction(trans.get(), &response_data); 1829 EXPECT_EQ(OK, rv); 1830 EXPECT_EQ("hello", response_data); 1831 } 1832 1833 // Test the request-challenge-retry sequence for basic auth. 1834 // (basic auth is the easiest to mock, because it has no randomness). 1835 TEST_P(HttpNetworkTransactionTest, BasicAuth) { 1836 HttpRequestInfo request; 1837 request.method = "GET"; 1838 request.url = GURL("http://www.google.com/"); 1839 request.load_flags = 0; 1840 1841 CapturingNetLog log; 1842 session_deps_.net_log = &log; 1843 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1844 scoped_ptr<HttpTransaction> trans( 1845 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1846 1847 MockWrite data_writes1[] = { 1848 MockWrite("GET / HTTP/1.1\r\n" 1849 "Host: www.google.com\r\n" 1850 "Connection: keep-alive\r\n\r\n"), 1851 }; 1852 1853 MockRead data_reads1[] = { 1854 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1855 // Give a couple authenticate options (only the middle one is actually 1856 // supported). 1857 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed. 1858 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1859 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 1860 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1861 // Large content-length -- won't matter, as connection will be reset. 1862 MockRead("Content-Length: 10000\r\n\r\n"), 1863 MockRead(SYNCHRONOUS, ERR_FAILED), 1864 }; 1865 1866 // After calling trans->RestartWithAuth(), this is the request we should 1867 // be issuing -- the final header line contains the credentials. 1868 MockWrite data_writes2[] = { 1869 MockWrite("GET / HTTP/1.1\r\n" 1870 "Host: www.google.com\r\n" 1871 "Connection: keep-alive\r\n" 1872 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 1873 }; 1874 1875 // Lastly, the server responds with the actual content. 1876 MockRead data_reads2[] = { 1877 MockRead("HTTP/1.0 200 OK\r\n"), 1878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1879 MockRead("Content-Length: 100\r\n\r\n"), 1880 MockRead(SYNCHRONOUS, OK), 1881 }; 1882 1883 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 1884 data_writes1, arraysize(data_writes1)); 1885 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 1886 data_writes2, arraysize(data_writes2)); 1887 session_deps_.socket_factory->AddSocketDataProvider(&data1); 1888 session_deps_.socket_factory->AddSocketDataProvider(&data2); 1889 1890 TestCompletionCallback callback1; 1891 1892 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 1893 EXPECT_EQ(ERR_IO_PENDING, rv); 1894 1895 rv = callback1.WaitForResult(); 1896 EXPECT_EQ(OK, rv); 1897 1898 LoadTimingInfo load_timing_info1; 1899 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); 1900 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); 1901 1902 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1)); 1903 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); 1904 1905 const HttpResponseInfo* response = trans->GetResponseInfo(); 1906 ASSERT_TRUE(response != NULL); 1907 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 1908 1909 TestCompletionCallback callback2; 1910 1911 rv = trans->RestartWithAuth( 1912 AuthCredentials(kFoo, kBar), callback2.callback()); 1913 EXPECT_EQ(ERR_IO_PENDING, rv); 1914 1915 rv = callback2.WaitForResult(); 1916 EXPECT_EQ(OK, rv); 1917 1918 LoadTimingInfo load_timing_info2; 1919 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); 1920 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES); 1921 // The load timing after restart should have a new socket ID, and times after 1922 // those of the first load timing. 1923 EXPECT_LE(load_timing_info1.receive_headers_end, 1924 load_timing_info2.connect_timing.connect_start); 1925 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 1926 1927 int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2)); 1928 EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes()); 1929 1930 response = trans->GetResponseInfo(); 1931 ASSERT_TRUE(response != NULL); 1932 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1933 EXPECT_EQ(100, response->headers->GetContentLength()); 1934 } 1935 1936 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { 1937 HttpRequestInfo request; 1938 request.method = "GET"; 1939 request.url = GURL("http://www.google.com/"); 1940 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 1941 1942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1943 scoped_ptr<HttpTransaction> trans( 1944 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 1945 1946 MockWrite data_writes[] = { 1947 MockWrite("GET / HTTP/1.1\r\n" 1948 "Host: www.google.com\r\n" 1949 "Connection: keep-alive\r\n\r\n"), 1950 }; 1951 1952 MockRead data_reads[] = { 1953 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 1954 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 1955 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 1956 // Large content-length -- won't matter, as connection will be reset. 1957 MockRead("Content-Length: 10000\r\n\r\n"), 1958 MockRead(SYNCHRONOUS, ERR_FAILED), 1959 }; 1960 1961 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 1962 data_writes, arraysize(data_writes)); 1963 session_deps_.socket_factory->AddSocketDataProvider(&data); 1964 TestCompletionCallback callback; 1965 1966 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 1967 EXPECT_EQ(ERR_IO_PENDING, rv); 1968 1969 rv = callback.WaitForResult(); 1970 EXPECT_EQ(0, rv); 1971 1972 int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); 1973 EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes()); 1974 1975 const HttpResponseInfo* response = trans->GetResponseInfo(); 1976 ASSERT_TRUE(response != NULL); 1977 EXPECT_TRUE(response->auth_challenge.get() == NULL); 1978 } 1979 1980 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 1981 // connection. 1982 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) { 1983 HttpRequestInfo request; 1984 request.method = "GET"; 1985 request.url = GURL("http://www.google.com/"); 1986 request.load_flags = 0; 1987 1988 CapturingNetLog log; 1989 session_deps_.net_log = &log; 1990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 1991 1992 MockWrite data_writes1[] = { 1993 MockWrite("GET / HTTP/1.1\r\n" 1994 "Host: www.google.com\r\n" 1995 "Connection: keep-alive\r\n\r\n"), 1996 1997 // After calling trans->RestartWithAuth(), this is the request we should 1998 // be issuing -- the final header line contains the credentials. 1999 MockWrite("GET / HTTP/1.1\r\n" 2000 "Host: www.google.com\r\n" 2001 "Connection: keep-alive\r\n" 2002 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2003 }; 2004 2005 MockRead data_reads1[] = { 2006 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 2007 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2008 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2009 MockRead("Content-Length: 14\r\n\r\n"), 2010 MockRead("Unauthorized\r\n"), 2011 2012 // Lastly, the server responds with the actual content. 2013 MockRead("HTTP/1.1 200 OK\r\n"), 2014 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2015 MockRead("Content-Length: 5\r\n\r\n"), 2016 MockRead("Hello"), 2017 }; 2018 2019 // If there is a regression where we disconnect a Keep-Alive 2020 // connection during an auth roundtrip, we'll end up reading this. 2021 MockRead data_reads2[] = { 2022 MockRead(SYNCHRONOUS, ERR_FAILED), 2023 }; 2024 2025 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2026 data_writes1, arraysize(data_writes1)); 2027 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2028 NULL, 0); 2029 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2030 session_deps_.socket_factory->AddSocketDataProvider(&data2); 2031 2032 TestCompletionCallback callback1; 2033 2034 scoped_ptr<HttpTransaction> trans( 2035 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2036 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 2037 EXPECT_EQ(ERR_IO_PENDING, rv); 2038 2039 rv = callback1.WaitForResult(); 2040 EXPECT_EQ(OK, rv); 2041 2042 LoadTimingInfo load_timing_info1; 2043 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); 2044 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); 2045 2046 const HttpResponseInfo* response = trans->GetResponseInfo(); 2047 ASSERT_TRUE(response != NULL); 2048 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 2049 2050 TestCompletionCallback callback2; 2051 2052 rv = trans->RestartWithAuth( 2053 AuthCredentials(kFoo, kBar), callback2.callback()); 2054 EXPECT_EQ(ERR_IO_PENDING, rv); 2055 2056 rv = callback2.WaitForResult(); 2057 EXPECT_EQ(OK, rv); 2058 2059 LoadTimingInfo load_timing_info2; 2060 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); 2061 TestLoadTimingReused(load_timing_info2); 2062 // The load timing after restart should have the same socket ID, and times 2063 // those of the first load timing. 2064 EXPECT_LE(load_timing_info1.receive_headers_end, 2065 load_timing_info2.send_start); 2066 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2067 2068 response = trans->GetResponseInfo(); 2069 ASSERT_TRUE(response != NULL); 2070 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2071 EXPECT_EQ(5, response->headers->GetContentLength()); 2072 2073 std::string response_data; 2074 rv = ReadTransaction(trans.get(), &response_data); 2075 EXPECT_EQ(OK, rv); 2076 int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1)); 2077 EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); 2078 } 2079 2080 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 2081 // connection and with no response body to drain. 2082 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) { 2083 HttpRequestInfo request; 2084 request.method = "GET"; 2085 request.url = GURL("http://www.google.com/"); 2086 request.load_flags = 0; 2087 2088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2089 2090 MockWrite data_writes1[] = { 2091 MockWrite("GET / HTTP/1.1\r\n" 2092 "Host: www.google.com\r\n" 2093 "Connection: keep-alive\r\n\r\n"), 2094 2095 // After calling trans->RestartWithAuth(), this is the request we should 2096 // be issuing -- the final header line contains the credentials. 2097 MockWrite("GET / HTTP/1.1\r\n" 2098 "Host: www.google.com\r\n" 2099 "Connection: keep-alive\r\n" 2100 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2101 }; 2102 2103 MockRead data_reads1[] = { 2104 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 2105 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2106 MockRead("Content-Length: 0\r\n\r\n"), // No response body. 2107 2108 // Lastly, the server responds with the actual content. 2109 MockRead("HTTP/1.1 200 OK\r\n"), 2110 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2111 MockRead("Content-Length: 5\r\n\r\n"), 2112 MockRead("hello"), 2113 }; 2114 2115 // An incorrect reconnect would cause this to be read. 2116 MockRead data_reads2[] = { 2117 MockRead(SYNCHRONOUS, ERR_FAILED), 2118 }; 2119 2120 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2121 data_writes1, arraysize(data_writes1)); 2122 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2123 NULL, 0); 2124 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2125 session_deps_.socket_factory->AddSocketDataProvider(&data2); 2126 2127 TestCompletionCallback callback1; 2128 2129 scoped_ptr<HttpTransaction> trans( 2130 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2131 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 2132 EXPECT_EQ(ERR_IO_PENDING, rv); 2133 2134 rv = callback1.WaitForResult(); 2135 EXPECT_EQ(OK, rv); 2136 2137 const HttpResponseInfo* response = trans->GetResponseInfo(); 2138 ASSERT_TRUE(response != NULL); 2139 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 2140 2141 TestCompletionCallback callback2; 2142 2143 rv = trans->RestartWithAuth( 2144 AuthCredentials(kFoo, kBar), callback2.callback()); 2145 EXPECT_EQ(ERR_IO_PENDING, rv); 2146 2147 rv = callback2.WaitForResult(); 2148 EXPECT_EQ(OK, rv); 2149 2150 response = trans->GetResponseInfo(); 2151 ASSERT_TRUE(response != NULL); 2152 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2153 EXPECT_EQ(5, response->headers->GetContentLength()); 2154 } 2155 2156 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 2157 // connection and with a large response body to drain. 2158 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) { 2159 HttpRequestInfo request; 2160 request.method = "GET"; 2161 request.url = GURL("http://www.google.com/"); 2162 request.load_flags = 0; 2163 2164 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2165 2166 MockWrite data_writes1[] = { 2167 MockWrite("GET / HTTP/1.1\r\n" 2168 "Host: www.google.com\r\n" 2169 "Connection: keep-alive\r\n\r\n"), 2170 2171 // After calling trans->RestartWithAuth(), this is the request we should 2172 // be issuing -- the final header line contains the credentials. 2173 MockWrite("GET / HTTP/1.1\r\n" 2174 "Host: www.google.com\r\n" 2175 "Connection: keep-alive\r\n" 2176 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2177 }; 2178 2179 // Respond with 5 kb of response body. 2180 std::string large_body_string("Unauthorized"); 2181 large_body_string.append(5 * 1024, ' '); 2182 large_body_string.append("\r\n"); 2183 2184 MockRead data_reads1[] = { 2185 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 2186 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2187 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2188 // 5134 = 12 + 5 * 1024 + 2 2189 MockRead("Content-Length: 5134\r\n\r\n"), 2190 MockRead(ASYNC, large_body_string.data(), large_body_string.size()), 2191 2192 // Lastly, the server responds with the actual content. 2193 MockRead("HTTP/1.1 200 OK\r\n"), 2194 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2195 MockRead("Content-Length: 5\r\n\r\n"), 2196 MockRead("hello"), 2197 }; 2198 2199 // An incorrect reconnect would cause this to be read. 2200 MockRead data_reads2[] = { 2201 MockRead(SYNCHRONOUS, ERR_FAILED), 2202 }; 2203 2204 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2205 data_writes1, arraysize(data_writes1)); 2206 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2207 NULL, 0); 2208 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2209 session_deps_.socket_factory->AddSocketDataProvider(&data2); 2210 2211 TestCompletionCallback callback1; 2212 2213 scoped_ptr<HttpTransaction> trans( 2214 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2215 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 2216 EXPECT_EQ(ERR_IO_PENDING, rv); 2217 2218 rv = callback1.WaitForResult(); 2219 EXPECT_EQ(OK, rv); 2220 2221 const HttpResponseInfo* response = trans->GetResponseInfo(); 2222 ASSERT_TRUE(response != NULL); 2223 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 2224 2225 TestCompletionCallback callback2; 2226 2227 rv = trans->RestartWithAuth( 2228 AuthCredentials(kFoo, kBar), callback2.callback()); 2229 EXPECT_EQ(ERR_IO_PENDING, rv); 2230 2231 rv = callback2.WaitForResult(); 2232 EXPECT_EQ(OK, rv); 2233 2234 response = trans->GetResponseInfo(); 2235 ASSERT_TRUE(response != NULL); 2236 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2237 EXPECT_EQ(5, response->headers->GetContentLength()); 2238 } 2239 2240 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 2241 // connection, but the server gets impatient and closes the connection. 2242 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) { 2243 HttpRequestInfo request; 2244 request.method = "GET"; 2245 request.url = GURL("http://www.google.com/"); 2246 request.load_flags = 0; 2247 2248 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2249 2250 MockWrite data_writes1[] = { 2251 MockWrite("GET / HTTP/1.1\r\n" 2252 "Host: www.google.com\r\n" 2253 "Connection: keep-alive\r\n\r\n"), 2254 // This simulates the seemingly successful write to a closed connection 2255 // if the bug is not fixed. 2256 MockWrite("GET / HTTP/1.1\r\n" 2257 "Host: www.google.com\r\n" 2258 "Connection: keep-alive\r\n" 2259 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2260 }; 2261 2262 MockRead data_reads1[] = { 2263 MockRead("HTTP/1.1 401 Unauthorized\r\n"), 2264 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2265 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2266 MockRead("Content-Length: 14\r\n\r\n"), 2267 // Tell MockTCPClientSocket to simulate the server closing the connection. 2268 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 2269 MockRead("Unauthorized\r\n"), 2270 MockRead(SYNCHRONOUS, OK), // The server closes the connection. 2271 }; 2272 2273 // After calling trans->RestartWithAuth(), this is the request we should 2274 // be issuing -- the final header line contains the credentials. 2275 MockWrite data_writes2[] = { 2276 MockWrite("GET / HTTP/1.1\r\n" 2277 "Host: www.google.com\r\n" 2278 "Connection: keep-alive\r\n" 2279 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2280 }; 2281 2282 // Lastly, the server responds with the actual content. 2283 MockRead data_reads2[] = { 2284 MockRead("HTTP/1.1 200 OK\r\n"), 2285 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2286 MockRead("Content-Length: 5\r\n\r\n"), 2287 MockRead("hello"), 2288 }; 2289 2290 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2291 data_writes1, arraysize(data_writes1)); 2292 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 2293 data_writes2, arraysize(data_writes2)); 2294 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2295 session_deps_.socket_factory->AddSocketDataProvider(&data2); 2296 2297 TestCompletionCallback callback1; 2298 2299 scoped_ptr<HttpTransaction> trans( 2300 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2301 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 2302 EXPECT_EQ(ERR_IO_PENDING, rv); 2303 2304 rv = callback1.WaitForResult(); 2305 EXPECT_EQ(OK, rv); 2306 2307 const HttpResponseInfo* response = trans->GetResponseInfo(); 2308 ASSERT_TRUE(response != NULL); 2309 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 2310 2311 TestCompletionCallback callback2; 2312 2313 rv = trans->RestartWithAuth( 2314 AuthCredentials(kFoo, kBar), callback2.callback()); 2315 EXPECT_EQ(ERR_IO_PENDING, rv); 2316 2317 rv = callback2.WaitForResult(); 2318 EXPECT_EQ(OK, rv); 2319 2320 response = trans->GetResponseInfo(); 2321 ASSERT_TRUE(response != NULL); 2322 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2323 EXPECT_EQ(5, response->headers->GetContentLength()); 2324 } 2325 2326 // Test the request-challenge-retry sequence for basic auth, over a connection 2327 // that requires a restart when setting up an SSL tunnel. 2328 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) { 2329 HttpRequestInfo request; 2330 request.method = "GET"; 2331 request.url = GURL("https://www.google.com/"); 2332 // when the no authentication data flag is set. 2333 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 2334 2335 // Configure against proxy server "myproxy:70". 2336 session_deps_.proxy_service.reset( 2337 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 2338 CapturingBoundNetLog log; 2339 session_deps_.net_log = log.bound().net_log(); 2340 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2341 2342 // Since we have proxy, should try to establish tunnel. 2343 MockWrite data_writes1[] = { 2344 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2345 "Host: www.google.com\r\n" 2346 "Proxy-Connection: keep-alive\r\n\r\n"), 2347 2348 // After calling trans->RestartWithAuth(), this is the request we should 2349 // be issuing -- the final header line contains the credentials. 2350 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2351 "Host: www.google.com\r\n" 2352 "Proxy-Connection: keep-alive\r\n" 2353 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 2354 2355 MockWrite("GET / HTTP/1.1\r\n" 2356 "Host: www.google.com\r\n" 2357 "Connection: keep-alive\r\n\r\n"), 2358 }; 2359 2360 // The proxy responds to the connect with a 407, using a persistent 2361 // connection. 2362 MockRead data_reads1[] = { 2363 // No credentials. 2364 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2365 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2366 MockRead("Proxy-Connection: close\r\n\r\n"), 2367 2368 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2369 2370 MockRead("HTTP/1.1 200 OK\r\n"), 2371 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2372 MockRead("Content-Length: 5\r\n\r\n"), 2373 MockRead(SYNCHRONOUS, "hello"), 2374 }; 2375 2376 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2377 data_writes1, arraysize(data_writes1)); 2378 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2379 SSLSocketDataProvider ssl(ASYNC, OK); 2380 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2381 2382 TestCompletionCallback callback1; 2383 2384 scoped_ptr<HttpTransaction> trans( 2385 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2386 2387 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2388 EXPECT_EQ(ERR_IO_PENDING, rv); 2389 2390 rv = callback1.WaitForResult(); 2391 EXPECT_EQ(OK, rv); 2392 net::CapturingNetLog::CapturedEntryList entries; 2393 log.GetEntries(&entries); 2394 size_t pos = ExpectLogContainsSomewhere( 2395 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2396 NetLog::PHASE_NONE); 2397 ExpectLogContainsSomewhere( 2398 entries, pos, 2399 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2400 NetLog::PHASE_NONE); 2401 2402 const HttpResponseInfo* response = trans->GetResponseInfo(); 2403 ASSERT_TRUE(response != NULL); 2404 ASSERT_FALSE(response->headers.get() == NULL); 2405 EXPECT_EQ(407, response->headers->response_code()); 2406 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2407 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2408 2409 LoadTimingInfo load_timing_info; 2410 // CONNECT requests and responses are handled at the connect job level, so 2411 // the transaction does not yet have a connection. 2412 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info)); 2413 2414 TestCompletionCallback callback2; 2415 2416 rv = trans->RestartWithAuth( 2417 AuthCredentials(kFoo, kBar), callback2.callback()); 2418 EXPECT_EQ(ERR_IO_PENDING, rv); 2419 2420 rv = callback2.WaitForResult(); 2421 EXPECT_EQ(OK, rv); 2422 2423 response = trans->GetResponseInfo(); 2424 ASSERT_TRUE(response != NULL); 2425 2426 EXPECT_TRUE(response->headers->IsKeepAlive()); 2427 EXPECT_EQ(200, response->headers->response_code()); 2428 EXPECT_EQ(5, response->headers->GetContentLength()); 2429 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2430 2431 // The password prompt info should not be set. 2432 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2433 2434 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2435 TestLoadTimingNotReusedWithPac(load_timing_info, 2436 CONNECT_TIMING_HAS_SSL_TIMES); 2437 2438 trans.reset(); 2439 session->CloseAllConnections(); 2440 } 2441 2442 // Test the request-challenge-retry sequence for basic auth, over a keep-alive 2443 // proxy connection, when setting up an SSL tunnel. 2444 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) { 2445 HttpRequestInfo request; 2446 request.method = "GET"; 2447 request.url = GURL("https://www.google.com/"); 2448 // Ensure that proxy authentication is attempted even 2449 // when the no authentication data flag is set. 2450 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 2451 2452 // Configure against proxy server "myproxy:70". 2453 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2454 CapturingBoundNetLog log; 2455 session_deps_.net_log = log.bound().net_log(); 2456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2457 2458 scoped_ptr<HttpTransaction> trans( 2459 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2460 2461 // Since we have proxy, should try to establish tunnel. 2462 MockWrite data_writes1[] = { 2463 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2464 "Host: www.google.com\r\n" 2465 "Proxy-Connection: keep-alive\r\n\r\n"), 2466 2467 // After calling trans->RestartWithAuth(), this is the request we should 2468 // be issuing -- the final header line contains the credentials. 2469 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2470 "Host: www.google.com\r\n" 2471 "Proxy-Connection: keep-alive\r\n" 2472 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 2473 }; 2474 2475 // The proxy responds to the connect with a 407, using a persistent 2476 // connection. 2477 MockRead data_reads1[] = { 2478 // No credentials. 2479 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2480 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2481 MockRead("Content-Length: 10\r\n\r\n"), 2482 MockRead("0123456789"), 2483 2484 // Wrong credentials (wrong password). 2485 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2486 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2487 MockRead("Content-Length: 10\r\n\r\n"), 2488 // No response body because the test stops reading here. 2489 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 2490 }; 2491 2492 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2493 data_writes1, arraysize(data_writes1)); 2494 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2495 2496 TestCompletionCallback callback1; 2497 2498 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2499 EXPECT_EQ(ERR_IO_PENDING, rv); 2500 2501 rv = callback1.WaitForResult(); 2502 EXPECT_EQ(OK, rv); 2503 net::CapturingNetLog::CapturedEntryList entries; 2504 log.GetEntries(&entries); 2505 size_t pos = ExpectLogContainsSomewhere( 2506 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2507 NetLog::PHASE_NONE); 2508 ExpectLogContainsSomewhere( 2509 entries, pos, 2510 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2511 NetLog::PHASE_NONE); 2512 2513 const HttpResponseInfo* response = trans->GetResponseInfo(); 2514 ASSERT_TRUE(response != NULL); 2515 ASSERT_FALSE(response->headers.get() == NULL); 2516 EXPECT_TRUE(response->headers->IsKeepAlive()); 2517 EXPECT_EQ(407, response->headers->response_code()); 2518 EXPECT_EQ(10, response->headers->GetContentLength()); 2519 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2520 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2521 2522 TestCompletionCallback callback2; 2523 2524 // Wrong password (should be "bar"). 2525 rv = trans->RestartWithAuth( 2526 AuthCredentials(kFoo, kBaz), callback2.callback()); 2527 EXPECT_EQ(ERR_IO_PENDING, rv); 2528 2529 rv = callback2.WaitForResult(); 2530 EXPECT_EQ(OK, rv); 2531 2532 response = trans->GetResponseInfo(); 2533 ASSERT_TRUE(response != NULL); 2534 ASSERT_FALSE(response->headers.get() == NULL); 2535 EXPECT_TRUE(response->headers->IsKeepAlive()); 2536 EXPECT_EQ(407, response->headers->response_code()); 2537 EXPECT_EQ(10, response->headers->GetContentLength()); 2538 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2539 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 2540 2541 // Flush the idle socket before the NetLog and HttpNetworkTransaction go 2542 // out of scope. 2543 session->CloseAllConnections(); 2544 } 2545 2546 // Test that we don't read the response body when we fail to establish a tunnel, 2547 // even if the user cancels the proxy's auth attempt. 2548 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) { 2549 HttpRequestInfo request; 2550 request.method = "GET"; 2551 request.url = GURL("https://www.google.com/"); 2552 request.load_flags = 0; 2553 2554 // Configure against proxy server "myproxy:70". 2555 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2556 2557 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2558 2559 scoped_ptr<HttpTransaction> trans( 2560 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2561 2562 // Since we have proxy, should try to establish tunnel. 2563 MockWrite data_writes[] = { 2564 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2565 "Host: www.google.com\r\n" 2566 "Proxy-Connection: keep-alive\r\n\r\n"), 2567 }; 2568 2569 // The proxy responds to the connect with a 407. 2570 MockRead data_reads[] = { 2571 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 2572 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2573 MockRead("Content-Length: 10\r\n\r\n"), 2574 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 2575 }; 2576 2577 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 2578 data_writes, arraysize(data_writes)); 2579 session_deps_.socket_factory->AddSocketDataProvider(&data); 2580 2581 TestCompletionCallback callback; 2582 2583 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 2584 EXPECT_EQ(ERR_IO_PENDING, rv); 2585 2586 rv = callback.WaitForResult(); 2587 EXPECT_EQ(OK, rv); 2588 2589 const HttpResponseInfo* response = trans->GetResponseInfo(); 2590 ASSERT_TRUE(response != NULL); 2591 2592 EXPECT_TRUE(response->headers->IsKeepAlive()); 2593 EXPECT_EQ(407, response->headers->response_code()); 2594 EXPECT_EQ(10, response->headers->GetContentLength()); 2595 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2596 2597 std::string response_data; 2598 rv = ReadTransaction(trans.get(), &response_data); 2599 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 2600 2601 // Flush the idle socket before the HttpNetworkTransaction goes out of scope. 2602 session->CloseAllConnections(); 2603 } 2604 2605 // Test when a server (non-proxy) returns a 407 (proxy-authenticate). 2606 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH. 2607 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) { 2608 HttpRequestInfo request; 2609 request.method = "GET"; 2610 request.url = GURL("http://www.google.com/"); 2611 request.load_flags = 0; 2612 2613 // We are using a DIRECT connection (i.e. no proxy) for this session. 2614 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2615 scoped_ptr<HttpTransaction> trans( 2616 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 2617 2618 MockWrite data_writes1[] = { 2619 MockWrite("GET / HTTP/1.1\r\n" 2620 "Host: www.google.com\r\n" 2621 "Connection: keep-alive\r\n\r\n"), 2622 }; 2623 2624 MockRead data_reads1[] = { 2625 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"), 2626 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2627 // Large content-length -- won't matter, as connection will be reset. 2628 MockRead("Content-Length: 10000\r\n\r\n"), 2629 MockRead(SYNCHRONOUS, ERR_FAILED), 2630 }; 2631 2632 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2633 data_writes1, arraysize(data_writes1)); 2634 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2635 2636 TestCompletionCallback callback; 2637 2638 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 2639 EXPECT_EQ(ERR_IO_PENDING, rv); 2640 2641 rv = callback.WaitForResult(); 2642 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 2643 } 2644 2645 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication) 2646 // through a non-authenticating proxy. The request should fail with 2647 // ERR_UNEXPECTED_PROXY_AUTH. 2648 // Note that it is impossible to detect if an HTTP server returns a 407 through 2649 // a non-authenticating proxy - there is nothing to indicate whether the 2650 // response came from the proxy or the server, so it is treated as if the proxy 2651 // issued the challenge. 2652 TEST_P(HttpNetworkTransactionTest, 2653 HttpsServerRequestsProxyAuthThroughProxy) { 2654 HttpRequestInfo request; 2655 request.method = "GET"; 2656 request.url = GURL("https://www.google.com/"); 2657 2658 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 2659 CapturingBoundNetLog log; 2660 session_deps_.net_log = log.bound().net_log(); 2661 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2662 2663 // Since we have proxy, should try to establish tunnel. 2664 MockWrite data_writes1[] = { 2665 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2666 "Host: www.google.com\r\n" 2667 "Proxy-Connection: keep-alive\r\n\r\n"), 2668 2669 MockWrite("GET / HTTP/1.1\r\n" 2670 "Host: www.google.com\r\n" 2671 "Connection: keep-alive\r\n\r\n"), 2672 }; 2673 2674 MockRead data_reads1[] = { 2675 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2676 2677 MockRead("HTTP/1.1 407 Unauthorized\r\n"), 2678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 2679 MockRead("\r\n"), 2680 MockRead(SYNCHRONOUS, OK), 2681 }; 2682 2683 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2684 data_writes1, arraysize(data_writes1)); 2685 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2686 SSLSocketDataProvider ssl(ASYNC, OK); 2687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2688 2689 TestCompletionCallback callback1; 2690 2691 scoped_ptr<HttpTransaction> trans( 2692 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2693 2694 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2695 EXPECT_EQ(ERR_IO_PENDING, rv); 2696 2697 rv = callback1.WaitForResult(); 2698 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); 2699 net::CapturingNetLog::CapturedEntryList entries; 2700 log.GetEntries(&entries); 2701 size_t pos = ExpectLogContainsSomewhere( 2702 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 2703 NetLog::PHASE_NONE); 2704 ExpectLogContainsSomewhere( 2705 entries, pos, 2706 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 2707 NetLog::PHASE_NONE); 2708 } 2709 2710 // Test the load timing for HTTPS requests with an HTTP proxy. 2711 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) { 2712 HttpRequestInfo request1; 2713 request1.method = "GET"; 2714 request1.url = GURL("https://www.google.com/1"); 2715 2716 HttpRequestInfo request2; 2717 request2.method = "GET"; 2718 request2.url = GURL("https://www.google.com/2"); 2719 2720 // Configure against proxy server "myproxy:70". 2721 session_deps_.proxy_service.reset( 2722 ProxyService::CreateFixed("PROXY myproxy:70")); 2723 CapturingBoundNetLog log; 2724 session_deps_.net_log = log.bound().net_log(); 2725 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2726 2727 // Since we have proxy, should try to establish tunnel. 2728 MockWrite data_writes1[] = { 2729 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2730 "Host: www.google.com\r\n" 2731 "Proxy-Connection: keep-alive\r\n\r\n"), 2732 2733 MockWrite("GET /1 HTTP/1.1\r\n" 2734 "Host: www.google.com\r\n" 2735 "Connection: keep-alive\r\n\r\n"), 2736 2737 MockWrite("GET /2 HTTP/1.1\r\n" 2738 "Host: www.google.com\r\n" 2739 "Connection: keep-alive\r\n\r\n"), 2740 }; 2741 2742 // The proxy responds to the connect with a 407, using a persistent 2743 // connection. 2744 MockRead data_reads1[] = { 2745 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2746 2747 MockRead("HTTP/1.1 200 OK\r\n"), 2748 MockRead("Content-Length: 1\r\n\r\n"), 2749 MockRead(SYNCHRONOUS, "1"), 2750 2751 MockRead("HTTP/1.1 200 OK\r\n"), 2752 MockRead("Content-Length: 2\r\n\r\n"), 2753 MockRead(SYNCHRONOUS, "22"), 2754 }; 2755 2756 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2757 data_writes1, arraysize(data_writes1)); 2758 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2759 SSLSocketDataProvider ssl(ASYNC, OK); 2760 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2761 2762 TestCompletionCallback callback1; 2763 scoped_ptr<HttpTransaction> trans1( 2764 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2765 2766 int rv = trans1->Start(&request1, callback1.callback(), log.bound()); 2767 EXPECT_EQ(ERR_IO_PENDING, rv); 2768 2769 rv = callback1.WaitForResult(); 2770 EXPECT_EQ(OK, rv); 2771 2772 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 2773 ASSERT_TRUE(response1 != NULL); 2774 ASSERT_TRUE(response1->headers.get() != NULL); 2775 EXPECT_EQ(1, response1->headers->GetContentLength()); 2776 2777 LoadTimingInfo load_timing_info1; 2778 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1)); 2779 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES); 2780 2781 trans1.reset(); 2782 2783 TestCompletionCallback callback2; 2784 scoped_ptr<HttpTransaction> trans2( 2785 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2786 2787 rv = trans2->Start(&request2, callback2.callback(), log.bound()); 2788 EXPECT_EQ(ERR_IO_PENDING, rv); 2789 2790 rv = callback2.WaitForResult(); 2791 EXPECT_EQ(OK, rv); 2792 2793 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 2794 ASSERT_TRUE(response2 != NULL); 2795 ASSERT_TRUE(response2->headers.get() != NULL); 2796 EXPECT_EQ(2, response2->headers->GetContentLength()); 2797 2798 LoadTimingInfo load_timing_info2; 2799 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 2800 TestLoadTimingReused(load_timing_info2); 2801 2802 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2803 2804 trans2.reset(); 2805 session->CloseAllConnections(); 2806 } 2807 2808 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script. 2809 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) { 2810 HttpRequestInfo request1; 2811 request1.method = "GET"; 2812 request1.url = GURL("https://www.google.com/1"); 2813 2814 HttpRequestInfo request2; 2815 request2.method = "GET"; 2816 request2.url = GURL("https://www.google.com/2"); 2817 2818 // Configure against proxy server "myproxy:70". 2819 session_deps_.proxy_service.reset( 2820 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); 2821 CapturingBoundNetLog log; 2822 session_deps_.net_log = log.bound().net_log(); 2823 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2824 2825 // Since we have proxy, should try to establish tunnel. 2826 MockWrite data_writes1[] = { 2827 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 2828 "Host: www.google.com\r\n" 2829 "Proxy-Connection: keep-alive\r\n\r\n"), 2830 2831 MockWrite("GET /1 HTTP/1.1\r\n" 2832 "Host: www.google.com\r\n" 2833 "Connection: keep-alive\r\n\r\n"), 2834 2835 MockWrite("GET /2 HTTP/1.1\r\n" 2836 "Host: www.google.com\r\n" 2837 "Connection: keep-alive\r\n\r\n"), 2838 }; 2839 2840 // The proxy responds to the connect with a 407, using a persistent 2841 // connection. 2842 MockRead data_reads1[] = { 2843 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), 2844 2845 MockRead("HTTP/1.1 200 OK\r\n"), 2846 MockRead("Content-Length: 1\r\n\r\n"), 2847 MockRead(SYNCHRONOUS, "1"), 2848 2849 MockRead("HTTP/1.1 200 OK\r\n"), 2850 MockRead("Content-Length: 2\r\n\r\n"), 2851 MockRead(SYNCHRONOUS, "22"), 2852 }; 2853 2854 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2855 data_writes1, arraysize(data_writes1)); 2856 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2857 SSLSocketDataProvider ssl(ASYNC, OK); 2858 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2859 2860 TestCompletionCallback callback1; 2861 scoped_ptr<HttpTransaction> trans1( 2862 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2863 2864 int rv = trans1->Start(&request1, callback1.callback(), log.bound()); 2865 EXPECT_EQ(ERR_IO_PENDING, rv); 2866 2867 rv = callback1.WaitForResult(); 2868 EXPECT_EQ(OK, rv); 2869 2870 const HttpResponseInfo* response1 = trans1->GetResponseInfo(); 2871 ASSERT_TRUE(response1 != NULL); 2872 ASSERT_TRUE(response1->headers.get() != NULL); 2873 EXPECT_EQ(1, response1->headers->GetContentLength()); 2874 2875 LoadTimingInfo load_timing_info1; 2876 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1)); 2877 TestLoadTimingNotReusedWithPac(load_timing_info1, 2878 CONNECT_TIMING_HAS_SSL_TIMES); 2879 2880 trans1.reset(); 2881 2882 TestCompletionCallback callback2; 2883 scoped_ptr<HttpTransaction> trans2( 2884 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2885 2886 rv = trans2->Start(&request2, callback2.callback(), log.bound()); 2887 EXPECT_EQ(ERR_IO_PENDING, rv); 2888 2889 rv = callback2.WaitForResult(); 2890 EXPECT_EQ(OK, rv); 2891 2892 const HttpResponseInfo* response2 = trans2->GetResponseInfo(); 2893 ASSERT_TRUE(response2 != NULL); 2894 ASSERT_TRUE(response2->headers.get() != NULL); 2895 EXPECT_EQ(2, response2->headers->GetContentLength()); 2896 2897 LoadTimingInfo load_timing_info2; 2898 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 2899 TestLoadTimingReusedWithPac(load_timing_info2); 2900 2901 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); 2902 2903 trans2.reset(); 2904 session->CloseAllConnections(); 2905 } 2906 2907 // Test a simple get through an HTTPS Proxy. 2908 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) { 2909 HttpRequestInfo request; 2910 request.method = "GET"; 2911 request.url = GURL("http://www.google.com/"); 2912 2913 // Configure against https proxy server "proxy:70". 2914 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2915 "https://proxy:70")); 2916 CapturingBoundNetLog log; 2917 session_deps_.net_log = log.bound().net_log(); 2918 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2919 2920 // Since we have proxy, should use full url 2921 MockWrite data_writes1[] = { 2922 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 2923 "Host: www.google.com\r\n" 2924 "Proxy-Connection: keep-alive\r\n\r\n"), 2925 }; 2926 2927 MockRead data_reads1[] = { 2928 MockRead("HTTP/1.1 200 OK\r\n"), 2929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 2930 MockRead("Content-Length: 100\r\n\r\n"), 2931 MockRead(SYNCHRONOUS, OK), 2932 }; 2933 2934 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 2935 data_writes1, arraysize(data_writes1)); 2936 session_deps_.socket_factory->AddSocketDataProvider(&data1); 2937 SSLSocketDataProvider ssl(ASYNC, OK); 2938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 2939 2940 TestCompletionCallback callback1; 2941 2942 scoped_ptr<HttpTransaction> trans( 2943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 2944 2945 int rv = trans->Start(&request, callback1.callback(), log.bound()); 2946 EXPECT_EQ(ERR_IO_PENDING, rv); 2947 2948 rv = callback1.WaitForResult(); 2949 EXPECT_EQ(OK, rv); 2950 2951 LoadTimingInfo load_timing_info; 2952 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 2953 TestLoadTimingNotReused(load_timing_info, 2954 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 2955 2956 const HttpResponseInfo* response = trans->GetResponseInfo(); 2957 ASSERT_TRUE(response != NULL); 2958 2959 EXPECT_TRUE(response->headers->IsKeepAlive()); 2960 EXPECT_EQ(200, response->headers->response_code()); 2961 EXPECT_EQ(100, response->headers->GetContentLength()); 2962 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 2963 2964 // The password prompt info should not be set. 2965 EXPECT_TRUE(response->auth_challenge.get() == NULL); 2966 } 2967 2968 // Test a SPDY get through an HTTPS Proxy. 2969 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) { 2970 HttpRequestInfo request; 2971 request.method = "GET"; 2972 request.url = GURL("http://www.google.com/"); 2973 request.load_flags = 0; 2974 2975 // Configure against https proxy server "proxy:70". 2976 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 2977 "https://proxy:70")); 2978 CapturingBoundNetLog log; 2979 session_deps_.net_log = log.bound().net_log(); 2980 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 2981 2982 // fetch http://www.google.com/ via SPDY 2983 scoped_ptr<SpdyFrame> req( 2984 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 2985 MockWrite spdy_writes[] = { CreateMockWrite(*req) }; 2986 2987 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 2988 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 2989 MockRead spdy_reads[] = { 2990 CreateMockRead(*resp), 2991 CreateMockRead(*data), 2992 MockRead(ASYNC, 0, 0), 2993 }; 2994 2995 DelayedSocketData spdy_data( 2996 1, // wait for one write to finish before reading. 2997 spdy_reads, arraysize(spdy_reads), 2998 spdy_writes, arraysize(spdy_writes)); 2999 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3000 3001 SSLSocketDataProvider ssl(ASYNC, OK); 3002 ssl.SetNextProto(GetParam()); 3003 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3004 3005 TestCompletionCallback callback1; 3006 3007 scoped_ptr<HttpTransaction> trans( 3008 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3009 3010 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3011 EXPECT_EQ(ERR_IO_PENDING, rv); 3012 3013 rv = callback1.WaitForResult(); 3014 EXPECT_EQ(OK, rv); 3015 3016 LoadTimingInfo load_timing_info; 3017 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3018 TestLoadTimingNotReused(load_timing_info, 3019 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3020 3021 const HttpResponseInfo* response = trans->GetResponseInfo(); 3022 ASSERT_TRUE(response != NULL); 3023 ASSERT_TRUE(response->headers.get() != NULL); 3024 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3025 3026 std::string response_data; 3027 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 3028 EXPECT_EQ(kUploadData, response_data); 3029 } 3030 3031 // Verifies that a session which races and wins against the owning transaction 3032 // (completing prior to host resolution), doesn't fail the transaction. 3033 // Regression test for crbug.com/334413. 3034 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) { 3035 HttpRequestInfo request; 3036 request.method = "GET"; 3037 request.url = GURL("http://www.google.com/"); 3038 request.load_flags = 0; 3039 3040 // Configure SPDY proxy server "proxy:70". 3041 session_deps_.proxy_service.reset( 3042 ProxyService::CreateFixed("https://proxy:70")); 3043 CapturingBoundNetLog log; 3044 session_deps_.net_log = log.bound().net_log(); 3045 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3046 3047 // Fetch http://www.google.com/ through the SPDY proxy. 3048 scoped_ptr<SpdyFrame> req( 3049 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 3050 MockWrite spdy_writes[] = {CreateMockWrite(*req)}; 3051 3052 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3053 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3054 MockRead spdy_reads[] = { 3055 CreateMockRead(*resp), CreateMockRead(*data), MockRead(ASYNC, 0, 0), 3056 }; 3057 3058 DelayedSocketData spdy_data( 3059 1, // wait for one write to finish before reading. 3060 spdy_reads, 3061 arraysize(spdy_reads), 3062 spdy_writes, 3063 arraysize(spdy_writes)); 3064 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3065 3066 SSLSocketDataProvider ssl(ASYNC, OK); 3067 ssl.SetNextProto(GetParam()); 3068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3069 3070 TestCompletionCallback callback1; 3071 3072 scoped_ptr<HttpTransaction> trans( 3073 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3074 3075 // Stall the hostname resolution begun by the transaction. 3076 session_deps_.host_resolver->set_synchronous_mode(false); 3077 session_deps_.host_resolver->set_ondemand_mode(true); 3078 3079 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3080 EXPECT_EQ(ERR_IO_PENDING, rv); 3081 3082 // Race a session to the proxy, which completes first. 3083 session_deps_.host_resolver->set_ondemand_mode(false); 3084 SpdySessionKey key( 3085 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED); 3086 base::WeakPtr<SpdySession> spdy_session = 3087 CreateSecureSpdySession(session, key, log.bound()); 3088 3089 // Unstall the resolution begun by the transaction. 3090 session_deps_.host_resolver->set_ondemand_mode(true); 3091 session_deps_.host_resolver->ResolveAllPending(); 3092 3093 EXPECT_FALSE(callback1.have_result()); 3094 rv = callback1.WaitForResult(); 3095 EXPECT_EQ(OK, rv); 3096 3097 const HttpResponseInfo* response = trans->GetResponseInfo(); 3098 ASSERT_TRUE(response != NULL); 3099 ASSERT_TRUE(response->headers.get() != NULL); 3100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3101 3102 std::string response_data; 3103 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 3104 EXPECT_EQ(kUploadData, response_data); 3105 } 3106 3107 // Test a SPDY get through an HTTPS Proxy. 3108 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) { 3109 HttpRequestInfo request; 3110 request.method = "GET"; 3111 request.url = GURL("http://www.google.com/"); 3112 request.load_flags = 0; 3113 3114 // Configure against https proxy server "myproxy:70". 3115 session_deps_.proxy_service.reset( 3116 ProxyService::CreateFixed("https://myproxy:70")); 3117 CapturingBoundNetLog log; 3118 session_deps_.net_log = log.bound().net_log(); 3119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3120 3121 // The first request will be a bare GET, the second request will be a 3122 // GET with a Proxy-Authorization header. 3123 scoped_ptr<SpdyFrame> req_get( 3124 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 3125 const char* const kExtraAuthorizationHeaders[] = { 3126 "proxy-authorization", "Basic Zm9vOmJhcg==" 3127 }; 3128 scoped_ptr<SpdyFrame> req_get_authorization( 3129 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 3130 arraysize(kExtraAuthorizationHeaders) / 2, 3131 false, 3132 3, 3133 LOWEST, 3134 false)); 3135 MockWrite spdy_writes[] = { 3136 CreateMockWrite(*req_get, 1), 3137 CreateMockWrite(*req_get_authorization, 4), 3138 }; 3139 3140 // The first response is a 407 proxy authentication challenge, and the second 3141 // response will be a 200 response since the second request includes a valid 3142 // Authorization header. 3143 const char* const kExtraAuthenticationHeaders[] = { 3144 "proxy-authenticate", "Basic realm=\"MyRealm1\"" 3145 }; 3146 scoped_ptr<SpdyFrame> resp_authentication( 3147 spdy_util_.ConstructSpdySynReplyError( 3148 "407 Proxy Authentication Required", 3149 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2, 3150 1)); 3151 scoped_ptr<SpdyFrame> body_authentication( 3152 spdy_util_.ConstructSpdyBodyFrame(1, true)); 3153 scoped_ptr<SpdyFrame> resp_data( 3154 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3155 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true)); 3156 MockRead spdy_reads[] = { 3157 CreateMockRead(*resp_authentication, 2), 3158 CreateMockRead(*body_authentication, 3), 3159 CreateMockRead(*resp_data, 5), 3160 CreateMockRead(*body_data, 6), 3161 MockRead(ASYNC, 0, 7), 3162 }; 3163 3164 OrderedSocketData data( 3165 spdy_reads, arraysize(spdy_reads), 3166 spdy_writes, arraysize(spdy_writes)); 3167 session_deps_.socket_factory->AddSocketDataProvider(&data); 3168 3169 SSLSocketDataProvider ssl(ASYNC, OK); 3170 ssl.SetNextProto(GetParam()); 3171 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3172 3173 TestCompletionCallback callback1; 3174 3175 scoped_ptr<HttpTransaction> trans( 3176 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3177 3178 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3179 EXPECT_EQ(ERR_IO_PENDING, rv); 3180 3181 rv = callback1.WaitForResult(); 3182 EXPECT_EQ(OK, rv); 3183 3184 const HttpResponseInfo* const response = trans->GetResponseInfo(); 3185 3186 ASSERT_TRUE(response != NULL); 3187 ASSERT_TRUE(response->headers.get() != NULL); 3188 EXPECT_EQ(407, response->headers->response_code()); 3189 EXPECT_TRUE(response->was_fetched_via_spdy); 3190 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 3191 3192 TestCompletionCallback callback2; 3193 3194 rv = trans->RestartWithAuth( 3195 AuthCredentials(kFoo, kBar), callback2.callback()); 3196 EXPECT_EQ(ERR_IO_PENDING, rv); 3197 3198 rv = callback2.WaitForResult(); 3199 EXPECT_EQ(OK, rv); 3200 3201 const HttpResponseInfo* const response_restart = trans->GetResponseInfo(); 3202 3203 ASSERT_TRUE(response_restart != NULL); 3204 ASSERT_TRUE(response_restart->headers.get() != NULL); 3205 EXPECT_EQ(200, response_restart->headers->response_code()); 3206 // The password prompt info should not be set. 3207 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL); 3208 } 3209 3210 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server. 3211 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) { 3212 HttpRequestInfo request; 3213 request.method = "GET"; 3214 request.url = GURL("https://www.google.com/"); 3215 request.load_flags = 0; 3216 3217 // Configure against https proxy server "proxy:70". 3218 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3219 "https://proxy:70")); 3220 CapturingBoundNetLog log; 3221 session_deps_.net_log = log.bound().net_log(); 3222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3223 3224 scoped_ptr<HttpTransaction> trans( 3225 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3226 3227 // CONNECT to www.google.com:443 via SPDY 3228 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3229 LOWEST)); 3230 // fetch https://www.google.com/ via HTTP 3231 3232 const char get[] = "GET / HTTP/1.1\r\n" 3233 "Host: www.google.com\r\n" 3234 "Connection: keep-alive\r\n\r\n"; 3235 scoped_ptr<SpdyFrame> wrapped_get( 3236 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false)); 3237 scoped_ptr<SpdyFrame> conn_resp( 3238 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3239 const char resp[] = "HTTP/1.1 200 OK\r\n" 3240 "Content-Length: 10\r\n\r\n"; 3241 scoped_ptr<SpdyFrame> wrapped_get_resp( 3242 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false)); 3243 scoped_ptr<SpdyFrame> wrapped_body( 3244 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false)); 3245 scoped_ptr<SpdyFrame> window_update( 3246 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size())); 3247 3248 MockWrite spdy_writes[] = { 3249 CreateMockWrite(*connect, 1), 3250 CreateMockWrite(*wrapped_get, 3), 3251 CreateMockWrite(*window_update, 5), 3252 }; 3253 3254 MockRead spdy_reads[] = { 3255 CreateMockRead(*conn_resp, 2, ASYNC), 3256 CreateMockRead(*wrapped_get_resp, 4, ASYNC), 3257 CreateMockRead(*wrapped_body, 6, ASYNC), 3258 CreateMockRead(*wrapped_body, 7, ASYNC), 3259 MockRead(ASYNC, 0, 8), 3260 }; 3261 3262 OrderedSocketData spdy_data( 3263 spdy_reads, arraysize(spdy_reads), 3264 spdy_writes, arraysize(spdy_writes)); 3265 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3266 3267 SSLSocketDataProvider ssl(ASYNC, OK); 3268 ssl.SetNextProto(GetParam()); 3269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3270 SSLSocketDataProvider ssl2(ASYNC, OK); 3271 ssl2.was_npn_negotiated = false; 3272 ssl2.protocol_negotiated = kProtoUnknown; 3273 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 3274 3275 TestCompletionCallback callback1; 3276 3277 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3278 EXPECT_EQ(ERR_IO_PENDING, rv); 3279 3280 rv = callback1.WaitForResult(); 3281 EXPECT_EQ(OK, rv); 3282 3283 LoadTimingInfo load_timing_info; 3284 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3285 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3286 3287 const HttpResponseInfo* response = trans->GetResponseInfo(); 3288 ASSERT_TRUE(response != NULL); 3289 ASSERT_TRUE(response->headers.get() != NULL); 3290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3291 3292 std::string response_data; 3293 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 3294 EXPECT_EQ("1234567890", response_data); 3295 } 3296 3297 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server. 3298 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) { 3299 HttpRequestInfo request; 3300 request.method = "GET"; 3301 request.url = GURL("https://www.google.com/"); 3302 request.load_flags = 0; 3303 3304 // Configure against https proxy server "proxy:70". 3305 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3306 "https://proxy:70")); 3307 CapturingBoundNetLog log; 3308 session_deps_.net_log = log.bound().net_log(); 3309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3310 3311 scoped_ptr<HttpTransaction> trans( 3312 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3313 3314 // CONNECT to www.google.com:443 via SPDY 3315 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3316 LOWEST)); 3317 // fetch https://www.google.com/ via SPDY 3318 const char* const kMyUrl = "https://www.google.com/"; 3319 scoped_ptr<SpdyFrame> get( 3320 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST)); 3321 scoped_ptr<SpdyFrame> wrapped_get( 3322 spdy_util_.ConstructWrappedSpdyFrame(get, 1)); 3323 scoped_ptr<SpdyFrame> conn_resp( 3324 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3325 scoped_ptr<SpdyFrame> get_resp( 3326 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3327 scoped_ptr<SpdyFrame> wrapped_get_resp( 3328 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1)); 3329 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3330 scoped_ptr<SpdyFrame> wrapped_body( 3331 spdy_util_.ConstructWrappedSpdyFrame(body, 1)); 3332 scoped_ptr<SpdyFrame> window_update_get_resp( 3333 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size())); 3334 scoped_ptr<SpdyFrame> window_update_body( 3335 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size())); 3336 3337 MockWrite spdy_writes[] = { 3338 CreateMockWrite(*connect, 1), 3339 CreateMockWrite(*wrapped_get, 3), 3340 CreateMockWrite(*window_update_get_resp, 5), 3341 CreateMockWrite(*window_update_body, 7), 3342 }; 3343 3344 MockRead spdy_reads[] = { 3345 CreateMockRead(*conn_resp, 2, ASYNC), 3346 CreateMockRead(*wrapped_get_resp, 4, ASYNC), 3347 CreateMockRead(*wrapped_body, 6, ASYNC), 3348 MockRead(ASYNC, 0, 8), 3349 }; 3350 3351 OrderedSocketData spdy_data( 3352 spdy_reads, arraysize(spdy_reads), 3353 spdy_writes, arraysize(spdy_writes)); 3354 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3355 3356 SSLSocketDataProvider ssl(ASYNC, OK); 3357 ssl.SetNextProto(GetParam()); 3358 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3359 SSLSocketDataProvider ssl2(ASYNC, OK); 3360 ssl2.SetNextProto(GetParam()); 3361 ssl2.protocol_negotiated = GetParam(); 3362 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 3363 3364 TestCompletionCallback callback1; 3365 3366 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3367 EXPECT_EQ(ERR_IO_PENDING, rv); 3368 3369 rv = callback1.WaitForResult(); 3370 EXPECT_EQ(OK, rv); 3371 3372 LoadTimingInfo load_timing_info; 3373 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3374 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3375 3376 const HttpResponseInfo* response = trans->GetResponseInfo(); 3377 ASSERT_TRUE(response != NULL); 3378 ASSERT_TRUE(response->headers.get() != NULL); 3379 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3380 3381 std::string response_data; 3382 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); 3383 EXPECT_EQ(kUploadData, response_data); 3384 } 3385 3386 // Test a SPDY CONNECT failure through an HTTPS Proxy. 3387 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) { 3388 HttpRequestInfo request; 3389 request.method = "GET"; 3390 request.url = GURL("https://www.google.com/"); 3391 request.load_flags = 0; 3392 3393 // Configure against https proxy server "proxy:70". 3394 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3395 "https://proxy:70")); 3396 CapturingBoundNetLog log; 3397 session_deps_.net_log = log.bound().net_log(); 3398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3399 3400 scoped_ptr<HttpTransaction> trans( 3401 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3402 3403 // CONNECT to www.google.com:443 via SPDY 3404 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3405 LOWEST)); 3406 scoped_ptr<SpdyFrame> get( 3407 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 3408 3409 MockWrite spdy_writes[] = { 3410 CreateMockWrite(*connect, 1), 3411 CreateMockWrite(*get, 3), 3412 }; 3413 3414 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1)); 3415 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true)); 3416 MockRead spdy_reads[] = { 3417 CreateMockRead(*resp, 2, ASYNC), 3418 MockRead(ASYNC, 0, 4), 3419 }; 3420 3421 OrderedSocketData spdy_data( 3422 spdy_reads, arraysize(spdy_reads), 3423 spdy_writes, arraysize(spdy_writes)); 3424 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 3425 3426 SSLSocketDataProvider ssl(ASYNC, OK); 3427 ssl.SetNextProto(GetParam()); 3428 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3429 SSLSocketDataProvider ssl2(ASYNC, OK); 3430 ssl2.SetNextProto(GetParam()); 3431 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 3432 3433 TestCompletionCallback callback1; 3434 3435 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3436 EXPECT_EQ(ERR_IO_PENDING, rv); 3437 3438 rv = callback1.WaitForResult(); 3439 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 3440 3441 // TODO(ttuttle): Anything else to check here? 3442 } 3443 3444 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY 3445 // HTTPS Proxy to different servers. 3446 TEST_P(HttpNetworkTransactionTest, 3447 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) { 3448 // Configure against https proxy server "proxy:70". 3449 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3450 "https://proxy:70")); 3451 CapturingBoundNetLog log; 3452 session_deps_.net_log = log.bound().net_log(); 3453 scoped_refptr<HttpNetworkSession> session( 3454 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3455 3456 HttpRequestInfo request1; 3457 request1.method = "GET"; 3458 request1.url = GURL("https://www.google.com/"); 3459 request1.load_flags = 0; 3460 3461 HttpRequestInfo request2; 3462 request2.method = "GET"; 3463 request2.url = GURL("https://news.google.com/"); 3464 request2.load_flags = 0; 3465 3466 // CONNECT to www.google.com:443 via SPDY. 3467 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3468 LOWEST)); 3469 scoped_ptr<SpdyFrame> conn_resp1( 3470 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3471 3472 // Fetch https://www.google.com/ via HTTP. 3473 const char get1[] = "GET / HTTP/1.1\r\n" 3474 "Host: www.google.com\r\n" 3475 "Connection: keep-alive\r\n\r\n"; 3476 scoped_ptr<SpdyFrame> wrapped_get1( 3477 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false)); 3478 const char resp1[] = "HTTP/1.1 200 OK\r\n" 3479 "Content-Length: 1\r\n\r\n"; 3480 scoped_ptr<SpdyFrame> wrapped_get_resp1( 3481 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false)); 3482 scoped_ptr<SpdyFrame> wrapped_body1( 3483 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false)); 3484 scoped_ptr<SpdyFrame> window_update( 3485 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size())); 3486 3487 // CONNECT to news.google.com:443 via SPDY. 3488 SpdySynStreamIR connect2_ir(3); 3489 spdy_util_.SetPriority(LOWEST, &connect2_ir); 3490 connect2_ir.SetHeader(spdy_util_.GetMethodKey(), "CONNECT"); 3491 connect2_ir.SetHeader(spdy_util_.GetPathKey(), "news.google.com:443"); 3492 connect2_ir.SetHeader(spdy_util_.GetHostKey(), "news.google.com"); 3493 spdy_util_.MaybeAddVersionHeader(&connect2_ir); 3494 scoped_ptr<SpdyFrame> connect2( 3495 spdy_util_.CreateFramer(false)->SerializeFrame(connect2_ir)); 3496 3497 scoped_ptr<SpdyFrame> conn_resp2( 3498 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3499 3500 // Fetch https://news.google.com/ via HTTP. 3501 const char get2[] = "GET / HTTP/1.1\r\n" 3502 "Host: news.google.com\r\n" 3503 "Connection: keep-alive\r\n\r\n"; 3504 scoped_ptr<SpdyFrame> wrapped_get2( 3505 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false)); 3506 const char resp2[] = "HTTP/1.1 200 OK\r\n" 3507 "Content-Length: 2\r\n\r\n"; 3508 scoped_ptr<SpdyFrame> wrapped_get_resp2( 3509 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false)); 3510 scoped_ptr<SpdyFrame> wrapped_body2( 3511 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false)); 3512 3513 MockWrite spdy_writes[] = { 3514 CreateMockWrite(*connect1, 0), 3515 CreateMockWrite(*wrapped_get1, 2), 3516 CreateMockWrite(*connect2, 5), 3517 CreateMockWrite(*wrapped_get2, 7), 3518 }; 3519 3520 MockRead spdy_reads[] = { 3521 CreateMockRead(*conn_resp1, 1, ASYNC), 3522 CreateMockRead(*wrapped_get_resp1, 3, ASYNC), 3523 CreateMockRead(*wrapped_body1, 4, ASYNC), 3524 CreateMockRead(*conn_resp2, 6, ASYNC), 3525 CreateMockRead(*wrapped_get_resp2, 8, ASYNC), 3526 CreateMockRead(*wrapped_body2, 9, ASYNC), 3527 MockRead(ASYNC, 0, 10), 3528 }; 3529 3530 DeterministicSocketData spdy_data( 3531 spdy_reads, arraysize(spdy_reads), 3532 spdy_writes, arraysize(spdy_writes)); 3533 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3534 3535 SSLSocketDataProvider ssl(ASYNC, OK); 3536 ssl.SetNextProto(GetParam()); 3537 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3538 SSLSocketDataProvider ssl2(ASYNC, OK); 3539 ssl2.was_npn_negotiated = false; 3540 ssl2.protocol_negotiated = kProtoUnknown; 3541 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 3542 SSLSocketDataProvider ssl3(ASYNC, OK); 3543 ssl3.was_npn_negotiated = false; 3544 ssl3.protocol_negotiated = kProtoUnknown; 3545 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3); 3546 3547 TestCompletionCallback callback; 3548 3549 scoped_ptr<HttpTransaction> trans( 3550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3551 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3552 EXPECT_EQ(ERR_IO_PENDING, rv); 3553 // The first connect and request, each of their responses, and the body. 3554 spdy_data.RunFor(5); 3555 3556 rv = callback.WaitForResult(); 3557 EXPECT_EQ(OK, rv); 3558 3559 LoadTimingInfo load_timing_info; 3560 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3561 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3562 3563 const HttpResponseInfo* response = trans->GetResponseInfo(); 3564 ASSERT_TRUE(response != NULL); 3565 ASSERT_TRUE(response->headers.get() != NULL); 3566 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3567 3568 std::string response_data; 3569 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3570 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); 3571 3572 scoped_ptr<HttpTransaction> trans2( 3573 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3574 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3575 EXPECT_EQ(ERR_IO_PENDING, rv); 3576 3577 // The second connect and request, each of their responses, and the body. 3578 spdy_data.RunFor(5); 3579 rv = callback.WaitForResult(); 3580 EXPECT_EQ(OK, rv); 3581 3582 LoadTimingInfo load_timing_info2; 3583 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3584 // Even though the SPDY connection is reused, a new tunnelled connection has 3585 // to be created, so the socket's load timing looks like a fresh connection. 3586 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES); 3587 3588 // The requests should have different IDs, since they each are using their own 3589 // separate stream. 3590 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3591 3592 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback())); 3593 } 3594 3595 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY 3596 // HTTPS Proxy to the same server. 3597 TEST_P(HttpNetworkTransactionTest, 3598 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) { 3599 // Configure against https proxy server "proxy:70". 3600 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3601 "https://proxy:70")); 3602 CapturingBoundNetLog log; 3603 session_deps_.net_log = log.bound().net_log(); 3604 scoped_refptr<HttpNetworkSession> session( 3605 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3606 3607 HttpRequestInfo request1; 3608 request1.method = "GET"; 3609 request1.url = GURL("https://www.google.com/"); 3610 request1.load_flags = 0; 3611 3612 HttpRequestInfo request2; 3613 request2.method = "GET"; 3614 request2.url = GURL("https://www.google.com/2"); 3615 request2.load_flags = 0; 3616 3617 // CONNECT to www.google.com:443 via SPDY. 3618 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 3619 LOWEST)); 3620 scoped_ptr<SpdyFrame> conn_resp1( 3621 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3622 3623 // Fetch https://www.google.com/ via HTTP. 3624 const char get1[] = "GET / HTTP/1.1\r\n" 3625 "Host: www.google.com\r\n" 3626 "Connection: keep-alive\r\n\r\n"; 3627 scoped_ptr<SpdyFrame> wrapped_get1( 3628 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false)); 3629 const char resp1[] = "HTTP/1.1 200 OK\r\n" 3630 "Content-Length: 1\r\n\r\n"; 3631 scoped_ptr<SpdyFrame> wrapped_get_resp1( 3632 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false)); 3633 scoped_ptr<SpdyFrame> wrapped_body1( 3634 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false)); 3635 scoped_ptr<SpdyFrame> window_update( 3636 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size())); 3637 3638 // Fetch https://www.google.com/2 via HTTP. 3639 const char get2[] = "GET /2 HTTP/1.1\r\n" 3640 "Host: www.google.com\r\n" 3641 "Connection: keep-alive\r\n\r\n"; 3642 scoped_ptr<SpdyFrame> wrapped_get2( 3643 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false)); 3644 const char resp2[] = "HTTP/1.1 200 OK\r\n" 3645 "Content-Length: 2\r\n\r\n"; 3646 scoped_ptr<SpdyFrame> wrapped_get_resp2( 3647 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false)); 3648 scoped_ptr<SpdyFrame> wrapped_body2( 3649 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false)); 3650 3651 MockWrite spdy_writes[] = { 3652 CreateMockWrite(*connect1, 0), 3653 CreateMockWrite(*wrapped_get1, 2), 3654 CreateMockWrite(*wrapped_get2, 5), 3655 }; 3656 3657 MockRead spdy_reads[] = { 3658 CreateMockRead(*conn_resp1, 1, ASYNC), 3659 CreateMockRead(*wrapped_get_resp1, 3, ASYNC), 3660 CreateMockRead(*wrapped_body1, 4, ASYNC), 3661 CreateMockRead(*wrapped_get_resp2, 6, ASYNC), 3662 CreateMockRead(*wrapped_body2, 7, ASYNC), 3663 MockRead(ASYNC, 0, 8), 3664 }; 3665 3666 DeterministicSocketData spdy_data( 3667 spdy_reads, arraysize(spdy_reads), 3668 spdy_writes, arraysize(spdy_writes)); 3669 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3670 3671 SSLSocketDataProvider ssl(ASYNC, OK); 3672 ssl.SetNextProto(GetParam()); 3673 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3674 SSLSocketDataProvider ssl2(ASYNC, OK); 3675 ssl2.was_npn_negotiated = false; 3676 ssl2.protocol_negotiated = kProtoUnknown; 3677 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); 3678 3679 TestCompletionCallback callback; 3680 3681 scoped_ptr<HttpTransaction> trans( 3682 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3683 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3684 EXPECT_EQ(ERR_IO_PENDING, rv); 3685 // The first connect and request, each of their responses, and the body. 3686 spdy_data.RunFor(5); 3687 3688 rv = callback.WaitForResult(); 3689 EXPECT_EQ(OK, rv); 3690 3691 LoadTimingInfo load_timing_info; 3692 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3693 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES); 3694 3695 const HttpResponseInfo* response = trans->GetResponseInfo(); 3696 ASSERT_TRUE(response != NULL); 3697 ASSERT_TRUE(response->headers.get() != NULL); 3698 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3699 3700 std::string response_data; 3701 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3702 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); 3703 trans.reset(); 3704 3705 scoped_ptr<HttpTransaction> trans2( 3706 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3707 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3708 EXPECT_EQ(ERR_IO_PENDING, rv); 3709 3710 // The second request, response, and body. There should not be a second 3711 // connect. 3712 spdy_data.RunFor(3); 3713 rv = callback.WaitForResult(); 3714 EXPECT_EQ(OK, rv); 3715 3716 LoadTimingInfo load_timing_info2; 3717 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3718 TestLoadTimingReused(load_timing_info2); 3719 3720 // The requests should have the same ID. 3721 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3722 3723 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback())); 3724 } 3725 3726 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS 3727 // Proxy to different servers. 3728 TEST_P(HttpNetworkTransactionTest, 3729 HttpsProxySpdyLoadTimingTwoHttpRequests) { 3730 // Configure against https proxy server "proxy:70". 3731 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 3732 "https://proxy:70")); 3733 CapturingBoundNetLog log; 3734 session_deps_.net_log = log.bound().net_log(); 3735 scoped_refptr<HttpNetworkSession> session( 3736 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_)); 3737 3738 HttpRequestInfo request1; 3739 request1.method = "GET"; 3740 request1.url = GURL("http://www.google.com/"); 3741 request1.load_flags = 0; 3742 3743 HttpRequestInfo request2; 3744 request2.method = "GET"; 3745 request2.url = GURL("http://news.google.com/"); 3746 request2.load_flags = 0; 3747 3748 // http://www.google.com/ 3749 scoped_ptr<SpdyHeaderBlock> headers( 3750 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/")); 3751 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame( 3752 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 3753 scoped_ptr<SpdyFrame> get_resp1( 3754 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 3755 scoped_ptr<SpdyFrame> body1( 3756 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true)); 3757 3758 // http://news.google.com/ 3759 scoped_ptr<SpdyHeaderBlock> headers2( 3760 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/")); 3761 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame( 3762 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0)); 3763 scoped_ptr<SpdyFrame> get_resp2( 3764 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 3765 scoped_ptr<SpdyFrame> body2( 3766 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true)); 3767 3768 MockWrite spdy_writes[] = { 3769 CreateMockWrite(*get1, 0), 3770 CreateMockWrite(*get2, 3), 3771 }; 3772 3773 MockRead spdy_reads[] = { 3774 CreateMockRead(*get_resp1, 1, ASYNC), 3775 CreateMockRead(*body1, 2, ASYNC), 3776 CreateMockRead(*get_resp2, 4, ASYNC), 3777 CreateMockRead(*body2, 5, ASYNC), 3778 MockRead(ASYNC, 0, 6), 3779 }; 3780 3781 DeterministicSocketData spdy_data( 3782 spdy_reads, arraysize(spdy_reads), 3783 spdy_writes, arraysize(spdy_writes)); 3784 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data); 3785 3786 SSLSocketDataProvider ssl(ASYNC, OK); 3787 ssl.SetNextProto(GetParam()); 3788 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); 3789 3790 TestCompletionCallback callback; 3791 3792 scoped_ptr<HttpTransaction> trans( 3793 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3794 int rv = trans->Start(&request1, callback.callback(), BoundNetLog()); 3795 EXPECT_EQ(ERR_IO_PENDING, rv); 3796 spdy_data.RunFor(2); 3797 3798 rv = callback.WaitForResult(); 3799 EXPECT_EQ(OK, rv); 3800 3801 LoadTimingInfo load_timing_info; 3802 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3803 TestLoadTimingNotReused(load_timing_info, 3804 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3805 3806 const HttpResponseInfo* response = trans->GetResponseInfo(); 3807 ASSERT_TRUE(response != NULL); 3808 ASSERT_TRUE(response->headers.get() != NULL); 3809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 3810 3811 std::string response_data; 3812 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); 3813 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback())); 3814 spdy_data.RunFor(1); 3815 EXPECT_EQ(1, callback.WaitForResult()); 3816 // Delete the first request, so the second one can reuse the socket. 3817 trans.reset(); 3818 3819 scoped_ptr<HttpTransaction> trans2( 3820 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3821 rv = trans2->Start(&request2, callback.callback(), BoundNetLog()); 3822 EXPECT_EQ(ERR_IO_PENDING, rv); 3823 3824 spdy_data.RunFor(2); 3825 rv = callback.WaitForResult(); 3826 EXPECT_EQ(OK, rv); 3827 3828 LoadTimingInfo load_timing_info2; 3829 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2)); 3830 TestLoadTimingReused(load_timing_info2); 3831 3832 // The requests should have the same ID. 3833 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id); 3834 3835 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback())); 3836 spdy_data.RunFor(1); 3837 EXPECT_EQ(2, callback.WaitForResult()); 3838 } 3839 3840 // Test the challenge-response-retry sequence through an HTTPS Proxy 3841 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) { 3842 HttpRequestInfo request; 3843 request.method = "GET"; 3844 request.url = GURL("http://www.google.com/"); 3845 // when the no authentication data flag is set. 3846 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 3847 3848 // Configure against https proxy server "myproxy:70". 3849 session_deps_.proxy_service.reset( 3850 ProxyService::CreateFixed("https://myproxy:70")); 3851 CapturingBoundNetLog log; 3852 session_deps_.net_log = log.bound().net_log(); 3853 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3854 3855 // Since we have proxy, should use full url 3856 MockWrite data_writes1[] = { 3857 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3858 "Host: www.google.com\r\n" 3859 "Proxy-Connection: keep-alive\r\n\r\n"), 3860 3861 // After calling trans->RestartWithAuth(), this is the request we should 3862 // be issuing -- the final header line contains the credentials. 3863 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 3864 "Host: www.google.com\r\n" 3865 "Proxy-Connection: keep-alive\r\n" 3866 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 3867 }; 3868 3869 // The proxy responds to the GET with a 407, using a persistent 3870 // connection. 3871 MockRead data_reads1[] = { 3872 // No credentials. 3873 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 3874 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 3875 MockRead("Proxy-Connection: keep-alive\r\n"), 3876 MockRead("Content-Length: 0\r\n\r\n"), 3877 3878 MockRead("HTTP/1.1 200 OK\r\n"), 3879 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 3880 MockRead("Content-Length: 100\r\n\r\n"), 3881 MockRead(SYNCHRONOUS, OK), 3882 }; 3883 3884 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 3885 data_writes1, arraysize(data_writes1)); 3886 session_deps_.socket_factory->AddSocketDataProvider(&data1); 3887 SSLSocketDataProvider ssl(ASYNC, OK); 3888 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 3889 3890 TestCompletionCallback callback1; 3891 3892 scoped_ptr<HttpTransaction> trans( 3893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3894 3895 int rv = trans->Start(&request, callback1.callback(), log.bound()); 3896 EXPECT_EQ(ERR_IO_PENDING, rv); 3897 3898 rv = callback1.WaitForResult(); 3899 EXPECT_EQ(OK, rv); 3900 3901 LoadTimingInfo load_timing_info; 3902 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3903 TestLoadTimingNotReused(load_timing_info, 3904 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 3905 3906 const HttpResponseInfo* response = trans->GetResponseInfo(); 3907 ASSERT_TRUE(response != NULL); 3908 ASSERT_FALSE(response->headers.get() == NULL); 3909 EXPECT_EQ(407, response->headers->response_code()); 3910 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 3911 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 3912 3913 TestCompletionCallback callback2; 3914 3915 rv = trans->RestartWithAuth( 3916 AuthCredentials(kFoo, kBar), callback2.callback()); 3917 EXPECT_EQ(ERR_IO_PENDING, rv); 3918 3919 rv = callback2.WaitForResult(); 3920 EXPECT_EQ(OK, rv); 3921 3922 load_timing_info = LoadTimingInfo(); 3923 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 3924 // Retrying with HTTP AUTH is considered to be reusing a socket. 3925 TestLoadTimingReused(load_timing_info); 3926 3927 response = trans->GetResponseInfo(); 3928 ASSERT_TRUE(response != NULL); 3929 3930 EXPECT_TRUE(response->headers->IsKeepAlive()); 3931 EXPECT_EQ(200, response->headers->response_code()); 3932 EXPECT_EQ(100, response->headers->GetContentLength()); 3933 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 3934 3935 // The password prompt info should not be set. 3936 EXPECT_TRUE(response->auth_challenge.get() == NULL); 3937 } 3938 3939 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( 3940 const MockRead& status, int expected_status) { 3941 HttpRequestInfo request; 3942 request.method = "GET"; 3943 request.url = GURL("https://www.google.com/"); 3944 request.load_flags = 0; 3945 3946 // Configure against proxy server "myproxy:70". 3947 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 3948 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 3949 3950 // Since we have proxy, should try to establish tunnel. 3951 MockWrite data_writes[] = { 3952 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 3953 "Host: www.google.com\r\n" 3954 "Proxy-Connection: keep-alive\r\n\r\n"), 3955 }; 3956 3957 MockRead data_reads[] = { 3958 status, 3959 MockRead("Content-Length: 10\r\n\r\n"), 3960 // No response body because the test stops reading here. 3961 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 3962 }; 3963 3964 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 3965 data_writes, arraysize(data_writes)); 3966 session_deps_.socket_factory->AddSocketDataProvider(&data); 3967 3968 TestCompletionCallback callback; 3969 3970 scoped_ptr<HttpTransaction> trans( 3971 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 3972 3973 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 3974 EXPECT_EQ(ERR_IO_PENDING, rv); 3975 3976 rv = callback.WaitForResult(); 3977 EXPECT_EQ(expected_status, rv); 3978 } 3979 3980 void HttpNetworkTransactionTest::ConnectStatusHelper( 3981 const MockRead& status) { 3982 ConnectStatusHelperWithExpectedStatus( 3983 status, ERR_TUNNEL_CONNECTION_FAILED); 3984 } 3985 3986 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) { 3987 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n")); 3988 } 3989 3990 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) { 3991 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n")); 3992 } 3993 3994 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) { 3995 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n")); 3996 } 3997 3998 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) { 3999 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n")); 4000 } 4001 4002 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) { 4003 ConnectStatusHelper( 4004 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n")); 4005 } 4006 4007 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) { 4008 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n")); 4009 } 4010 4011 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) { 4012 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n")); 4013 } 4014 4015 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) { 4016 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n")); 4017 } 4018 4019 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) { 4020 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n")); 4021 } 4022 4023 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) { 4024 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n")); 4025 } 4026 4027 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) { 4028 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n")); 4029 } 4030 4031 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) { 4032 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n")); 4033 } 4034 4035 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) { 4036 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n")); 4037 } 4038 4039 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) { 4040 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n")); 4041 } 4042 4043 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) { 4044 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n")); 4045 } 4046 4047 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) { 4048 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n")); 4049 } 4050 4051 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) { 4052 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n")); 4053 } 4054 4055 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) { 4056 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n")); 4057 } 4058 4059 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) { 4060 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n")); 4061 } 4062 4063 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) { 4064 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n")); 4065 } 4066 4067 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) { 4068 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n")); 4069 } 4070 4071 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) { 4072 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n")); 4073 } 4074 4075 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) { 4076 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n")); 4077 } 4078 4079 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) { 4080 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n")); 4081 } 4082 4083 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) { 4084 ConnectStatusHelperWithExpectedStatus( 4085 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 4086 ERR_PROXY_AUTH_UNSUPPORTED); 4087 } 4088 4089 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) { 4090 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n")); 4091 } 4092 4093 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) { 4094 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n")); 4095 } 4096 4097 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) { 4098 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n")); 4099 } 4100 4101 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) { 4102 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n")); 4103 } 4104 4105 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) { 4106 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n")); 4107 } 4108 4109 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) { 4110 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n")); 4111 } 4112 4113 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) { 4114 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n")); 4115 } 4116 4117 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) { 4118 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n")); 4119 } 4120 4121 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) { 4122 ConnectStatusHelper( 4123 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n")); 4124 } 4125 4126 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) { 4127 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n")); 4128 } 4129 4130 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) { 4131 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n")); 4132 } 4133 4134 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) { 4135 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n")); 4136 } 4137 4138 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) { 4139 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n")); 4140 } 4141 4142 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) { 4143 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n")); 4144 } 4145 4146 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) { 4147 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n")); 4148 } 4149 4150 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) { 4151 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n")); 4152 } 4153 4154 // Test the flow when both the proxy server AND origin server require 4155 // authentication. Again, this uses basic auth for both since that is 4156 // the simplest to mock. 4157 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { 4158 HttpRequestInfo request; 4159 request.method = "GET"; 4160 request.url = GURL("http://www.google.com/"); 4161 request.load_flags = 0; 4162 4163 // Configure against proxy server "myproxy:70". 4164 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 4165 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4166 4167 scoped_ptr<HttpTransaction> trans( 4168 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 4169 4170 MockWrite data_writes1[] = { 4171 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 4172 "Host: www.google.com\r\n" 4173 "Proxy-Connection: keep-alive\r\n\r\n"), 4174 }; 4175 4176 MockRead data_reads1[] = { 4177 MockRead("HTTP/1.0 407 Unauthorized\r\n"), 4178 // Give a couple authenticate options (only the middle one is actually 4179 // supported). 4180 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed. 4181 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4182 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), 4183 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4184 // Large content-length -- won't matter, as connection will be reset. 4185 MockRead("Content-Length: 10000\r\n\r\n"), 4186 MockRead(SYNCHRONOUS, ERR_FAILED), 4187 }; 4188 4189 // After calling trans->RestartWithAuth() the first time, this is the 4190 // request we should be issuing -- the final header line contains the 4191 // proxy's credentials. 4192 MockWrite data_writes2[] = { 4193 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 4194 "Host: www.google.com\r\n" 4195 "Proxy-Connection: keep-alive\r\n" 4196 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 4197 }; 4198 4199 // Now the proxy server lets the request pass through to origin server. 4200 // The origin server responds with a 401. 4201 MockRead data_reads2[] = { 4202 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 4203 // Note: We are using the same realm-name as the proxy server. This is 4204 // completely valid, as realms are unique across hosts. 4205 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 4206 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4207 MockRead("Content-Length: 2000\r\n\r\n"), 4208 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached. 4209 }; 4210 4211 // After calling trans->RestartWithAuth() the second time, we should send 4212 // the credentials for both the proxy and origin server. 4213 MockWrite data_writes3[] = { 4214 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n" 4215 "Host: www.google.com\r\n" 4216 "Proxy-Connection: keep-alive\r\n" 4217 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n" 4218 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 4219 }; 4220 4221 // Lastly we get the desired content. 4222 MockRead data_reads3[] = { 4223 MockRead("HTTP/1.0 200 OK\r\n"), 4224 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 4225 MockRead("Content-Length: 100\r\n\r\n"), 4226 MockRead(SYNCHRONOUS, OK), 4227 }; 4228 4229 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4230 data_writes1, arraysize(data_writes1)); 4231 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4232 data_writes2, arraysize(data_writes2)); 4233 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4234 data_writes3, arraysize(data_writes3)); 4235 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4236 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4237 session_deps_.socket_factory->AddSocketDataProvider(&data3); 4238 4239 TestCompletionCallback callback1; 4240 4241 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4242 EXPECT_EQ(ERR_IO_PENDING, rv); 4243 4244 rv = callback1.WaitForResult(); 4245 EXPECT_EQ(OK, rv); 4246 4247 const HttpResponseInfo* response = trans->GetResponseInfo(); 4248 ASSERT_TRUE(response != NULL); 4249 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 4250 4251 TestCompletionCallback callback2; 4252 4253 rv = trans->RestartWithAuth( 4254 AuthCredentials(kFoo, kBar), callback2.callback()); 4255 EXPECT_EQ(ERR_IO_PENDING, rv); 4256 4257 rv = callback2.WaitForResult(); 4258 EXPECT_EQ(OK, rv); 4259 4260 response = trans->GetResponseInfo(); 4261 ASSERT_TRUE(response != NULL); 4262 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 4263 4264 TestCompletionCallback callback3; 4265 4266 rv = trans->RestartWithAuth( 4267 AuthCredentials(kFoo2, kBar2), callback3.callback()); 4268 EXPECT_EQ(ERR_IO_PENDING, rv); 4269 4270 rv = callback3.WaitForResult(); 4271 EXPECT_EQ(OK, rv); 4272 4273 response = trans->GetResponseInfo(); 4274 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4275 EXPECT_EQ(100, response->headers->GetContentLength()); 4276 } 4277 4278 // For the NTLM implementation using SSPI, we skip the NTLM tests since we 4279 // can't hook into its internals to cause it to generate predictable NTLM 4280 // authorization headers. 4281 #if defined(NTLM_PORTABLE) 4282 // The NTLM authentication unit tests were generated by capturing the HTTP 4283 // requests and responses using Fiddler 2 and inspecting the generated random 4284 // bytes in the debugger. 4285 4286 // Enter the correct password and authenticate successfully. 4287 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) { 4288 HttpRequestInfo request; 4289 request.method = "GET"; 4290 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 4291 4292 // Ensure load is not disrupted by flags which suppress behaviour specific 4293 // to other auth schemes. 4294 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; 4295 4296 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1, 4297 MockGetHostName); 4298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4299 4300 MockWrite data_writes1[] = { 4301 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4302 "Host: 172.22.68.17\r\n" 4303 "Connection: keep-alive\r\n\r\n"), 4304 }; 4305 4306 MockRead data_reads1[] = { 4307 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4308 // Negotiate and NTLM are often requested together. However, we only want 4309 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 4310 // the header that requests Negotiate for this test. 4311 MockRead("WWW-Authenticate: NTLM\r\n"), 4312 MockRead("Connection: close\r\n"), 4313 MockRead("Content-Length: 42\r\n"), 4314 MockRead("Content-Type: text/html\r\n\r\n"), 4315 // Missing content -- won't matter, as connection will be reset. 4316 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4317 }; 4318 4319 MockWrite data_writes2[] = { 4320 // After restarting with a null identity, this is the 4321 // request we should be issuing -- the final header line contains a Type 4322 // 1 message. 4323 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4324 "Host: 172.22.68.17\r\n" 4325 "Connection: keep-alive\r\n" 4326 "Authorization: NTLM " 4327 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4328 4329 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4330 // (the credentials for the origin server). The second request continues 4331 // on the same connection. 4332 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4333 "Host: 172.22.68.17\r\n" 4334 "Connection: keep-alive\r\n" 4335 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4336 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4337 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW" 4338 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX" 4339 "ahlhx5I=\r\n\r\n"), 4340 }; 4341 4342 MockRead data_reads2[] = { 4343 // The origin server responds with a Type 2 message. 4344 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4345 MockRead("WWW-Authenticate: NTLM " 4346 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo" 4347 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4348 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4349 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4350 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4351 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4352 "BtAAAAAAA=\r\n"), 4353 MockRead("Content-Length: 42\r\n"), 4354 MockRead("Content-Type: text/html\r\n\r\n"), 4355 MockRead("You are not authorized to view this page\r\n"), 4356 4357 // Lastly we get the desired content. 4358 MockRead("HTTP/1.1 200 OK\r\n"), 4359 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 4360 MockRead("Content-Length: 13\r\n\r\n"), 4361 MockRead("Please Login\r\n"), 4362 MockRead(SYNCHRONOUS, OK), 4363 }; 4364 4365 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4366 data_writes1, arraysize(data_writes1)); 4367 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4368 data_writes2, arraysize(data_writes2)); 4369 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4370 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4371 4372 TestCompletionCallback callback1; 4373 4374 scoped_ptr<HttpTransaction> trans( 4375 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4376 4377 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4378 EXPECT_EQ(ERR_IO_PENDING, rv); 4379 4380 rv = callback1.WaitForResult(); 4381 EXPECT_EQ(OK, rv); 4382 4383 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4384 4385 const HttpResponseInfo* response = trans->GetResponseInfo(); 4386 ASSERT_FALSE(response == NULL); 4387 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4388 4389 TestCompletionCallback callback2; 4390 4391 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM), 4392 callback2.callback()); 4393 EXPECT_EQ(ERR_IO_PENDING, rv); 4394 4395 rv = callback2.WaitForResult(); 4396 EXPECT_EQ(OK, rv); 4397 4398 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4399 4400 response = trans->GetResponseInfo(); 4401 ASSERT_TRUE(response != NULL); 4402 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4403 4404 TestCompletionCallback callback3; 4405 4406 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback()); 4407 EXPECT_EQ(ERR_IO_PENDING, rv); 4408 4409 rv = callback3.WaitForResult(); 4410 EXPECT_EQ(OK, rv); 4411 4412 response = trans->GetResponseInfo(); 4413 ASSERT_TRUE(response != NULL); 4414 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4415 EXPECT_EQ(13, response->headers->GetContentLength()); 4416 } 4417 4418 // Enter a wrong password, and then the correct one. 4419 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) { 4420 HttpRequestInfo request; 4421 request.method = "GET"; 4422 request.url = GURL("http://172.22.68.17/kids/login.aspx"); 4423 request.load_flags = 0; 4424 4425 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2, 4426 MockGetHostName); 4427 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4428 4429 MockWrite data_writes1[] = { 4430 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4431 "Host: 172.22.68.17\r\n" 4432 "Connection: keep-alive\r\n\r\n"), 4433 }; 4434 4435 MockRead data_reads1[] = { 4436 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4437 // Negotiate and NTLM are often requested together. However, we only want 4438 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip 4439 // the header that requests Negotiate for this test. 4440 MockRead("WWW-Authenticate: NTLM\r\n"), 4441 MockRead("Connection: close\r\n"), 4442 MockRead("Content-Length: 42\r\n"), 4443 MockRead("Content-Type: text/html\r\n\r\n"), 4444 // Missing content -- won't matter, as connection will be reset. 4445 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4446 }; 4447 4448 MockWrite data_writes2[] = { 4449 // After restarting with a null identity, this is the 4450 // request we should be issuing -- the final header line contains a Type 4451 // 1 message. 4452 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4453 "Host: 172.22.68.17\r\n" 4454 "Connection: keep-alive\r\n" 4455 "Authorization: NTLM " 4456 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4457 4458 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4459 // (the credentials for the origin server). The second request continues 4460 // on the same connection. 4461 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4462 "Host: 172.22.68.17\r\n" 4463 "Connection: keep-alive\r\n" 4464 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4465 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4466 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY" 4467 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj" 4468 "4Ww7b7E=\r\n\r\n"), 4469 }; 4470 4471 MockRead data_reads2[] = { 4472 // The origin server responds with a Type 2 message. 4473 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4474 MockRead("WWW-Authenticate: NTLM " 4475 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo" 4476 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4477 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4478 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4479 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4480 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4481 "BtAAAAAAA=\r\n"), 4482 MockRead("Content-Length: 42\r\n"), 4483 MockRead("Content-Type: text/html\r\n\r\n"), 4484 MockRead("You are not authorized to view this page\r\n"), 4485 4486 // Wrong password. 4487 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4488 MockRead("WWW-Authenticate: NTLM\r\n"), 4489 MockRead("Connection: close\r\n"), 4490 MockRead("Content-Length: 42\r\n"), 4491 MockRead("Content-Type: text/html\r\n\r\n"), 4492 // Missing content -- won't matter, as connection will be reset. 4493 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), 4494 }; 4495 4496 MockWrite data_writes3[] = { 4497 // After restarting with a null identity, this is the 4498 // request we should be issuing -- the final header line contains a Type 4499 // 1 message. 4500 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4501 "Host: 172.22.68.17\r\n" 4502 "Connection: keep-alive\r\n" 4503 "Authorization: NTLM " 4504 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"), 4505 4506 // After calling trans->RestartWithAuth(), we should send a Type 3 message 4507 // (the credentials for the origin server). The second request continues 4508 // on the same connection. 4509 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n" 4510 "Host: 172.22.68.17\r\n" 4511 "Connection: keep-alive\r\n" 4512 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA" 4513 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA" 4514 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54" 4515 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI" 4516 "+4MUm7c=\r\n\r\n"), 4517 }; 4518 4519 MockRead data_reads3[] = { 4520 // The origin server responds with a Type 2 message. 4521 MockRead("HTTP/1.1 401 Access Denied\r\n"), 4522 MockRead("WWW-Authenticate: NTLM " 4523 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo" 4524 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE" 4525 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA" 4526 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy" 4527 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB" 4528 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw" 4529 "BtAAAAAAA=\r\n"), 4530 MockRead("Content-Length: 42\r\n"), 4531 MockRead("Content-Type: text/html\r\n\r\n"), 4532 MockRead("You are not authorized to view this page\r\n"), 4533 4534 // Lastly we get the desired content. 4535 MockRead("HTTP/1.1 200 OK\r\n"), 4536 MockRead("Content-Type: text/html; charset=utf-8\r\n"), 4537 MockRead("Content-Length: 13\r\n\r\n"), 4538 MockRead("Please Login\r\n"), 4539 MockRead(SYNCHRONOUS, OK), 4540 }; 4541 4542 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4543 data_writes1, arraysize(data_writes1)); 4544 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 4545 data_writes2, arraysize(data_writes2)); 4546 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 4547 data_writes3, arraysize(data_writes3)); 4548 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4549 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4550 session_deps_.socket_factory->AddSocketDataProvider(&data3); 4551 4552 TestCompletionCallback callback1; 4553 4554 scoped_ptr<HttpTransaction> trans( 4555 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4556 4557 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4558 EXPECT_EQ(ERR_IO_PENDING, rv); 4559 4560 rv = callback1.WaitForResult(); 4561 EXPECT_EQ(OK, rv); 4562 4563 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4564 4565 const HttpResponseInfo* response = trans->GetResponseInfo(); 4566 ASSERT_TRUE(response != NULL); 4567 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4568 4569 TestCompletionCallback callback2; 4570 4571 // Enter the wrong password. 4572 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword), 4573 callback2.callback()); 4574 EXPECT_EQ(ERR_IO_PENDING, rv); 4575 4576 rv = callback2.WaitForResult(); 4577 EXPECT_EQ(OK, rv); 4578 4579 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4580 TestCompletionCallback callback3; 4581 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback()); 4582 EXPECT_EQ(ERR_IO_PENDING, rv); 4583 rv = callback3.WaitForResult(); 4584 EXPECT_EQ(OK, rv); 4585 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 4586 4587 response = trans->GetResponseInfo(); 4588 ASSERT_FALSE(response == NULL); 4589 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get())); 4590 4591 TestCompletionCallback callback4; 4592 4593 // Now enter the right password. 4594 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM), 4595 callback4.callback()); 4596 EXPECT_EQ(ERR_IO_PENDING, rv); 4597 4598 rv = callback4.WaitForResult(); 4599 EXPECT_EQ(OK, rv); 4600 4601 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 4602 4603 TestCompletionCallback callback5; 4604 4605 // One more roundtrip 4606 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback()); 4607 EXPECT_EQ(ERR_IO_PENDING, rv); 4608 4609 rv = callback5.WaitForResult(); 4610 EXPECT_EQ(OK, rv); 4611 4612 response = trans->GetResponseInfo(); 4613 EXPECT_TRUE(response->auth_challenge.get() == NULL); 4614 EXPECT_EQ(13, response->headers->GetContentLength()); 4615 } 4616 #endif // NTLM_PORTABLE 4617 4618 // Test reading a server response which has only headers, and no body. 4619 // After some maximum number of bytes is consumed, the transaction should 4620 // fail with ERR_RESPONSE_HEADERS_TOO_BIG. 4621 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) { 4622 HttpRequestInfo request; 4623 request.method = "GET"; 4624 request.url = GURL("http://www.google.com/"); 4625 request.load_flags = 0; 4626 4627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4628 scoped_ptr<HttpTransaction> trans( 4629 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 4630 4631 // Respond with 300 kb of headers (we should fail after 256 kb). 4632 std::string large_headers_string; 4633 FillLargeHeadersString(&large_headers_string, 300 * 1024); 4634 4635 MockRead data_reads[] = { 4636 MockRead("HTTP/1.0 200 OK\r\n"), 4637 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()), 4638 MockRead("\r\nBODY"), 4639 MockRead(SYNCHRONOUS, OK), 4640 }; 4641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4642 session_deps_.socket_factory->AddSocketDataProvider(&data); 4643 4644 TestCompletionCallback callback; 4645 4646 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4647 EXPECT_EQ(ERR_IO_PENDING, rv); 4648 4649 rv = callback.WaitForResult(); 4650 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv); 4651 4652 const HttpResponseInfo* response = trans->GetResponseInfo(); 4653 EXPECT_TRUE(response == NULL); 4654 } 4655 4656 // Make sure that we don't try to reuse a TCPClientSocket when failing to 4657 // establish tunnel. 4658 // http://code.google.com/p/chromium/issues/detail?id=3772 4659 TEST_P(HttpNetworkTransactionTest, 4660 DontRecycleTransportSocketForSSLTunnel) { 4661 HttpRequestInfo request; 4662 request.method = "GET"; 4663 request.url = GURL("https://www.google.com/"); 4664 request.load_flags = 0; 4665 4666 // Configure against proxy server "myproxy:70". 4667 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 4668 4669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4670 4671 scoped_ptr<HttpTransaction> trans( 4672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4673 4674 // Since we have proxy, should try to establish tunnel. 4675 MockWrite data_writes1[] = { 4676 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 4677 "Host: www.google.com\r\n" 4678 "Proxy-Connection: keep-alive\r\n\r\n"), 4679 }; 4680 4681 // The proxy responds to the connect with a 404, using a persistent 4682 // connection. Usually a proxy would return 501 (not implemented), 4683 // or 200 (tunnel established). 4684 MockRead data_reads1[] = { 4685 MockRead("HTTP/1.1 404 Not Found\r\n"), 4686 MockRead("Content-Length: 10\r\n\r\n"), 4687 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. 4688 }; 4689 4690 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 4691 data_writes1, arraysize(data_writes1)); 4692 session_deps_.socket_factory->AddSocketDataProvider(&data1); 4693 4694 TestCompletionCallback callback1; 4695 4696 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 4697 EXPECT_EQ(ERR_IO_PENDING, rv); 4698 4699 rv = callback1.WaitForResult(); 4700 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 4701 4702 const HttpResponseInfo* response = trans->GetResponseInfo(); 4703 EXPECT_TRUE(response == NULL); 4704 4705 // Empty the current queue. This is necessary because idle sockets are 4706 // added to the connection pool asynchronously with a PostTask. 4707 base::MessageLoop::current()->RunUntilIdle(); 4708 4709 // We now check to make sure the TCPClientSocket was not added back to 4710 // the pool. 4711 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4712 trans.reset(); 4713 base::MessageLoop::current()->RunUntilIdle(); 4714 // Make sure that the socket didn't get recycled after calling the destructor. 4715 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4716 } 4717 4718 // Make sure that we recycle a socket after reading all of the response body. 4719 TEST_P(HttpNetworkTransactionTest, RecycleSocket) { 4720 HttpRequestInfo request; 4721 request.method = "GET"; 4722 request.url = GURL("http://www.google.com/"); 4723 request.load_flags = 0; 4724 4725 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4726 4727 scoped_ptr<HttpTransaction> trans( 4728 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4729 4730 MockRead data_reads[] = { 4731 // A part of the response body is received with the response headers. 4732 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"), 4733 // The rest of the response body is received in two parts. 4734 MockRead("lo"), 4735 MockRead(" world"), 4736 MockRead("junk"), // Should not be read!! 4737 MockRead(SYNCHRONOUS, OK), 4738 }; 4739 4740 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4741 session_deps_.socket_factory->AddSocketDataProvider(&data); 4742 4743 TestCompletionCallback callback; 4744 4745 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4746 EXPECT_EQ(ERR_IO_PENDING, rv); 4747 4748 rv = callback.WaitForResult(); 4749 EXPECT_EQ(OK, rv); 4750 4751 const HttpResponseInfo* response = trans->GetResponseInfo(); 4752 ASSERT_TRUE(response != NULL); 4753 4754 EXPECT_TRUE(response->headers.get() != NULL); 4755 std::string status_line = response->headers->GetStatusLine(); 4756 EXPECT_EQ("HTTP/1.1 200 OK", status_line); 4757 4758 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4759 4760 std::string response_data; 4761 rv = ReadTransaction(trans.get(), &response_data); 4762 EXPECT_EQ(OK, rv); 4763 EXPECT_EQ("hello world", response_data); 4764 4765 // Empty the current queue. This is necessary because idle sockets are 4766 // added to the connection pool asynchronously with a PostTask. 4767 base::MessageLoop::current()->RunUntilIdle(); 4768 4769 // We now check to make sure the socket was added back to the pool. 4770 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get())); 4771 } 4772 4773 // Make sure that we recycle a SSL socket after reading all of the response 4774 // body. 4775 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) { 4776 HttpRequestInfo request; 4777 request.method = "GET"; 4778 request.url = GURL("https://www.google.com/"); 4779 request.load_flags = 0; 4780 4781 MockWrite data_writes[] = { 4782 MockWrite("GET / HTTP/1.1\r\n" 4783 "Host: www.google.com\r\n" 4784 "Connection: keep-alive\r\n\r\n"), 4785 }; 4786 4787 MockRead data_reads[] = { 4788 MockRead("HTTP/1.1 200 OK\r\n"), 4789 MockRead("Content-Length: 11\r\n\r\n"), 4790 MockRead("hello world"), 4791 MockRead(SYNCHRONOUS, OK), 4792 }; 4793 4794 SSLSocketDataProvider ssl(ASYNC, OK); 4795 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 4796 4797 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4798 data_writes, arraysize(data_writes)); 4799 session_deps_.socket_factory->AddSocketDataProvider(&data); 4800 4801 TestCompletionCallback callback; 4802 4803 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4804 scoped_ptr<HttpTransaction> trans( 4805 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4806 4807 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4808 4809 EXPECT_EQ(ERR_IO_PENDING, rv); 4810 EXPECT_EQ(OK, callback.WaitForResult()); 4811 4812 const HttpResponseInfo* response = trans->GetResponseInfo(); 4813 ASSERT_TRUE(response != NULL); 4814 ASSERT_TRUE(response->headers.get() != NULL); 4815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4816 4817 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4818 4819 std::string response_data; 4820 rv = ReadTransaction(trans.get(), &response_data); 4821 EXPECT_EQ(OK, rv); 4822 EXPECT_EQ("hello world", response_data); 4823 4824 // Empty the current queue. This is necessary because idle sockets are 4825 // added to the connection pool asynchronously with a PostTask. 4826 base::MessageLoop::current()->RunUntilIdle(); 4827 4828 // We now check to make sure the socket was added back to the pool. 4829 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4830 } 4831 4832 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it 4833 // from the pool and make sure that we recover okay. 4834 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) { 4835 HttpRequestInfo request; 4836 request.method = "GET"; 4837 request.url = GURL("https://www.google.com/"); 4838 request.load_flags = 0; 4839 4840 MockWrite data_writes[] = { 4841 MockWrite("GET / HTTP/1.1\r\n" 4842 "Host: www.google.com\r\n" 4843 "Connection: keep-alive\r\n\r\n"), 4844 MockWrite("GET / HTTP/1.1\r\n" 4845 "Host: www.google.com\r\n" 4846 "Connection: keep-alive\r\n\r\n"), 4847 }; 4848 4849 MockRead data_reads[] = { 4850 MockRead("HTTP/1.1 200 OK\r\n"), 4851 MockRead("Content-Length: 11\r\n\r\n"), 4852 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 4853 MockRead("hello world"), 4854 MockRead(ASYNC, 0, 0) // EOF 4855 }; 4856 4857 SSLSocketDataProvider ssl(ASYNC, OK); 4858 SSLSocketDataProvider ssl2(ASYNC, OK); 4859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 4860 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); 4861 4862 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 4863 data_writes, arraysize(data_writes)); 4864 StaticSocketDataProvider data2(data_reads, arraysize(data_reads), 4865 data_writes, arraysize(data_writes)); 4866 session_deps_.socket_factory->AddSocketDataProvider(&data); 4867 session_deps_.socket_factory->AddSocketDataProvider(&data2); 4868 4869 TestCompletionCallback callback; 4870 4871 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4872 scoped_ptr<HttpTransaction> trans( 4873 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4874 4875 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4876 4877 EXPECT_EQ(ERR_IO_PENDING, rv); 4878 EXPECT_EQ(OK, callback.WaitForResult()); 4879 4880 const HttpResponseInfo* response = trans->GetResponseInfo(); 4881 ASSERT_TRUE(response != NULL); 4882 ASSERT_TRUE(response->headers.get() != NULL); 4883 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4884 4885 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4886 4887 std::string response_data; 4888 rv = ReadTransaction(trans.get(), &response_data); 4889 EXPECT_EQ(OK, rv); 4890 EXPECT_EQ("hello world", response_data); 4891 4892 // Empty the current queue. This is necessary because idle sockets are 4893 // added to the connection pool asynchronously with a PostTask. 4894 base::MessageLoop::current()->RunUntilIdle(); 4895 4896 // We now check to make sure the socket was added back to the pool. 4897 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4898 4899 // Now start the second transaction, which should reuse the previous socket. 4900 4901 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4902 4903 rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4904 4905 EXPECT_EQ(ERR_IO_PENDING, rv); 4906 EXPECT_EQ(OK, callback.WaitForResult()); 4907 4908 response = trans->GetResponseInfo(); 4909 ASSERT_TRUE(response != NULL); 4910 ASSERT_TRUE(response->headers.get() != NULL); 4911 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 4912 4913 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4914 4915 rv = ReadTransaction(trans.get(), &response_data); 4916 EXPECT_EQ(OK, rv); 4917 EXPECT_EQ("hello world", response_data); 4918 4919 // Empty the current queue. This is necessary because idle sockets are 4920 // added to the connection pool asynchronously with a PostTask. 4921 base::MessageLoop::current()->RunUntilIdle(); 4922 4923 // We now check to make sure the socket was added back to the pool. 4924 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get())); 4925 } 4926 4927 // Make sure that we recycle a socket after a zero-length response. 4928 // http://crbug.com/9880 4929 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { 4930 HttpRequestInfo request; 4931 request.method = "GET"; 4932 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&" 4933 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&" 4934 "e=17259,18167,19592,19773,19981,20133,20173,20233&" 4935 "rt=prt.2642,ol.2649,xjs.2951"); 4936 request.load_flags = 0; 4937 4938 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 4939 4940 scoped_ptr<HttpTransaction> trans( 4941 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 4942 4943 MockRead data_reads[] = { 4944 MockRead("HTTP/1.1 204 No Content\r\n" 4945 "Content-Length: 0\r\n" 4946 "Content-Type: text/html\r\n\r\n"), 4947 MockRead("junk"), // Should not be read!! 4948 MockRead(SYNCHRONOUS, OK), 4949 }; 4950 4951 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); 4952 session_deps_.socket_factory->AddSocketDataProvider(&data); 4953 4954 TestCompletionCallback callback; 4955 4956 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 4957 EXPECT_EQ(ERR_IO_PENDING, rv); 4958 4959 rv = callback.WaitForResult(); 4960 EXPECT_EQ(OK, rv); 4961 4962 const HttpResponseInfo* response = trans->GetResponseInfo(); 4963 ASSERT_TRUE(response != NULL); 4964 4965 EXPECT_TRUE(response->headers.get() != NULL); 4966 std::string status_line = response->headers->GetStatusLine(); 4967 EXPECT_EQ("HTTP/1.1 204 No Content", status_line); 4968 4969 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get())); 4970 4971 std::string response_data; 4972 rv = ReadTransaction(trans.get(), &response_data); 4973 EXPECT_EQ(OK, rv); 4974 EXPECT_EQ("", response_data); 4975 4976 // Empty the current queue. This is necessary because idle sockets are 4977 // added to the connection pool asynchronously with a PostTask. 4978 base::MessageLoop::current()->RunUntilIdle(); 4979 4980 // We now check to make sure the socket was added back to the pool. 4981 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get())); 4982 } 4983 4984 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) { 4985 ScopedVector<UploadElementReader> element_readers; 4986 element_readers.push_back(new UploadBytesElementReader("foo", 3)); 4987 UploadDataStream upload_data_stream(element_readers.Pass(), 0); 4988 4989 HttpRequestInfo request[2]; 4990 // Transaction 1: a GET request that succeeds. The socket is recycled 4991 // after use. 4992 request[0].method = "GET"; 4993 request[0].url = GURL("http://www.google.com/"); 4994 request[0].load_flags = 0; 4995 // Transaction 2: a POST request. Reuses the socket kept alive from 4996 // transaction 1. The first attempts fails when writing the POST data. 4997 // This causes the transaction to retry with a new socket. The second 4998 // attempt succeeds. 4999 request[1].method = "POST"; 5000 request[1].url = GURL("http://www.google.com/login.cgi"); 5001 request[1].upload_data_stream = &upload_data_stream; 5002 request[1].load_flags = 0; 5003 5004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5005 5006 // The first socket is used for transaction 1 and the first attempt of 5007 // transaction 2. 5008 5009 // The response of transaction 1. 5010 MockRead data_reads1[] = { 5011 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"), 5012 MockRead("hello world"), 5013 MockRead(SYNCHRONOUS, OK), 5014 }; 5015 // The mock write results of transaction 1 and the first attempt of 5016 // transaction 2. 5017 MockWrite data_writes1[] = { 5018 MockWrite(SYNCHRONOUS, 64), // GET 5019 MockWrite(SYNCHRONOUS, 93), // POST 5020 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data 5021 }; 5022 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5023 data_writes1, arraysize(data_writes1)); 5024 5025 // The second socket is used for the second attempt of transaction 2. 5026 5027 // The response of transaction 2. 5028 MockRead data_reads2[] = { 5029 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"), 5030 MockRead("welcome"), 5031 MockRead(SYNCHRONOUS, OK), 5032 }; 5033 // The mock write results of the second attempt of transaction 2. 5034 MockWrite data_writes2[] = { 5035 MockWrite(SYNCHRONOUS, 93), // POST 5036 MockWrite(SYNCHRONOUS, 3), // POST data 5037 }; 5038 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5039 data_writes2, arraysize(data_writes2)); 5040 5041 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5042 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5043 5044 const char* kExpectedResponseData[] = { 5045 "hello world", "welcome" 5046 }; 5047 5048 for (int i = 0; i < 2; ++i) { 5049 scoped_ptr<HttpTransaction> trans( 5050 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5051 5052 TestCompletionCallback callback; 5053 5054 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog()); 5055 EXPECT_EQ(ERR_IO_PENDING, rv); 5056 5057 rv = callback.WaitForResult(); 5058 EXPECT_EQ(OK, rv); 5059 5060 const HttpResponseInfo* response = trans->GetResponseInfo(); 5061 ASSERT_TRUE(response != NULL); 5062 5063 EXPECT_TRUE(response->headers.get() != NULL); 5064 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); 5065 5066 std::string response_data; 5067 rv = ReadTransaction(trans.get(), &response_data); 5068 EXPECT_EQ(OK, rv); 5069 EXPECT_EQ(kExpectedResponseData[i], response_data); 5070 } 5071 } 5072 5073 // Test the request-challenge-retry sequence for basic auth when there is 5074 // an identity in the URL. The request should be sent as normal, but when 5075 // it fails the identity from the URL is used to answer the challenge. 5076 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) { 5077 HttpRequestInfo request; 5078 request.method = "GET"; 5079 request.url = GURL("http://foo:b@r@www.google.com/"); 5080 request.load_flags = LOAD_NORMAL; 5081 5082 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5083 scoped_ptr<HttpTransaction> trans( 5084 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5085 5086 // The password contains an escaped character -- for this test to pass it 5087 // will need to be unescaped by HttpNetworkTransaction. 5088 EXPECT_EQ("b%40r", request.url.password()); 5089 5090 MockWrite data_writes1[] = { 5091 MockWrite("GET / HTTP/1.1\r\n" 5092 "Host: www.google.com\r\n" 5093 "Connection: keep-alive\r\n\r\n"), 5094 }; 5095 5096 MockRead data_reads1[] = { 5097 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5098 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5099 MockRead("Content-Length: 10\r\n\r\n"), 5100 MockRead(SYNCHRONOUS, ERR_FAILED), 5101 }; 5102 5103 // After the challenge above, the transaction will be restarted using the 5104 // identity from the url (foo, b@r) to answer the challenge. 5105 MockWrite data_writes2[] = { 5106 MockWrite("GET / HTTP/1.1\r\n" 5107 "Host: www.google.com\r\n" 5108 "Connection: keep-alive\r\n" 5109 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"), 5110 }; 5111 5112 MockRead data_reads2[] = { 5113 MockRead("HTTP/1.0 200 OK\r\n"), 5114 MockRead("Content-Length: 100\r\n\r\n"), 5115 MockRead(SYNCHRONOUS, OK), 5116 }; 5117 5118 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5119 data_writes1, arraysize(data_writes1)); 5120 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5121 data_writes2, arraysize(data_writes2)); 5122 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5123 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5124 5125 TestCompletionCallback callback1; 5126 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5127 EXPECT_EQ(ERR_IO_PENDING, rv); 5128 rv = callback1.WaitForResult(); 5129 EXPECT_EQ(OK, rv); 5130 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5131 5132 TestCompletionCallback callback2; 5133 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5134 EXPECT_EQ(ERR_IO_PENDING, rv); 5135 rv = callback2.WaitForResult(); 5136 EXPECT_EQ(OK, rv); 5137 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5138 5139 const HttpResponseInfo* response = trans->GetResponseInfo(); 5140 ASSERT_TRUE(response != NULL); 5141 5142 // There is no challenge info, since the identity in URL worked. 5143 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5144 5145 EXPECT_EQ(100, response->headers->GetContentLength()); 5146 5147 // Empty the current queue. 5148 base::MessageLoop::current()->RunUntilIdle(); 5149 } 5150 5151 // Test the request-challenge-retry sequence for basic auth when there is an 5152 // incorrect identity in the URL. The identity from the URL should be used only 5153 // once. 5154 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) { 5155 HttpRequestInfo request; 5156 request.method = "GET"; 5157 // Note: the URL has a username:password in it. The password "baz" is 5158 // wrong (should be "bar"). 5159 request.url = GURL("http://foo:baz@www.google.com/"); 5160 5161 request.load_flags = LOAD_NORMAL; 5162 5163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5164 scoped_ptr<HttpTransaction> trans( 5165 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5166 5167 MockWrite data_writes1[] = { 5168 MockWrite("GET / HTTP/1.1\r\n" 5169 "Host: www.google.com\r\n" 5170 "Connection: keep-alive\r\n\r\n"), 5171 }; 5172 5173 MockRead data_reads1[] = { 5174 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5175 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5176 MockRead("Content-Length: 10\r\n\r\n"), 5177 MockRead(SYNCHRONOUS, ERR_FAILED), 5178 }; 5179 5180 // After the challenge above, the transaction will be restarted using the 5181 // identity from the url (foo, baz) to answer the challenge. 5182 MockWrite data_writes2[] = { 5183 MockWrite("GET / HTTP/1.1\r\n" 5184 "Host: www.google.com\r\n" 5185 "Connection: keep-alive\r\n" 5186 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"), 5187 }; 5188 5189 MockRead data_reads2[] = { 5190 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5191 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5192 MockRead("Content-Length: 10\r\n\r\n"), 5193 MockRead(SYNCHRONOUS, ERR_FAILED), 5194 }; 5195 5196 // After the challenge above, the transaction will be restarted using the 5197 // identity supplied by the user (foo, bar) to answer the challenge. 5198 MockWrite data_writes3[] = { 5199 MockWrite("GET / HTTP/1.1\r\n" 5200 "Host: www.google.com\r\n" 5201 "Connection: keep-alive\r\n" 5202 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5203 }; 5204 5205 MockRead data_reads3[] = { 5206 MockRead("HTTP/1.0 200 OK\r\n"), 5207 MockRead("Content-Length: 100\r\n\r\n"), 5208 MockRead(SYNCHRONOUS, OK), 5209 }; 5210 5211 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5212 data_writes1, arraysize(data_writes1)); 5213 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5214 data_writes2, arraysize(data_writes2)); 5215 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 5216 data_writes3, arraysize(data_writes3)); 5217 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5218 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5219 session_deps_.socket_factory->AddSocketDataProvider(&data3); 5220 5221 TestCompletionCallback callback1; 5222 5223 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5224 EXPECT_EQ(ERR_IO_PENDING, rv); 5225 5226 rv = callback1.WaitForResult(); 5227 EXPECT_EQ(OK, rv); 5228 5229 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5230 TestCompletionCallback callback2; 5231 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5232 EXPECT_EQ(ERR_IO_PENDING, rv); 5233 rv = callback2.WaitForResult(); 5234 EXPECT_EQ(OK, rv); 5235 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5236 5237 const HttpResponseInfo* response = trans->GetResponseInfo(); 5238 ASSERT_TRUE(response != NULL); 5239 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5240 5241 TestCompletionCallback callback3; 5242 rv = trans->RestartWithAuth( 5243 AuthCredentials(kFoo, kBar), callback3.callback()); 5244 EXPECT_EQ(ERR_IO_PENDING, rv); 5245 rv = callback3.WaitForResult(); 5246 EXPECT_EQ(OK, rv); 5247 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5248 5249 response = trans->GetResponseInfo(); 5250 ASSERT_TRUE(response != NULL); 5251 5252 // There is no challenge info, since the identity worked. 5253 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5254 5255 EXPECT_EQ(100, response->headers->GetContentLength()); 5256 5257 // Empty the current queue. 5258 base::MessageLoop::current()->RunUntilIdle(); 5259 } 5260 5261 5262 // Test the request-challenge-retry sequence for basic auth when there is a 5263 // correct identity in the URL, but its use is being suppressed. The identity 5264 // from the URL should never be used. 5265 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) { 5266 HttpRequestInfo request; 5267 request.method = "GET"; 5268 request.url = GURL("http://foo:bar@www.google.com/"); 5269 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY; 5270 5271 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5272 scoped_ptr<HttpTransaction> trans( 5273 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5274 5275 MockWrite data_writes1[] = { 5276 MockWrite("GET / HTTP/1.1\r\n" 5277 "Host: www.google.com\r\n" 5278 "Connection: keep-alive\r\n\r\n"), 5279 }; 5280 5281 MockRead data_reads1[] = { 5282 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5283 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5284 MockRead("Content-Length: 10\r\n\r\n"), 5285 MockRead(SYNCHRONOUS, ERR_FAILED), 5286 }; 5287 5288 // After the challenge above, the transaction will be restarted using the 5289 // identity supplied by the user, not the one in the URL, to answer the 5290 // challenge. 5291 MockWrite data_writes3[] = { 5292 MockWrite("GET / HTTP/1.1\r\n" 5293 "Host: www.google.com\r\n" 5294 "Connection: keep-alive\r\n" 5295 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5296 }; 5297 5298 MockRead data_reads3[] = { 5299 MockRead("HTTP/1.0 200 OK\r\n"), 5300 MockRead("Content-Length: 100\r\n\r\n"), 5301 MockRead(SYNCHRONOUS, OK), 5302 }; 5303 5304 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5305 data_writes1, arraysize(data_writes1)); 5306 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 5307 data_writes3, arraysize(data_writes3)); 5308 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5309 session_deps_.socket_factory->AddSocketDataProvider(&data3); 5310 5311 TestCompletionCallback callback1; 5312 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5313 EXPECT_EQ(ERR_IO_PENDING, rv); 5314 rv = callback1.WaitForResult(); 5315 EXPECT_EQ(OK, rv); 5316 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5317 5318 const HttpResponseInfo* response = trans->GetResponseInfo(); 5319 ASSERT_TRUE(response != NULL); 5320 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5321 5322 TestCompletionCallback callback3; 5323 rv = trans->RestartWithAuth( 5324 AuthCredentials(kFoo, kBar), callback3.callback()); 5325 EXPECT_EQ(ERR_IO_PENDING, rv); 5326 rv = callback3.WaitForResult(); 5327 EXPECT_EQ(OK, rv); 5328 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5329 5330 response = trans->GetResponseInfo(); 5331 ASSERT_TRUE(response != NULL); 5332 5333 // There is no challenge info, since the identity worked. 5334 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5335 EXPECT_EQ(100, response->headers->GetContentLength()); 5336 5337 // Empty the current queue. 5338 base::MessageLoop::current()->RunUntilIdle(); 5339 } 5340 5341 // Test that previously tried username/passwords for a realm get re-used. 5342 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) { 5343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5344 5345 // Transaction 1: authenticate (foo, bar) on MyRealm1 5346 { 5347 HttpRequestInfo request; 5348 request.method = "GET"; 5349 request.url = GURL("http://www.google.com/x/y/z"); 5350 request.load_flags = 0; 5351 5352 scoped_ptr<HttpTransaction> trans( 5353 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5354 5355 MockWrite data_writes1[] = { 5356 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5357 "Host: www.google.com\r\n" 5358 "Connection: keep-alive\r\n\r\n"), 5359 }; 5360 5361 MockRead data_reads1[] = { 5362 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5363 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5364 MockRead("Content-Length: 10000\r\n\r\n"), 5365 MockRead(SYNCHRONOUS, ERR_FAILED), 5366 }; 5367 5368 // Resend with authorization (username=foo, password=bar) 5369 MockWrite data_writes2[] = { 5370 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5371 "Host: www.google.com\r\n" 5372 "Connection: keep-alive\r\n" 5373 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5374 }; 5375 5376 // Sever accepts the authorization. 5377 MockRead data_reads2[] = { 5378 MockRead("HTTP/1.0 200 OK\r\n"), 5379 MockRead("Content-Length: 100\r\n\r\n"), 5380 MockRead(SYNCHRONOUS, OK), 5381 }; 5382 5383 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5384 data_writes1, arraysize(data_writes1)); 5385 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5386 data_writes2, arraysize(data_writes2)); 5387 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5388 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5389 5390 TestCompletionCallback callback1; 5391 5392 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5393 EXPECT_EQ(ERR_IO_PENDING, rv); 5394 5395 rv = callback1.WaitForResult(); 5396 EXPECT_EQ(OK, rv); 5397 5398 const HttpResponseInfo* response = trans->GetResponseInfo(); 5399 ASSERT_TRUE(response != NULL); 5400 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5401 5402 TestCompletionCallback callback2; 5403 5404 rv = trans->RestartWithAuth( 5405 AuthCredentials(kFoo, kBar), callback2.callback()); 5406 EXPECT_EQ(ERR_IO_PENDING, rv); 5407 5408 rv = callback2.WaitForResult(); 5409 EXPECT_EQ(OK, rv); 5410 5411 response = trans->GetResponseInfo(); 5412 ASSERT_TRUE(response != NULL); 5413 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5414 EXPECT_EQ(100, response->headers->GetContentLength()); 5415 } 5416 5417 // ------------------------------------------------------------------------ 5418 5419 // Transaction 2: authenticate (foo2, bar2) on MyRealm2 5420 { 5421 HttpRequestInfo request; 5422 request.method = "GET"; 5423 // Note that Transaction 1 was at /x/y/z, so this is in the same 5424 // protection space as MyRealm1. 5425 request.url = GURL("http://www.google.com/x/y/a/b"); 5426 request.load_flags = 0; 5427 5428 scoped_ptr<HttpTransaction> trans( 5429 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5430 5431 MockWrite data_writes1[] = { 5432 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5433 "Host: www.google.com\r\n" 5434 "Connection: keep-alive\r\n" 5435 // Send preemptive authorization for MyRealm1 5436 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5437 }; 5438 5439 // The server didn't like the preemptive authorization, and 5440 // challenges us for a different realm (MyRealm2). 5441 MockRead data_reads1[] = { 5442 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5443 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"), 5444 MockRead("Content-Length: 10000\r\n\r\n"), 5445 MockRead(SYNCHRONOUS, ERR_FAILED), 5446 }; 5447 5448 // Resend with authorization for MyRealm2 (username=foo2, password=bar2) 5449 MockWrite data_writes2[] = { 5450 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5451 "Host: www.google.com\r\n" 5452 "Connection: keep-alive\r\n" 5453 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"), 5454 }; 5455 5456 // Sever accepts the authorization. 5457 MockRead data_reads2[] = { 5458 MockRead("HTTP/1.0 200 OK\r\n"), 5459 MockRead("Content-Length: 100\r\n\r\n"), 5460 MockRead(SYNCHRONOUS, OK), 5461 }; 5462 5463 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5464 data_writes1, arraysize(data_writes1)); 5465 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5466 data_writes2, arraysize(data_writes2)); 5467 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5468 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5469 5470 TestCompletionCallback callback1; 5471 5472 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5473 EXPECT_EQ(ERR_IO_PENDING, rv); 5474 5475 rv = callback1.WaitForResult(); 5476 EXPECT_EQ(OK, rv); 5477 5478 const HttpResponseInfo* response = trans->GetResponseInfo(); 5479 ASSERT_TRUE(response != NULL); 5480 ASSERT_TRUE(response->auth_challenge.get()); 5481 EXPECT_FALSE(response->auth_challenge->is_proxy); 5482 EXPECT_EQ("www.google.com:80", 5483 response->auth_challenge->challenger.ToString()); 5484 EXPECT_EQ("MyRealm2", response->auth_challenge->realm); 5485 EXPECT_EQ("basic", response->auth_challenge->scheme); 5486 5487 TestCompletionCallback callback2; 5488 5489 rv = trans->RestartWithAuth( 5490 AuthCredentials(kFoo2, kBar2), callback2.callback()); 5491 EXPECT_EQ(ERR_IO_PENDING, rv); 5492 5493 rv = callback2.WaitForResult(); 5494 EXPECT_EQ(OK, rv); 5495 5496 response = trans->GetResponseInfo(); 5497 ASSERT_TRUE(response != NULL); 5498 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5499 EXPECT_EQ(100, response->headers->GetContentLength()); 5500 } 5501 5502 // ------------------------------------------------------------------------ 5503 5504 // Transaction 3: Resend a request in MyRealm's protection space -- 5505 // succeed with preemptive authorization. 5506 { 5507 HttpRequestInfo request; 5508 request.method = "GET"; 5509 request.url = GURL("http://www.google.com/x/y/z2"); 5510 request.load_flags = 0; 5511 5512 scoped_ptr<HttpTransaction> trans( 5513 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5514 5515 MockWrite data_writes1[] = { 5516 MockWrite("GET /x/y/z2 HTTP/1.1\r\n" 5517 "Host: www.google.com\r\n" 5518 "Connection: keep-alive\r\n" 5519 // The authorization for MyRealm1 gets sent preemptively 5520 // (since the url is in the same protection space) 5521 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5522 }; 5523 5524 // Sever accepts the preemptive authorization 5525 MockRead data_reads1[] = { 5526 MockRead("HTTP/1.0 200 OK\r\n"), 5527 MockRead("Content-Length: 100\r\n\r\n"), 5528 MockRead(SYNCHRONOUS, OK), 5529 }; 5530 5531 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5532 data_writes1, arraysize(data_writes1)); 5533 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5534 5535 TestCompletionCallback callback1; 5536 5537 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5538 EXPECT_EQ(ERR_IO_PENDING, rv); 5539 5540 rv = callback1.WaitForResult(); 5541 EXPECT_EQ(OK, rv); 5542 5543 const HttpResponseInfo* response = trans->GetResponseInfo(); 5544 ASSERT_TRUE(response != NULL); 5545 5546 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5547 EXPECT_EQ(100, response->headers->GetContentLength()); 5548 } 5549 5550 // ------------------------------------------------------------------------ 5551 5552 // Transaction 4: request another URL in MyRealm (however the 5553 // url is not known to belong to the protection space, so no pre-auth). 5554 { 5555 HttpRequestInfo request; 5556 request.method = "GET"; 5557 request.url = GURL("http://www.google.com/x/1"); 5558 request.load_flags = 0; 5559 5560 scoped_ptr<HttpTransaction> trans( 5561 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5562 5563 MockWrite data_writes1[] = { 5564 MockWrite("GET /x/1 HTTP/1.1\r\n" 5565 "Host: www.google.com\r\n" 5566 "Connection: keep-alive\r\n\r\n"), 5567 }; 5568 5569 MockRead data_reads1[] = { 5570 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5571 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5572 MockRead("Content-Length: 10000\r\n\r\n"), 5573 MockRead(SYNCHRONOUS, ERR_FAILED), 5574 }; 5575 5576 // Resend with authorization from MyRealm's cache. 5577 MockWrite data_writes2[] = { 5578 MockWrite("GET /x/1 HTTP/1.1\r\n" 5579 "Host: www.google.com\r\n" 5580 "Connection: keep-alive\r\n" 5581 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5582 }; 5583 5584 // Sever accepts the authorization. 5585 MockRead data_reads2[] = { 5586 MockRead("HTTP/1.0 200 OK\r\n"), 5587 MockRead("Content-Length: 100\r\n\r\n"), 5588 MockRead(SYNCHRONOUS, OK), 5589 }; 5590 5591 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5592 data_writes1, arraysize(data_writes1)); 5593 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5594 data_writes2, arraysize(data_writes2)); 5595 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5596 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5597 5598 TestCompletionCallback callback1; 5599 5600 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5601 EXPECT_EQ(ERR_IO_PENDING, rv); 5602 5603 rv = callback1.WaitForResult(); 5604 EXPECT_EQ(OK, rv); 5605 5606 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5607 TestCompletionCallback callback2; 5608 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5609 EXPECT_EQ(ERR_IO_PENDING, rv); 5610 rv = callback2.WaitForResult(); 5611 EXPECT_EQ(OK, rv); 5612 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5613 5614 const HttpResponseInfo* response = trans->GetResponseInfo(); 5615 ASSERT_TRUE(response != NULL); 5616 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5617 EXPECT_EQ(100, response->headers->GetContentLength()); 5618 } 5619 5620 // ------------------------------------------------------------------------ 5621 5622 // Transaction 5: request a URL in MyRealm, but the server rejects the 5623 // cached identity. Should invalidate and re-prompt. 5624 { 5625 HttpRequestInfo request; 5626 request.method = "GET"; 5627 request.url = GURL("http://www.google.com/p/q/t"); 5628 request.load_flags = 0; 5629 5630 scoped_ptr<HttpTransaction> trans( 5631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5632 5633 MockWrite data_writes1[] = { 5634 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5635 "Host: www.google.com\r\n" 5636 "Connection: keep-alive\r\n\r\n"), 5637 }; 5638 5639 MockRead data_reads1[] = { 5640 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5641 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5642 MockRead("Content-Length: 10000\r\n\r\n"), 5643 MockRead(SYNCHRONOUS, ERR_FAILED), 5644 }; 5645 5646 // Resend with authorization from cache for MyRealm. 5647 MockWrite data_writes2[] = { 5648 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5649 "Host: www.google.com\r\n" 5650 "Connection: keep-alive\r\n" 5651 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), 5652 }; 5653 5654 // Sever rejects the authorization. 5655 MockRead data_reads2[] = { 5656 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5657 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 5658 MockRead("Content-Length: 10000\r\n\r\n"), 5659 MockRead(SYNCHRONOUS, ERR_FAILED), 5660 }; 5661 5662 // At this point we should prompt for new credentials for MyRealm. 5663 // Restart with username=foo3, password=foo4. 5664 MockWrite data_writes3[] = { 5665 MockWrite("GET /p/q/t HTTP/1.1\r\n" 5666 "Host: www.google.com\r\n" 5667 "Connection: keep-alive\r\n" 5668 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"), 5669 }; 5670 5671 // Sever accepts the authorization. 5672 MockRead data_reads3[] = { 5673 MockRead("HTTP/1.0 200 OK\r\n"), 5674 MockRead("Content-Length: 100\r\n\r\n"), 5675 MockRead(SYNCHRONOUS, OK), 5676 }; 5677 5678 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5679 data_writes1, arraysize(data_writes1)); 5680 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5681 data_writes2, arraysize(data_writes2)); 5682 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3), 5683 data_writes3, arraysize(data_writes3)); 5684 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5685 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5686 session_deps_.socket_factory->AddSocketDataProvider(&data3); 5687 5688 TestCompletionCallback callback1; 5689 5690 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5691 EXPECT_EQ(ERR_IO_PENDING, rv); 5692 5693 rv = callback1.WaitForResult(); 5694 EXPECT_EQ(OK, rv); 5695 5696 EXPECT_TRUE(trans->IsReadyToRestartForAuth()); 5697 TestCompletionCallback callback2; 5698 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback()); 5699 EXPECT_EQ(ERR_IO_PENDING, rv); 5700 rv = callback2.WaitForResult(); 5701 EXPECT_EQ(OK, rv); 5702 EXPECT_FALSE(trans->IsReadyToRestartForAuth()); 5703 5704 const HttpResponseInfo* response = trans->GetResponseInfo(); 5705 ASSERT_TRUE(response != NULL); 5706 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); 5707 5708 TestCompletionCallback callback3; 5709 5710 rv = trans->RestartWithAuth( 5711 AuthCredentials(kFoo3, kBar3), callback3.callback()); 5712 EXPECT_EQ(ERR_IO_PENDING, rv); 5713 5714 rv = callback3.WaitForResult(); 5715 EXPECT_EQ(OK, rv); 5716 5717 response = trans->GetResponseInfo(); 5718 ASSERT_TRUE(response != NULL); 5719 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5720 EXPECT_EQ(100, response->headers->GetContentLength()); 5721 } 5722 } 5723 5724 // Tests that nonce count increments when multiple auth attempts 5725 // are started with the same nonce. 5726 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) { 5727 HttpAuthHandlerDigest::Factory* digest_factory = 5728 new HttpAuthHandlerDigest::Factory(); 5729 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator = 5730 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef"); 5731 digest_factory->set_nonce_generator(nonce_generator); 5732 session_deps_.http_auth_handler_factory.reset(digest_factory); 5733 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5734 5735 // Transaction 1: authenticate (foo, bar) on MyRealm1 5736 { 5737 HttpRequestInfo request; 5738 request.method = "GET"; 5739 request.url = GURL("http://www.google.com/x/y/z"); 5740 request.load_flags = 0; 5741 5742 scoped_ptr<HttpTransaction> trans( 5743 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5744 5745 MockWrite data_writes1[] = { 5746 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5747 "Host: www.google.com\r\n" 5748 "Connection: keep-alive\r\n\r\n"), 5749 }; 5750 5751 MockRead data_reads1[] = { 5752 MockRead("HTTP/1.0 401 Unauthorized\r\n"), 5753 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", " 5754 "algorithm=MD5, qop=\"auth\"\r\n\r\n"), 5755 MockRead(SYNCHRONOUS, OK), 5756 }; 5757 5758 // Resend with authorization (username=foo, password=bar) 5759 MockWrite data_writes2[] = { 5760 MockWrite("GET /x/y/z HTTP/1.1\r\n" 5761 "Host: www.google.com\r\n" 5762 "Connection: keep-alive\r\n" 5763 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 5764 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, " 5765 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, " 5766 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"), 5767 }; 5768 5769 // Sever accepts the authorization. 5770 MockRead data_reads2[] = { 5771 MockRead("HTTP/1.0 200 OK\r\n"), 5772 MockRead(SYNCHRONOUS, OK), 5773 }; 5774 5775 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5776 data_writes1, arraysize(data_writes1)); 5777 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), 5778 data_writes2, arraysize(data_writes2)); 5779 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5780 session_deps_.socket_factory->AddSocketDataProvider(&data2); 5781 5782 TestCompletionCallback callback1; 5783 5784 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5785 EXPECT_EQ(ERR_IO_PENDING, rv); 5786 5787 rv = callback1.WaitForResult(); 5788 EXPECT_EQ(OK, rv); 5789 5790 const HttpResponseInfo* response = trans->GetResponseInfo(); 5791 ASSERT_TRUE(response != NULL); 5792 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get())); 5793 5794 TestCompletionCallback callback2; 5795 5796 rv = trans->RestartWithAuth( 5797 AuthCredentials(kFoo, kBar), callback2.callback()); 5798 EXPECT_EQ(ERR_IO_PENDING, rv); 5799 5800 rv = callback2.WaitForResult(); 5801 EXPECT_EQ(OK, rv); 5802 5803 response = trans->GetResponseInfo(); 5804 ASSERT_TRUE(response != NULL); 5805 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5806 } 5807 5808 // ------------------------------------------------------------------------ 5809 5810 // Transaction 2: Request another resource in digestive's protection space. 5811 // This will preemptively add an Authorization header which should have an 5812 // "nc" value of 2 (as compared to 1 in the first use. 5813 { 5814 HttpRequestInfo request; 5815 request.method = "GET"; 5816 // Note that Transaction 1 was at /x/y/z, so this is in the same 5817 // protection space as digest. 5818 request.url = GURL("http://www.google.com/x/y/a/b"); 5819 request.load_flags = 0; 5820 5821 scoped_ptr<HttpTransaction> trans( 5822 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 5823 5824 MockWrite data_writes1[] = { 5825 MockWrite("GET /x/y/a/b HTTP/1.1\r\n" 5826 "Host: www.google.com\r\n" 5827 "Connection: keep-alive\r\n" 5828 "Authorization: Digest username=\"foo\", realm=\"digestive\", " 5829 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, " 5830 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, " 5831 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"), 5832 }; 5833 5834 // Sever accepts the authorization. 5835 MockRead data_reads1[] = { 5836 MockRead("HTTP/1.0 200 OK\r\n"), 5837 MockRead("Content-Length: 100\r\n\r\n"), 5838 MockRead(SYNCHRONOUS, OK), 5839 }; 5840 5841 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), 5842 data_writes1, arraysize(data_writes1)); 5843 session_deps_.socket_factory->AddSocketDataProvider(&data1); 5844 5845 TestCompletionCallback callback1; 5846 5847 int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); 5848 EXPECT_EQ(ERR_IO_PENDING, rv); 5849 5850 rv = callback1.WaitForResult(); 5851 EXPECT_EQ(OK, rv); 5852 5853 const HttpResponseInfo* response = trans->GetResponseInfo(); 5854 ASSERT_TRUE(response != NULL); 5855 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5856 } 5857 } 5858 5859 // Test the ResetStateForRestart() private method. 5860 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) { 5861 // Create a transaction (the dependencies aren't important). 5862 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5863 scoped_ptr<HttpNetworkTransaction> trans( 5864 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5865 5866 // Setup some state (which we expect ResetStateForRestart() will clear). 5867 trans->read_buf_ = new IOBuffer(15); 5868 trans->read_buf_len_ = 15; 5869 trans->request_headers_.SetHeader("Authorization", "NTLM"); 5870 5871 // Setup state in response_ 5872 HttpResponseInfo* response = &trans->response_; 5873 response->auth_challenge = new AuthChallengeInfo(); 5874 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical. 5875 response->response_time = base::Time::Now(); 5876 response->was_cached = true; // (Wouldn't ever actually be true...) 5877 5878 { // Setup state for response_.vary_data 5879 HttpRequestInfo request; 5880 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n"); 5881 std::replace(temp.begin(), temp.end(), '\n', '\0'); 5882 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp)); 5883 request.extra_headers.SetHeader("Foo", "1"); 5884 request.extra_headers.SetHeader("bar", "23"); 5885 EXPECT_TRUE(response->vary_data.Init(request, *headers.get())); 5886 } 5887 5888 // Cause the above state to be reset. 5889 trans->ResetStateForRestart(); 5890 5891 // Verify that the state that needed to be reset, has been reset. 5892 EXPECT_TRUE(trans->read_buf_.get() == NULL); 5893 EXPECT_EQ(0, trans->read_buf_len_); 5894 EXPECT_TRUE(trans->request_headers_.IsEmpty()); 5895 EXPECT_TRUE(response->auth_challenge.get() == NULL); 5896 EXPECT_TRUE(response->headers.get() == NULL); 5897 EXPECT_FALSE(response->was_cached); 5898 EXPECT_EQ(0U, response->ssl_info.cert_status); 5899 EXPECT_FALSE(response->vary_data.is_valid()); 5900 } 5901 5902 // Test HTTPS connections to a site with a bad certificate 5903 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) { 5904 HttpRequestInfo request; 5905 request.method = "GET"; 5906 request.url = GURL("https://www.google.com/"); 5907 request.load_flags = 0; 5908 5909 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 5910 scoped_ptr<HttpTransaction> trans( 5911 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 5912 5913 MockWrite data_writes[] = { 5914 MockWrite("GET / HTTP/1.1\r\n" 5915 "Host: www.google.com\r\n" 5916 "Connection: keep-alive\r\n\r\n"), 5917 }; 5918 5919 MockRead data_reads[] = { 5920 MockRead("HTTP/1.0 200 OK\r\n"), 5921 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5922 MockRead("Content-Length: 100\r\n\r\n"), 5923 MockRead(SYNCHRONOUS, OK), 5924 }; 5925 5926 StaticSocketDataProvider ssl_bad_certificate; 5927 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5928 data_writes, arraysize(data_writes)); 5929 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 5930 SSLSocketDataProvider ssl(ASYNC, OK); 5931 5932 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 5933 session_deps_.socket_factory->AddSocketDataProvider(&data); 5934 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 5935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 5936 5937 TestCompletionCallback callback; 5938 5939 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 5940 EXPECT_EQ(ERR_IO_PENDING, rv); 5941 5942 rv = callback.WaitForResult(); 5943 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 5944 5945 rv = trans->RestartIgnoringLastError(callback.callback()); 5946 EXPECT_EQ(ERR_IO_PENDING, rv); 5947 5948 rv = callback.WaitForResult(); 5949 EXPECT_EQ(OK, rv); 5950 5951 const HttpResponseInfo* response = trans->GetResponseInfo(); 5952 5953 ASSERT_TRUE(response != NULL); 5954 EXPECT_EQ(100, response->headers->GetContentLength()); 5955 } 5956 5957 // Test HTTPS connections to a site with a bad certificate, going through a 5958 // proxy 5959 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { 5960 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 5961 5962 HttpRequestInfo request; 5963 request.method = "GET"; 5964 request.url = GURL("https://www.google.com/"); 5965 request.load_flags = 0; 5966 5967 MockWrite proxy_writes[] = { 5968 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5969 "Host: www.google.com\r\n" 5970 "Proxy-Connection: keep-alive\r\n\r\n"), 5971 }; 5972 5973 MockRead proxy_reads[] = { 5974 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5975 MockRead(SYNCHRONOUS, OK) 5976 }; 5977 5978 MockWrite data_writes[] = { 5979 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 5980 "Host: www.google.com\r\n" 5981 "Proxy-Connection: keep-alive\r\n\r\n"), 5982 MockWrite("GET / HTTP/1.1\r\n" 5983 "Host: www.google.com\r\n" 5984 "Connection: keep-alive\r\n\r\n"), 5985 }; 5986 5987 MockRead data_reads[] = { 5988 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 5989 MockRead("HTTP/1.0 200 OK\r\n"), 5990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 5991 MockRead("Content-Length: 100\r\n\r\n"), 5992 MockRead(SYNCHRONOUS, OK), 5993 }; 5994 5995 StaticSocketDataProvider ssl_bad_certificate( 5996 proxy_reads, arraysize(proxy_reads), 5997 proxy_writes, arraysize(proxy_writes)); 5998 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 5999 data_writes, arraysize(data_writes)); 6000 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 6001 SSLSocketDataProvider ssl(ASYNC, OK); 6002 6003 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 6004 session_deps_.socket_factory->AddSocketDataProvider(&data); 6005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 6006 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6007 6008 TestCompletionCallback callback; 6009 6010 for (int i = 0; i < 2; i++) { 6011 session_deps_.socket_factory->ResetNextMockIndexes(); 6012 6013 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6014 scoped_ptr<HttpTransaction> trans( 6015 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6016 6017 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6018 EXPECT_EQ(ERR_IO_PENDING, rv); 6019 6020 rv = callback.WaitForResult(); 6021 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 6022 6023 rv = trans->RestartIgnoringLastError(callback.callback()); 6024 EXPECT_EQ(ERR_IO_PENDING, rv); 6025 6026 rv = callback.WaitForResult(); 6027 EXPECT_EQ(OK, rv); 6028 6029 const HttpResponseInfo* response = trans->GetResponseInfo(); 6030 6031 ASSERT_TRUE(response != NULL); 6032 EXPECT_EQ(100, response->headers->GetContentLength()); 6033 } 6034 } 6035 6036 6037 // Test HTTPS connections to a site, going through an HTTPS proxy 6038 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { 6039 session_deps_.proxy_service.reset( 6040 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 6041 CapturingNetLog net_log; 6042 session_deps_.net_log = &net_log; 6043 6044 HttpRequestInfo request; 6045 request.method = "GET"; 6046 request.url = GURL("https://www.google.com/"); 6047 request.load_flags = 0; 6048 6049 MockWrite data_writes[] = { 6050 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6051 "Host: www.google.com\r\n" 6052 "Proxy-Connection: keep-alive\r\n\r\n"), 6053 MockWrite("GET / HTTP/1.1\r\n" 6054 "Host: www.google.com\r\n" 6055 "Connection: keep-alive\r\n\r\n"), 6056 }; 6057 6058 MockRead data_reads[] = { 6059 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6060 MockRead("HTTP/1.1 200 OK\r\n"), 6061 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6062 MockRead("Content-Length: 100\r\n\r\n"), 6063 MockRead(SYNCHRONOUS, OK), 6064 }; 6065 6066 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6067 data_writes, arraysize(data_writes)); 6068 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6069 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel 6070 6071 session_deps_.socket_factory->AddSocketDataProvider(&data); 6072 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6073 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl); 6074 6075 TestCompletionCallback callback; 6076 6077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6078 scoped_ptr<HttpTransaction> trans( 6079 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6080 6081 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6082 EXPECT_EQ(ERR_IO_PENDING, rv); 6083 6084 rv = callback.WaitForResult(); 6085 EXPECT_EQ(OK, rv); 6086 const HttpResponseInfo* response = trans->GetResponseInfo(); 6087 6088 ASSERT_TRUE(response != NULL); 6089 6090 EXPECT_TRUE(response->headers->IsKeepAlive()); 6091 EXPECT_EQ(200, response->headers->response_code()); 6092 EXPECT_EQ(100, response->headers->GetContentLength()); 6093 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6094 6095 LoadTimingInfo load_timing_info; 6096 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6097 TestLoadTimingNotReusedWithPac(load_timing_info, 6098 CONNECT_TIMING_HAS_SSL_TIMES); 6099 } 6100 6101 // Test an HTTPS Proxy's ability to redirect a CONNECT request 6102 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { 6103 session_deps_.proxy_service.reset( 6104 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); 6105 CapturingNetLog net_log; 6106 session_deps_.net_log = &net_log; 6107 6108 HttpRequestInfo request; 6109 request.method = "GET"; 6110 request.url = GURL("https://www.google.com/"); 6111 request.load_flags = 0; 6112 6113 MockWrite data_writes[] = { 6114 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6115 "Host: www.google.com\r\n" 6116 "Proxy-Connection: keep-alive\r\n\r\n"), 6117 }; 6118 6119 MockRead data_reads[] = { 6120 MockRead("HTTP/1.1 302 Redirect\r\n"), 6121 MockRead("Location: http://login.example.com/\r\n"), 6122 MockRead("Content-Length: 0\r\n\r\n"), 6123 MockRead(SYNCHRONOUS, OK), 6124 }; 6125 6126 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6127 data_writes, arraysize(data_writes)); 6128 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6129 6130 session_deps_.socket_factory->AddSocketDataProvider(&data); 6131 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6132 6133 TestCompletionCallback callback; 6134 6135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6136 scoped_ptr<HttpTransaction> trans( 6137 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6138 6139 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6140 EXPECT_EQ(ERR_IO_PENDING, rv); 6141 6142 rv = callback.WaitForResult(); 6143 EXPECT_EQ(OK, rv); 6144 const HttpResponseInfo* response = trans->GetResponseInfo(); 6145 6146 ASSERT_TRUE(response != NULL); 6147 6148 EXPECT_EQ(302, response->headers->response_code()); 6149 std::string url; 6150 EXPECT_TRUE(response->headers->IsRedirect(&url)); 6151 EXPECT_EQ("http://login.example.com/", url); 6152 6153 // In the case of redirects from proxies, HttpNetworkTransaction returns 6154 // timing for the proxy connection instead of the connection to the host, 6155 // and no send / receive times. 6156 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse. 6157 LoadTimingInfo load_timing_info; 6158 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6159 6160 EXPECT_FALSE(load_timing_info.socket_reused); 6161 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 6162 6163 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); 6164 EXPECT_LE(load_timing_info.proxy_resolve_start, 6165 load_timing_info.proxy_resolve_end); 6166 EXPECT_LE(load_timing_info.proxy_resolve_end, 6167 load_timing_info.connect_timing.connect_start); 6168 ExpectConnectTimingHasTimes( 6169 load_timing_info.connect_timing, 6170 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES); 6171 6172 EXPECT_TRUE(load_timing_info.send_start.is_null()); 6173 EXPECT_TRUE(load_timing_info.send_end.is_null()); 6174 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); 6175 } 6176 6177 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request 6178 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { 6179 session_deps_.proxy_service.reset( 6180 ProxyService::CreateFixed("https://proxy:70")); 6181 6182 HttpRequestInfo request; 6183 request.method = "GET"; 6184 request.url = GURL("https://www.google.com/"); 6185 request.load_flags = 0; 6186 6187 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 6188 LOWEST)); 6189 scoped_ptr<SpdyFrame> goaway( 6190 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 6191 MockWrite data_writes[] = { 6192 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), 6193 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS), 6194 }; 6195 6196 static const char* const kExtraHeaders[] = { 6197 "location", 6198 "http://login.example.com/", 6199 }; 6200 scoped_ptr<SpdyFrame> resp( 6201 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders, 6202 arraysize(kExtraHeaders)/2, 1)); 6203 MockRead data_reads[] = { 6204 CreateMockRead(*resp.get(), 1, SYNCHRONOUS), 6205 MockRead(ASYNC, 0, 2), // EOF 6206 }; 6207 6208 DelayedSocketData data( 6209 1, // wait for one write to finish before reading. 6210 data_reads, arraysize(data_reads), 6211 data_writes, arraysize(data_writes)); 6212 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6213 proxy_ssl.SetNextProto(GetParam()); 6214 6215 session_deps_.socket_factory->AddSocketDataProvider(&data); 6216 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6217 6218 TestCompletionCallback callback; 6219 6220 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6221 scoped_ptr<HttpTransaction> trans( 6222 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6223 6224 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6225 EXPECT_EQ(ERR_IO_PENDING, rv); 6226 6227 rv = callback.WaitForResult(); 6228 EXPECT_EQ(OK, rv); 6229 const HttpResponseInfo* response = trans->GetResponseInfo(); 6230 6231 ASSERT_TRUE(response != NULL); 6232 6233 EXPECT_EQ(302, response->headers->response_code()); 6234 std::string url; 6235 EXPECT_TRUE(response->headers->IsRedirect(&url)); 6236 EXPECT_EQ("http://login.example.com/", url); 6237 } 6238 6239 // Test that an HTTPS proxy's response to a CONNECT request is filtered. 6240 TEST_P(HttpNetworkTransactionTest, 6241 ErrorResponseToHttpsConnectViaHttpsProxy) { 6242 session_deps_.proxy_service.reset( 6243 ProxyService::CreateFixed("https://proxy:70")); 6244 6245 HttpRequestInfo request; 6246 request.method = "GET"; 6247 request.url = GURL("https://www.google.com/"); 6248 request.load_flags = 0; 6249 6250 MockWrite data_writes[] = { 6251 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6252 "Host: www.google.com\r\n" 6253 "Proxy-Connection: keep-alive\r\n\r\n"), 6254 }; 6255 6256 MockRead data_reads[] = { 6257 MockRead("HTTP/1.1 404 Not Found\r\n"), 6258 MockRead("Content-Length: 23\r\n\r\n"), 6259 MockRead("The host does not exist"), 6260 MockRead(SYNCHRONOUS, OK), 6261 }; 6262 6263 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6264 data_writes, arraysize(data_writes)); 6265 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6266 6267 session_deps_.socket_factory->AddSocketDataProvider(&data); 6268 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6269 6270 TestCompletionCallback callback; 6271 6272 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6273 scoped_ptr<HttpTransaction> trans( 6274 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6275 6276 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6277 EXPECT_EQ(ERR_IO_PENDING, rv); 6278 6279 rv = callback.WaitForResult(); 6280 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 6281 6282 // TODO(ttuttle): Anything else to check here? 6283 } 6284 6285 // Test that a SPDY proxy's response to a CONNECT request is filtered. 6286 TEST_P(HttpNetworkTransactionTest, 6287 ErrorResponseToHttpsConnectViaSpdyProxy) { 6288 session_deps_.proxy_service.reset( 6289 ProxyService::CreateFixed("https://proxy:70")); 6290 6291 HttpRequestInfo request; 6292 request.method = "GET"; 6293 request.url = GURL("https://www.google.com/"); 6294 request.load_flags = 0; 6295 6296 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 6297 LOWEST)); 6298 scoped_ptr<SpdyFrame> rst( 6299 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 6300 MockWrite data_writes[] = { 6301 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS), 6302 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS), 6303 }; 6304 6305 static const char* const kExtraHeaders[] = { 6306 "location", 6307 "http://login.example.com/", 6308 }; 6309 scoped_ptr<SpdyFrame> resp( 6310 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders, 6311 arraysize(kExtraHeaders)/2, 1)); 6312 scoped_ptr<SpdyFrame> body( 6313 spdy_util_.ConstructSpdyBodyFrame( 6314 1, "The host does not exist", 23, true)); 6315 MockRead data_reads[] = { 6316 CreateMockRead(*resp.get(), 1, SYNCHRONOUS), 6317 CreateMockRead(*body.get(), 2, SYNCHRONOUS), 6318 MockRead(ASYNC, 0, 4), // EOF 6319 }; 6320 6321 DelayedSocketData data( 6322 1, // wait for one write to finish before reading. 6323 data_reads, arraysize(data_reads), 6324 data_writes, arraysize(data_writes)); 6325 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy 6326 proxy_ssl.SetNextProto(GetParam()); 6327 6328 session_deps_.socket_factory->AddSocketDataProvider(&data); 6329 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl); 6330 6331 TestCompletionCallback callback; 6332 6333 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6334 scoped_ptr<HttpTransaction> trans( 6335 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6336 6337 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6338 EXPECT_EQ(ERR_IO_PENDING, rv); 6339 6340 rv = callback.WaitForResult(); 6341 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv); 6342 6343 // TODO(ttuttle): Anything else to check here? 6344 } 6345 6346 // Test the request-challenge-retry sequence for basic auth, through 6347 // a SPDY proxy over a single SPDY session. 6348 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) { 6349 HttpRequestInfo request; 6350 request.method = "GET"; 6351 request.url = GURL("https://www.google.com/"); 6352 // when the no authentication data flag is set. 6353 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; 6354 6355 // Configure against https proxy server "myproxy:70". 6356 session_deps_.proxy_service.reset( 6357 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); 6358 CapturingBoundNetLog log; 6359 session_deps_.net_log = log.bound().net_log(); 6360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6361 6362 // Since we have proxy, should try to establish tunnel. 6363 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1, 6364 LOWEST)); 6365 scoped_ptr<SpdyFrame> rst( 6366 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL)); 6367 6368 // After calling trans->RestartWithAuth(), this is the request we should 6369 // be issuing -- the final header line contains the credentials. 6370 const char* const kAuthCredentials[] = { 6371 "proxy-authorization", "Basic Zm9vOmJhcg==", 6372 }; 6373 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect( 6374 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST)); 6375 // fetch https://www.google.com/ via HTTP 6376 const char get[] = "GET / HTTP/1.1\r\n" 6377 "Host: www.google.com\r\n" 6378 "Connection: keep-alive\r\n\r\n"; 6379 scoped_ptr<SpdyFrame> wrapped_get( 6380 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false)); 6381 6382 MockWrite spdy_writes[] = { 6383 CreateMockWrite(*req, 1, ASYNC), 6384 CreateMockWrite(*rst, 4, ASYNC), 6385 CreateMockWrite(*connect2, 5), 6386 CreateMockWrite(*wrapped_get, 8), 6387 }; 6388 6389 // The proxy responds to the connect with a 407, using a persistent 6390 // connection. 6391 const char* const kAuthChallenge[] = { 6392 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required", 6393 spdy_util_.GetVersionKey(), "HTTP/1.1", 6394 "proxy-authenticate", "Basic realm=\"MyRealm1\"", 6395 }; 6396 6397 scoped_ptr<SpdyFrame> conn_auth_resp( 6398 spdy_util_.ConstructSpdyControlFrame(NULL, 6399 0, 6400 false, 6401 1, 6402 LOWEST, 6403 SYN_REPLY, 6404 CONTROL_FLAG_NONE, 6405 kAuthChallenge, 6406 arraysize(kAuthChallenge), 6407 0)); 6408 6409 scoped_ptr<SpdyFrame> conn_resp( 6410 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); 6411 const char resp[] = "HTTP/1.1 200 OK\r\n" 6412 "Content-Length: 5\r\n\r\n"; 6413 6414 scoped_ptr<SpdyFrame> wrapped_get_resp( 6415 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false)); 6416 scoped_ptr<SpdyFrame> wrapped_body( 6417 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false)); 6418 MockRead spdy_reads[] = { 6419 CreateMockRead(*conn_auth_resp, 2, ASYNC), 6420 CreateMockRead(*conn_resp, 6, ASYNC), 6421 CreateMockRead(*wrapped_get_resp, 9, ASYNC), 6422 CreateMockRead(*wrapped_body, 10, ASYNC), 6423 MockRead(ASYNC, OK, 11), // EOF. May or may not be read. 6424 }; 6425 6426 OrderedSocketData spdy_data( 6427 spdy_reads, arraysize(spdy_reads), 6428 spdy_writes, arraysize(spdy_writes)); 6429 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6430 // Negotiate SPDY to the proxy 6431 SSLSocketDataProvider proxy(ASYNC, OK); 6432 proxy.SetNextProto(GetParam()); 6433 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6434 // Vanilla SSL to the server 6435 SSLSocketDataProvider server(ASYNC, OK); 6436 session_deps_.socket_factory->AddSSLSocketDataProvider(&server); 6437 6438 TestCompletionCallback callback1; 6439 6440 scoped_ptr<HttpTransaction> trans( 6441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6442 6443 int rv = trans->Start(&request, callback1.callback(), log.bound()); 6444 EXPECT_EQ(ERR_IO_PENDING, rv); 6445 6446 rv = callback1.WaitForResult(); 6447 EXPECT_EQ(OK, rv); 6448 net::CapturingNetLog::CapturedEntryList entries; 6449 log.GetEntries(&entries); 6450 size_t pos = ExpectLogContainsSomewhere( 6451 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, 6452 NetLog::PHASE_NONE); 6453 ExpectLogContainsSomewhere( 6454 entries, pos, 6455 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS, 6456 NetLog::PHASE_NONE); 6457 6458 const HttpResponseInfo* response = trans->GetResponseInfo(); 6459 ASSERT_TRUE(response != NULL); 6460 ASSERT_FALSE(response->headers.get() == NULL); 6461 EXPECT_EQ(407, response->headers->response_code()); 6462 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6463 EXPECT_TRUE(response->auth_challenge.get() != NULL); 6464 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get())); 6465 6466 TestCompletionCallback callback2; 6467 6468 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), 6469 callback2.callback()); 6470 EXPECT_EQ(ERR_IO_PENDING, rv); 6471 6472 rv = callback2.WaitForResult(); 6473 EXPECT_EQ(OK, rv); 6474 6475 response = trans->GetResponseInfo(); 6476 ASSERT_TRUE(response != NULL); 6477 6478 EXPECT_TRUE(response->headers->IsKeepAlive()); 6479 EXPECT_EQ(200, response->headers->response_code()); 6480 EXPECT_EQ(5, response->headers->GetContentLength()); 6481 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6482 6483 // The password prompt info should not be set. 6484 EXPECT_TRUE(response->auth_challenge.get() == NULL); 6485 6486 LoadTimingInfo load_timing_info; 6487 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6488 TestLoadTimingNotReusedWithPac(load_timing_info, 6489 CONNECT_TIMING_HAS_SSL_TIMES); 6490 6491 trans.reset(); 6492 session->CloseAllConnections(); 6493 } 6494 6495 // Test that an explicitly trusted SPDY proxy can push a resource from an 6496 // origin that is different from that of its associated resource. 6497 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) { 6498 HttpRequestInfo request; 6499 HttpRequestInfo push_request; 6500 6501 request.method = "GET"; 6502 request.url = GURL("http://www.google.com/"); 6503 push_request.method = "GET"; 6504 push_request.url = GURL("http://www.another-origin.com/foo.dat"); 6505 6506 // Configure against https proxy server "myproxy:70". 6507 session_deps_.proxy_service.reset( 6508 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); 6509 CapturingBoundNetLog log; 6510 session_deps_.net_log = log.bound().net_log(); 6511 6512 // Enable cross-origin push. 6513 session_deps_.trusted_spdy_proxy = "myproxy:70"; 6514 6515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6516 6517 scoped_ptr<SpdyFrame> stream1_syn( 6518 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 6519 6520 MockWrite spdy_writes[] = { 6521 CreateMockWrite(*stream1_syn, 1, ASYNC), 6522 }; 6523 6524 scoped_ptr<SpdyFrame> 6525 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 6526 6527 scoped_ptr<SpdyFrame> 6528 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6529 6530 scoped_ptr<SpdyFrame> 6531 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 6532 0, 6533 2, 6534 1, 6535 "http://www.another-origin.com/foo.dat")); 6536 const char kPushedData[] = "pushed"; 6537 scoped_ptr<SpdyFrame> stream2_body( 6538 spdy_util_.ConstructSpdyBodyFrame( 6539 2, kPushedData, strlen(kPushedData), true)); 6540 6541 MockRead spdy_reads[] = { 6542 CreateMockRead(*stream1_reply, 2, ASYNC), 6543 CreateMockRead(*stream2_syn, 3, ASYNC), 6544 CreateMockRead(*stream1_body, 4, ASYNC), 6545 CreateMockRead(*stream2_body, 5, ASYNC), 6546 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 6547 }; 6548 6549 OrderedSocketData spdy_data( 6550 spdy_reads, arraysize(spdy_reads), 6551 spdy_writes, arraysize(spdy_writes)); 6552 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6553 // Negotiate SPDY to the proxy 6554 SSLSocketDataProvider proxy(ASYNC, OK); 6555 proxy.SetNextProto(GetParam()); 6556 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6557 6558 scoped_ptr<HttpTransaction> trans( 6559 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6560 TestCompletionCallback callback; 6561 int rv = trans->Start(&request, callback.callback(), log.bound()); 6562 EXPECT_EQ(ERR_IO_PENDING, rv); 6563 6564 rv = callback.WaitForResult(); 6565 EXPECT_EQ(OK, rv); 6566 const HttpResponseInfo* response = trans->GetResponseInfo(); 6567 6568 scoped_ptr<HttpTransaction> push_trans( 6569 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6570 rv = push_trans->Start(&push_request, callback.callback(), log.bound()); 6571 EXPECT_EQ(ERR_IO_PENDING, rv); 6572 6573 rv = callback.WaitForResult(); 6574 EXPECT_EQ(OK, rv); 6575 const HttpResponseInfo* push_response = push_trans->GetResponseInfo(); 6576 6577 ASSERT_TRUE(response != NULL); 6578 EXPECT_TRUE(response->headers->IsKeepAlive()); 6579 6580 EXPECT_EQ(200, response->headers->response_code()); 6581 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6582 6583 std::string response_data; 6584 rv = ReadTransaction(trans.get(), &response_data); 6585 EXPECT_EQ(OK, rv); 6586 EXPECT_EQ("hello!", response_data); 6587 6588 LoadTimingInfo load_timing_info; 6589 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); 6590 TestLoadTimingNotReusedWithPac(load_timing_info, 6591 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); 6592 6593 // Verify the pushed stream. 6594 EXPECT_TRUE(push_response->headers.get() != NULL); 6595 EXPECT_EQ(200, push_response->headers->response_code()); 6596 6597 rv = ReadTransaction(push_trans.get(), &response_data); 6598 EXPECT_EQ(OK, rv); 6599 EXPECT_EQ("pushed", response_data); 6600 6601 LoadTimingInfo push_load_timing_info; 6602 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info)); 6603 TestLoadTimingReusedWithPac(push_load_timing_info); 6604 // The transactions should share a socket ID, despite being for different 6605 // origins. 6606 EXPECT_EQ(load_timing_info.socket_log_id, 6607 push_load_timing_info.socket_log_id); 6608 6609 trans.reset(); 6610 push_trans.reset(); 6611 session->CloseAllConnections(); 6612 } 6613 6614 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content. 6615 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) { 6616 HttpRequestInfo request; 6617 6618 request.method = "GET"; 6619 request.url = GURL("http://www.google.com/"); 6620 6621 // Configure against https proxy server "myproxy:70". 6622 session_deps_.proxy_service.reset( 6623 ProxyService::CreateFixed("https://myproxy:70")); 6624 CapturingBoundNetLog log; 6625 session_deps_.net_log = log.bound().net_log(); 6626 6627 // Enable cross-origin push. 6628 session_deps_.trusted_spdy_proxy = "myproxy:70"; 6629 6630 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6631 6632 scoped_ptr<SpdyFrame> stream1_syn( 6633 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false)); 6634 6635 scoped_ptr<SpdyFrame> push_rst( 6636 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM)); 6637 6638 MockWrite spdy_writes[] = { 6639 CreateMockWrite(*stream1_syn, 1, ASYNC), 6640 CreateMockWrite(*push_rst, 4), 6641 }; 6642 6643 scoped_ptr<SpdyFrame> 6644 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 6645 6646 scoped_ptr<SpdyFrame> 6647 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true)); 6648 6649 scoped_ptr<SpdyFrame> 6650 stream2_syn(spdy_util_.ConstructSpdyPush(NULL, 6651 0, 6652 2, 6653 1, 6654 "https://www.another-origin.com/foo.dat")); 6655 6656 MockRead spdy_reads[] = { 6657 CreateMockRead(*stream1_reply, 2, ASYNC), 6658 CreateMockRead(*stream2_syn, 3, ASYNC), 6659 CreateMockRead(*stream1_body, 5, ASYNC), 6660 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause 6661 }; 6662 6663 OrderedSocketData spdy_data( 6664 spdy_reads, arraysize(spdy_reads), 6665 spdy_writes, arraysize(spdy_writes)); 6666 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); 6667 // Negotiate SPDY to the proxy 6668 SSLSocketDataProvider proxy(ASYNC, OK); 6669 proxy.SetNextProto(GetParam()); 6670 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy); 6671 6672 scoped_ptr<HttpTransaction> trans( 6673 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); 6674 TestCompletionCallback callback; 6675 int rv = trans->Start(&request, callback.callback(), log.bound()); 6676 EXPECT_EQ(ERR_IO_PENDING, rv); 6677 6678 rv = callback.WaitForResult(); 6679 EXPECT_EQ(OK, rv); 6680 const HttpResponseInfo* response = trans->GetResponseInfo(); 6681 6682 ASSERT_TRUE(response != NULL); 6683 EXPECT_TRUE(response->headers->IsKeepAlive()); 6684 6685 EXPECT_EQ(200, response->headers->response_code()); 6686 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion()); 6687 6688 std::string response_data; 6689 rv = ReadTransaction(trans.get(), &response_data); 6690 EXPECT_EQ(OK, rv); 6691 EXPECT_EQ("hello!", response_data); 6692 6693 trans.reset(); 6694 session->CloseAllConnections(); 6695 } 6696 6697 // Test HTTPS connections to a site with a bad certificate, going through an 6698 // HTTPS proxy 6699 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { 6700 session_deps_.proxy_service.reset(ProxyService::CreateFixed( 6701 "https://proxy:70")); 6702 6703 HttpRequestInfo request; 6704 request.method = "GET"; 6705 request.url = GURL("https://www.google.com/"); 6706 request.load_flags = 0; 6707 6708 // Attempt to fetch the URL from a server with a bad cert 6709 MockWrite bad_cert_writes[] = { 6710 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6711 "Host: www.google.com\r\n" 6712 "Proxy-Connection: keep-alive\r\n\r\n"), 6713 }; 6714 6715 MockRead bad_cert_reads[] = { 6716 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6717 MockRead(SYNCHRONOUS, OK) 6718 }; 6719 6720 // Attempt to fetch the URL with a good cert 6721 MockWrite good_data_writes[] = { 6722 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n" 6723 "Host: www.google.com\r\n" 6724 "Proxy-Connection: keep-alive\r\n\r\n"), 6725 MockWrite("GET / HTTP/1.1\r\n" 6726 "Host: www.google.com\r\n" 6727 "Connection: keep-alive\r\n\r\n"), 6728 }; 6729 6730 MockRead good_cert_reads[] = { 6731 MockRead("HTTP/1.0 200 Connected\r\n\r\n"), 6732 MockRead("HTTP/1.0 200 OK\r\n"), 6733 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6734 MockRead("Content-Length: 100\r\n\r\n"), 6735 MockRead(SYNCHRONOUS, OK), 6736 }; 6737 6738 StaticSocketDataProvider ssl_bad_certificate( 6739 bad_cert_reads, arraysize(bad_cert_reads), 6740 bad_cert_writes, arraysize(bad_cert_writes)); 6741 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads), 6742 good_data_writes, arraysize(good_data_writes)); 6743 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID); 6744 SSLSocketDataProvider ssl(ASYNC, OK); 6745 6746 // SSL to the proxy, then CONNECT request, then SSL with bad certificate 6747 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6748 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate); 6749 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad); 6750 6751 // SSL to the proxy, then CONNECT request, then valid SSL certificate 6752 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6753 session_deps_.socket_factory->AddSocketDataProvider(&data); 6754 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); 6755 6756 TestCompletionCallback callback; 6757 6758 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6759 scoped_ptr<HttpTransaction> trans( 6760 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6761 6762 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6763 EXPECT_EQ(ERR_IO_PENDING, rv); 6764 6765 rv = callback.WaitForResult(); 6766 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv); 6767 6768 rv = trans->RestartIgnoringLastError(callback.callback()); 6769 EXPECT_EQ(ERR_IO_PENDING, rv); 6770 6771 rv = callback.WaitForResult(); 6772 EXPECT_EQ(OK, rv); 6773 6774 const HttpResponseInfo* response = trans->GetResponseInfo(); 6775 6776 ASSERT_TRUE(response != NULL); 6777 EXPECT_EQ(100, response->headers->GetContentLength()); 6778 } 6779 6780 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) { 6781 HttpRequestInfo request; 6782 request.method = "GET"; 6783 request.url = GURL("http://www.google.com/"); 6784 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 6785 "Chromium Ultra Awesome X Edition"); 6786 6787 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6788 scoped_ptr<HttpTransaction> trans( 6789 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6790 6791 MockWrite data_writes[] = { 6792 MockWrite("GET / HTTP/1.1\r\n" 6793 "Host: www.google.com\r\n" 6794 "Connection: keep-alive\r\n" 6795 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 6796 }; 6797 6798 // Lastly, the server responds with the actual content. 6799 MockRead data_reads[] = { 6800 MockRead("HTTP/1.0 200 OK\r\n"), 6801 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6802 MockRead("Content-Length: 100\r\n\r\n"), 6803 MockRead(SYNCHRONOUS, OK), 6804 }; 6805 6806 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6807 data_writes, arraysize(data_writes)); 6808 session_deps_.socket_factory->AddSocketDataProvider(&data); 6809 6810 TestCompletionCallback callback; 6811 6812 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6813 EXPECT_EQ(ERR_IO_PENDING, rv); 6814 6815 rv = callback.WaitForResult(); 6816 EXPECT_EQ(OK, rv); 6817 } 6818 6819 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) { 6820 HttpRequestInfo request; 6821 request.method = "GET"; 6822 request.url = GURL("https://www.google.com/"); 6823 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, 6824 "Chromium Ultra Awesome X Edition"); 6825 6826 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); 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("CONNECT www.google.com:443 HTTP/1.1\r\n" 6833 "Host: www.google.com\r\n" 6834 "Proxy-Connection: keep-alive\r\n" 6835 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"), 6836 }; 6837 MockRead data_reads[] = { 6838 // Return an error, so the transaction stops here (this test isn't 6839 // interested in the rest). 6840 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), 6841 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), 6842 MockRead("Proxy-Connection: close\r\n\r\n"), 6843 }; 6844 6845 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6846 data_writes, arraysize(data_writes)); 6847 session_deps_.socket_factory->AddSocketDataProvider(&data); 6848 6849 TestCompletionCallback callback; 6850 6851 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6852 EXPECT_EQ(ERR_IO_PENDING, rv); 6853 6854 rv = callback.WaitForResult(); 6855 EXPECT_EQ(OK, rv); 6856 } 6857 6858 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) { 6859 HttpRequestInfo request; 6860 request.method = "GET"; 6861 request.url = GURL("http://www.google.com/"); 6862 request.load_flags = 0; 6863 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer, 6864 "http://the.previous.site.com/"); 6865 6866 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6867 scoped_ptr<HttpTransaction> trans( 6868 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6869 6870 MockWrite data_writes[] = { 6871 MockWrite("GET / HTTP/1.1\r\n" 6872 "Host: www.google.com\r\n" 6873 "Connection: keep-alive\r\n" 6874 "Referer: http://the.previous.site.com/\r\n\r\n"), 6875 }; 6876 6877 // Lastly, the server responds with the actual content. 6878 MockRead data_reads[] = { 6879 MockRead("HTTP/1.0 200 OK\r\n"), 6880 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6881 MockRead("Content-Length: 100\r\n\r\n"), 6882 MockRead(SYNCHRONOUS, OK), 6883 }; 6884 6885 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6886 data_writes, arraysize(data_writes)); 6887 session_deps_.socket_factory->AddSocketDataProvider(&data); 6888 6889 TestCompletionCallback callback; 6890 6891 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6892 EXPECT_EQ(ERR_IO_PENDING, rv); 6893 6894 rv = callback.WaitForResult(); 6895 EXPECT_EQ(OK, rv); 6896 } 6897 6898 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) { 6899 HttpRequestInfo request; 6900 request.method = "POST"; 6901 request.url = GURL("http://www.google.com/"); 6902 6903 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6904 scoped_ptr<HttpTransaction> trans( 6905 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6906 6907 MockWrite data_writes[] = { 6908 MockWrite("POST / HTTP/1.1\r\n" 6909 "Host: www.google.com\r\n" 6910 "Connection: keep-alive\r\n" 6911 "Content-Length: 0\r\n\r\n"), 6912 }; 6913 6914 // Lastly, the server responds with the actual content. 6915 MockRead data_reads[] = { 6916 MockRead("HTTP/1.0 200 OK\r\n"), 6917 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6918 MockRead("Content-Length: 100\r\n\r\n"), 6919 MockRead(SYNCHRONOUS, OK), 6920 }; 6921 6922 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6923 data_writes, arraysize(data_writes)); 6924 session_deps_.socket_factory->AddSocketDataProvider(&data); 6925 6926 TestCompletionCallback callback; 6927 6928 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6929 EXPECT_EQ(ERR_IO_PENDING, rv); 6930 6931 rv = callback.WaitForResult(); 6932 EXPECT_EQ(OK, rv); 6933 } 6934 6935 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) { 6936 HttpRequestInfo request; 6937 request.method = "PUT"; 6938 request.url = GURL("http://www.google.com/"); 6939 6940 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6941 scoped_ptr<HttpTransaction> trans( 6942 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6943 6944 MockWrite data_writes[] = { 6945 MockWrite("PUT / HTTP/1.1\r\n" 6946 "Host: www.google.com\r\n" 6947 "Connection: keep-alive\r\n" 6948 "Content-Length: 0\r\n\r\n"), 6949 }; 6950 6951 // Lastly, the server responds with the actual content. 6952 MockRead data_reads[] = { 6953 MockRead("HTTP/1.0 200 OK\r\n"), 6954 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6955 MockRead("Content-Length: 100\r\n\r\n"), 6956 MockRead(SYNCHRONOUS, OK), 6957 }; 6958 6959 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6960 data_writes, arraysize(data_writes)); 6961 session_deps_.socket_factory->AddSocketDataProvider(&data); 6962 6963 TestCompletionCallback callback; 6964 6965 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 6966 EXPECT_EQ(ERR_IO_PENDING, rv); 6967 6968 rv = callback.WaitForResult(); 6969 EXPECT_EQ(OK, rv); 6970 } 6971 6972 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) { 6973 HttpRequestInfo request; 6974 request.method = "HEAD"; 6975 request.url = GURL("http://www.google.com/"); 6976 6977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 6978 scoped_ptr<HttpTransaction> trans( 6979 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 6980 6981 MockWrite data_writes[] = { 6982 MockWrite("HEAD / HTTP/1.1\r\n" 6983 "Host: www.google.com\r\n" 6984 "Connection: keep-alive\r\n" 6985 "Content-Length: 0\r\n\r\n"), 6986 }; 6987 6988 // Lastly, the server responds with the actual content. 6989 MockRead data_reads[] = { 6990 MockRead("HTTP/1.0 200 OK\r\n"), 6991 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 6992 MockRead("Content-Length: 100\r\n\r\n"), 6993 MockRead(SYNCHRONOUS, OK), 6994 }; 6995 6996 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 6997 data_writes, arraysize(data_writes)); 6998 session_deps_.socket_factory->AddSocketDataProvider(&data); 6999 7000 TestCompletionCallback callback; 7001 7002 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7003 EXPECT_EQ(ERR_IO_PENDING, rv); 7004 7005 rv = callback.WaitForResult(); 7006 EXPECT_EQ(OK, rv); 7007 } 7008 7009 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) { 7010 HttpRequestInfo request; 7011 request.method = "GET"; 7012 request.url = GURL("http://www.google.com/"); 7013 request.load_flags = LOAD_BYPASS_CACHE; 7014 7015 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7016 scoped_ptr<HttpTransaction> trans( 7017 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7018 7019 MockWrite data_writes[] = { 7020 MockWrite("GET / HTTP/1.1\r\n" 7021 "Host: www.google.com\r\n" 7022 "Connection: keep-alive\r\n" 7023 "Pragma: no-cache\r\n" 7024 "Cache-Control: no-cache\r\n\r\n"), 7025 }; 7026 7027 // Lastly, the server responds with the actual content. 7028 MockRead data_reads[] = { 7029 MockRead("HTTP/1.0 200 OK\r\n"), 7030 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7031 MockRead("Content-Length: 100\r\n\r\n"), 7032 MockRead(SYNCHRONOUS, OK), 7033 }; 7034 7035 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7036 data_writes, arraysize(data_writes)); 7037 session_deps_.socket_factory->AddSocketDataProvider(&data); 7038 7039 TestCompletionCallback callback; 7040 7041 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7042 EXPECT_EQ(ERR_IO_PENDING, rv); 7043 7044 rv = callback.WaitForResult(); 7045 EXPECT_EQ(OK, rv); 7046 } 7047 7048 TEST_P(HttpNetworkTransactionTest, 7049 BuildRequest_CacheControlValidateCache) { 7050 HttpRequestInfo request; 7051 request.method = "GET"; 7052 request.url = GURL("http://www.google.com/"); 7053 request.load_flags = LOAD_VALIDATE_CACHE; 7054 7055 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7056 scoped_ptr<HttpTransaction> trans( 7057 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7058 7059 MockWrite data_writes[] = { 7060 MockWrite("GET / HTTP/1.1\r\n" 7061 "Host: www.google.com\r\n" 7062 "Connection: keep-alive\r\n" 7063 "Cache-Control: max-age=0\r\n\r\n"), 7064 }; 7065 7066 // Lastly, the server responds with the actual content. 7067 MockRead data_reads[] = { 7068 MockRead("HTTP/1.0 200 OK\r\n"), 7069 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7070 MockRead("Content-Length: 100\r\n\r\n"), 7071 MockRead(SYNCHRONOUS, OK), 7072 }; 7073 7074 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7075 data_writes, arraysize(data_writes)); 7076 session_deps_.socket_factory->AddSocketDataProvider(&data); 7077 7078 TestCompletionCallback callback; 7079 7080 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7081 EXPECT_EQ(ERR_IO_PENDING, rv); 7082 7083 rv = callback.WaitForResult(); 7084 EXPECT_EQ(OK, rv); 7085 } 7086 7087 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) { 7088 HttpRequestInfo request; 7089 request.method = "GET"; 7090 request.url = GURL("http://www.google.com/"); 7091 request.extra_headers.SetHeader("FooHeader", "Bar"); 7092 7093 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7094 scoped_ptr<HttpTransaction> trans( 7095 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7096 7097 MockWrite data_writes[] = { 7098 MockWrite("GET / HTTP/1.1\r\n" 7099 "Host: www.google.com\r\n" 7100 "Connection: keep-alive\r\n" 7101 "FooHeader: Bar\r\n\r\n"), 7102 }; 7103 7104 // Lastly, the server responds with the actual content. 7105 MockRead data_reads[] = { 7106 MockRead("HTTP/1.0 200 OK\r\n"), 7107 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), 7108 MockRead("Content-Length: 100\r\n\r\n"), 7109 MockRead(SYNCHRONOUS, OK), 7110 }; 7111 7112 StaticSocketDataProvider data(data_reads, arraysize(data_reads), 7113 data_writes, arraysize(data_writes)); 7114 session_deps_.socket_factory->AddSocketDataProvider(&data); 7115 7116 TestCompletionCallback callback; 7117 7118 int rv = trans->Start(&request, callback.callback(), BoundNetLog()); 7119 EXPECT_EQ(ERR_IO_PENDING, rv); 7120 7121 rv = callback.WaitForResult(); 7122 EXPECT_EQ(OK, rv); 7123 } 7124 7125 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) { 7126 HttpRequestInfo request; 7127 request.method = "GET"; 7128 request.url = GURL("http://www.google.com/"); 7129 request.extra_headers.SetHeader("referer", "www.foo.com"); 7130 request.extra_headers.SetHeader("hEllo", "Kitty"); 7131 request.extra_headers.SetHeader("FoO", "bar"); 7132 7133 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); 7134 scoped_ptr<HttpTransaction> trans( 7135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session)); 7136