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.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/test_file_util.h"
22 #include "net/base/auth.h"
23 #include "net/base/capturing_net_log.h"
24 #include "net/base/completion_callback.h"
25 #include "net/base/load_timing_info.h"
26 #include "net/base/load_timing_info_test_util.h"
27 #include "net/base/net_log.h"
28 #include "net/base/net_log_unittest.h"
29 #include "net/base/request_priority.h"
30 #include "net/base/test_completion_callback.h"
31 #include "net/base/test_data_directory.h"
32 #include "net/base/upload_bytes_element_reader.h"
33 #include "net/base/upload_data_stream.h"
34 #include "net/base/upload_file_element_reader.h"
35 #include "net/cert/mock_cert_verifier.h"
36 #include "net/dns/host_cache.h"
37 #include "net/dns/mock_host_resolver.h"
38 #include "net/http/http_auth_handler_digest.h"
39 #include "net/http/http_auth_handler_mock.h"
40 #include "net/http/http_auth_handler_ntlm.h"
41 #include "net/http/http_basic_stream.h"
42 #include "net/http/http_network_session.h"
43 #include "net/http/http_network_session_peer.h"
44 #include "net/http/http_server_properties_impl.h"
45 #include "net/http/http_stream.h"
46 #include "net/http/http_stream_factory.h"
47 #include "net/http/http_transaction_unittest.h"
48 #include "net/proxy/proxy_config_service_fixed.h"
49 #include "net/proxy/proxy_info.h"
50 #include "net/proxy/proxy_resolver.h"
51 #include "net/proxy/proxy_service.h"
52 #include "net/socket/client_socket_factory.h"
53 #include "net/socket/client_socket_pool_manager.h"
54 #include "net/socket/mock_client_socket_pool_manager.h"
55 #include "net/socket/next_proto.h"
56 #include "net/socket/socket_test_util.h"
57 #include "net/socket/ssl_client_socket.h"
58 #include "net/spdy/spdy_framer.h"
59 #include "net/spdy/spdy_session.h"
60 #include "net/spdy/spdy_session_pool.h"
61 #include "net/spdy/spdy_test_util_common.h"
62 #include "net/ssl/ssl_cert_request_info.h"
63 #include "net/ssl/ssl_config_service.h"
64 #include "net/ssl/ssl_config_service_defaults.h"
65 #include "net/ssl/ssl_info.h"
66 #include "net/test/cert_test_util.h"
67 #include "testing/gtest/include/gtest/gtest.h"
68 #include "testing/platform_test.h"
71 //-----------------------------------------------------------------------------
75 const base::string16 kBar(ASCIIToUTF16("bar"));
76 const base::string16 kBar2(ASCIIToUTF16("bar2"));
77 const base::string16 kBar3(ASCIIToUTF16("bar3"));
78 const base::string16 kBaz(ASCIIToUTF16("baz"));
79 const base::string16 kFirst(ASCIIToUTF16("first"));
80 const base::string16 kFoo(ASCIIToUTF16("foo"));
81 const base::string16 kFoo2(ASCIIToUTF16("foo2"));
82 const base::string16 kFoo3(ASCIIToUTF16("foo3"));
83 const base::string16 kFou(ASCIIToUTF16("fou"));
84 const base::string16 kSecond(ASCIIToUTF16("second"));
85 const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
86 const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
88 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) {
89 return session->GetTransportSocketPool(
90 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
93 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) {
94 return session->GetSSLSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount();
98 bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) {
99 return session->GetTransportSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled();
103 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
104 // a JSONified list of headers as a single string. Uses single quotes instead
105 // of double quotes for easier comparison. Returns false on failure.
106 bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
109 base::ListValue* header_list;
110 if (!params->GetList("headers", &header_list))
112 std::string double_quote_headers;
113 base::JSONWriter::Write(header_list, &double_quote_headers);
114 ReplaceChars(double_quote_headers, "\"", "'", headers);
118 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
120 void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) {
121 EXPECT_TRUE(load_timing_info.socket_reused);
122 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
124 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
125 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
127 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
128 EXPECT_FALSE(load_timing_info.send_start.is_null());
130 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
132 // Set at a higher level.
133 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
134 EXPECT_TRUE(load_timing_info.request_start.is_null());
135 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
138 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
140 void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info,
141 int connect_timing_flags) {
142 EXPECT_FALSE(load_timing_info.socket_reused);
143 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
145 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
146 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
148 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
149 connect_timing_flags);
150 EXPECT_LE(load_timing_info.connect_timing.connect_end,
151 load_timing_info.send_start);
153 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
155 // Set at a higher level.
156 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
157 EXPECT_TRUE(load_timing_info.request_start.is_null());
158 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
161 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
163 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) {
164 EXPECT_TRUE(load_timing_info.socket_reused);
165 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
167 net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
169 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
170 EXPECT_LE(load_timing_info.proxy_resolve_start,
171 load_timing_info.proxy_resolve_end);
172 EXPECT_LE(load_timing_info.proxy_resolve_end,
173 load_timing_info.send_start);
174 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
176 // Set at a higher level.
177 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
178 EXPECT_TRUE(load_timing_info.request_start.is_null());
179 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
182 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
184 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info,
185 int connect_timing_flags) {
186 EXPECT_FALSE(load_timing_info.socket_reused);
187 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
189 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
190 EXPECT_LE(load_timing_info.proxy_resolve_start,
191 load_timing_info.proxy_resolve_end);
192 EXPECT_LE(load_timing_info.proxy_resolve_end,
193 load_timing_info.connect_timing.connect_start);
194 net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
195 connect_timing_flags);
196 EXPECT_LE(load_timing_info.connect_timing.connect_end,
197 load_timing_info.send_start);
199 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
201 // Set at a higher level.
202 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
203 EXPECT_TRUE(load_timing_info.request_start.is_null());
204 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
213 HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) {
214 return SpdySessionDependencies::SpdyCreateSession(session_deps);
219 class HttpNetworkTransactionTest
220 : public PlatformTest,
221 public ::testing::WithParamInterface<NextProto> {
223 virtual ~HttpNetworkTransactionTest() {
224 // Important to restore the per-pool limit first, since the pool limit must
225 // always be greater than group limit, and the tests reduce both limits.
226 ClientSocketPoolManager::set_max_sockets_per_pool(
227 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
228 ClientSocketPoolManager::set_max_sockets_per_group(
229 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
233 HttpNetworkTransactionTest()
234 : spdy_util_(GetParam()),
235 session_deps_(GetParam()),
236 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
237 HttpNetworkSession::NORMAL_SOCKET_POOL)),
238 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
239 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
242 struct SimpleGetHelperResult {
244 std::string status_line;
245 std::string response_data;
246 LoadTimingInfo load_timing_info;
249 virtual void SetUp() {
250 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
251 base::MessageLoop::current()->RunUntilIdle();
254 virtual void TearDown() {
255 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
256 base::MessageLoop::current()->RunUntilIdle();
257 // Empty the current queue.
258 base::MessageLoop::current()->RunUntilIdle();
259 PlatformTest::TearDown();
260 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
261 base::MessageLoop::current()->RunUntilIdle();
262 HttpStreamFactory::set_use_alternate_protocols(false);
263 HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
266 // This is the expected return from a current server advertising SPDY.
267 std::string GetAlternateProtocolHttpHeader() {
269 std::string("Alternate-Protocol: 443:") +
270 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
274 // Either |write_failure| specifies a write failure or |read_failure|
275 // specifies a read failure when using a reused socket. In either case, the
276 // failure should cause the network transaction to resend the request, and the
277 // other argument should be NULL.
278 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
279 const MockRead* read_failure);
281 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
283 SimpleGetHelperResult out;
285 HttpRequestInfo request;
286 request.method = "GET";
287 request.url = GURL("http://www.google.com/");
288 request.load_flags = 0;
290 CapturingBoundNetLog log;
291 session_deps_.net_log = log.bound().net_log();
292 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
293 scoped_ptr<HttpTransaction> trans(
294 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
296 for (size_t i = 0; i < data_count; ++i) {
297 session_deps_.socket_factory->AddSocketDataProvider(data[i]);
300 TestCompletionCallback callback;
302 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
303 int rv = trans->Start(&request, callback.callback(), log.bound());
304 EXPECT_EQ(ERR_IO_PENDING, rv);
306 out.rv = callback.WaitForResult();
308 // Even in the failure cases that use this function, connections are always
309 // successfully established before the error.
310 EXPECT_TRUE(trans->GetLoadTimingInfo(&out.load_timing_info));
311 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
316 const HttpResponseInfo* response = trans->GetResponseInfo();
317 // Can't use ASSERT_* inside helper functions like this, so
319 if (response == NULL || response->headers.get() == NULL) {
320 out.rv = ERR_UNEXPECTED;
323 out.status_line = response->headers->GetStatusLine();
325 EXPECT_EQ("127.0.0.1", response->socket_address.host());
326 EXPECT_EQ(80, response->socket_address.port());
328 rv = ReadTransaction(trans.get(), &out.response_data);
331 net::CapturingNetLog::CapturedEntryList entries;
332 log.GetEntries(&entries);
333 size_t pos = ExpectLogContainsSomewhere(
334 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
336 ExpectLogContainsSomewhere(
338 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
342 EXPECT_TRUE(entries[pos].GetStringValue("line", &line));
343 EXPECT_EQ("GET / HTTP/1.1\r\n", line);
345 HttpRequestHeaders request_headers;
346 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
348 EXPECT_TRUE(request_headers.GetHeader("Host", &value));
349 EXPECT_EQ("www.google.com", value);
350 EXPECT_TRUE(request_headers.GetHeader("Connection", &value));
351 EXPECT_EQ("keep-alive", value);
353 std::string response_headers;
354 EXPECT_TRUE(GetHeaders(entries[pos].params.get(), &response_headers));
355 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
361 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
362 size_t reads_count) {
363 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
364 StaticSocketDataProvider* data[] = { &reads };
365 return SimpleGetHelperForData(data, 1);
368 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
369 int expected_status);
371 void ConnectStatusHelper(const MockRead& status);
373 void BypassHostCacheOnRefreshHelper(int load_flags);
375 void CheckErrorIsPassedBack(int error, IoMode mode);
377 SpdyTestUtil spdy_util_;
378 SpdySessionDependencies session_deps_;
380 // Original socket limits. Some tests set these. Safest to always restore
381 // them once each test has been run.
382 int old_max_group_sockets_;
383 int old_max_pool_sockets_;
386 INSTANTIATE_TEST_CASE_P(
388 HttpNetworkTransactionTest,
389 testing::Values(kProtoDeprecatedSPDY2,
390 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
391 kProtoHTTP2Draft04));
395 // Fill |str| with a long header list that consumes >= |size| bytes.
396 void FillLargeHeadersString(std::string* str, int size) {
398 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
399 const int sizeof_row = strlen(row);
400 const int num_rows = static_cast<int>(
401 ceil(static_cast<float>(size) / sizeof_row));
402 const int sizeof_data = num_rows * sizeof_row;
403 DCHECK(sizeof_data >= size);
404 str->reserve(sizeof_data);
406 for (int i = 0; i < num_rows; ++i)
407 str->append(row, sizeof_row);
410 // Alternative functions that eliminate randomness and dependency on the local
411 // host name so that the generated NTLM messages are reproducible.
412 void MockGenerateRandom1(uint8* output, size_t n) {
413 static const uint8 bytes[] = {
414 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
416 static size_t current_byte = 0;
417 for (size_t i = 0; i < n; ++i) {
418 output[i] = bytes[current_byte++];
419 current_byte %= arraysize(bytes);
423 void MockGenerateRandom2(uint8* output, size_t n) {
424 static const uint8 bytes[] = {
425 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
426 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
428 static size_t current_byte = 0;
429 for (size_t i = 0; i < n; ++i) {
430 output[i] = bytes[current_byte++];
431 current_byte %= arraysize(bytes);
435 std::string MockGetHostName() {
439 template<typename ParentPool>
440 class CaptureGroupNameSocketPool : public ParentPool {
442 CaptureGroupNameSocketPool(HostResolver* host_resolver,
443 CertVerifier* cert_verifier);
445 const std::string last_group_name_received() const {
446 return last_group_name_;
449 virtual int RequestSocket(const std::string& group_name,
450 const void* socket_params,
451 RequestPriority priority,
452 ClientSocketHandle* handle,
453 const CompletionCallback& callback,
454 const BoundNetLog& net_log) {
455 last_group_name_ = group_name;
456 return ERR_IO_PENDING;
458 virtual void CancelRequest(const std::string& group_name,
459 ClientSocketHandle* handle) {}
460 virtual void ReleaseSocket(const std::string& group_name,
461 scoped_ptr<StreamSocket> socket,
463 virtual void CloseIdleSockets() {}
464 virtual int IdleSocketCount() const {
467 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
470 virtual LoadState GetLoadState(const std::string& group_name,
471 const ClientSocketHandle* handle) const {
472 return LOAD_STATE_IDLE;
474 virtual base::TimeDelta ConnectionTimeout() const {
475 return base::TimeDelta();
479 std::string last_group_name_;
482 typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
483 CaptureGroupNameTransportSocketPool;
484 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
485 CaptureGroupNameHttpProxySocketPool;
486 typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
487 CaptureGroupNameSOCKSSocketPool;
488 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
489 CaptureGroupNameSSLSocketPool;
491 template<typename ParentPool>
492 CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
493 HostResolver* host_resolver,
494 CertVerifier* /* cert_verifier */)
495 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
498 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
499 HostResolver* host_resolver,
500 CertVerifier* /* cert_verifier */)
501 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
504 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
505 HostResolver* host_resolver,
506 CertVerifier* cert_verifier)
507 : SSLClientSocketPool(0,
522 //-----------------------------------------------------------------------------
524 // Helper functions for validating that AuthChallengeInfo's are correctly
525 // configured for common cases.
526 bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
529 EXPECT_FALSE(auth_challenge->is_proxy);
530 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
531 EXPECT_EQ("MyRealm1", auth_challenge->realm);
532 EXPECT_EQ("basic", auth_challenge->scheme);
536 bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
539 EXPECT_TRUE(auth_challenge->is_proxy);
540 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
541 EXPECT_EQ("MyRealm1", auth_challenge->realm);
542 EXPECT_EQ("basic", auth_challenge->scheme);
546 bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
549 EXPECT_FALSE(auth_challenge->is_proxy);
550 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
551 EXPECT_EQ("digestive", auth_challenge->realm);
552 EXPECT_EQ("digest", auth_challenge->scheme);
556 bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
559 EXPECT_FALSE(auth_challenge->is_proxy);
560 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
561 EXPECT_EQ(std::string(), auth_challenge->realm);
562 EXPECT_EQ("ntlm", auth_challenge->scheme);
568 TEST_P(HttpNetworkTransactionTest, Basic) {
569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
570 scoped_ptr<HttpTransaction> trans(
571 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
574 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
575 MockRead data_reads[] = {
576 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
577 MockRead("hello world"),
578 MockRead(SYNCHRONOUS, OK),
580 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
581 arraysize(data_reads));
582 EXPECT_EQ(OK, out.rv);
583 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
584 EXPECT_EQ("hello world", out.response_data);
587 // Response with no status line.
588 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
589 MockRead data_reads[] = {
590 MockRead("hello world"),
591 MockRead(SYNCHRONOUS, OK),
593 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
594 arraysize(data_reads));
595 EXPECT_EQ(OK, out.rv);
596 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
597 EXPECT_EQ("hello world", out.response_data);
600 // Allow up to 4 bytes of junk to precede status line.
601 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
602 MockRead data_reads[] = {
603 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
604 MockRead(SYNCHRONOUS, OK),
606 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
607 arraysize(data_reads));
608 EXPECT_EQ(OK, out.rv);
609 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
610 EXPECT_EQ("DATA", out.response_data);
613 // Allow up to 4 bytes of junk to precede status line.
614 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
615 MockRead data_reads[] = {
616 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
617 MockRead(SYNCHRONOUS, OK),
619 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
620 arraysize(data_reads));
621 EXPECT_EQ(OK, out.rv);
622 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
623 EXPECT_EQ("DATA", out.response_data);
626 // Beyond 4 bytes of slop and it should fail to find a status line.
627 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
628 MockRead data_reads[] = {
629 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
630 MockRead(SYNCHRONOUS, OK),
632 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
633 arraysize(data_reads));
634 EXPECT_EQ(OK, out.rv);
635 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
636 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
639 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
640 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
641 MockRead data_reads[] = {
646 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
647 MockRead(SYNCHRONOUS, OK),
649 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
650 arraysize(data_reads));
651 EXPECT_EQ(OK, out.rv);
652 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
653 EXPECT_EQ("DATA", out.response_data);
656 // Close the connection before enough bytes to have a status line.
657 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
658 MockRead data_reads[] = {
660 MockRead(SYNCHRONOUS, OK),
662 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
663 arraysize(data_reads));
664 EXPECT_EQ(OK, out.rv);
665 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
666 EXPECT_EQ("HTT", out.response_data);
669 // Simulate a 204 response, lacking a Content-Length header, sent over a
670 // persistent connection. The response should still terminate since a 204
671 // cannot have a response body.
672 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
673 MockRead data_reads[] = {
674 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
675 MockRead("junk"), // Should not be read!!
676 MockRead(SYNCHRONOUS, OK),
678 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
679 arraysize(data_reads));
680 EXPECT_EQ(OK, out.rv);
681 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
682 EXPECT_EQ("", out.response_data);
685 // A simple request using chunked encoding with some extra data after.
686 // (Like might be seen in a pipelined response.)
687 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
688 MockRead data_reads[] = {
689 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
690 MockRead("5\r\nHello\r\n"),
693 MockRead("5\r\nworld\r\n"),
694 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
695 MockRead(SYNCHRONOUS, OK),
697 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
698 arraysize(data_reads));
699 EXPECT_EQ(OK, out.rv);
700 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
701 EXPECT_EQ("Hello world", out.response_data);
704 // Next tests deal with http://crbug.com/56344.
706 TEST_P(HttpNetworkTransactionTest,
707 MultipleContentLengthHeadersNoTransferEncoding) {
708 MockRead data_reads[] = {
709 MockRead("HTTP/1.1 200 OK\r\n"),
710 MockRead("Content-Length: 10\r\n"),
711 MockRead("Content-Length: 5\r\n\r\n"),
713 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
714 arraysize(data_reads));
715 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
718 TEST_P(HttpNetworkTransactionTest,
719 DuplicateContentLengthHeadersNoTransferEncoding) {
720 MockRead data_reads[] = {
721 MockRead("HTTP/1.1 200 OK\r\n"),
722 MockRead("Content-Length: 5\r\n"),
723 MockRead("Content-Length: 5\r\n\r\n"),
726 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
727 arraysize(data_reads));
728 EXPECT_EQ(OK, out.rv);
729 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
730 EXPECT_EQ("Hello", out.response_data);
733 TEST_P(HttpNetworkTransactionTest,
734 ComplexContentLengthHeadersNoTransferEncoding) {
735 // More than 2 dupes.
737 MockRead data_reads[] = {
738 MockRead("HTTP/1.1 200 OK\r\n"),
739 MockRead("Content-Length: 5\r\n"),
740 MockRead("Content-Length: 5\r\n"),
741 MockRead("Content-Length: 5\r\n\r\n"),
744 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
745 arraysize(data_reads));
746 EXPECT_EQ(OK, out.rv);
747 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
748 EXPECT_EQ("Hello", out.response_data);
752 MockRead data_reads[] = {
753 MockRead("HTTP/1.0 200 OK\r\n"),
754 MockRead("Content-Length: 5\r\n"),
755 MockRead("Content-Length: 5\r\n"),
756 MockRead("Content-Length: 5\r\n\r\n"),
759 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
760 arraysize(data_reads));
761 EXPECT_EQ(OK, out.rv);
762 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
763 EXPECT_EQ("Hello", out.response_data);
765 // 2 dupes and one mismatched.
767 MockRead data_reads[] = {
768 MockRead("HTTP/1.1 200 OK\r\n"),
769 MockRead("Content-Length: 10\r\n"),
770 MockRead("Content-Length: 10\r\n"),
771 MockRead("Content-Length: 5\r\n\r\n"),
773 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
774 arraysize(data_reads));
775 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
779 TEST_P(HttpNetworkTransactionTest,
780 MultipleContentLengthHeadersTransferEncoding) {
781 MockRead data_reads[] = {
782 MockRead("HTTP/1.1 200 OK\r\n"),
783 MockRead("Content-Length: 666\r\n"),
784 MockRead("Content-Length: 1337\r\n"),
785 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
786 MockRead("5\r\nHello\r\n"),
789 MockRead("5\r\nworld\r\n"),
790 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
791 MockRead(SYNCHRONOUS, OK),
793 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
794 arraysize(data_reads));
795 EXPECT_EQ(OK, out.rv);
796 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
797 EXPECT_EQ("Hello world", out.response_data);
800 // Next tests deal with http://crbug.com/98895.
802 // Checks that a single Content-Disposition header results in no error.
803 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
804 MockRead data_reads[] = {
805 MockRead("HTTP/1.1 200 OK\r\n"),
806 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
807 MockRead("Content-Length: 5\r\n\r\n"),
810 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
811 arraysize(data_reads));
812 EXPECT_EQ(OK, out.rv);
813 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
814 EXPECT_EQ("Hello", out.response_data);
817 // Checks that two identical Content-Disposition headers result in no error.
818 TEST_P(HttpNetworkTransactionTest,
819 TwoIdenticalContentDispositionHeaders) {
820 MockRead data_reads[] = {
821 MockRead("HTTP/1.1 200 OK\r\n"),
822 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
823 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
824 MockRead("Content-Length: 5\r\n\r\n"),
827 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
828 arraysize(data_reads));
829 EXPECT_EQ(OK, out.rv);
830 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
831 EXPECT_EQ("Hello", out.response_data);
834 // Checks that two distinct Content-Disposition headers result in an error.
835 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
836 MockRead data_reads[] = {
837 MockRead("HTTP/1.1 200 OK\r\n"),
838 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
839 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
840 MockRead("Content-Length: 5\r\n\r\n"),
843 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
844 arraysize(data_reads));
845 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
848 // Checks that two identical Location headers result in no error.
849 // Also tests Location header behavior.
850 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
851 MockRead data_reads[] = {
852 MockRead("HTTP/1.1 302 Redirect\r\n"),
853 MockRead("Location: http://good.com/\r\n"),
854 MockRead("Location: http://good.com/\r\n"),
855 MockRead("Content-Length: 0\r\n\r\n"),
856 MockRead(SYNCHRONOUS, OK),
859 HttpRequestInfo request;
860 request.method = "GET";
861 request.url = GURL("http://redirect.com/");
862 request.load_flags = 0;
864 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
865 scoped_ptr<HttpTransaction> trans(
866 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
868 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
869 session_deps_.socket_factory->AddSocketDataProvider(&data);
871 TestCompletionCallback callback;
873 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
874 EXPECT_EQ(ERR_IO_PENDING, rv);
876 EXPECT_EQ(OK, callback.WaitForResult());
878 const HttpResponseInfo* response = trans->GetResponseInfo();
879 ASSERT_TRUE(response != NULL && response->headers.get() != NULL);
880 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
882 EXPECT_TRUE(response->headers->IsRedirect(&url));
883 EXPECT_EQ("http://good.com/", url);
886 // Checks that two distinct Location headers result in an error.
887 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
888 MockRead data_reads[] = {
889 MockRead("HTTP/1.1 302 Redirect\r\n"),
890 MockRead("Location: http://good.com/\r\n"),
891 MockRead("Location: http://evil.com/\r\n"),
892 MockRead("Content-Length: 0\r\n\r\n"),
893 MockRead(SYNCHRONOUS, OK),
895 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
896 arraysize(data_reads));
897 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
900 // Do a request using the HEAD method. Verify that we don't try to read the
901 // message body (since HEAD has none).
902 TEST_P(HttpNetworkTransactionTest, Head) {
903 HttpRequestInfo request;
904 request.method = "HEAD";
905 request.url = GURL("http://www.google.com/");
906 request.load_flags = 0;
908 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
909 scoped_ptr<HttpTransaction> trans(
910 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
912 MockWrite data_writes1[] = {
913 MockWrite("HEAD / HTTP/1.1\r\n"
914 "Host: www.google.com\r\n"
915 "Connection: keep-alive\r\n"
916 "Content-Length: 0\r\n\r\n"),
918 MockRead data_reads1[] = {
919 MockRead("HTTP/1.1 404 Not Found\r\n"),
920 MockRead("Server: Blah\r\n"),
921 MockRead("Content-Length: 1234\r\n\r\n"),
923 // No response body because the test stops reading here.
924 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
927 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
928 data_writes1, arraysize(data_writes1));
929 session_deps_.socket_factory->AddSocketDataProvider(&data1);
931 TestCompletionCallback callback1;
933 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
934 EXPECT_EQ(ERR_IO_PENDING, rv);
936 rv = callback1.WaitForResult();
939 const HttpResponseInfo* response = trans->GetResponseInfo();
940 ASSERT_TRUE(response != NULL);
942 // Check that the headers got parsed.
943 EXPECT_TRUE(response->headers.get() != NULL);
944 EXPECT_EQ(1234, response->headers->GetContentLength());
945 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
947 std::string server_header;
949 bool has_server_header = response->headers->EnumerateHeader(
950 &iter, "Server", &server_header);
951 EXPECT_TRUE(has_server_header);
952 EXPECT_EQ("Blah", server_header);
954 // Reading should give EOF right away, since there is no message body
955 // (despite non-zero content-length).
956 std::string response_data;
957 rv = ReadTransaction(trans.get(), &response_data);
959 EXPECT_EQ("", response_data);
962 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
963 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
965 MockRead data_reads[] = {
966 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
968 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
970 MockRead(SYNCHRONOUS, OK),
972 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
973 session_deps_.socket_factory->AddSocketDataProvider(&data);
975 const char* const kExpectedResponseData[] = {
979 for (int i = 0; i < 2; ++i) {
980 HttpRequestInfo request;
981 request.method = "GET";
982 request.url = GURL("http://www.google.com/");
983 request.load_flags = 0;
985 scoped_ptr<HttpTransaction> trans(
986 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
988 TestCompletionCallback callback;
990 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
991 EXPECT_EQ(ERR_IO_PENDING, rv);
993 rv = callback.WaitForResult();
996 const HttpResponseInfo* response = trans->GetResponseInfo();
997 ASSERT_TRUE(response != NULL);
999 EXPECT_TRUE(response->headers.get() != NULL);
1000 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1002 std::string response_data;
1003 rv = ReadTransaction(trans.get(), &response_data);
1005 EXPECT_EQ(kExpectedResponseData[i], response_data);
1009 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1010 ScopedVector<UploadElementReader> element_readers;
1011 element_readers.push_back(new UploadBytesElementReader("foo", 3));
1012 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
1014 HttpRequestInfo request;
1015 request.method = "POST";
1016 request.url = GURL("http://www.foo.com/");
1017 request.upload_data_stream = &upload_data_stream;
1018 request.load_flags = 0;
1020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1021 scoped_ptr<HttpTransaction> trans(
1022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1024 MockRead data_reads[] = {
1025 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1026 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1027 MockRead("hello world"),
1028 MockRead(SYNCHRONOUS, OK),
1030 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1031 session_deps_.socket_factory->AddSocketDataProvider(&data);
1033 TestCompletionCallback callback;
1035 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1036 EXPECT_EQ(ERR_IO_PENDING, rv);
1038 rv = callback.WaitForResult();
1041 const HttpResponseInfo* response = trans->GetResponseInfo();
1042 ASSERT_TRUE(response != NULL);
1044 EXPECT_TRUE(response->headers.get() != NULL);
1045 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1047 std::string response_data;
1048 rv = ReadTransaction(trans.get(), &response_data);
1050 EXPECT_EQ("hello world", response_data);
1053 // This test is almost the same as Ignores100 above, but the response contains
1054 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1055 // HTTP/1.1 and the two status headers are read in one read.
1056 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1057 HttpRequestInfo request;
1058 request.method = "GET";
1059 request.url = GURL("http://www.foo.com/");
1060 request.load_flags = 0;
1062 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1063 scoped_ptr<HttpTransaction> trans(
1064 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1066 MockRead data_reads[] = {
1067 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1068 "HTTP/1.1 200 OK\r\n\r\n"),
1069 MockRead("hello world"),
1070 MockRead(SYNCHRONOUS, OK),
1072 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1073 session_deps_.socket_factory->AddSocketDataProvider(&data);
1075 TestCompletionCallback callback;
1077 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1078 EXPECT_EQ(ERR_IO_PENDING, rv);
1080 rv = callback.WaitForResult();
1083 const HttpResponseInfo* response = trans->GetResponseInfo();
1084 ASSERT_TRUE(response != NULL);
1086 EXPECT_TRUE(response->headers.get() != NULL);
1087 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1089 std::string response_data;
1090 rv = ReadTransaction(trans.get(), &response_data);
1092 EXPECT_EQ("hello world", response_data);
1095 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1096 HttpRequestInfo request;
1097 request.method = "POST";
1098 request.url = GURL("http://www.foo.com/");
1099 request.load_flags = 0;
1101 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1102 scoped_ptr<HttpTransaction> trans(
1103 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1105 MockRead data_reads[] = {
1106 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1109 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1110 session_deps_.socket_factory->AddSocketDataProvider(&data);
1112 TestCompletionCallback callback;
1114 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1115 EXPECT_EQ(ERR_IO_PENDING, rv);
1117 rv = callback.WaitForResult();
1120 std::string response_data;
1121 rv = ReadTransaction(trans.get(), &response_data);
1123 EXPECT_EQ("", response_data);
1126 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1127 HttpRequestInfo request;
1128 request.method = "POST";
1129 request.url = GURL("http://www.foo.com/");
1130 request.load_flags = 0;
1132 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1133 scoped_ptr<HttpTransaction> trans(
1134 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1137 MockRead data_reads[] = {
1140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1141 session_deps_.socket_factory->AddSocketDataProvider(&data);
1143 TestCompletionCallback callback;
1145 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1146 EXPECT_EQ(ERR_IO_PENDING, rv);
1148 rv = callback.WaitForResult();
1149 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1152 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1153 const MockWrite* write_failure,
1154 const MockRead* read_failure) {
1155 HttpRequestInfo request;
1156 request.method = "GET";
1157 request.url = GURL("http://www.foo.com/");
1158 request.load_flags = 0;
1160 CapturingNetLog net_log;
1161 session_deps_.net_log = &net_log;
1162 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1164 // Written data for successfully sending both requests.
1165 MockWrite data1_writes[] = {
1166 MockWrite("GET / HTTP/1.1\r\n"
1167 "Host: www.foo.com\r\n"
1168 "Connection: keep-alive\r\n\r\n"),
1169 MockWrite("GET / HTTP/1.1\r\n"
1170 "Host: www.foo.com\r\n"
1171 "Connection: keep-alive\r\n\r\n")
1174 // Read results for the first request.
1175 MockRead data1_reads[] = {
1176 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1178 MockRead(ASYNC, OK),
1181 if (write_failure) {
1182 ASSERT_TRUE(!read_failure);
1183 data1_writes[1] = *write_failure;
1185 ASSERT_TRUE(read_failure);
1186 data1_reads[2] = *read_failure;
1189 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1190 data1_writes, arraysize(data1_writes));
1191 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1193 MockRead data2_reads[] = {
1194 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1196 MockRead(ASYNC, OK),
1198 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1199 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1201 const char* kExpectedResponseData[] = {
1205 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1206 for (int i = 0; i < 2; ++i) {
1207 TestCompletionCallback callback;
1209 scoped_ptr<HttpTransaction> trans(
1210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1212 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1213 EXPECT_EQ(ERR_IO_PENDING, rv);
1215 rv = callback.WaitForResult();
1218 LoadTimingInfo load_timing_info;
1219 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1220 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1222 first_socket_log_id = load_timing_info.socket_log_id;
1224 // The second request should be using a new socket.
1225 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
1228 const HttpResponseInfo* response = trans->GetResponseInfo();
1229 ASSERT_TRUE(response != NULL);
1231 EXPECT_TRUE(response->headers.get() != NULL);
1232 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1234 std::string response_data;
1235 rv = ReadTransaction(trans.get(), &response_data);
1237 EXPECT_EQ(kExpectedResponseData[i], response_data);
1241 TEST_P(HttpNetworkTransactionTest,
1242 KeepAliveConnectionNotConnectedOnWrite) {
1243 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
1244 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1247 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
1248 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
1249 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1252 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
1253 MockRead read_failure(SYNCHRONOUS, OK); // EOF
1254 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
1257 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
1258 HttpRequestInfo request;
1259 request.method = "GET";
1260 request.url = GURL("http://www.google.com/");
1261 request.load_flags = 0;
1263 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1264 scoped_ptr<HttpTransaction> trans(
1265 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1267 MockRead data_reads[] = {
1268 MockRead(ASYNC, ERR_CONNECTION_RESET),
1269 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1270 MockRead("hello world"),
1271 MockRead(SYNCHRONOUS, OK),
1273 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1274 session_deps_.socket_factory->AddSocketDataProvider(&data);
1276 TestCompletionCallback callback;
1278 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1279 EXPECT_EQ(ERR_IO_PENDING, rv);
1281 rv = callback.WaitForResult();
1282 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
1284 const HttpResponseInfo* response = trans->GetResponseInfo();
1285 EXPECT_TRUE(response == NULL);
1288 // What do various browsers do when the server closes a non-keepalive
1289 // connection without sending any response header or body?
1292 // Safari 3.1.2 (Windows): error page
1293 // Firefox 3.0.1: blank page
1294 // Opera 9.52: after five attempts, blank page
1295 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1296 // Us: error page (EMPTY_RESPONSE)
1297 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1298 MockRead data_reads[] = {
1299 MockRead(SYNCHRONOUS, OK), // EOF
1300 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1301 MockRead("hello world"),
1302 MockRead(SYNCHRONOUS, OK),
1304 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1305 arraysize(data_reads));
1306 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
1309 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1310 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1311 // destructor in such situations.
1312 // See http://crbug.com/154712 and http://crbug.com/156609.
1313 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
1314 HttpRequestInfo request;
1315 request.method = "GET";
1316 request.url = GURL("http://www.google.com/");
1317 request.load_flags = 0;
1319 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1320 scoped_ptr<HttpTransaction> trans(
1321 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1323 MockRead data_reads[] = {
1324 MockRead("HTTP/1.0 200 OK\r\n"),
1325 MockRead("Connection: keep-alive\r\n"),
1326 MockRead("Content-Length: 100\r\n\r\n"),
1328 MockRead(SYNCHRONOUS, 0),
1330 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1331 session_deps_.socket_factory->AddSocketDataProvider(&data);
1333 TestCompletionCallback callback;
1335 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1336 EXPECT_EQ(ERR_IO_PENDING, rv);
1338 rv = callback.WaitForResult();
1341 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1342 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1343 if (rv == ERR_IO_PENDING)
1344 rv = callback.WaitForResult();
1346 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1347 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1350 base::MessageLoop::current()->RunUntilIdle();
1351 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1354 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
1355 HttpRequestInfo request;
1356 request.method = "GET";
1357 request.url = GURL("http://www.google.com/");
1358 request.load_flags = 0;
1360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1361 scoped_ptr<HttpTransaction> trans(
1362 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1364 MockRead data_reads[] = {
1365 MockRead("HTTP/1.0 200 OK\r\n"),
1366 MockRead("Connection: keep-alive\r\n"),
1367 MockRead("Content-Length: 100\r\n\r\n"),
1368 MockRead(SYNCHRONOUS, 0),
1370 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
1371 session_deps_.socket_factory->AddSocketDataProvider(&data);
1373 TestCompletionCallback callback;
1375 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1376 EXPECT_EQ(ERR_IO_PENDING, rv);
1378 rv = callback.WaitForResult();
1381 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100));
1382 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
1383 if (rv == ERR_IO_PENDING)
1384 rv = callback.WaitForResult();
1385 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
1388 base::MessageLoop::current()->RunUntilIdle();
1389 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
1392 // Test that we correctly reuse a keep-alive connection after not explicitly
1393 // reading the body.
1394 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
1395 HttpRequestInfo request;
1396 request.method = "GET";
1397 request.url = GURL("http://www.foo.com/");
1398 request.load_flags = 0;
1400 CapturingNetLog net_log;
1401 session_deps_.net_log = &net_log;
1402 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1404 // Note that because all these reads happen in the same
1405 // StaticSocketDataProvider, it shows that the same socket is being reused for
1406 // all transactions.
1407 MockRead data1_reads[] = {
1408 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1409 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1410 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1411 MockRead("HTTP/1.1 302 Found\r\n"
1412 "Content-Length: 0\r\n\r\n"),
1413 MockRead("HTTP/1.1 302 Found\r\n"
1414 "Content-Length: 5\r\n\r\n"
1416 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1417 "Content-Length: 0\r\n\r\n"),
1418 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1419 "Content-Length: 5\r\n\r\n"
1421 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1424 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1425 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1427 MockRead data2_reads[] = {
1428 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
1430 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1431 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1433 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1434 std::string response_lines[kNumUnreadBodies];
1436 uint32 first_socket_log_id = NetLog::Source::kInvalidId;
1437 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
1438 TestCompletionCallback callback;
1440 scoped_ptr<HttpTransaction> trans(
1441 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1443 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1444 EXPECT_EQ(ERR_IO_PENDING, rv);
1446 rv = callback.WaitForResult();
1449 LoadTimingInfo load_timing_info;
1450 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
1452 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
1453 first_socket_log_id = load_timing_info.socket_log_id;
1455 TestLoadTimingReused(load_timing_info);
1456 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
1459 const HttpResponseInfo* response = trans->GetResponseInfo();
1460 ASSERT_TRUE(response != NULL);
1462 ASSERT_TRUE(response->headers.get() != NULL);
1463 response_lines[i] = response->headers->GetStatusLine();
1465 // We intentionally don't read the response bodies.
1468 const char* const kStatusLines[] = {
1469 "HTTP/1.1 204 No Content",
1470 "HTTP/1.1 205 Reset Content",
1471 "HTTP/1.1 304 Not Modified",
1472 "HTTP/1.1 302 Found",
1473 "HTTP/1.1 302 Found",
1474 "HTTP/1.1 301 Moved Permanently",
1475 "HTTP/1.1 301 Moved Permanently",
1478 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1479 forgot_to_update_kStatusLines);
1481 for (int i = 0; i < kNumUnreadBodies; ++i)
1482 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1484 TestCompletionCallback callback;
1485 scoped_ptr<HttpTransaction> trans(
1486 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1487 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1488 EXPECT_EQ(ERR_IO_PENDING, rv);
1489 rv = callback.WaitForResult();
1491 const HttpResponseInfo* response = trans->GetResponseInfo();
1492 ASSERT_TRUE(response != NULL);
1493 ASSERT_TRUE(response->headers.get() != NULL);
1494 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1495 std::string response_data;
1496 rv = ReadTransaction(trans.get(), &response_data);
1498 EXPECT_EQ("hello", response_data);
1501 // Test the request-challenge-retry sequence for basic auth.
1502 // (basic auth is the easiest to mock, because it has no randomness).
1503 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
1504 HttpRequestInfo request;
1505 request.method = "GET";
1506 request.url = GURL("http://www.google.com/");
1507 request.load_flags = 0;
1509 CapturingNetLog log;
1510 session_deps_.net_log = &log;
1511 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1512 scoped_ptr<HttpTransaction> trans(
1513 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1515 MockWrite data_writes1[] = {
1516 MockWrite("GET / HTTP/1.1\r\n"
1517 "Host: www.google.com\r\n"
1518 "Connection: keep-alive\r\n\r\n"),
1521 MockRead data_reads1[] = {
1522 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1523 // Give a couple authenticate options (only the middle one is actually
1525 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1526 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1527 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1528 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1529 // Large content-length -- won't matter, as connection will be reset.
1530 MockRead("Content-Length: 10000\r\n\r\n"),
1531 MockRead(SYNCHRONOUS, ERR_FAILED),
1534 // After calling trans->RestartWithAuth(), this is the request we should
1535 // be issuing -- the final header line contains the credentials.
1536 MockWrite data_writes2[] = {
1537 MockWrite("GET / HTTP/1.1\r\n"
1538 "Host: www.google.com\r\n"
1539 "Connection: keep-alive\r\n"
1540 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1543 // Lastly, the server responds with the actual content.
1544 MockRead data_reads2[] = {
1545 MockRead("HTTP/1.0 200 OK\r\n"),
1546 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1547 MockRead("Content-Length: 100\r\n\r\n"),
1548 MockRead(SYNCHRONOUS, OK),
1551 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1552 data_writes1, arraysize(data_writes1));
1553 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1554 data_writes2, arraysize(data_writes2));
1555 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1556 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1558 TestCompletionCallback callback1;
1560 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1561 EXPECT_EQ(ERR_IO_PENDING, rv);
1563 rv = callback1.WaitForResult();
1566 LoadTimingInfo load_timing_info1;
1567 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1568 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1570 const HttpResponseInfo* response = trans->GetResponseInfo();
1571 ASSERT_TRUE(response != NULL);
1572 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1574 TestCompletionCallback callback2;
1576 rv = trans->RestartWithAuth(
1577 AuthCredentials(kFoo, kBar), callback2.callback());
1578 EXPECT_EQ(ERR_IO_PENDING, rv);
1580 rv = callback2.WaitForResult();
1583 LoadTimingInfo load_timing_info2;
1584 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1585 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
1586 // The load timing after restart should have a new socket ID, and times after
1587 // those of the first load timing.
1588 EXPECT_LE(load_timing_info1.receive_headers_end,
1589 load_timing_info2.connect_timing.connect_start);
1590 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1592 response = trans->GetResponseInfo();
1593 ASSERT_TRUE(response != NULL);
1594 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1595 EXPECT_EQ(100, response->headers->GetContentLength());
1598 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
1599 HttpRequestInfo request;
1600 request.method = "GET";
1601 request.url = GURL("http://www.google.com/");
1602 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1604 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1605 scoped_ptr<HttpTransaction> trans(
1606 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
1608 MockWrite data_writes[] = {
1609 MockWrite("GET / HTTP/1.1\r\n"
1610 "Host: www.google.com\r\n"
1611 "Connection: keep-alive\r\n\r\n"),
1614 MockRead data_reads[] = {
1615 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1616 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1617 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1618 // Large content-length -- won't matter, as connection will be reset.
1619 MockRead("Content-Length: 10000\r\n\r\n"),
1620 MockRead(SYNCHRONOUS, ERR_FAILED),
1623 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1624 data_writes, arraysize(data_writes));
1625 session_deps_.socket_factory->AddSocketDataProvider(&data);
1626 TestCompletionCallback callback;
1628 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
1629 EXPECT_EQ(ERR_IO_PENDING, rv);
1631 rv = callback.WaitForResult();
1634 const HttpResponseInfo* response = trans->GetResponseInfo();
1635 ASSERT_TRUE(response != NULL);
1636 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1639 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1641 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
1642 HttpRequestInfo request;
1643 request.method = "GET";
1644 request.url = GURL("http://www.google.com/");
1645 request.load_flags = 0;
1647 CapturingNetLog log;
1648 session_deps_.net_log = &log;
1649 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1651 MockWrite data_writes1[] = {
1652 MockWrite("GET / HTTP/1.1\r\n"
1653 "Host: www.google.com\r\n"
1654 "Connection: keep-alive\r\n\r\n"),
1656 // After calling trans->RestartWithAuth(), this is the request we should
1657 // be issuing -- the final header line contains the credentials.
1658 MockWrite("GET / HTTP/1.1\r\n"
1659 "Host: www.google.com\r\n"
1660 "Connection: keep-alive\r\n"
1661 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1664 MockRead data_reads1[] = {
1665 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1666 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1667 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1668 MockRead("Content-Length: 14\r\n\r\n"),
1669 MockRead("Unauthorized\r\n"),
1671 // Lastly, the server responds with the actual content.
1672 MockRead("HTTP/1.1 200 OK\r\n"),
1673 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1674 MockRead("Content-Length: 5\r\n\r\n"),
1678 // If there is a regression where we disconnect a Keep-Alive
1679 // connection during an auth roundtrip, we'll end up reading this.
1680 MockRead data_reads2[] = {
1681 MockRead(SYNCHRONOUS, ERR_FAILED),
1684 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1685 data_writes1, arraysize(data_writes1));
1686 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1688 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1689 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1691 TestCompletionCallback callback1;
1693 scoped_ptr<HttpTransaction> trans(
1694 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1695 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1696 EXPECT_EQ(ERR_IO_PENDING, rv);
1698 rv = callback1.WaitForResult();
1701 LoadTimingInfo load_timing_info1;
1702 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1));
1703 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
1705 const HttpResponseInfo* response = trans->GetResponseInfo();
1706 ASSERT_TRUE(response != NULL);
1707 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1709 TestCompletionCallback callback2;
1711 rv = trans->RestartWithAuth(
1712 AuthCredentials(kFoo, kBar), callback2.callback());
1713 EXPECT_EQ(ERR_IO_PENDING, rv);
1715 rv = callback2.WaitForResult();
1718 LoadTimingInfo load_timing_info2;
1719 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2));
1720 TestLoadTimingReused(load_timing_info2);
1721 // The load timing after restart should have the same socket ID, and times
1722 // those of the first load timing.
1723 EXPECT_LE(load_timing_info1.receive_headers_end,
1724 load_timing_info2.send_start);
1725 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
1727 response = trans->GetResponseInfo();
1728 ASSERT_TRUE(response != NULL);
1729 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1730 EXPECT_EQ(5, response->headers->GetContentLength());
1733 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1734 // connection and with no response body to drain.
1735 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
1736 HttpRequestInfo request;
1737 request.method = "GET";
1738 request.url = GURL("http://www.google.com/");
1739 request.load_flags = 0;
1741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1743 MockWrite data_writes1[] = {
1744 MockWrite("GET / HTTP/1.1\r\n"
1745 "Host: www.google.com\r\n"
1746 "Connection: keep-alive\r\n\r\n"),
1748 // After calling trans->RestartWithAuth(), this is the request we should
1749 // be issuing -- the final header line contains the credentials.
1750 MockWrite("GET / HTTP/1.1\r\n"
1751 "Host: www.google.com\r\n"
1752 "Connection: keep-alive\r\n"
1753 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1756 MockRead data_reads1[] = {
1757 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1758 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1759 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
1761 // Lastly, the server responds with the actual content.
1762 MockRead("HTTP/1.1 200 OK\r\n"),
1763 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1764 MockRead("Content-Length: 5\r\n\r\n"),
1768 // An incorrect reconnect would cause this to be read.
1769 MockRead data_reads2[] = {
1770 MockRead(SYNCHRONOUS, ERR_FAILED),
1773 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1774 data_writes1, arraysize(data_writes1));
1775 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1777 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1778 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1780 TestCompletionCallback callback1;
1782 scoped_ptr<HttpTransaction> trans(
1783 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1784 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1785 EXPECT_EQ(ERR_IO_PENDING, rv);
1787 rv = callback1.WaitForResult();
1790 const HttpResponseInfo* response = trans->GetResponseInfo();
1791 ASSERT_TRUE(response != NULL);
1792 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1794 TestCompletionCallback callback2;
1796 rv = trans->RestartWithAuth(
1797 AuthCredentials(kFoo, kBar), callback2.callback());
1798 EXPECT_EQ(ERR_IO_PENDING, rv);
1800 rv = callback2.WaitForResult();
1803 response = trans->GetResponseInfo();
1804 ASSERT_TRUE(response != NULL);
1805 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1806 EXPECT_EQ(5, response->headers->GetContentLength());
1809 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1810 // connection and with a large response body to drain.
1811 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
1812 HttpRequestInfo request;
1813 request.method = "GET";
1814 request.url = GURL("http://www.google.com/");
1815 request.load_flags = 0;
1817 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1819 MockWrite data_writes1[] = {
1820 MockWrite("GET / HTTP/1.1\r\n"
1821 "Host: www.google.com\r\n"
1822 "Connection: keep-alive\r\n\r\n"),
1824 // After calling trans->RestartWithAuth(), this is the request we should
1825 // be issuing -- the final header line contains the credentials.
1826 MockWrite("GET / HTTP/1.1\r\n"
1827 "Host: www.google.com\r\n"
1828 "Connection: keep-alive\r\n"
1829 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1832 // Respond with 5 kb of response body.
1833 std::string large_body_string("Unauthorized");
1834 large_body_string.append(5 * 1024, ' ');
1835 large_body_string.append("\r\n");
1837 MockRead data_reads1[] = {
1838 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1839 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1840 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1841 // 5134 = 12 + 5 * 1024 + 2
1842 MockRead("Content-Length: 5134\r\n\r\n"),
1843 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
1845 // Lastly, the server responds with the actual content.
1846 MockRead("HTTP/1.1 200 OK\r\n"),
1847 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1848 MockRead("Content-Length: 5\r\n\r\n"),
1852 // An incorrect reconnect would cause this to be read.
1853 MockRead data_reads2[] = {
1854 MockRead(SYNCHRONOUS, ERR_FAILED),
1857 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1858 data_writes1, arraysize(data_writes1));
1859 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1861 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1862 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1864 TestCompletionCallback callback1;
1866 scoped_ptr<HttpTransaction> trans(
1867 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1868 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1869 EXPECT_EQ(ERR_IO_PENDING, rv);
1871 rv = callback1.WaitForResult();
1874 const HttpResponseInfo* response = trans->GetResponseInfo();
1875 ASSERT_TRUE(response != NULL);
1876 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1878 TestCompletionCallback callback2;
1880 rv = trans->RestartWithAuth(
1881 AuthCredentials(kFoo, kBar), callback2.callback());
1882 EXPECT_EQ(ERR_IO_PENDING, rv);
1884 rv = callback2.WaitForResult();
1887 response = trans->GetResponseInfo();
1888 ASSERT_TRUE(response != NULL);
1889 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1890 EXPECT_EQ(5, response->headers->GetContentLength());
1893 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1894 // connection, but the server gets impatient and closes the connection.
1895 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1896 HttpRequestInfo request;
1897 request.method = "GET";
1898 request.url = GURL("http://www.google.com/");
1899 request.load_flags = 0;
1901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1903 MockWrite data_writes1[] = {
1904 MockWrite("GET / HTTP/1.1\r\n"
1905 "Host: www.google.com\r\n"
1906 "Connection: keep-alive\r\n\r\n"),
1907 // This simulates the seemingly successful write to a closed connection
1908 // if the bug is not fixed.
1909 MockWrite("GET / HTTP/1.1\r\n"
1910 "Host: www.google.com\r\n"
1911 "Connection: keep-alive\r\n"
1912 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1915 MockRead data_reads1[] = {
1916 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1917 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1918 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1919 MockRead("Content-Length: 14\r\n\r\n"),
1920 // Tell MockTCPClientSocket to simulate the server closing the connection.
1921 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1922 MockRead("Unauthorized\r\n"),
1923 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
1926 // After calling trans->RestartWithAuth(), this is the request we should
1927 // be issuing -- the final header line contains the credentials.
1928 MockWrite data_writes2[] = {
1929 MockWrite("GET / HTTP/1.1\r\n"
1930 "Host: www.google.com\r\n"
1931 "Connection: keep-alive\r\n"
1932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1935 // Lastly, the server responds with the actual content.
1936 MockRead data_reads2[] = {
1937 MockRead("HTTP/1.1 200 OK\r\n"),
1938 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1939 MockRead("Content-Length: 5\r\n\r\n"),
1943 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1944 data_writes1, arraysize(data_writes1));
1945 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1946 data_writes2, arraysize(data_writes2));
1947 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1948 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1950 TestCompletionCallback callback1;
1952 scoped_ptr<HttpTransaction> trans(
1953 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
1954 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
1955 EXPECT_EQ(ERR_IO_PENDING, rv);
1957 rv = callback1.WaitForResult();
1960 const HttpResponseInfo* response = trans->GetResponseInfo();
1961 ASSERT_TRUE(response != NULL);
1962 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
1964 TestCompletionCallback callback2;
1966 rv = trans->RestartWithAuth(
1967 AuthCredentials(kFoo, kBar), callback2.callback());
1968 EXPECT_EQ(ERR_IO_PENDING, rv);
1970 rv = callback2.WaitForResult();
1973 response = trans->GetResponseInfo();
1974 ASSERT_TRUE(response != NULL);
1975 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1976 EXPECT_EQ(5, response->headers->GetContentLength());
1979 // Test the request-challenge-retry sequence for basic auth, over a connection
1980 // that requires a restart when setting up an SSL tunnel.
1981 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1982 HttpRequestInfo request;
1983 request.method = "GET";
1984 request.url = GURL("https://www.google.com/");
1985 // when the no authentication data flag is set.
1986 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1988 // Configure against proxy server "myproxy:70".
1989 session_deps_.proxy_service.reset(
1990 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
1991 CapturingBoundNetLog log;
1992 session_deps_.net_log = log.bound().net_log();
1993 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1995 // Since we have proxy, should try to establish tunnel.
1996 MockWrite data_writes1[] = {
1997 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1998 "Host: www.google.com\r\n"
1999 "Proxy-Connection: keep-alive\r\n\r\n"),
2001 // After calling trans->RestartWithAuth(), this is the request we should
2002 // be issuing -- the final header line contains the credentials.
2003 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2004 "Host: www.google.com\r\n"
2005 "Proxy-Connection: keep-alive\r\n"
2006 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2008 MockWrite("GET / HTTP/1.1\r\n"
2009 "Host: www.google.com\r\n"
2010 "Connection: keep-alive\r\n\r\n"),
2013 // The proxy responds to the connect with a 407, using a persistent
2015 MockRead data_reads1[] = {
2017 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2018 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2019 MockRead("Proxy-Connection: close\r\n\r\n"),
2021 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2023 MockRead("HTTP/1.1 200 OK\r\n"),
2024 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2025 MockRead("Content-Length: 5\r\n\r\n"),
2026 MockRead(SYNCHRONOUS, "hello"),
2029 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2030 data_writes1, arraysize(data_writes1));
2031 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2032 SSLSocketDataProvider ssl(ASYNC, OK);
2033 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2035 TestCompletionCallback callback1;
2037 scoped_ptr<HttpTransaction> trans(
2038 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2040 int rv = trans->Start(&request, callback1.callback(), log.bound());
2041 EXPECT_EQ(ERR_IO_PENDING, rv);
2043 rv = callback1.WaitForResult();
2045 net::CapturingNetLog::CapturedEntryList entries;
2046 log.GetEntries(&entries);
2047 size_t pos = ExpectLogContainsSomewhere(
2048 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2049 NetLog::PHASE_NONE);
2050 ExpectLogContainsSomewhere(
2052 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2053 NetLog::PHASE_NONE);
2055 const HttpResponseInfo* response = trans->GetResponseInfo();
2056 ASSERT_TRUE(response != NULL);
2057 ASSERT_FALSE(response->headers.get() == NULL);
2058 EXPECT_EQ(407, response->headers->response_code());
2059 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2060 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2062 LoadTimingInfo load_timing_info;
2063 // CONNECT requests and responses are handled at the connect job level, so
2064 // the transaction does not yet have a connection.
2065 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
2067 TestCompletionCallback callback2;
2069 rv = trans->RestartWithAuth(
2070 AuthCredentials(kFoo, kBar), callback2.callback());
2071 EXPECT_EQ(ERR_IO_PENDING, rv);
2073 rv = callback2.WaitForResult();
2076 response = trans->GetResponseInfo();
2077 ASSERT_TRUE(response != NULL);
2079 EXPECT_TRUE(response->headers->IsKeepAlive());
2080 EXPECT_EQ(200, response->headers->response_code());
2081 EXPECT_EQ(5, response->headers->GetContentLength());
2082 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2084 // The password prompt info should not be set.
2085 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2087 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2088 TestLoadTimingNotReusedWithPac(load_timing_info,
2089 CONNECT_TIMING_HAS_SSL_TIMES);
2092 session->CloseAllConnections();
2095 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2096 // proxy connection, when setting up an SSL tunnel.
2097 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
2098 HttpRequestInfo request;
2099 request.method = "GET";
2100 request.url = GURL("https://www.google.com/");
2101 // Ensure that proxy authentication is attempted even
2102 // when the no authentication data flag is set.
2103 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2105 // Configure against proxy server "myproxy:70".
2106 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2107 CapturingBoundNetLog log;
2108 session_deps_.net_log = log.bound().net_log();
2109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2111 scoped_ptr<HttpTransaction> trans(
2112 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2114 // Since we have proxy, should try to establish tunnel.
2115 MockWrite data_writes1[] = {
2116 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2117 "Host: www.google.com\r\n"
2118 "Proxy-Connection: keep-alive\r\n\r\n"),
2120 // After calling trans->RestartWithAuth(), this is the request we should
2121 // be issuing -- the final header line contains the credentials.
2122 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2123 "Host: www.google.com\r\n"
2124 "Proxy-Connection: keep-alive\r\n"
2125 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2128 // The proxy responds to the connect with a 407, using a persistent
2130 MockRead data_reads1[] = {
2132 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2133 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2134 MockRead("Content-Length: 10\r\n\r\n"),
2135 MockRead("0123456789"),
2137 // Wrong credentials (wrong password).
2138 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2139 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2140 MockRead("Content-Length: 10\r\n\r\n"),
2141 // No response body because the test stops reading here.
2142 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2145 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2146 data_writes1, arraysize(data_writes1));
2147 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2149 TestCompletionCallback callback1;
2151 int rv = trans->Start(&request, callback1.callback(), log.bound());
2152 EXPECT_EQ(ERR_IO_PENDING, rv);
2154 rv = callback1.WaitForResult();
2156 net::CapturingNetLog::CapturedEntryList entries;
2157 log.GetEntries(&entries);
2158 size_t pos = ExpectLogContainsSomewhere(
2159 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2160 NetLog::PHASE_NONE);
2161 ExpectLogContainsSomewhere(
2163 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2164 NetLog::PHASE_NONE);
2166 const HttpResponseInfo* response = trans->GetResponseInfo();
2167 ASSERT_TRUE(response != NULL);
2168 ASSERT_FALSE(response->headers.get() == NULL);
2169 EXPECT_TRUE(response->headers->IsKeepAlive());
2170 EXPECT_EQ(407, response->headers->response_code());
2171 EXPECT_EQ(10, response->headers->GetContentLength());
2172 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2173 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2175 TestCompletionCallback callback2;
2177 // Wrong password (should be "bar").
2178 rv = trans->RestartWithAuth(
2179 AuthCredentials(kFoo, kBaz), callback2.callback());
2180 EXPECT_EQ(ERR_IO_PENDING, rv);
2182 rv = callback2.WaitForResult();
2185 response = trans->GetResponseInfo();
2186 ASSERT_TRUE(response != NULL);
2187 ASSERT_FALSE(response->headers.get() == NULL);
2188 EXPECT_TRUE(response->headers->IsKeepAlive());
2189 EXPECT_EQ(407, response->headers->response_code());
2190 EXPECT_EQ(10, response->headers->GetContentLength());
2191 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2192 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2194 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2196 session->CloseAllConnections();
2199 // Test that we don't read the response body when we fail to establish a tunnel,
2200 // even if the user cancels the proxy's auth attempt.
2201 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
2202 HttpRequestInfo request;
2203 request.method = "GET";
2204 request.url = GURL("https://www.google.com/");
2205 request.load_flags = 0;
2207 // Configure against proxy server "myproxy:70".
2208 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2210 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2212 scoped_ptr<HttpTransaction> trans(
2213 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2215 // Since we have proxy, should try to establish tunnel.
2216 MockWrite data_writes[] = {
2217 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2218 "Host: www.google.com\r\n"
2219 "Proxy-Connection: keep-alive\r\n\r\n"),
2222 // The proxy responds to the connect with a 407.
2223 MockRead data_reads[] = {
2224 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2225 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2226 MockRead("Content-Length: 10\r\n\r\n"),
2227 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
2230 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2231 data_writes, arraysize(data_writes));
2232 session_deps_.socket_factory->AddSocketDataProvider(&data);
2234 TestCompletionCallback callback;
2236 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2237 EXPECT_EQ(ERR_IO_PENDING, rv);
2239 rv = callback.WaitForResult();
2242 const HttpResponseInfo* response = trans->GetResponseInfo();
2243 ASSERT_TRUE(response != NULL);
2245 EXPECT_TRUE(response->headers->IsKeepAlive());
2246 EXPECT_EQ(407, response->headers->response_code());
2247 EXPECT_EQ(10, response->headers->GetContentLength());
2248 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2250 std::string response_data;
2251 rv = ReadTransaction(trans.get(), &response_data);
2252 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2254 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2255 session->CloseAllConnections();
2258 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2259 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2260 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
2261 HttpRequestInfo request;
2262 request.method = "GET";
2263 request.url = GURL("http://www.google.com/");
2264 request.load_flags = 0;
2266 // We are using a DIRECT connection (i.e. no proxy) for this session.
2267 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2268 scoped_ptr<HttpTransaction> trans(
2269 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
2271 MockWrite data_writes1[] = {
2272 MockWrite("GET / HTTP/1.1\r\n"
2273 "Host: www.google.com\r\n"
2274 "Connection: keep-alive\r\n\r\n"),
2277 MockRead data_reads1[] = {
2278 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2279 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2280 // Large content-length -- won't matter, as connection will be reset.
2281 MockRead("Content-Length: 10000\r\n\r\n"),
2282 MockRead(SYNCHRONOUS, ERR_FAILED),
2285 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2286 data_writes1, arraysize(data_writes1));
2287 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2289 TestCompletionCallback callback;
2291 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
2292 EXPECT_EQ(ERR_IO_PENDING, rv);
2294 rv = callback.WaitForResult();
2295 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2298 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2299 // through a non-authenticating proxy. The request should fail with
2300 // ERR_UNEXPECTED_PROXY_AUTH.
2301 // Note that it is impossible to detect if an HTTP server returns a 407 through
2302 // a non-authenticating proxy - there is nothing to indicate whether the
2303 // response came from the proxy or the server, so it is treated as if the proxy
2304 // issued the challenge.
2305 TEST_P(HttpNetworkTransactionTest,
2306 HttpsServerRequestsProxyAuthThroughProxy) {
2307 HttpRequestInfo request;
2308 request.method = "GET";
2309 request.url = GURL("https://www.google.com/");
2311 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
2312 CapturingBoundNetLog log;
2313 session_deps_.net_log = log.bound().net_log();
2314 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2316 // Since we have proxy, should try to establish tunnel.
2317 MockWrite data_writes1[] = {
2318 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2319 "Host: www.google.com\r\n"
2320 "Proxy-Connection: keep-alive\r\n\r\n"),
2322 MockWrite("GET / HTTP/1.1\r\n"
2323 "Host: www.google.com\r\n"
2324 "Connection: keep-alive\r\n\r\n"),
2327 MockRead data_reads1[] = {
2328 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2330 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2331 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2333 MockRead(SYNCHRONOUS, OK),
2336 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2337 data_writes1, arraysize(data_writes1));
2338 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2339 SSLSocketDataProvider ssl(ASYNC, OK);
2340 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2342 TestCompletionCallback callback1;
2344 scoped_ptr<HttpTransaction> trans(
2345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2347 int rv = trans->Start(&request, callback1.callback(), log.bound());
2348 EXPECT_EQ(ERR_IO_PENDING, rv);
2350 rv = callback1.WaitForResult();
2351 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2352 net::CapturingNetLog::CapturedEntryList entries;
2353 log.GetEntries(&entries);
2354 size_t pos = ExpectLogContainsSomewhere(
2355 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
2356 NetLog::PHASE_NONE);
2357 ExpectLogContainsSomewhere(
2359 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2360 NetLog::PHASE_NONE);
2363 // Test the load timing for HTTPS requests with an HTTP proxy.
2364 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
2365 HttpRequestInfo request1;
2366 request1.method = "GET";
2367 request1.url = GURL("https://www.google.com/1");
2369 HttpRequestInfo request2;
2370 request2.method = "GET";
2371 request2.url = GURL("https://www.google.com/2");
2373 // Configure against proxy server "myproxy:70".
2374 session_deps_.proxy_service.reset(
2375 ProxyService::CreateFixed("PROXY myproxy:70"));
2376 CapturingBoundNetLog log;
2377 session_deps_.net_log = log.bound().net_log();
2378 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2380 // Since we have proxy, should try to establish tunnel.
2381 MockWrite data_writes1[] = {
2382 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2383 "Host: www.google.com\r\n"
2384 "Proxy-Connection: keep-alive\r\n\r\n"),
2386 MockWrite("GET /1 HTTP/1.1\r\n"
2387 "Host: www.google.com\r\n"
2388 "Connection: keep-alive\r\n\r\n"),
2390 MockWrite("GET /2 HTTP/1.1\r\n"
2391 "Host: www.google.com\r\n"
2392 "Connection: keep-alive\r\n\r\n"),
2395 // The proxy responds to the connect with a 407, using a persistent
2397 MockRead data_reads1[] = {
2398 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2400 MockRead("HTTP/1.1 200 OK\r\n"),
2401 MockRead("Content-Length: 1\r\n\r\n"),
2402 MockRead(SYNCHRONOUS, "1"),
2404 MockRead("HTTP/1.1 200 OK\r\n"),
2405 MockRead("Content-Length: 2\r\n\r\n"),
2406 MockRead(SYNCHRONOUS, "22"),
2409 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2410 data_writes1, arraysize(data_writes1));
2411 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2412 SSLSocketDataProvider ssl(ASYNC, OK);
2413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2415 TestCompletionCallback callback1;
2416 scoped_ptr<HttpTransaction> trans1(
2417 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2419 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2420 EXPECT_EQ(ERR_IO_PENDING, rv);
2422 rv = callback1.WaitForResult();
2425 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2426 ASSERT_TRUE(response1 != NULL);
2427 ASSERT_TRUE(response1->headers.get() != NULL);
2428 EXPECT_EQ(1, response1->headers->GetContentLength());
2430 LoadTimingInfo load_timing_info1;
2431 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2432 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
2436 TestCompletionCallback callback2;
2437 scoped_ptr<HttpTransaction> trans2(
2438 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2440 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2441 EXPECT_EQ(ERR_IO_PENDING, rv);
2443 rv = callback2.WaitForResult();
2446 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2447 ASSERT_TRUE(response2 != NULL);
2448 ASSERT_TRUE(response2->headers.get() != NULL);
2449 EXPECT_EQ(2, response2->headers->GetContentLength());
2451 LoadTimingInfo load_timing_info2;
2452 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2453 TestLoadTimingReused(load_timing_info2);
2455 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2458 session->CloseAllConnections();
2461 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2462 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
2463 HttpRequestInfo request1;
2464 request1.method = "GET";
2465 request1.url = GURL("https://www.google.com/1");
2467 HttpRequestInfo request2;
2468 request2.method = "GET";
2469 request2.url = GURL("https://www.google.com/2");
2471 // Configure against proxy server "myproxy:70".
2472 session_deps_.proxy_service.reset(
2473 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2474 CapturingBoundNetLog log;
2475 session_deps_.net_log = log.bound().net_log();
2476 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2478 // Since we have proxy, should try to establish tunnel.
2479 MockWrite data_writes1[] = {
2480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2481 "Host: www.google.com\r\n"
2482 "Proxy-Connection: keep-alive\r\n\r\n"),
2484 MockWrite("GET /1 HTTP/1.1\r\n"
2485 "Host: www.google.com\r\n"
2486 "Connection: keep-alive\r\n\r\n"),
2488 MockWrite("GET /2 HTTP/1.1\r\n"
2489 "Host: www.google.com\r\n"
2490 "Connection: keep-alive\r\n\r\n"),
2493 // The proxy responds to the connect with a 407, using a persistent
2495 MockRead data_reads1[] = {
2496 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2498 MockRead("HTTP/1.1 200 OK\r\n"),
2499 MockRead("Content-Length: 1\r\n\r\n"),
2500 MockRead(SYNCHRONOUS, "1"),
2502 MockRead("HTTP/1.1 200 OK\r\n"),
2503 MockRead("Content-Length: 2\r\n\r\n"),
2504 MockRead(SYNCHRONOUS, "22"),
2507 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2508 data_writes1, arraysize(data_writes1));
2509 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2510 SSLSocketDataProvider ssl(ASYNC, OK);
2511 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2513 TestCompletionCallback callback1;
2514 scoped_ptr<HttpTransaction> trans1(
2515 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2517 int rv = trans1->Start(&request1, callback1.callback(), log.bound());
2518 EXPECT_EQ(ERR_IO_PENDING, rv);
2520 rv = callback1.WaitForResult();
2523 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2524 ASSERT_TRUE(response1 != NULL);
2525 ASSERT_TRUE(response1->headers.get() != NULL);
2526 EXPECT_EQ(1, response1->headers->GetContentLength());
2528 LoadTimingInfo load_timing_info1;
2529 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
2530 TestLoadTimingNotReusedWithPac(load_timing_info1,
2531 CONNECT_TIMING_HAS_SSL_TIMES);
2535 TestCompletionCallback callback2;
2536 scoped_ptr<HttpTransaction> trans2(
2537 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2539 rv = trans2->Start(&request2, callback2.callback(), log.bound());
2540 EXPECT_EQ(ERR_IO_PENDING, rv);
2542 rv = callback2.WaitForResult();
2545 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2546 ASSERT_TRUE(response2 != NULL);
2547 ASSERT_TRUE(response2->headers.get() != NULL);
2548 EXPECT_EQ(2, response2->headers->GetContentLength());
2550 LoadTimingInfo load_timing_info2;
2551 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
2552 TestLoadTimingReusedWithPac(load_timing_info2);
2554 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
2557 session->CloseAllConnections();
2560 // Test a simple get through an HTTPS Proxy.
2561 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
2562 HttpRequestInfo request;
2563 request.method = "GET";
2564 request.url = GURL("http://www.google.com/");
2566 // Configure against https proxy server "proxy:70".
2567 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2568 "https://proxy:70"));
2569 CapturingBoundNetLog log;
2570 session_deps_.net_log = log.bound().net_log();
2571 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2573 // Since we have proxy, should use full url
2574 MockWrite data_writes1[] = {
2575 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2576 "Host: www.google.com\r\n"
2577 "Proxy-Connection: keep-alive\r\n\r\n"),
2580 MockRead data_reads1[] = {
2581 MockRead("HTTP/1.1 200 OK\r\n"),
2582 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2583 MockRead("Content-Length: 100\r\n\r\n"),
2584 MockRead(SYNCHRONOUS, OK),
2587 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2588 data_writes1, arraysize(data_writes1));
2589 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2590 SSLSocketDataProvider ssl(ASYNC, OK);
2591 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2593 TestCompletionCallback callback1;
2595 scoped_ptr<HttpTransaction> trans(
2596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2598 int rv = trans->Start(&request, callback1.callback(), log.bound());
2599 EXPECT_EQ(ERR_IO_PENDING, rv);
2601 rv = callback1.WaitForResult();
2604 LoadTimingInfo load_timing_info;
2605 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2606 TestLoadTimingNotReused(load_timing_info,
2607 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2609 const HttpResponseInfo* response = trans->GetResponseInfo();
2610 ASSERT_TRUE(response != NULL);
2612 EXPECT_TRUE(response->headers->IsKeepAlive());
2613 EXPECT_EQ(200, response->headers->response_code());
2614 EXPECT_EQ(100, response->headers->GetContentLength());
2615 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2617 // The password prompt info should not be set.
2618 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2621 // Test a SPDY get through an HTTPS Proxy.
2622 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
2623 HttpRequestInfo request;
2624 request.method = "GET";
2625 request.url = GURL("http://www.google.com/");
2626 request.load_flags = 0;
2628 // Configure against https proxy server "proxy:70".
2629 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2630 "https://proxy:70"));
2631 CapturingBoundNetLog log;
2632 session_deps_.net_log = log.bound().net_log();
2633 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2635 // fetch http://www.google.com/ via SPDY
2636 scoped_ptr<SpdyFrame> req(
2637 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2638 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2640 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2641 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2642 MockRead spdy_reads[] = {
2643 CreateMockRead(*resp),
2644 CreateMockRead(*data),
2645 MockRead(ASYNC, 0, 0),
2648 DelayedSocketData spdy_data(
2649 1, // wait for one write to finish before reading.
2650 spdy_reads, arraysize(spdy_reads),
2651 spdy_writes, arraysize(spdy_writes));
2652 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2654 SSLSocketDataProvider ssl(ASYNC, OK);
2655 ssl.SetNextProto(GetParam());
2656 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2658 TestCompletionCallback callback1;
2660 scoped_ptr<HttpTransaction> trans(
2661 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2663 int rv = trans->Start(&request, callback1.callback(), log.bound());
2664 EXPECT_EQ(ERR_IO_PENDING, rv);
2666 rv = callback1.WaitForResult();
2669 LoadTimingInfo load_timing_info;
2670 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2671 TestLoadTimingNotReused(load_timing_info,
2672 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
2674 const HttpResponseInfo* response = trans->GetResponseInfo();
2675 ASSERT_TRUE(response != NULL);
2676 ASSERT_TRUE(response->headers.get() != NULL);
2677 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2679 std::string response_data;
2680 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2681 EXPECT_EQ(kUploadData, response_data);
2684 // Test a SPDY get through an HTTPS Proxy.
2685 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
2686 HttpRequestInfo request;
2687 request.method = "GET";
2688 request.url = GURL("http://www.google.com/");
2689 request.load_flags = 0;
2691 // Configure against https proxy server "myproxy:70".
2692 session_deps_.proxy_service.reset(
2693 ProxyService::CreateFixed("https://myproxy:70"));
2694 CapturingBoundNetLog log;
2695 session_deps_.net_log = log.bound().net_log();
2696 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2698 // The first request will be a bare GET, the second request will be a
2699 // GET with a Proxy-Authorization header.
2700 scoped_ptr<SpdyFrame> req_get(
2701 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2702 const char* const kExtraAuthorizationHeaders[] = {
2703 "proxy-authorization", "Basic Zm9vOmJhcg=="
2705 scoped_ptr<SpdyFrame> req_get_authorization(
2706 spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders,
2707 arraysize(kExtraAuthorizationHeaders) / 2,
2712 MockWrite spdy_writes[] = {
2713 CreateMockWrite(*req_get, 1),
2714 CreateMockWrite(*req_get_authorization, 4),
2717 // The first response is a 407 proxy authentication challenge, and the second
2718 // response will be a 200 response since the second request includes a valid
2719 // Authorization header.
2720 const char* const kExtraAuthenticationHeaders[] = {
2721 "proxy-authenticate", "Basic realm=\"MyRealm1\""
2723 scoped_ptr<SpdyFrame> resp_authentication(
2724 spdy_util_.ConstructSpdySynReplyError(
2725 "407 Proxy Authentication Required",
2726 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2728 scoped_ptr<SpdyFrame> body_authentication(
2729 spdy_util_.ConstructSpdyBodyFrame(1, true));
2730 scoped_ptr<SpdyFrame> resp_data(
2731 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
2732 scoped_ptr<SpdyFrame> body_data(spdy_util_.ConstructSpdyBodyFrame(3, true));
2733 MockRead spdy_reads[] = {
2734 CreateMockRead(*resp_authentication, 2),
2735 CreateMockRead(*body_authentication, 3),
2736 CreateMockRead(*resp_data, 5),
2737 CreateMockRead(*body_data, 6),
2738 MockRead(ASYNC, 0, 7),
2741 OrderedSocketData data(
2742 spdy_reads, arraysize(spdy_reads),
2743 spdy_writes, arraysize(spdy_writes));
2744 session_deps_.socket_factory->AddSocketDataProvider(&data);
2746 SSLSocketDataProvider ssl(ASYNC, OK);
2747 ssl.SetNextProto(GetParam());
2748 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2750 TestCompletionCallback callback1;
2752 scoped_ptr<HttpTransaction> trans(
2753 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2755 int rv = trans->Start(&request, callback1.callback(), log.bound());
2756 EXPECT_EQ(ERR_IO_PENDING, rv);
2758 rv = callback1.WaitForResult();
2761 const HttpResponseInfo* const response = trans->GetResponseInfo();
2763 ASSERT_TRUE(response != NULL);
2764 ASSERT_TRUE(response->headers.get() != NULL);
2765 EXPECT_EQ(407, response->headers->response_code());
2766 EXPECT_TRUE(response->was_fetched_via_spdy);
2767 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
2769 TestCompletionCallback callback2;
2771 rv = trans->RestartWithAuth(
2772 AuthCredentials(kFoo, kBar), callback2.callback());
2773 EXPECT_EQ(ERR_IO_PENDING, rv);
2775 rv = callback2.WaitForResult();
2778 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2780 ASSERT_TRUE(response_restart != NULL);
2781 ASSERT_TRUE(response_restart->headers.get() != NULL);
2782 EXPECT_EQ(200, response_restart->headers->response_code());
2783 // The password prompt info should not be set.
2784 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2787 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2788 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2789 HttpRequestInfo request;
2790 request.method = "GET";
2791 request.url = GURL("https://www.google.com/");
2792 request.load_flags = 0;
2794 // Configure against https proxy server "proxy:70".
2795 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2796 "https://proxy:70"));
2797 CapturingBoundNetLog log;
2798 session_deps_.net_log = log.bound().net_log();
2799 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2801 scoped_ptr<HttpTransaction> trans(
2802 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2804 // CONNECT to www.google.com:443 via SPDY
2805 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
2807 // fetch https://www.google.com/ via HTTP
2809 const char get[] = "GET / HTTP/1.1\r\n"
2810 "Host: www.google.com\r\n"
2811 "Connection: keep-alive\r\n\r\n";
2812 scoped_ptr<SpdyFrame> wrapped_get(
2813 spdy_util_.ConstructSpdyBodyFrame(1, get, strlen(get), false));
2814 scoped_ptr<SpdyFrame> conn_resp(
2815 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2816 const char resp[] = "HTTP/1.1 200 OK\r\n"
2817 "Content-Length: 10\r\n\r\n";
2818 scoped_ptr<SpdyFrame> wrapped_get_resp(
2819 spdy_util_.ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2820 scoped_ptr<SpdyFrame> wrapped_body(
2821 spdy_util_.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2822 scoped_ptr<SpdyFrame> window_update(
2823 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2825 MockWrite spdy_writes[] = {
2826 CreateMockWrite(*connect, 1),
2827 CreateMockWrite(*wrapped_get, 3),
2828 CreateMockWrite(*window_update, 5),
2831 MockRead spdy_reads[] = {
2832 CreateMockRead(*conn_resp, 2, ASYNC),
2833 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2834 CreateMockRead(*wrapped_body, 6, ASYNC),
2835 CreateMockRead(*wrapped_body, 7, ASYNC),
2836 MockRead(ASYNC, 0, 8),
2839 OrderedSocketData spdy_data(
2840 spdy_reads, arraysize(spdy_reads),
2841 spdy_writes, arraysize(spdy_writes));
2842 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2844 SSLSocketDataProvider ssl(ASYNC, OK);
2845 ssl.SetNextProto(GetParam());
2846 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2847 SSLSocketDataProvider ssl2(ASYNC, OK);
2848 ssl2.was_npn_negotiated = false;
2849 ssl2.protocol_negotiated = kProtoUnknown;
2850 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2852 TestCompletionCallback callback1;
2854 int rv = trans->Start(&request, callback1.callback(), log.bound());
2855 EXPECT_EQ(ERR_IO_PENDING, rv);
2857 rv = callback1.WaitForResult();
2860 LoadTimingInfo load_timing_info;
2861 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2862 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
2864 const HttpResponseInfo* response = trans->GetResponseInfo();
2865 ASSERT_TRUE(response != NULL);
2866 ASSERT_TRUE(response->headers.get() != NULL);
2867 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2869 std::string response_data;
2870 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2871 EXPECT_EQ("1234567890", response_data);
2874 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2875 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2876 HttpRequestInfo request;
2877 request.method = "GET";
2878 request.url = GURL("https://www.google.com/");
2879 request.load_flags = 0;
2881 // Configure against https proxy server "proxy:70".
2882 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2883 "https://proxy:70"));
2884 CapturingBoundNetLog log;
2885 session_deps_.net_log = log.bound().net_log();
2886 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2888 scoped_ptr<HttpTransaction> trans(
2889 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2891 // CONNECT to www.google.com:443 via SPDY
2892 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
2894 // fetch https://www.google.com/ via SPDY
2895 const char* const kMyUrl = "https://www.google.com/";
2896 scoped_ptr<SpdyFrame> get(
2897 spdy_util_.ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2898 scoped_ptr<SpdyFrame> wrapped_get(
2899 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
2900 scoped_ptr<SpdyFrame> conn_resp(
2901 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2902 scoped_ptr<SpdyFrame> get_resp(
2903 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
2904 scoped_ptr<SpdyFrame> wrapped_get_resp(
2905 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
2906 scoped_ptr<SpdyFrame> body(spdy_util_.ConstructSpdyBodyFrame(1, true));
2907 scoped_ptr<SpdyFrame> wrapped_body(
2908 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
2909 scoped_ptr<SpdyFrame> window_update_get_resp(
2910 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp->size()));
2911 scoped_ptr<SpdyFrame> window_update_body(
2912 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body->size()));
2914 MockWrite spdy_writes[] = {
2915 CreateMockWrite(*connect, 1),
2916 CreateMockWrite(*wrapped_get, 3),
2917 CreateMockWrite(*window_update_get_resp, 5),
2918 CreateMockWrite(*window_update_body, 7),
2921 MockRead spdy_reads[] = {
2922 CreateMockRead(*conn_resp, 2, ASYNC),
2923 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2924 CreateMockRead(*wrapped_body, 6, ASYNC),
2925 MockRead(ASYNC, 0, 8),
2928 OrderedSocketData spdy_data(
2929 spdy_reads, arraysize(spdy_reads),
2930 spdy_writes, arraysize(spdy_writes));
2931 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
2933 SSLSocketDataProvider ssl(ASYNC, OK);
2934 ssl.SetNextProto(GetParam());
2935 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
2936 SSLSocketDataProvider ssl2(ASYNC, OK);
2937 ssl2.SetNextProto(GetParam());
2938 ssl2.protocol_negotiated = GetParam();
2939 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2941 TestCompletionCallback callback1;
2943 int rv = trans->Start(&request, callback1.callback(), log.bound());
2944 EXPECT_EQ(ERR_IO_PENDING, rv);
2946 rv = callback1.WaitForResult();
2949 LoadTimingInfo load_timing_info;
2950 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2951 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
2953 const HttpResponseInfo* response = trans->GetResponseInfo();
2954 ASSERT_TRUE(response != NULL);
2955 ASSERT_TRUE(response->headers.get() != NULL);
2956 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2958 std::string response_data;
2959 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2960 EXPECT_EQ(kUploadData, response_data);
2963 // Test a SPDY CONNECT failure through an HTTPS Proxy.
2964 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2965 HttpRequestInfo request;
2966 request.method = "GET";
2967 request.url = GURL("https://www.google.com/");
2968 request.load_flags = 0;
2970 // Configure against https proxy server "proxy:70".
2971 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
2972 "https://proxy:70"));
2973 CapturingBoundNetLog log;
2974 session_deps_.net_log = log.bound().net_log();
2975 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2977 scoped_ptr<HttpTransaction> trans(
2978 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
2980 // CONNECT to www.google.com:443 via SPDY
2981 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
2983 scoped_ptr<SpdyFrame> get(
2984 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
2986 MockWrite spdy_writes[] = {
2987 CreateMockWrite(*connect, 1),
2988 CreateMockWrite(*get, 3),
2991 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
2992 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
2993 MockRead spdy_reads[] = {
2994 CreateMockRead(*resp, 2, ASYNC),
2995 MockRead(ASYNC, 0, 4),
2998 OrderedSocketData spdy_data(
2999 spdy_reads, arraysize(spdy_reads),
3000 spdy_writes, arraysize(spdy_writes));
3001 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
3003 SSLSocketDataProvider ssl(ASYNC, OK);
3004 ssl.SetNextProto(GetParam());
3005 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3006 SSLSocketDataProvider ssl2(ASYNC, OK);
3007 ssl2.SetNextProto(GetParam());
3008 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
3010 TestCompletionCallback callback1;
3012 int rv = trans->Start(&request, callback1.callback(), log.bound());
3013 EXPECT_EQ(ERR_IO_PENDING, rv);
3015 rv = callback1.WaitForResult();
3016 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
3018 // TODO(ttuttle): Anything else to check here?
3021 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3022 // HTTPS Proxy to different servers.
3023 TEST_P(HttpNetworkTransactionTest,
3024 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
3025 // Configure against https proxy server "proxy:70".
3026 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3027 "https://proxy:70"));
3028 CapturingBoundNetLog log;
3029 session_deps_.net_log = log.bound().net_log();
3030 scoped_refptr<HttpNetworkSession> session(
3031 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3033 HttpRequestInfo request1;
3034 request1.method = "GET";
3035 request1.url = GURL("https://www.google.com/");
3036 request1.load_flags = 0;
3038 HttpRequestInfo request2;
3039 request2.method = "GET";
3040 request2.url = GURL("https://news.google.com/");
3041 request2.load_flags = 0;
3043 // CONNECT to www.google.com:443 via SPDY.
3044 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3046 scoped_ptr<SpdyFrame> conn_resp1(
3047 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3049 // Fetch https://www.google.com/ via HTTP.
3050 const char get1[] = "GET / HTTP/1.1\r\n"
3051 "Host: www.google.com\r\n"
3052 "Connection: keep-alive\r\n\r\n";
3053 scoped_ptr<SpdyFrame> wrapped_get1(
3054 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3055 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3056 "Content-Length: 1\r\n\r\n";
3057 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3058 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3059 scoped_ptr<SpdyFrame> wrapped_body1(
3060 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3061 scoped_ptr<SpdyFrame> window_update(
3062 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3064 // CONNECT to news.google.com:443 via SPDY.
3065 const char* const kConnectHeaders2[] = {
3066 spdy_util_.GetMethodKey(), "CONNECT",
3067 spdy_util_.GetPathKey(), "news.google.com:443",
3068 spdy_util_.GetHostKey(), "news.google.com",
3069 spdy_util_.GetVersionKey(), "HTTP/1.1",
3071 scoped_ptr<SpdyFrame> connect2(
3072 spdy_util_.ConstructSpdyControlFrame(NULL,
3074 /*compressed*/ false,
3080 arraysize(kConnectHeaders2),
3082 scoped_ptr<SpdyFrame> conn_resp2(
3083 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3085 // Fetch https://news.google.com/ via HTTP.
3086 const char get2[] = "GET / HTTP/1.1\r\n"
3087 "Host: news.google.com\r\n"
3088 "Connection: keep-alive\r\n\r\n";
3089 scoped_ptr<SpdyFrame> wrapped_get2(
3090 spdy_util_.ConstructSpdyBodyFrame(3, get2, strlen(get2), false));
3091 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3092 "Content-Length: 2\r\n\r\n";
3093 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3094 spdy_util_.ConstructSpdyBodyFrame(3, resp2, strlen(resp2), false));
3095 scoped_ptr<SpdyFrame> wrapped_body2(
3096 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, false));
3098 MockWrite spdy_writes[] = {
3099 CreateMockWrite(*connect1, 0),
3100 CreateMockWrite(*wrapped_get1, 2),
3101 CreateMockWrite(*connect2, 5),
3102 CreateMockWrite(*wrapped_get2, 7),
3105 MockRead spdy_reads[] = {
3106 CreateMockRead(*conn_resp1, 1, ASYNC),
3107 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3108 CreateMockRead(*wrapped_body1, 4, ASYNC),
3109 CreateMockRead(*conn_resp2, 6, ASYNC),
3110 CreateMockRead(*wrapped_get_resp2, 8, ASYNC),
3111 CreateMockRead(*wrapped_body2, 9, ASYNC),
3112 MockRead(ASYNC, 0, 10),
3115 DeterministicSocketData spdy_data(
3116 spdy_reads, arraysize(spdy_reads),
3117 spdy_writes, arraysize(spdy_writes));
3118 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3120 SSLSocketDataProvider ssl(ASYNC, OK);
3121 ssl.SetNextProto(GetParam());
3122 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3123 SSLSocketDataProvider ssl2(ASYNC, OK);
3124 ssl2.was_npn_negotiated = false;
3125 ssl2.protocol_negotiated = kProtoUnknown;
3126 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3127 SSLSocketDataProvider ssl3(ASYNC, OK);
3128 ssl3.was_npn_negotiated = false;
3129 ssl3.protocol_negotiated = kProtoUnknown;
3130 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3);
3132 TestCompletionCallback callback;
3134 scoped_ptr<HttpTransaction> trans(
3135 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3136 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3137 EXPECT_EQ(ERR_IO_PENDING, rv);
3138 // The first connect and request, each of their responses, and the body.
3139 spdy_data.RunFor(5);
3141 rv = callback.WaitForResult();
3144 LoadTimingInfo load_timing_info;
3145 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3146 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3148 const HttpResponseInfo* response = trans->GetResponseInfo();
3149 ASSERT_TRUE(response != NULL);
3150 ASSERT_TRUE(response->headers.get() != NULL);
3151 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3153 std::string response_data;
3154 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3155 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3157 scoped_ptr<HttpTransaction> trans2(
3158 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3159 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3160 EXPECT_EQ(ERR_IO_PENDING, rv);
3162 // The second connect and request, each of their responses, and the body.
3163 spdy_data.RunFor(5);
3164 rv = callback.WaitForResult();
3167 LoadTimingInfo load_timing_info2;
3168 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3169 // Even though the SPDY connection is reused, a new tunnelled connection has
3170 // to be created, so the socket's load timing looks like a fresh connection.
3171 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
3173 // The requests should have different IDs, since they each are using their own
3175 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3177 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3180 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3181 // HTTPS Proxy to the same server.
3182 TEST_P(HttpNetworkTransactionTest,
3183 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
3184 // Configure against https proxy server "proxy:70".
3185 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3186 "https://proxy:70"));
3187 CapturingBoundNetLog log;
3188 session_deps_.net_log = log.bound().net_log();
3189 scoped_refptr<HttpNetworkSession> session(
3190 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3192 HttpRequestInfo request1;
3193 request1.method = "GET";
3194 request1.url = GURL("https://www.google.com/");
3195 request1.load_flags = 0;
3197 HttpRequestInfo request2;
3198 request2.method = "GET";
3199 request2.url = GURL("https://www.google.com/2");
3200 request2.load_flags = 0;
3202 // CONNECT to www.google.com:443 via SPDY.
3203 scoped_ptr<SpdyFrame> connect1(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
3205 scoped_ptr<SpdyFrame> conn_resp1(
3206 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3208 // Fetch https://www.google.com/ via HTTP.
3209 const char get1[] = "GET / HTTP/1.1\r\n"
3210 "Host: www.google.com\r\n"
3211 "Connection: keep-alive\r\n\r\n";
3212 scoped_ptr<SpdyFrame> wrapped_get1(
3213 spdy_util_.ConstructSpdyBodyFrame(1, get1, strlen(get1), false));
3214 const char resp1[] = "HTTP/1.1 200 OK\r\n"
3215 "Content-Length: 1\r\n\r\n";
3216 scoped_ptr<SpdyFrame> wrapped_get_resp1(
3217 spdy_util_.ConstructSpdyBodyFrame(1, resp1, strlen(resp1), false));
3218 scoped_ptr<SpdyFrame> wrapped_body1(
3219 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, false));
3220 scoped_ptr<SpdyFrame> window_update(
3221 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp1->size()));
3223 // Fetch https://www.google.com/2 via HTTP.
3224 const char get2[] = "GET /2 HTTP/1.1\r\n"
3225 "Host: www.google.com\r\n"
3226 "Connection: keep-alive\r\n\r\n";
3227 scoped_ptr<SpdyFrame> wrapped_get2(
3228 spdy_util_.ConstructSpdyBodyFrame(1, get2, strlen(get2), false));
3229 const char resp2[] = "HTTP/1.1 200 OK\r\n"
3230 "Content-Length: 2\r\n\r\n";
3231 scoped_ptr<SpdyFrame> wrapped_get_resp2(
3232 spdy_util_.ConstructSpdyBodyFrame(1, resp2, strlen(resp2), false));
3233 scoped_ptr<SpdyFrame> wrapped_body2(
3234 spdy_util_.ConstructSpdyBodyFrame(1, "22", 2, false));
3236 MockWrite spdy_writes[] = {
3237 CreateMockWrite(*connect1, 0),
3238 CreateMockWrite(*wrapped_get1, 2),
3239 CreateMockWrite(*wrapped_get2, 5),
3242 MockRead spdy_reads[] = {
3243 CreateMockRead(*conn_resp1, 1, ASYNC),
3244 CreateMockRead(*wrapped_get_resp1, 3, ASYNC),
3245 CreateMockRead(*wrapped_body1, 4, ASYNC),
3246 CreateMockRead(*wrapped_get_resp2, 6, ASYNC),
3247 CreateMockRead(*wrapped_body2, 7, ASYNC),
3248 MockRead(ASYNC, 0, 8),
3251 DeterministicSocketData spdy_data(
3252 spdy_reads, arraysize(spdy_reads),
3253 spdy_writes, arraysize(spdy_writes));
3254 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3256 SSLSocketDataProvider ssl(ASYNC, OK);
3257 ssl.SetNextProto(GetParam());
3258 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3259 SSLSocketDataProvider ssl2(ASYNC, OK);
3260 ssl2.was_npn_negotiated = false;
3261 ssl2.protocol_negotiated = kProtoUnknown;
3262 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
3264 TestCompletionCallback callback;
3266 scoped_ptr<HttpTransaction> trans(
3267 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3268 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3269 EXPECT_EQ(ERR_IO_PENDING, rv);
3270 // The first connect and request, each of their responses, and the body.
3271 spdy_data.RunFor(5);
3273 rv = callback.WaitForResult();
3276 LoadTimingInfo load_timing_info;
3277 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3278 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
3280 const HttpResponseInfo* response = trans->GetResponseInfo();
3281 ASSERT_TRUE(response != NULL);
3282 ASSERT_TRUE(response->headers.get() != NULL);
3283 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3285 std::string response_data;
3286 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3287 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
3290 scoped_ptr<HttpTransaction> trans2(
3291 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3292 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3293 EXPECT_EQ(ERR_IO_PENDING, rv);
3295 // The second request, response, and body. There should not be a second
3297 spdy_data.RunFor(3);
3298 rv = callback.WaitForResult();
3301 LoadTimingInfo load_timing_info2;
3302 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3303 TestLoadTimingReused(load_timing_info2);
3305 // The requests should have the same ID.
3306 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3308 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
3311 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3312 // Proxy to different servers.
3313 TEST_P(HttpNetworkTransactionTest,
3314 HttpsProxySpdyLoadTimingTwoHttpRequests) {
3315 // Configure against https proxy server "proxy:70".
3316 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
3317 "https://proxy:70"));
3318 CapturingBoundNetLog log;
3319 session_deps_.net_log = log.bound().net_log();
3320 scoped_refptr<HttpNetworkSession> session(
3321 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
3323 HttpRequestInfo request1;
3324 request1.method = "GET";
3325 request1.url = GURL("http://www.google.com/");
3326 request1.load_flags = 0;
3328 HttpRequestInfo request2;
3329 request2.method = "GET";
3330 request2.url = GURL("http://news.google.com/");
3331 request2.load_flags = 0;
3333 // http://www.google.com/
3334 scoped_ptr<SpdyHeaderBlock> headers(
3335 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3336 scoped_ptr<SpdyFrame> get1(spdy_util_.ConstructSpdyControlFrame(
3337 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3338 scoped_ptr<SpdyFrame> get_resp1(
3339 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
3340 scoped_ptr<SpdyFrame> body1(
3341 spdy_util_.ConstructSpdyBodyFrame(1, "1", 1, true));
3343 // http://news.google.com/
3344 scoped_ptr<SpdyHeaderBlock> headers2(
3345 spdy_util_.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3346 scoped_ptr<SpdyFrame> get2(spdy_util_.ConstructSpdyControlFrame(
3347 headers2.Pass(), false, 3, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
3348 scoped_ptr<SpdyFrame> get_resp2(
3349 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
3350 scoped_ptr<SpdyFrame> body2(
3351 spdy_util_.ConstructSpdyBodyFrame(3, "22", 2, true));
3353 MockWrite spdy_writes[] = {
3354 CreateMockWrite(*get1, 0),
3355 CreateMockWrite(*get2, 3),
3358 MockRead spdy_reads[] = {
3359 CreateMockRead(*get_resp1, 1, ASYNC),
3360 CreateMockRead(*body1, 2, ASYNC),
3361 CreateMockRead(*get_resp2, 4, ASYNC),
3362 CreateMockRead(*body2, 5, ASYNC),
3363 MockRead(ASYNC, 0, 6),
3366 DeterministicSocketData spdy_data(
3367 spdy_reads, arraysize(spdy_reads),
3368 spdy_writes, arraysize(spdy_writes));
3369 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&spdy_data);
3371 SSLSocketDataProvider ssl(ASYNC, OK);
3372 ssl.SetNextProto(GetParam());
3373 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
3375 TestCompletionCallback callback;
3377 scoped_ptr<HttpTransaction> trans(
3378 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3379 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
3380 EXPECT_EQ(ERR_IO_PENDING, rv);
3381 spdy_data.RunFor(2);
3383 rv = callback.WaitForResult();
3386 LoadTimingInfo load_timing_info;
3387 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3388 TestLoadTimingNotReused(load_timing_info,
3389 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3391 const HttpResponseInfo* response = trans->GetResponseInfo();
3392 ASSERT_TRUE(response != NULL);
3393 ASSERT_TRUE(response->headers.get() != NULL);
3394 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3396 std::string response_data;
3397 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256));
3398 EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback()));
3399 spdy_data.RunFor(1);
3400 EXPECT_EQ(1, callback.WaitForResult());
3401 // Delete the first request, so the second one can reuse the socket.
3404 scoped_ptr<HttpTransaction> trans2(
3405 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3406 rv = trans2->Start(&request2, callback.callback(), BoundNetLog());
3407 EXPECT_EQ(ERR_IO_PENDING, rv);
3409 spdy_data.RunFor(2);
3410 rv = callback.WaitForResult();
3413 LoadTimingInfo load_timing_info2;
3414 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
3415 TestLoadTimingReused(load_timing_info2);
3417 // The requests should have the same ID.
3418 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
3420 EXPECT_EQ(ERR_IO_PENDING, trans2->Read(buf.get(), 256, callback.callback()));
3421 spdy_data.RunFor(1);
3422 EXPECT_EQ(2, callback.WaitForResult());
3425 // Test the challenge-response-retry sequence through an HTTPS Proxy
3426 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
3427 HttpRequestInfo request;
3428 request.method = "GET";
3429 request.url = GURL("http://www.google.com/");
3430 // when the no authentication data flag is set.
3431 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
3433 // Configure against https proxy server "myproxy:70".
3434 session_deps_.proxy_service.reset(
3435 ProxyService::CreateFixed("https://myproxy:70"));
3436 CapturingBoundNetLog log;
3437 session_deps_.net_log = log.bound().net_log();
3438 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3440 // Since we have proxy, should use full url
3441 MockWrite data_writes1[] = {
3442 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3443 "Host: www.google.com\r\n"
3444 "Proxy-Connection: keep-alive\r\n\r\n"),
3446 // After calling trans->RestartWithAuth(), this is the request we should
3447 // be issuing -- the final header line contains the credentials.
3448 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3449 "Host: www.google.com\r\n"
3450 "Proxy-Connection: keep-alive\r\n"
3451 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3454 // The proxy responds to the GET with a 407, using a persistent
3456 MockRead data_reads1[] = {
3458 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3459 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3460 MockRead("Proxy-Connection: keep-alive\r\n"),
3461 MockRead("Content-Length: 0\r\n\r\n"),
3463 MockRead("HTTP/1.1 200 OK\r\n"),
3464 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3465 MockRead("Content-Length: 100\r\n\r\n"),
3466 MockRead(SYNCHRONOUS, OK),
3469 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3470 data_writes1, arraysize(data_writes1));
3471 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3472 SSLSocketDataProvider ssl(ASYNC, OK);
3473 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3475 TestCompletionCallback callback1;
3477 scoped_ptr<HttpTransaction> trans(
3478 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3480 int rv = trans->Start(&request, callback1.callback(), log.bound());
3481 EXPECT_EQ(ERR_IO_PENDING, rv);
3483 rv = callback1.WaitForResult();
3486 LoadTimingInfo load_timing_info;
3487 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3488 TestLoadTimingNotReused(load_timing_info,
3489 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
3491 const HttpResponseInfo* response = trans->GetResponseInfo();
3492 ASSERT_TRUE(response != NULL);
3493 ASSERT_FALSE(response->headers.get() == NULL);
3494 EXPECT_EQ(407, response->headers->response_code());
3495 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3496 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3498 TestCompletionCallback callback2;
3500 rv = trans->RestartWithAuth(
3501 AuthCredentials(kFoo, kBar), callback2.callback());
3502 EXPECT_EQ(ERR_IO_PENDING, rv);
3504 rv = callback2.WaitForResult();
3507 load_timing_info = LoadTimingInfo();
3508 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3509 // Retrying with HTTP AUTH is considered to be reusing a socket.
3510 TestLoadTimingReused(load_timing_info);
3512 response = trans->GetResponseInfo();
3513 ASSERT_TRUE(response != NULL);
3515 EXPECT_TRUE(response->headers->IsKeepAlive());
3516 EXPECT_EQ(200, response->headers->response_code());
3517 EXPECT_EQ(100, response->headers->GetContentLength());
3518 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3520 // The password prompt info should not be set.
3521 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3524 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3525 const MockRead& status, int expected_status) {
3526 HttpRequestInfo request;
3527 request.method = "GET";
3528 request.url = GURL("https://www.google.com/");
3529 request.load_flags = 0;
3531 // Configure against proxy server "myproxy:70".
3532 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3533 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3535 // Since we have proxy, should try to establish tunnel.
3536 MockWrite data_writes[] = {
3537 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3538 "Host: www.google.com\r\n"
3539 "Proxy-Connection: keep-alive\r\n\r\n"),
3542 MockRead data_reads[] = {
3544 MockRead("Content-Length: 10\r\n\r\n"),
3545 // No response body because the test stops reading here.
3546 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
3549 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3550 data_writes, arraysize(data_writes));
3551 session_deps_.socket_factory->AddSocketDataProvider(&data);
3553 TestCompletionCallback callback;
3555 scoped_ptr<HttpTransaction> trans(
3556 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3558 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
3559 EXPECT_EQ(ERR_IO_PENDING, rv);
3561 rv = callback.WaitForResult();
3562 EXPECT_EQ(expected_status, rv);
3565 void HttpNetworkTransactionTest::ConnectStatusHelper(
3566 const MockRead& status) {
3567 ConnectStatusHelperWithExpectedStatus(
3568 status, ERR_TUNNEL_CONNECTION_FAILED);
3571 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
3572 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3575 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
3576 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3579 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
3580 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3583 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
3584 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3587 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
3588 ConnectStatusHelper(
3589 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3592 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
3593 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3596 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
3597 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3600 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
3601 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3604 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
3605 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3608 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
3609 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3612 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
3613 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3616 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
3617 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3620 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
3621 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3624 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
3625 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3628 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
3629 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3632 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
3633 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3636 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
3637 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3640 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
3641 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3644 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
3645 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3648 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
3649 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3652 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
3653 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3656 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
3657 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3660 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
3661 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3664 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
3665 ConnectStatusHelperWithExpectedStatus(
3666 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3667 ERR_PROXY_AUTH_UNSUPPORTED);
3670 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
3671 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3674 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
3675 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3678 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
3679 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3682 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
3683 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
3686 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
3687 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
3690 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
3691 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
3694 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
3695 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
3698 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
3699 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
3702 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
3703 ConnectStatusHelper(
3704 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
3707 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
3708 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
3711 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
3712 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
3715 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
3716 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
3719 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
3720 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
3723 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
3724 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
3727 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
3728 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
3731 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
3732 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
3735 // Test the flow when both the proxy server AND origin server require
3736 // authentication. Again, this uses basic auth for both since that is
3737 // the simplest to mock.
3738 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
3739 HttpRequestInfo request;
3740 request.method = "GET";
3741 request.url = GURL("http://www.google.com/");
3742 request.load_flags = 0;
3744 // Configure against proxy server "myproxy:70".
3745 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
3746 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3748 scoped_ptr<HttpTransaction> trans(
3749 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
3751 MockWrite data_writes1[] = {
3752 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3753 "Host: www.google.com\r\n"
3754 "Proxy-Connection: keep-alive\r\n\r\n"),
3757 MockRead data_reads1[] = {
3758 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
3759 // Give a couple authenticate options (only the middle one is actually
3761 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
3762 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3763 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3764 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3765 // Large content-length -- won't matter, as connection will be reset.
3766 MockRead("Content-Length: 10000\r\n\r\n"),
3767 MockRead(SYNCHRONOUS, ERR_FAILED),
3770 // After calling trans->RestartWithAuth() the first time, this is the
3771 // request we should be issuing -- the final header line contains the
3772 // proxy's credentials.
3773 MockWrite data_writes2[] = {
3774 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3775 "Host: www.google.com\r\n"
3776 "Proxy-Connection: keep-alive\r\n"
3777 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3780 // Now the proxy server lets the request pass through to origin server.
3781 // The origin server responds with a 401.
3782 MockRead data_reads2[] = {
3783 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3784 // Note: We are using the same realm-name as the proxy server. This is
3785 // completely valid, as realms are unique across hosts.
3786 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3787 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3788 MockRead("Content-Length: 2000\r\n\r\n"),
3789 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
3792 // After calling trans->RestartWithAuth() the second time, we should send
3793 // the credentials for both the proxy and origin server.
3794 MockWrite data_writes3[] = {
3795 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3796 "Host: www.google.com\r\n"
3797 "Proxy-Connection: keep-alive\r\n"
3798 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
3799 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3802 // Lastly we get the desired content.
3803 MockRead data_reads3[] = {
3804 MockRead("HTTP/1.0 200 OK\r\n"),
3805 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3806 MockRead("Content-Length: 100\r\n\r\n"),
3807 MockRead(SYNCHRONOUS, OK),
3810 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3811 data_writes1, arraysize(data_writes1));
3812 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3813 data_writes2, arraysize(data_writes2));
3814 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3815 data_writes3, arraysize(data_writes3));
3816 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3817 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3818 session_deps_.socket_factory->AddSocketDataProvider(&data3);
3820 TestCompletionCallback callback1;
3822 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3823 EXPECT_EQ(ERR_IO_PENDING, rv);
3825 rv = callback1.WaitForResult();
3828 const HttpResponseInfo* response = trans->GetResponseInfo();
3829 ASSERT_TRUE(response != NULL);
3830 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
3832 TestCompletionCallback callback2;
3834 rv = trans->RestartWithAuth(
3835 AuthCredentials(kFoo, kBar), callback2.callback());
3836 EXPECT_EQ(ERR_IO_PENDING, rv);
3838 rv = callback2.WaitForResult();
3841 response = trans->GetResponseInfo();
3842 ASSERT_TRUE(response != NULL);
3843 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
3845 TestCompletionCallback callback3;
3847 rv = trans->RestartWithAuth(
3848 AuthCredentials(kFoo2, kBar2), callback3.callback());
3849 EXPECT_EQ(ERR_IO_PENDING, rv);
3851 rv = callback3.WaitForResult();
3854 response = trans->GetResponseInfo();
3855 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3856 EXPECT_EQ(100, response->headers->GetContentLength());
3859 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
3860 // can't hook into its internals to cause it to generate predictable NTLM
3861 // authorization headers.
3862 #if defined(NTLM_PORTABLE)
3863 // The NTLM authentication unit tests were generated by capturing the HTTP
3864 // requests and responses using Fiddler 2 and inspecting the generated random
3865 // bytes in the debugger.
3867 // Enter the correct password and authenticate successfully.
3868 TEST_P(HttpNetworkTransactionTest, NTLMAuth1) {
3869 HttpRequestInfo request;
3870 request.method = "GET";
3871 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3873 // Ensure load is not disrupted by flags which suppress behaviour specific
3874 // to other auth schemes.
3875 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
3877 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
3879 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3881 MockWrite data_writes1[] = {
3882 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3883 "Host: 172.22.68.17\r\n"
3884 "Connection: keep-alive\r\n\r\n"),
3887 MockRead data_reads1[] = {
3888 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3889 // Negotiate and NTLM are often requested together. However, we only want
3890 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3891 // the header that requests Negotiate for this test.
3892 MockRead("WWW-Authenticate: NTLM\r\n"),
3893 MockRead("Connection: close\r\n"),
3894 MockRead("Content-Length: 42\r\n"),
3895 MockRead("Content-Type: text/html\r\n\r\n"),
3896 // Missing content -- won't matter, as connection will be reset.
3897 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
3900 MockWrite data_writes2[] = {
3901 // After restarting with a null identity, this is the
3902 // request we should be issuing -- the final header line contains a Type
3904 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3905 "Host: 172.22.68.17\r\n"
3906 "Connection: keep-alive\r\n"
3907 "Authorization: NTLM "
3908 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3910 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3911 // (the credentials for the origin server). The second request continues
3912 // on the same connection.
3913 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3914 "Host: 172.22.68.17\r\n"
3915 "Connection: keep-alive\r\n"
3916 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3917 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3918 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
3919 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
3920 "ahlhx5I=\r\n\r\n"),
3923 MockRead data_reads2[] = {
3924 // The origin server responds with a Type 2 message.
3925 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3926 MockRead("WWW-Authenticate: NTLM "
3927 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
3928 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3929 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3930 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3931 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3932 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3934 MockRead("Content-Length: 42\r\n"),
3935 MockRead("Content-Type: text/html\r\n\r\n"),
3936 MockRead("You are not authorized to view this page\r\n"),
3938 // Lastly we get the desired content.
3939 MockRead("HTTP/1.1 200 OK\r\n"),
3940 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3941 MockRead("Content-Length: 13\r\n\r\n"),
3942 MockRead("Please Login\r\n"),
3943 MockRead(SYNCHRONOUS, OK),
3946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3947 data_writes1, arraysize(data_writes1));
3948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3949 data_writes2, arraysize(data_writes2));
3950 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3951 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3953 TestCompletionCallback callback1;
3955 scoped_ptr<HttpTransaction> trans(
3956 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
3958 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
3959 EXPECT_EQ(ERR_IO_PENDING, rv);
3961 rv = callback1.WaitForResult();
3964 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3966 const HttpResponseInfo* response = trans->GetResponseInfo();
3967 ASSERT_FALSE(response == NULL);
3968 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
3970 TestCompletionCallback callback2;
3972 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
3973 callback2.callback());
3974 EXPECT_EQ(ERR_IO_PENDING, rv);
3976 rv = callback2.WaitForResult();
3979 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3981 response = trans->GetResponseInfo();
3982 ASSERT_TRUE(response != NULL);
3983 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3985 TestCompletionCallback callback3;
3987 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
3988 EXPECT_EQ(ERR_IO_PENDING, rv);
3990 rv = callback3.WaitForResult();
3993 response = trans->GetResponseInfo();
3994 ASSERT_TRUE(response != NULL);
3995 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3996 EXPECT_EQ(13, response->headers->GetContentLength());
3999 // Enter a wrong password, and then the correct one.
4000 TEST_P(HttpNetworkTransactionTest, NTLMAuth2) {
4001 HttpRequestInfo request;
4002 request.method = "GET";
4003 request.url = GURL("http://172.22.68.17/kids/login.aspx");
4004 request.load_flags = 0;
4006 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
4008 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4010 MockWrite data_writes1[] = {
4011 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4012 "Host: 172.22.68.17\r\n"
4013 "Connection: keep-alive\r\n\r\n"),
4016 MockRead data_reads1[] = {
4017 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4018 // Negotiate and NTLM are often requested together. However, we only want
4019 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4020 // the header that requests Negotiate for this test.
4021 MockRead("WWW-Authenticate: NTLM\r\n"),
4022 MockRead("Connection: close\r\n"),
4023 MockRead("Content-Length: 42\r\n"),
4024 MockRead("Content-Type: text/html\r\n\r\n"),
4025 // Missing content -- won't matter, as connection will be reset.
4026 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4029 MockWrite data_writes2[] = {
4030 // After restarting with a null identity, this is the
4031 // request we should be issuing -- the final header line contains a Type
4033 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4034 "Host: 172.22.68.17\r\n"
4035 "Connection: keep-alive\r\n"
4036 "Authorization: NTLM "
4037 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4039 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4040 // (the credentials for the origin server). The second request continues
4041 // on the same connection.
4042 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4043 "Host: 172.22.68.17\r\n"
4044 "Connection: keep-alive\r\n"
4045 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4046 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4047 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4048 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4049 "4Ww7b7E=\r\n\r\n"),
4052 MockRead data_reads2[] = {
4053 // The origin server responds with a Type 2 message.
4054 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4055 MockRead("WWW-Authenticate: NTLM "
4056 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4057 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4058 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4059 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4060 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4061 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4063 MockRead("Content-Length: 42\r\n"),
4064 MockRead("Content-Type: text/html\r\n\r\n"),
4065 MockRead("You are not authorized to view this page\r\n"),
4068 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4069 MockRead("WWW-Authenticate: NTLM\r\n"),
4070 MockRead("Connection: close\r\n"),
4071 MockRead("Content-Length: 42\r\n"),
4072 MockRead("Content-Type: text/html\r\n\r\n"),
4073 // Missing content -- won't matter, as connection will be reset.
4074 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4077 MockWrite data_writes3[] = {
4078 // After restarting with a null identity, this is the
4079 // request we should be issuing -- the final header line contains a Type
4081 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4082 "Host: 172.22.68.17\r\n"
4083 "Connection: keep-alive\r\n"
4084 "Authorization: NTLM "
4085 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4087 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4088 // (the credentials for the origin server). The second request continues
4089 // on the same connection.
4090 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4091 "Host: 172.22.68.17\r\n"
4092 "Connection: keep-alive\r\n"
4093 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4094 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4095 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4096 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4097 "+4MUm7c=\r\n\r\n"),
4100 MockRead data_reads3[] = {
4101 // The origin server responds with a Type 2 message.
4102 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4103 MockRead("WWW-Authenticate: NTLM "
4104 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4105 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4106 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4107 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4108 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4109 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4111 MockRead("Content-Length: 42\r\n"),
4112 MockRead("Content-Type: text/html\r\n\r\n"),
4113 MockRead("You are not authorized to view this page\r\n"),
4115 // Lastly we get the desired content.
4116 MockRead("HTTP/1.1 200 OK\r\n"),
4117 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4118 MockRead("Content-Length: 13\r\n\r\n"),
4119 MockRead("Please Login\r\n"),
4120 MockRead(SYNCHRONOUS, OK),
4123 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4124 data_writes1, arraysize(data_writes1));
4125 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4126 data_writes2, arraysize(data_writes2));
4127 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4128 data_writes3, arraysize(data_writes3));
4129 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4130 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4131 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4133 TestCompletionCallback callback1;
4135 scoped_ptr<HttpTransaction> trans(
4136 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4138 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4139 EXPECT_EQ(ERR_IO_PENDING, rv);
4141 rv = callback1.WaitForResult();
4144 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4146 const HttpResponseInfo* response = trans->GetResponseInfo();
4147 ASSERT_TRUE(response != NULL);
4148 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4150 TestCompletionCallback callback2;
4152 // Enter the wrong password.
4153 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
4154 callback2.callback());
4155 EXPECT_EQ(ERR_IO_PENDING, rv);
4157 rv = callback2.WaitForResult();
4160 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4161 TestCompletionCallback callback3;
4162 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
4163 EXPECT_EQ(ERR_IO_PENDING, rv);
4164 rv = callback3.WaitForResult();
4166 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4168 response = trans->GetResponseInfo();
4169 ASSERT_FALSE(response == NULL);
4170 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
4172 TestCompletionCallback callback4;
4174 // Now enter the right password.
4175 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
4176 callback4.callback());
4177 EXPECT_EQ(ERR_IO_PENDING, rv);
4179 rv = callback4.WaitForResult();
4182 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4184 TestCompletionCallback callback5;
4186 // One more roundtrip
4187 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
4188 EXPECT_EQ(ERR_IO_PENDING, rv);
4190 rv = callback5.WaitForResult();
4193 response = trans->GetResponseInfo();
4194 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4195 EXPECT_EQ(13, response->headers->GetContentLength());
4197 #endif // NTLM_PORTABLE
4199 // Test reading a server response which has only headers, and no body.
4200 // After some maximum number of bytes is consumed, the transaction should
4201 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4202 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
4203 HttpRequestInfo request;
4204 request.method = "GET";
4205 request.url = GURL("http://www.google.com/");
4206 request.load_flags = 0;
4208 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4209 scoped_ptr<HttpTransaction> trans(
4210 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4212 // Respond with 300 kb of headers (we should fail after 256 kb).
4213 std::string large_headers_string;
4214 FillLargeHeadersString(&large_headers_string, 300 * 1024);
4216 MockRead data_reads[] = {
4217 MockRead("HTTP/1.0 200 OK\r\n"),
4218 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
4219 MockRead("\r\nBODY"),
4220 MockRead(SYNCHRONOUS, OK),
4222 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4223 session_deps_.socket_factory->AddSocketDataProvider(&data);
4225 TestCompletionCallback callback;
4227 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4228 EXPECT_EQ(ERR_IO_PENDING, rv);
4230 rv = callback.WaitForResult();
4231 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
4233 const HttpResponseInfo* response = trans->GetResponseInfo();
4234 EXPECT_TRUE(response == NULL);
4237 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4238 // establish tunnel.
4239 // http://code.google.com/p/chromium/issues/detail?id=3772
4240 TEST_P(HttpNetworkTransactionTest,
4241 DontRecycleTransportSocketForSSLTunnel) {
4242 HttpRequestInfo request;
4243 request.method = "GET";
4244 request.url = GURL("https://www.google.com/");
4245 request.load_flags = 0;
4247 // Configure against proxy server "myproxy:70".
4248 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
4250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4252 scoped_ptr<HttpTransaction> trans(
4253 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4255 // Since we have proxy, should try to establish tunnel.
4256 MockWrite data_writes1[] = {
4257 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4258 "Host: www.google.com\r\n"
4259 "Proxy-Connection: keep-alive\r\n\r\n"),
4262 // The proxy responds to the connect with a 404, using a persistent
4263 // connection. Usually a proxy would return 501 (not implemented),
4264 // or 200 (tunnel established).
4265 MockRead data_reads1[] = {
4266 MockRead("HTTP/1.1 404 Not Found\r\n"),
4267 MockRead("Content-Length: 10\r\n\r\n"),
4268 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
4271 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4272 data_writes1, arraysize(data_writes1));
4273 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4275 TestCompletionCallback callback1;
4277 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4278 EXPECT_EQ(ERR_IO_PENDING, rv);
4280 rv = callback1.WaitForResult();
4281 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4283 const HttpResponseInfo* response = trans->GetResponseInfo();
4284 EXPECT_TRUE(response == NULL);
4286 // Empty the current queue. This is necessary because idle sockets are
4287 // added to the connection pool asynchronously with a PostTask.
4288 base::MessageLoop::current()->RunUntilIdle();
4290 // We now check to make sure the TCPClientSocket was not added back to
4292 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4294 base::MessageLoop::current()->RunUntilIdle();
4295 // Make sure that the socket didn't get recycled after calling the destructor.
4296 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4299 // Make sure that we recycle a socket after reading all of the response body.
4300 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
4301 HttpRequestInfo request;
4302 request.method = "GET";
4303 request.url = GURL("http://www.google.com/");
4304 request.load_flags = 0;
4306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4308 scoped_ptr<HttpTransaction> trans(
4309 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4311 MockRead data_reads[] = {
4312 // A part of the response body is received with the response headers.
4313 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4314 // The rest of the response body is received in two parts.
4317 MockRead("junk"), // Should not be read!!
4318 MockRead(SYNCHRONOUS, OK),
4321 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4322 session_deps_.socket_factory->AddSocketDataProvider(&data);
4324 TestCompletionCallback callback;
4326 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4327 EXPECT_EQ(ERR_IO_PENDING, rv);
4329 rv = callback.WaitForResult();
4332 const HttpResponseInfo* response = trans->GetResponseInfo();
4333 ASSERT_TRUE(response != NULL);
4335 EXPECT_TRUE(response->headers.get() != NULL);
4336 std::string status_line = response->headers->GetStatusLine();
4337 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
4339 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4341 std::string response_data;
4342 rv = ReadTransaction(trans.get(), &response_data);
4344 EXPECT_EQ("hello world", response_data);
4346 // Empty the current queue. This is necessary because idle sockets are
4347 // added to the connection pool asynchronously with a PostTask.
4348 base::MessageLoop::current()->RunUntilIdle();
4350 // We now check to make sure the socket was added back to the pool.
4351 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4354 // Make sure that we recycle a SSL socket after reading all of the response
4356 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
4357 HttpRequestInfo request;
4358 request.method = "GET";
4359 request.url = GURL("https://www.google.com/");
4360 request.load_flags = 0;
4362 MockWrite data_writes[] = {
4363 MockWrite("GET / HTTP/1.1\r\n"
4364 "Host: www.google.com\r\n"
4365 "Connection: keep-alive\r\n\r\n"),
4368 MockRead data_reads[] = {
4369 MockRead("HTTP/1.1 200 OK\r\n"),
4370 MockRead("Content-Length: 11\r\n\r\n"),
4371 MockRead("hello world"),
4372 MockRead(SYNCHRONOUS, OK),
4375 SSLSocketDataProvider ssl(ASYNC, OK);
4376 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4378 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4379 data_writes, arraysize(data_writes));
4380 session_deps_.socket_factory->AddSocketDataProvider(&data);
4382 TestCompletionCallback callback;
4384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4385 scoped_ptr<HttpTransaction> trans(
4386 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4388 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4390 EXPECT_EQ(ERR_IO_PENDING, rv);
4391 EXPECT_EQ(OK, callback.WaitForResult());
4393 const HttpResponseInfo* response = trans->GetResponseInfo();
4394 ASSERT_TRUE(response != NULL);
4395 ASSERT_TRUE(response->headers.get() != NULL);
4396 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4398 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4400 std::string response_data;
4401 rv = ReadTransaction(trans.get(), &response_data);
4403 EXPECT_EQ("hello world", response_data);
4405 // Empty the current queue. This is necessary because idle sockets are
4406 // added to the connection pool asynchronously with a PostTask.
4407 base::MessageLoop::current()->RunUntilIdle();
4409 // We now check to make sure the socket was added back to the pool.
4410 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4413 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4414 // from the pool and make sure that we recover okay.
4415 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
4416 HttpRequestInfo request;
4417 request.method = "GET";
4418 request.url = GURL("https://www.google.com/");
4419 request.load_flags = 0;
4421 MockWrite data_writes[] = {
4422 MockWrite("GET / HTTP/1.1\r\n"
4423 "Host: www.google.com\r\n"
4424 "Connection: keep-alive\r\n\r\n"),
4425 MockWrite("GET / HTTP/1.1\r\n"
4426 "Host: www.google.com\r\n"
4427 "Connection: keep-alive\r\n\r\n"),
4430 MockRead data_reads[] = {
4431 MockRead("HTTP/1.1 200 OK\r\n"),
4432 MockRead("Content-Length: 11\r\n\r\n"),
4433 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
4434 MockRead("hello world"),
4435 MockRead(ASYNC, 0, 0) // EOF
4438 SSLSocketDataProvider ssl(ASYNC, OK);
4439 SSLSocketDataProvider ssl2(ASYNC, OK);
4440 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4441 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4443 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4444 data_writes, arraysize(data_writes));
4445 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
4446 data_writes, arraysize(data_writes));
4447 session_deps_.socket_factory->AddSocketDataProvider(&data);
4448 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4450 TestCompletionCallback callback;
4452 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4453 scoped_ptr<HttpTransaction> trans(
4454 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4456 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4458 EXPECT_EQ(ERR_IO_PENDING, rv);
4459 EXPECT_EQ(OK, callback.WaitForResult());
4461 const HttpResponseInfo* response = trans->GetResponseInfo();
4462 ASSERT_TRUE(response != NULL);
4463 ASSERT_TRUE(response->headers.get() != NULL);
4464 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4466 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4468 std::string response_data;
4469 rv = ReadTransaction(trans.get(), &response_data);
4471 EXPECT_EQ("hello world", response_data);
4473 // Empty the current queue. This is necessary because idle sockets are
4474 // added to the connection pool asynchronously with a PostTask.
4475 base::MessageLoop::current()->RunUntilIdle();
4477 // We now check to make sure the socket was added back to the pool.
4478 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4480 // Now start the second transaction, which should reuse the previous socket.
4482 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4484 rv = trans->Start(&request, callback.callback(), BoundNetLog());
4486 EXPECT_EQ(ERR_IO_PENDING, rv);
4487 EXPECT_EQ(OK, callback.WaitForResult());
4489 response = trans->GetResponseInfo();
4490 ASSERT_TRUE(response != NULL);
4491 ASSERT_TRUE(response->headers.get() != NULL);
4492 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4494 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4496 rv = ReadTransaction(trans.get(), &response_data);
4498 EXPECT_EQ("hello world", response_data);
4500 // Empty the current queue. This is necessary because idle sockets are
4501 // added to the connection pool asynchronously with a PostTask.
4502 base::MessageLoop::current()->RunUntilIdle();
4504 // We now check to make sure the socket was added back to the pool.
4505 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
4508 // Make sure that we recycle a socket after a zero-length response.
4509 // http://crbug.com/9880
4510 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
4511 HttpRequestInfo request;
4512 request.method = "GET";
4513 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
4514 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4515 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4516 "rt=prt.2642,ol.2649,xjs.2951");
4517 request.load_flags = 0;
4519 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4521 scoped_ptr<HttpTransaction> trans(
4522 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4524 MockRead data_reads[] = {
4525 MockRead("HTTP/1.1 204 No Content\r\n"
4526 "Content-Length: 0\r\n"
4527 "Content-Type: text/html\r\n\r\n"),
4528 MockRead("junk"), // Should not be read!!
4529 MockRead(SYNCHRONOUS, OK),
4532 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4533 session_deps_.socket_factory->AddSocketDataProvider(&data);
4535 TestCompletionCallback callback;
4537 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
4538 EXPECT_EQ(ERR_IO_PENDING, rv);
4540 rv = callback.WaitForResult();
4543 const HttpResponseInfo* response = trans->GetResponseInfo();
4544 ASSERT_TRUE(response != NULL);
4546 EXPECT_TRUE(response->headers.get() != NULL);
4547 std::string status_line = response->headers->GetStatusLine();
4548 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
4550 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
4552 std::string response_data;
4553 rv = ReadTransaction(trans.get(), &response_data);
4555 EXPECT_EQ("", response_data);
4557 // Empty the current queue. This is necessary because idle sockets are
4558 // added to the connection pool asynchronously with a PostTask.
4559 base::MessageLoop::current()->RunUntilIdle();
4561 // We now check to make sure the socket was added back to the pool.
4562 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
4565 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
4566 ScopedVector<UploadElementReader> element_readers;
4567 element_readers.push_back(new UploadBytesElementReader("foo", 3));
4568 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
4570 HttpRequestInfo request[2];
4571 // Transaction 1: a GET request that succeeds. The socket is recycled
4573 request[0].method = "GET";
4574 request[0].url = GURL("http://www.google.com/");
4575 request[0].load_flags = 0;
4576 // Transaction 2: a POST request. Reuses the socket kept alive from
4577 // transaction 1. The first attempts fails when writing the POST data.
4578 // This causes the transaction to retry with a new socket. The second
4579 // attempt succeeds.
4580 request[1].method = "POST";
4581 request[1].url = GURL("http://www.google.com/login.cgi");
4582 request[1].upload_data_stream = &upload_data_stream;
4583 request[1].load_flags = 0;
4585 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4587 // The first socket is used for transaction 1 and the first attempt of
4590 // The response of transaction 1.
4591 MockRead data_reads1[] = {
4592 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4593 MockRead("hello world"),
4594 MockRead(SYNCHRONOUS, OK),
4596 // The mock write results of transaction 1 and the first attempt of
4598 MockWrite data_writes1[] = {
4599 MockWrite(SYNCHRONOUS, 64), // GET
4600 MockWrite(SYNCHRONOUS, 93), // POST
4601 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
4603 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4604 data_writes1, arraysize(data_writes1));
4606 // The second socket is used for the second attempt of transaction 2.
4608 // The response of transaction 2.
4609 MockRead data_reads2[] = {
4610 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4611 MockRead("welcome"),
4612 MockRead(SYNCHRONOUS, OK),
4614 // The mock write results of the second attempt of transaction 2.
4615 MockWrite data_writes2[] = {
4616 MockWrite(SYNCHRONOUS, 93), // POST
4617 MockWrite(SYNCHRONOUS, 3), // POST data
4619 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4620 data_writes2, arraysize(data_writes2));
4622 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4623 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4625 const char* kExpectedResponseData[] = {
4626 "hello world", "welcome"
4629 for (int i = 0; i < 2; ++i) {
4630 scoped_ptr<HttpTransaction> trans(
4631 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4633 TestCompletionCallback callback;
4635 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
4636 EXPECT_EQ(ERR_IO_PENDING, rv);
4638 rv = callback.WaitForResult();
4641 const HttpResponseInfo* response = trans->GetResponseInfo();
4642 ASSERT_TRUE(response != NULL);
4644 EXPECT_TRUE(response->headers.get() != NULL);
4645 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4647 std::string response_data;
4648 rv = ReadTransaction(trans.get(), &response_data);
4650 EXPECT_EQ(kExpectedResponseData[i], response_data);
4654 // Test the request-challenge-retry sequence for basic auth when there is
4655 // an identity in the URL. The request should be sent as normal, but when
4656 // it fails the identity from the URL is used to answer the challenge.
4657 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
4658 HttpRequestInfo request;
4659 request.method = "GET";
4660 request.url = GURL("http://foo:b@r@www.google.com/");
4661 request.load_flags = LOAD_NORMAL;
4663 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4664 scoped_ptr<HttpTransaction> trans(
4665 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4667 // The password contains an escaped character -- for this test to pass it
4668 // will need to be unescaped by HttpNetworkTransaction.
4669 EXPECT_EQ("b%40r", request.url.password());
4671 MockWrite data_writes1[] = {
4672 MockWrite("GET / HTTP/1.1\r\n"
4673 "Host: www.google.com\r\n"
4674 "Connection: keep-alive\r\n\r\n"),
4677 MockRead data_reads1[] = {
4678 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4679 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4680 MockRead("Content-Length: 10\r\n\r\n"),
4681 MockRead(SYNCHRONOUS, ERR_FAILED),
4684 // After the challenge above, the transaction will be restarted using the
4685 // identity from the url (foo, b@r) to answer the challenge.
4686 MockWrite data_writes2[] = {
4687 MockWrite("GET / HTTP/1.1\r\n"
4688 "Host: www.google.com\r\n"
4689 "Connection: keep-alive\r\n"
4690 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
4693 MockRead data_reads2[] = {
4694 MockRead("HTTP/1.0 200 OK\r\n"),
4695 MockRead("Content-Length: 100\r\n\r\n"),
4696 MockRead(SYNCHRONOUS, OK),
4699 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4700 data_writes1, arraysize(data_writes1));
4701 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4702 data_writes2, arraysize(data_writes2));
4703 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4704 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4706 TestCompletionCallback callback1;
4707 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4708 EXPECT_EQ(ERR_IO_PENDING, rv);
4709 rv = callback1.WaitForResult();
4711 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4713 TestCompletionCallback callback2;
4714 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4715 EXPECT_EQ(ERR_IO_PENDING, rv);
4716 rv = callback2.WaitForResult();
4718 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4720 const HttpResponseInfo* response = trans->GetResponseInfo();
4721 ASSERT_TRUE(response != NULL);
4723 // There is no challenge info, since the identity in URL worked.
4724 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4726 EXPECT_EQ(100, response->headers->GetContentLength());
4728 // Empty the current queue.
4729 base::MessageLoop::current()->RunUntilIdle();
4732 // Test the request-challenge-retry sequence for basic auth when there is an
4733 // incorrect identity in the URL. The identity from the URL should be used only
4735 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
4736 HttpRequestInfo request;
4737 request.method = "GET";
4738 // Note: the URL has a username:password in it. The password "baz" is
4739 // wrong (should be "bar").
4740 request.url = GURL("http://foo:baz@www.google.com/");
4742 request.load_flags = LOAD_NORMAL;
4744 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4745 scoped_ptr<HttpTransaction> trans(
4746 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4748 MockWrite data_writes1[] = {
4749 MockWrite("GET / HTTP/1.1\r\n"
4750 "Host: www.google.com\r\n"
4751 "Connection: keep-alive\r\n\r\n"),
4754 MockRead data_reads1[] = {
4755 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4756 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4757 MockRead("Content-Length: 10\r\n\r\n"),
4758 MockRead(SYNCHRONOUS, ERR_FAILED),
4761 // After the challenge above, the transaction will be restarted using the
4762 // identity from the url (foo, baz) to answer the challenge.
4763 MockWrite data_writes2[] = {
4764 MockWrite("GET / HTTP/1.1\r\n"
4765 "Host: www.google.com\r\n"
4766 "Connection: keep-alive\r\n"
4767 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
4770 MockRead data_reads2[] = {
4771 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4772 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4773 MockRead("Content-Length: 10\r\n\r\n"),
4774 MockRead(SYNCHRONOUS, ERR_FAILED),
4777 // After the challenge above, the transaction will be restarted using the
4778 // identity supplied by the user (foo, bar) to answer the challenge.
4779 MockWrite data_writes3[] = {
4780 MockWrite("GET / HTTP/1.1\r\n"
4781 "Host: www.google.com\r\n"
4782 "Connection: keep-alive\r\n"
4783 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4786 MockRead data_reads3[] = {
4787 MockRead("HTTP/1.0 200 OK\r\n"),
4788 MockRead("Content-Length: 100\r\n\r\n"),
4789 MockRead(SYNCHRONOUS, OK),
4792 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4793 data_writes1, arraysize(data_writes1));
4794 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4795 data_writes2, arraysize(data_writes2));
4796 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4797 data_writes3, arraysize(data_writes3));
4798 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4799 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4800 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4802 TestCompletionCallback callback1;
4804 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4805 EXPECT_EQ(ERR_IO_PENDING, rv);
4807 rv = callback1.WaitForResult();
4810 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4811 TestCompletionCallback callback2;
4812 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
4813 EXPECT_EQ(ERR_IO_PENDING, rv);
4814 rv = callback2.WaitForResult();
4816 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4818 const HttpResponseInfo* response = trans->GetResponseInfo();
4819 ASSERT_TRUE(response != NULL);
4820 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4822 TestCompletionCallback callback3;
4823 rv = trans->RestartWithAuth(
4824 AuthCredentials(kFoo, kBar), callback3.callback());
4825 EXPECT_EQ(ERR_IO_PENDING, rv);
4826 rv = callback3.WaitForResult();
4828 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4830 response = trans->GetResponseInfo();
4831 ASSERT_TRUE(response != NULL);
4833 // There is no challenge info, since the identity worked.
4834 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4836 EXPECT_EQ(100, response->headers->GetContentLength());
4838 // Empty the current queue.
4839 base::MessageLoop::current()->RunUntilIdle();
4843 // Test the request-challenge-retry sequence for basic auth when there is a
4844 // correct identity in the URL, but its use is being suppressed. The identity
4845 // from the URL should never be used.
4846 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
4847 HttpRequestInfo request;
4848 request.method = "GET";
4849 request.url = GURL("http://foo:bar@www.google.com/");
4850 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
4852 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4853 scoped_ptr<HttpTransaction> trans(
4854 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
4856 MockWrite data_writes1[] = {
4857 MockWrite("GET / HTTP/1.1\r\n"
4858 "Host: www.google.com\r\n"
4859 "Connection: keep-alive\r\n\r\n"),
4862 MockRead data_reads1[] = {
4863 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4864 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4865 MockRead("Content-Length: 10\r\n\r\n"),
4866 MockRead(SYNCHRONOUS, ERR_FAILED),
4869 // After the challenge above, the transaction will be restarted using the
4870 // identity supplied by the user, not the one in the URL, to answer the
4872 MockWrite data_writes3[] = {
4873 MockWrite("GET / HTTP/1.1\r\n"
4874 "Host: www.google.com\r\n"
4875 "Connection: keep-alive\r\n"
4876 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4879 MockRead data_reads3[] = {
4880 MockRead("HTTP/1.0 200 OK\r\n"),
4881 MockRead("Content-Length: 100\r\n\r\n"),
4882 MockRead(SYNCHRONOUS, OK),
4885 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4886 data_writes1, arraysize(data_writes1));
4887 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4888 data_writes3, arraysize(data_writes3));
4889 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4890 session_deps_.socket_factory->AddSocketDataProvider(&data3);
4892 TestCompletionCallback callback1;
4893 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4894 EXPECT_EQ(ERR_IO_PENDING, rv);
4895 rv = callback1.WaitForResult();
4897 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4899 const HttpResponseInfo* response = trans->GetResponseInfo();
4900 ASSERT_TRUE(response != NULL);
4901 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4903 TestCompletionCallback callback3;
4904 rv = trans->RestartWithAuth(
4905 AuthCredentials(kFoo, kBar), callback3.callback());
4906 EXPECT_EQ(ERR_IO_PENDING, rv);
4907 rv = callback3.WaitForResult();
4909 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4911 response = trans->GetResponseInfo();
4912 ASSERT_TRUE(response != NULL);
4914 // There is no challenge info, since the identity worked.
4915 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4916 EXPECT_EQ(100, response->headers->GetContentLength());
4918 // Empty the current queue.
4919 base::MessageLoop::current()->RunUntilIdle();
4922 // Test that previously tried username/passwords for a realm get re-used.
4923 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
4924 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4926 // Transaction 1: authenticate (foo, bar) on MyRealm1
4928 HttpRequestInfo request;
4929 request.method = "GET";
4930 request.url = GURL("http://www.google.com/x/y/z");
4931 request.load_flags = 0;
4933 scoped_ptr<HttpTransaction> trans(
4934 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
4936 MockWrite data_writes1[] = {
4937 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4938 "Host: www.google.com\r\n"
4939 "Connection: keep-alive\r\n\r\n"),
4942 MockRead data_reads1[] = {
4943 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4944 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4945 MockRead("Content-Length: 10000\r\n\r\n"),
4946 MockRead(SYNCHRONOUS, ERR_FAILED),
4949 // Resend with authorization (username=foo, password=bar)
4950 MockWrite data_writes2[] = {
4951 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4952 "Host: www.google.com\r\n"
4953 "Connection: keep-alive\r\n"
4954 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4957 // Sever accepts the authorization.
4958 MockRead data_reads2[] = {
4959 MockRead("HTTP/1.0 200 OK\r\n"),
4960 MockRead("Content-Length: 100\r\n\r\n"),
4961 MockRead(SYNCHRONOUS, OK),
4964 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4965 data_writes1, arraysize(data_writes1));
4966 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4967 data_writes2, arraysize(data_writes2));
4968 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4969 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4971 TestCompletionCallback callback1;
4973 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
4974 EXPECT_EQ(ERR_IO_PENDING, rv);
4976 rv = callback1.WaitForResult();
4979 const HttpResponseInfo* response = trans->GetResponseInfo();
4980 ASSERT_TRUE(response != NULL);
4981 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
4983 TestCompletionCallback callback2;
4985 rv = trans->RestartWithAuth(
4986 AuthCredentials(kFoo, kBar), callback2.callback());
4987 EXPECT_EQ(ERR_IO_PENDING, rv);
4989 rv = callback2.WaitForResult();
4992 response = trans->GetResponseInfo();
4993 ASSERT_TRUE(response != NULL);
4994 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4995 EXPECT_EQ(100, response->headers->GetContentLength());
4998 // ------------------------------------------------------------------------
5000 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5002 HttpRequestInfo request;
5003 request.method = "GET";
5004 // Note that Transaction 1 was at /x/y/z, so this is in the same
5005 // protection space as MyRealm1.
5006 request.url = GURL("http://www.google.com/x/y/a/b");
5007 request.load_flags = 0;
5009 scoped_ptr<HttpTransaction> trans(
5010 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5012 MockWrite data_writes1[] = {
5013 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5014 "Host: www.google.com\r\n"
5015 "Connection: keep-alive\r\n"
5016 // Send preemptive authorization for MyRealm1
5017 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5020 // The server didn't like the preemptive authorization, and
5021 // challenges us for a different realm (MyRealm2).
5022 MockRead data_reads1[] = {
5023 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5024 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5025 MockRead("Content-Length: 10000\r\n\r\n"),
5026 MockRead(SYNCHRONOUS, ERR_FAILED),
5029 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5030 MockWrite data_writes2[] = {
5031 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5032 "Host: www.google.com\r\n"
5033 "Connection: keep-alive\r\n"
5034 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5037 // Sever accepts the authorization.
5038 MockRead data_reads2[] = {
5039 MockRead("HTTP/1.0 200 OK\r\n"),
5040 MockRead("Content-Length: 100\r\n\r\n"),
5041 MockRead(SYNCHRONOUS, OK),
5044 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5045 data_writes1, arraysize(data_writes1));
5046 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5047 data_writes2, arraysize(data_writes2));
5048 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5049 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5051 TestCompletionCallback callback1;
5053 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5054 EXPECT_EQ(ERR_IO_PENDING, rv);
5056 rv = callback1.WaitForResult();
5059 const HttpResponseInfo* response = trans->GetResponseInfo();
5060 ASSERT_TRUE(response != NULL);
5061 ASSERT_TRUE(response->auth_challenge.get());
5062 EXPECT_FALSE(response->auth_challenge->is_proxy);
5063 EXPECT_EQ("www.google.com:80",
5064 response->auth_challenge->challenger.ToString());
5065 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
5066 EXPECT_EQ("basic", response->auth_challenge->scheme);
5068 TestCompletionCallback callback2;
5070 rv = trans->RestartWithAuth(
5071 AuthCredentials(kFoo2, kBar2), callback2.callback());
5072 EXPECT_EQ(ERR_IO_PENDING, rv);
5074 rv = callback2.WaitForResult();
5077 response = trans->GetResponseInfo();
5078 ASSERT_TRUE(response != NULL);
5079 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5080 EXPECT_EQ(100, response->headers->GetContentLength());
5083 // ------------------------------------------------------------------------
5085 // Transaction 3: Resend a request in MyRealm's protection space --
5086 // succeed with preemptive authorization.
5088 HttpRequestInfo request;
5089 request.method = "GET";
5090 request.url = GURL("http://www.google.com/x/y/z2");
5091 request.load_flags = 0;
5093 scoped_ptr<HttpTransaction> trans(
5094 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5096 MockWrite data_writes1[] = {
5097 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5098 "Host: www.google.com\r\n"
5099 "Connection: keep-alive\r\n"
5100 // The authorization for MyRealm1 gets sent preemptively
5101 // (since the url is in the same protection space)
5102 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5105 // Sever accepts the preemptive authorization
5106 MockRead data_reads1[] = {
5107 MockRead("HTTP/1.0 200 OK\r\n"),
5108 MockRead("Content-Length: 100\r\n\r\n"),
5109 MockRead(SYNCHRONOUS, OK),
5112 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5113 data_writes1, arraysize(data_writes1));
5114 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5116 TestCompletionCallback callback1;
5118 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5119 EXPECT_EQ(ERR_IO_PENDING, rv);
5121 rv = callback1.WaitForResult();
5124 const HttpResponseInfo* response = trans->GetResponseInfo();
5125 ASSERT_TRUE(response != NULL);
5127 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5128 EXPECT_EQ(100, response->headers->GetContentLength());
5131 // ------------------------------------------------------------------------
5133 // Transaction 4: request another URL in MyRealm (however the
5134 // url is not known to belong to the protection space, so no pre-auth).
5136 HttpRequestInfo request;
5137 request.method = "GET";
5138 request.url = GURL("http://www.google.com/x/1");
5139 request.load_flags = 0;
5141 scoped_ptr<HttpTransaction> trans(
5142 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5144 MockWrite data_writes1[] = {
5145 MockWrite("GET /x/1 HTTP/1.1\r\n"
5146 "Host: www.google.com\r\n"
5147 "Connection: keep-alive\r\n\r\n"),
5150 MockRead data_reads1[] = {
5151 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5152 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5153 MockRead("Content-Length: 10000\r\n\r\n"),
5154 MockRead(SYNCHRONOUS, ERR_FAILED),
5157 // Resend with authorization from MyRealm's cache.
5158 MockWrite data_writes2[] = {
5159 MockWrite("GET /x/1 HTTP/1.1\r\n"
5160 "Host: www.google.com\r\n"
5161 "Connection: keep-alive\r\n"
5162 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5165 // Sever accepts the authorization.
5166 MockRead data_reads2[] = {
5167 MockRead("HTTP/1.0 200 OK\r\n"),
5168 MockRead("Content-Length: 100\r\n\r\n"),
5169 MockRead(SYNCHRONOUS, OK),
5172 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5173 data_writes1, arraysize(data_writes1));
5174 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5175 data_writes2, arraysize(data_writes2));
5176 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5177 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5179 TestCompletionCallback callback1;
5181 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5182 EXPECT_EQ(ERR_IO_PENDING, rv);
5184 rv = callback1.WaitForResult();
5187 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5188 TestCompletionCallback callback2;
5189 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5190 EXPECT_EQ(ERR_IO_PENDING, rv);
5191 rv = callback2.WaitForResult();
5193 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5195 const HttpResponseInfo* response = trans->GetResponseInfo();
5196 ASSERT_TRUE(response != NULL);
5197 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5198 EXPECT_EQ(100, response->headers->GetContentLength());
5201 // ------------------------------------------------------------------------
5203 // Transaction 5: request a URL in MyRealm, but the server rejects the
5204 // cached identity. Should invalidate and re-prompt.
5206 HttpRequestInfo request;
5207 request.method = "GET";
5208 request.url = GURL("http://www.google.com/p/q/t");
5209 request.load_flags = 0;
5211 scoped_ptr<HttpTransaction> trans(
5212 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5214 MockWrite data_writes1[] = {
5215 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5216 "Host: www.google.com\r\n"
5217 "Connection: keep-alive\r\n\r\n"),
5220 MockRead data_reads1[] = {
5221 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5222 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5223 MockRead("Content-Length: 10000\r\n\r\n"),
5224 MockRead(SYNCHRONOUS, ERR_FAILED),
5227 // Resend with authorization from cache for MyRealm.
5228 MockWrite data_writes2[] = {
5229 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n"
5232 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5235 // Sever rejects the authorization.
5236 MockRead data_reads2[] = {
5237 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5238 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5239 MockRead("Content-Length: 10000\r\n\r\n"),
5240 MockRead(SYNCHRONOUS, ERR_FAILED),
5243 // At this point we should prompt for new credentials for MyRealm.
5244 // Restart with username=foo3, password=foo4.
5245 MockWrite data_writes3[] = {
5246 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5247 "Host: www.google.com\r\n"
5248 "Connection: keep-alive\r\n"
5249 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5252 // Sever accepts the authorization.
5253 MockRead data_reads3[] = {
5254 MockRead("HTTP/1.0 200 OK\r\n"),
5255 MockRead("Content-Length: 100\r\n\r\n"),
5256 MockRead(SYNCHRONOUS, OK),
5259 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5260 data_writes1, arraysize(data_writes1));
5261 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5262 data_writes2, arraysize(data_writes2));
5263 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5264 data_writes3, arraysize(data_writes3));
5265 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5266 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5267 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5269 TestCompletionCallback callback1;
5271 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5272 EXPECT_EQ(ERR_IO_PENDING, rv);
5274 rv = callback1.WaitForResult();
5277 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5278 TestCompletionCallback callback2;
5279 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
5280 EXPECT_EQ(ERR_IO_PENDING, rv);
5281 rv = callback2.WaitForResult();
5283 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5285 const HttpResponseInfo* response = trans->GetResponseInfo();
5286 ASSERT_TRUE(response != NULL);
5287 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
5289 TestCompletionCallback callback3;
5291 rv = trans->RestartWithAuth(
5292 AuthCredentials(kFoo3, kBar3), callback3.callback());
5293 EXPECT_EQ(ERR_IO_PENDING, rv);
5295 rv = callback3.WaitForResult();
5298 response = trans->GetResponseInfo();
5299 ASSERT_TRUE(response != NULL);
5300 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5301 EXPECT_EQ(100, response->headers->GetContentLength());
5305 // Tests that nonce count increments when multiple auth attempts
5306 // are started with the same nonce.
5307 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
5308 HttpAuthHandlerDigest::Factory* digest_factory =
5309 new HttpAuthHandlerDigest::Factory();
5310 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
5311 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5312 digest_factory->set_nonce_generator(nonce_generator);
5313 session_deps_.http_auth_handler_factory.reset(digest_factory);
5314 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5316 // Transaction 1: authenticate (foo, bar) on MyRealm1
5318 HttpRequestInfo request;
5319 request.method = "GET";
5320 request.url = GURL("http://www.google.com/x/y/z");
5321 request.load_flags = 0;
5323 scoped_ptr<HttpTransaction> trans(
5324 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5326 MockWrite data_writes1[] = {
5327 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5328 "Host: www.google.com\r\n"
5329 "Connection: keep-alive\r\n\r\n"),
5332 MockRead data_reads1[] = {
5333 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5334 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5335 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5336 MockRead(SYNCHRONOUS, OK),
5339 // Resend with authorization (username=foo, password=bar)
5340 MockWrite data_writes2[] = {
5341 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5342 "Host: www.google.com\r\n"
5343 "Connection: keep-alive\r\n"
5344 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5345 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5346 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5347 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5350 // Sever accepts the authorization.
5351 MockRead data_reads2[] = {
5352 MockRead("HTTP/1.0 200 OK\r\n"),
5353 MockRead(SYNCHRONOUS, OK),
5356 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5357 data_writes1, arraysize(data_writes1));
5358 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5359 data_writes2, arraysize(data_writes2));
5360 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5361 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5363 TestCompletionCallback callback1;
5365 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5366 EXPECT_EQ(ERR_IO_PENDING, rv);
5368 rv = callback1.WaitForResult();
5371 const HttpResponseInfo* response = trans->GetResponseInfo();
5372 ASSERT_TRUE(response != NULL);
5373 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
5375 TestCompletionCallback callback2;
5377 rv = trans->RestartWithAuth(
5378 AuthCredentials(kFoo, kBar), callback2.callback());
5379 EXPECT_EQ(ERR_IO_PENDING, rv);
5381 rv = callback2.WaitForResult();
5384 response = trans->GetResponseInfo();
5385 ASSERT_TRUE(response != NULL);
5386 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5389 // ------------------------------------------------------------------------
5391 // Transaction 2: Request another resource in digestive's protection space.
5392 // This will preemptively add an Authorization header which should have an
5393 // "nc" value of 2 (as compared to 1 in the first use.
5395 HttpRequestInfo request;
5396 request.method = "GET";
5397 // Note that Transaction 1 was at /x/y/z, so this is in the same
5398 // protection space as digest.
5399 request.url = GURL("http://www.google.com/x/y/a/b");
5400 request.load_flags = 0;
5402 scoped_ptr<HttpTransaction> trans(
5403 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
5405 MockWrite data_writes1[] = {
5406 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5407 "Host: www.google.com\r\n"
5408 "Connection: keep-alive\r\n"
5409 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5410 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5411 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5412 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5415 // Sever accepts the authorization.
5416 MockRead data_reads1[] = {
5417 MockRead("HTTP/1.0 200 OK\r\n"),
5418 MockRead("Content-Length: 100\r\n\r\n"),
5419 MockRead(SYNCHRONOUS, OK),
5422 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5423 data_writes1, arraysize(data_writes1));
5424 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5426 TestCompletionCallback callback1;
5428 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
5429 EXPECT_EQ(ERR_IO_PENDING, rv);
5431 rv = callback1.WaitForResult();
5434 const HttpResponseInfo* response = trans->GetResponseInfo();
5435 ASSERT_TRUE(response != NULL);
5436 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5440 // Test the ResetStateForRestart() private method.
5441 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
5442 // Create a transaction (the dependencies aren't important).
5443 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5444 scoped_ptr<HttpNetworkTransaction> trans(
5445 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5447 // Setup some state (which we expect ResetStateForRestart() will clear).
5448 trans->read_buf_ = new IOBuffer(15);
5449 trans->read_buf_len_ = 15;
5450 trans->request_headers_.SetHeader("Authorization", "NTLM");
5452 // Setup state in response_
5453 HttpResponseInfo* response = &trans->response_;
5454 response->auth_challenge = new AuthChallengeInfo();
5455 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
5456 response->response_time = base::Time::Now();
5457 response->was_cached = true; // (Wouldn't ever actually be true...)
5459 { // Setup state for response_.vary_data
5460 HttpRequestInfo request;
5461 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5462 std::replace(temp.begin(), temp.end(), '\n', '\0');
5463 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
5464 request.extra_headers.SetHeader("Foo", "1");
5465 request.extra_headers.SetHeader("bar", "23");
5466 EXPECT_TRUE(response->vary_data.Init(request, *headers.get()));
5469 // Cause the above state to be reset.
5470 trans->ResetStateForRestart();
5472 // Verify that the state that needed to be reset, has been reset.
5473 EXPECT_TRUE(trans->read_buf_.get() == NULL);
5474 EXPECT_EQ(0, trans->read_buf_len_);
5475 EXPECT_TRUE(trans->request_headers_.IsEmpty());
5476 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5477 EXPECT_TRUE(response->headers.get() == NULL);
5478 EXPECT_FALSE(response->was_cached);
5479 EXPECT_EQ(0U, response->ssl_info.cert_status);
5480 EXPECT_FALSE(response->vary_data.is_valid());
5483 // Test HTTPS connections to a site with a bad certificate
5484 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
5485 HttpRequestInfo request;
5486 request.method = "GET";
5487 request.url = GURL("https://www.google.com/");
5488 request.load_flags = 0;
5490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5491 scoped_ptr<HttpTransaction> trans(
5492 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5494 MockWrite data_writes[] = {
5495 MockWrite("GET / HTTP/1.1\r\n"
5496 "Host: www.google.com\r\n"
5497 "Connection: keep-alive\r\n\r\n"),
5500 MockRead data_reads[] = {
5501 MockRead("HTTP/1.0 200 OK\r\n"),
5502 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5503 MockRead("Content-Length: 100\r\n\r\n"),
5504 MockRead(SYNCHRONOUS, OK),
5507 StaticSocketDataProvider ssl_bad_certificate;
5508 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5509 data_writes, arraysize(data_writes));
5510 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5511 SSLSocketDataProvider ssl(ASYNC, OK);
5513 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5514 session_deps_.socket_factory->AddSocketDataProvider(&data);
5515 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5516 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5518 TestCompletionCallback callback;
5520 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5521 EXPECT_EQ(ERR_IO_PENDING, rv);
5523 rv = callback.WaitForResult();
5524 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5526 rv = trans->RestartIgnoringLastError(callback.callback());
5527 EXPECT_EQ(ERR_IO_PENDING, rv);
5529 rv = callback.WaitForResult();
5532 const HttpResponseInfo* response = trans->GetResponseInfo();
5534 ASSERT_TRUE(response != NULL);
5535 EXPECT_EQ(100, response->headers->GetContentLength());
5538 // Test HTTPS connections to a site with a bad certificate, going through a
5540 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
5541 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
5543 HttpRequestInfo request;
5544 request.method = "GET";
5545 request.url = GURL("https://www.google.com/");
5546 request.load_flags = 0;
5548 MockWrite proxy_writes[] = {
5549 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5550 "Host: www.google.com\r\n"
5551 "Proxy-Connection: keep-alive\r\n\r\n"),
5554 MockRead proxy_reads[] = {
5555 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5556 MockRead(SYNCHRONOUS, OK)
5559 MockWrite data_writes[] = {
5560 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5561 "Host: www.google.com\r\n"
5562 "Proxy-Connection: keep-alive\r\n\r\n"),
5563 MockWrite("GET / HTTP/1.1\r\n"
5564 "Host: www.google.com\r\n"
5565 "Connection: keep-alive\r\n\r\n"),
5568 MockRead data_reads[] = {
5569 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5570 MockRead("HTTP/1.0 200 OK\r\n"),
5571 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5572 MockRead("Content-Length: 100\r\n\r\n"),
5573 MockRead(SYNCHRONOUS, OK),
5576 StaticSocketDataProvider ssl_bad_certificate(
5577 proxy_reads, arraysize(proxy_reads),
5578 proxy_writes, arraysize(proxy_writes));
5579 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5580 data_writes, arraysize(data_writes));
5581 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
5582 SSLSocketDataProvider ssl(ASYNC, OK);
5584 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
5585 session_deps_.socket_factory->AddSocketDataProvider(&data);
5586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
5587 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5589 TestCompletionCallback callback;
5591 for (int i = 0; i < 2; i++) {
5592 session_deps_.socket_factory->ResetNextMockIndexes();
5594 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5595 scoped_ptr<HttpTransaction> trans(
5596 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5598 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5599 EXPECT_EQ(ERR_IO_PENDING, rv);
5601 rv = callback.WaitForResult();
5602 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
5604 rv = trans->RestartIgnoringLastError(callback.callback());
5605 EXPECT_EQ(ERR_IO_PENDING, rv);
5607 rv = callback.WaitForResult();
5610 const HttpResponseInfo* response = trans->GetResponseInfo();
5612 ASSERT_TRUE(response != NULL);
5613 EXPECT_EQ(100, response->headers->GetContentLength());
5618 // Test HTTPS connections to a site, going through an HTTPS proxy
5619 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
5620 session_deps_.proxy_service.reset(
5621 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5622 CapturingNetLog net_log;
5623 session_deps_.net_log = &net_log;
5625 HttpRequestInfo request;
5626 request.method = "GET";
5627 request.url = GURL("https://www.google.com/");
5628 request.load_flags = 0;
5630 MockWrite data_writes[] = {
5631 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5632 "Host: www.google.com\r\n"
5633 "Proxy-Connection: keep-alive\r\n\r\n"),
5634 MockWrite("GET / HTTP/1.1\r\n"
5635 "Host: www.google.com\r\n"
5636 "Connection: keep-alive\r\n\r\n"),
5639 MockRead data_reads[] = {
5640 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5641 MockRead("HTTP/1.1 200 OK\r\n"),
5642 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5643 MockRead("Content-Length: 100\r\n\r\n"),
5644 MockRead(SYNCHRONOUS, OK),
5647 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5648 data_writes, arraysize(data_writes));
5649 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5650 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
5652 session_deps_.socket_factory->AddSocketDataProvider(&data);
5653 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5654 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
5656 TestCompletionCallback callback;
5658 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5659 scoped_ptr<HttpTransaction> trans(
5660 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5662 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5663 EXPECT_EQ(ERR_IO_PENDING, rv);
5665 rv = callback.WaitForResult();
5667 const HttpResponseInfo* response = trans->GetResponseInfo();
5669 ASSERT_TRUE(response != NULL);
5671 EXPECT_TRUE(response->headers->IsKeepAlive());
5672 EXPECT_EQ(200, response->headers->response_code());
5673 EXPECT_EQ(100, response->headers->GetContentLength());
5674 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5676 LoadTimingInfo load_timing_info;
5677 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5678 TestLoadTimingNotReusedWithPac(load_timing_info,
5679 CONNECT_TIMING_HAS_SSL_TIMES);
5682 // Test an HTTPS Proxy's ability to redirect a CONNECT request
5683 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
5684 session_deps_.proxy_service.reset(
5685 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5686 CapturingNetLog net_log;
5687 session_deps_.net_log = &net_log;
5689 HttpRequestInfo request;
5690 request.method = "GET";
5691 request.url = GURL("https://www.google.com/");
5692 request.load_flags = 0;
5694 MockWrite data_writes[] = {
5695 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5696 "Host: www.google.com\r\n"
5697 "Proxy-Connection: keep-alive\r\n\r\n"),
5700 MockRead data_reads[] = {
5701 MockRead("HTTP/1.1 302 Redirect\r\n"),
5702 MockRead("Location: http://login.example.com/\r\n"),
5703 MockRead("Content-Length: 0\r\n\r\n"),
5704 MockRead(SYNCHRONOUS, OK),
5707 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5708 data_writes, arraysize(data_writes));
5709 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5711 session_deps_.socket_factory->AddSocketDataProvider(&data);
5712 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5714 TestCompletionCallback callback;
5716 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5717 scoped_ptr<HttpTransaction> trans(
5718 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5720 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5721 EXPECT_EQ(ERR_IO_PENDING, rv);
5723 rv = callback.WaitForResult();
5725 const HttpResponseInfo* response = trans->GetResponseInfo();
5727 ASSERT_TRUE(response != NULL);
5729 EXPECT_EQ(302, response->headers->response_code());
5731 EXPECT_TRUE(response->headers->IsRedirect(&url));
5732 EXPECT_EQ("http://login.example.com/", url);
5734 // In the case of redirects from proxies, HttpNetworkTransaction returns
5735 // timing for the proxy connection instead of the connection to the host,
5736 // and no send / receive times.
5737 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
5738 LoadTimingInfo load_timing_info;
5739 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5741 EXPECT_FALSE(load_timing_info.socket_reused);
5742 EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
5744 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
5745 EXPECT_LE(load_timing_info.proxy_resolve_start,
5746 load_timing_info.proxy_resolve_end);
5747 EXPECT_LE(load_timing_info.proxy_resolve_end,
5748 load_timing_info.connect_timing.connect_start);
5749 ExpectConnectTimingHasTimes(
5750 load_timing_info.connect_timing,
5751 CONNECT_TIMING_HAS_DNS_TIMES | CONNECT_TIMING_HAS_SSL_TIMES);
5753 EXPECT_TRUE(load_timing_info.send_start.is_null());
5754 EXPECT_TRUE(load_timing_info.send_end.is_null());
5755 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
5758 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
5759 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
5760 session_deps_.proxy_service.reset(
5761 ProxyService::CreateFixed("https://proxy:70"));
5763 HttpRequestInfo request;
5764 request.method = "GET";
5765 request.url = GURL("https://www.google.com/");
5766 request.load_flags = 0;
5768 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
5770 scoped_ptr<SpdyFrame> goaway(
5771 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5772 MockWrite data_writes[] = {
5773 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5774 CreateMockWrite(*goaway.get(), 3, SYNCHRONOUS),
5777 static const char* const kExtraHeaders[] = {
5779 "http://login.example.com/",
5781 scoped_ptr<SpdyFrame> resp(
5782 spdy_util_.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
5783 arraysize(kExtraHeaders)/2, 1));
5784 MockRead data_reads[] = {
5785 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5786 MockRead(ASYNC, 0, 2), // EOF
5789 DelayedSocketData data(
5790 1, // wait for one write to finish before reading.
5791 data_reads, arraysize(data_reads),
5792 data_writes, arraysize(data_writes));
5793 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5794 proxy_ssl.SetNextProto(GetParam());
5796 session_deps_.socket_factory->AddSocketDataProvider(&data);
5797 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5799 TestCompletionCallback callback;
5801 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5802 scoped_ptr<HttpTransaction> trans(
5803 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5805 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5806 EXPECT_EQ(ERR_IO_PENDING, rv);
5808 rv = callback.WaitForResult();
5810 const HttpResponseInfo* response = trans->GetResponseInfo();
5812 ASSERT_TRUE(response != NULL);
5814 EXPECT_EQ(302, response->headers->response_code());
5816 EXPECT_TRUE(response->headers->IsRedirect(&url));
5817 EXPECT_EQ("http://login.example.com/", url);
5820 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
5821 TEST_P(HttpNetworkTransactionTest,
5822 ErrorResponseToHttpsConnectViaHttpsProxy) {
5823 session_deps_.proxy_service.reset(
5824 ProxyService::CreateFixed("https://proxy:70"));
5826 HttpRequestInfo request;
5827 request.method = "GET";
5828 request.url = GURL("https://www.google.com/");
5829 request.load_flags = 0;
5831 MockWrite data_writes[] = {
5832 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5833 "Host: www.google.com\r\n"
5834 "Proxy-Connection: keep-alive\r\n\r\n"),
5837 MockRead data_reads[] = {
5838 MockRead("HTTP/1.1 404 Not Found\r\n"),
5839 MockRead("Content-Length: 23\r\n\r\n"),
5840 MockRead("The host does not exist"),
5841 MockRead(SYNCHRONOUS, OK),
5844 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5845 data_writes, arraysize(data_writes));
5846 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5848 session_deps_.socket_factory->AddSocketDataProvider(&data);
5849 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5851 TestCompletionCallback callback;
5853 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5854 scoped_ptr<HttpTransaction> trans(
5855 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5857 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5858 EXPECT_EQ(ERR_IO_PENDING, rv);
5860 rv = callback.WaitForResult();
5861 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5863 // TODO(ttuttle): Anything else to check here?
5866 // Test that a SPDY proxy's response to a CONNECT request is filtered.
5867 TEST_P(HttpNetworkTransactionTest,
5868 ErrorResponseToHttpsConnectViaSpdyProxy) {
5869 session_deps_.proxy_service.reset(
5870 ProxyService::CreateFixed("https://proxy:70"));
5872 HttpRequestInfo request;
5873 request.method = "GET";
5874 request.url = GURL("https://www.google.com/");
5875 request.load_flags = 0;
5877 scoped_ptr<SpdyFrame> conn(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
5879 scoped_ptr<SpdyFrame> rst(
5880 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5881 MockWrite data_writes[] = {
5882 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
5883 CreateMockWrite(*rst.get(), 3, SYNCHRONOUS),
5886 static const char* const kExtraHeaders[] = {
5888 "http://login.example.com/",
5890 scoped_ptr<SpdyFrame> resp(
5891 spdy_util_.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
5892 arraysize(kExtraHeaders)/2, 1));
5893 scoped_ptr<SpdyFrame> body(
5894 spdy_util_.ConstructSpdyBodyFrame(
5895 1, "The host does not exist", 23, true));
5896 MockRead data_reads[] = {
5897 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
5898 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
5899 MockRead(ASYNC, 0, 4), // EOF
5902 DelayedSocketData data(
5903 1, // wait for one write to finish before reading.
5904 data_reads, arraysize(data_reads),
5905 data_writes, arraysize(data_writes));
5906 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
5907 proxy_ssl.SetNextProto(GetParam());
5909 session_deps_.socket_factory->AddSocketDataProvider(&data);
5910 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
5912 TestCompletionCallback callback;
5914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5915 scoped_ptr<HttpTransaction> trans(
5916 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
5918 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
5919 EXPECT_EQ(ERR_IO_PENDING, rv);
5921 rv = callback.WaitForResult();
5922 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5924 // TODO(ttuttle): Anything else to check here?
5927 // Test the request-challenge-retry sequence for basic auth, through
5928 // a SPDY proxy over a single SPDY session.
5929 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
5930 HttpRequestInfo request;
5931 request.method = "GET";
5932 request.url = GURL("https://www.google.com/");
5933 // when the no authentication data flag is set.
5934 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
5936 // Configure against https proxy server "myproxy:70".
5937 session_deps_.proxy_service.reset(
5938 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
5939 CapturingBoundNetLog log;
5940 session_deps_.net_log = log.bound().net_log();
5941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5943 // Since we have proxy, should try to establish tunnel.
5944 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
5946 scoped_ptr<SpdyFrame> rst(
5947 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
5949 // After calling trans->RestartWithAuth(), this is the request we should
5950 // be issuing -- the final header line contains the credentials.
5951 const char* const kAuthCredentials[] = {
5952 "proxy-authorization", "Basic Zm9vOmJhcg==",
5954 scoped_ptr<SpdyFrame> connect2(spdy_util_.ConstructSpdyConnect(
5955 kAuthCredentials, arraysize(kAuthCredentials) / 2, 3, LOWEST));
5956 // fetch https://www.google.com/ via HTTP
5957 const char get[] = "GET / HTTP/1.1\r\n"
5958 "Host: www.google.com\r\n"
5959 "Connection: keep-alive\r\n\r\n";
5960 scoped_ptr<SpdyFrame> wrapped_get(
5961 spdy_util_.ConstructSpdyBodyFrame(3, get, strlen(get), false));
5963 MockWrite spdy_writes[] = {
5964 CreateMockWrite(*req, 1, ASYNC),
5965 CreateMockWrite(*rst, 4, ASYNC),
5966 CreateMockWrite(*connect2, 5),
5967 CreateMockWrite(*wrapped_get, 8),
5970 // The proxy responds to the connect with a 407, using a persistent
5972 const char* const kAuthChallenge[] = {
5973 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
5974 spdy_util_.GetVersionKey(), "HTTP/1.1",
5975 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
5978 scoped_ptr<SpdyFrame> conn_auth_resp(
5979 spdy_util_.ConstructSpdyControlFrame(NULL,
5987 arraysize(kAuthChallenge),
5990 scoped_ptr<SpdyFrame> conn_resp(
5991 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
5992 const char resp[] = "HTTP/1.1 200 OK\r\n"
5993 "Content-Length: 5\r\n\r\n";
5995 scoped_ptr<SpdyFrame> wrapped_get_resp(
5996 spdy_util_.ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
5997 scoped_ptr<SpdyFrame> wrapped_body(
5998 spdy_util_.ConstructSpdyBodyFrame(3, "hello", 5, false));
5999 MockRead spdy_reads[] = {
6000 CreateMockRead(*conn_auth_resp, 2, ASYNC),
6001 CreateMockRead(*conn_resp, 6, ASYNC),
6002 CreateMockRead(*wrapped_get_resp, 9, ASYNC),
6003 CreateMockRead(*wrapped_body, 10, ASYNC),
6004 MockRead(ASYNC, OK, 11), // EOF. May or may not be read.
6007 OrderedSocketData spdy_data(
6008 spdy_reads, arraysize(spdy_reads),
6009 spdy_writes, arraysize(spdy_writes));
6010 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6011 // Negotiate SPDY to the proxy
6012 SSLSocketDataProvider proxy(ASYNC, OK);
6013 proxy.SetNextProto(GetParam());
6014 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6015 // Vanilla SSL to the server
6016 SSLSocketDataProvider server(ASYNC, OK);
6017 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
6019 TestCompletionCallback callback1;
6021 scoped_ptr<HttpTransaction> trans(
6022 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6024 int rv = trans->Start(&request, callback1.callback(), log.bound());
6025 EXPECT_EQ(ERR_IO_PENDING, rv);
6027 rv = callback1.WaitForResult();
6029 net::CapturingNetLog::CapturedEntryList entries;
6030 log.GetEntries(&entries);
6031 size_t pos = ExpectLogContainsSomewhere(
6032 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6033 NetLog::PHASE_NONE);
6034 ExpectLogContainsSomewhere(
6036 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6037 NetLog::PHASE_NONE);
6039 const HttpResponseInfo* response = trans->GetResponseInfo();
6040 ASSERT_TRUE(response != NULL);
6041 ASSERT_FALSE(response->headers.get() == NULL);
6042 EXPECT_EQ(407, response->headers->response_code());
6043 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6044 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6045 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
6047 TestCompletionCallback callback2;
6049 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
6050 callback2.callback());
6051 EXPECT_EQ(ERR_IO_PENDING, rv);
6053 rv = callback2.WaitForResult();
6056 response = trans->GetResponseInfo();
6057 ASSERT_TRUE(response != NULL);
6059 EXPECT_TRUE(response->headers->IsKeepAlive());
6060 EXPECT_EQ(200, response->headers->response_code());
6061 EXPECT_EQ(5, response->headers->GetContentLength());
6062 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6064 // The password prompt info should not be set.
6065 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6067 LoadTimingInfo load_timing_info;
6068 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6069 TestLoadTimingNotReusedWithPac(load_timing_info,
6070 CONNECT_TIMING_HAS_SSL_TIMES);
6073 session->CloseAllConnections();
6076 // Test that an explicitly trusted SPDY proxy can push a resource from an
6077 // origin that is different from that of its associated resource.
6078 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) {
6079 HttpRequestInfo request;
6080 HttpRequestInfo push_request;
6082 request.method = "GET";
6083 request.url = GURL("http://www.google.com/");
6084 push_request.method = "GET";
6085 push_request.url = GURL("http://www.another-origin.com/foo.dat");
6087 // Configure against https proxy server "myproxy:70".
6088 session_deps_.proxy_service.reset(
6089 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6090 CapturingBoundNetLog log;
6091 session_deps_.net_log = log.bound().net_log();
6093 // Enable cross-origin push.
6094 session_deps_.trusted_spdy_proxy = "myproxy:70";
6096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6098 scoped_ptr<SpdyFrame> stream1_syn(
6099 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6101 MockWrite spdy_writes[] = {
6102 CreateMockWrite(*stream1_syn, 1, ASYNC),
6105 scoped_ptr<SpdyFrame>
6106 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6108 scoped_ptr<SpdyFrame>
6109 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6111 scoped_ptr<SpdyFrame>
6112 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6116 "http://www.another-origin.com/foo.dat"));
6117 const char kPushedData[] = "pushed";
6118 scoped_ptr<SpdyFrame> stream2_body(
6119 spdy_util_.ConstructSpdyBodyFrame(
6120 2, kPushedData, strlen(kPushedData), true));
6122 MockRead spdy_reads[] = {
6123 CreateMockRead(*stream1_reply, 2, ASYNC),
6124 CreateMockRead(*stream2_syn, 3, ASYNC),
6125 CreateMockRead(*stream1_body, 4, ASYNC),
6126 CreateMockRead(*stream2_body, 5, ASYNC),
6127 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6130 OrderedSocketData spdy_data(
6131 spdy_reads, arraysize(spdy_reads),
6132 spdy_writes, arraysize(spdy_writes));
6133 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6134 // Negotiate SPDY to the proxy
6135 SSLSocketDataProvider proxy(ASYNC, OK);
6136 proxy.SetNextProto(GetParam());
6137 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6139 scoped_ptr<HttpTransaction> trans(
6140 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6141 TestCompletionCallback callback;
6142 int rv = trans->Start(&request, callback.callback(), log.bound());
6143 EXPECT_EQ(ERR_IO_PENDING, rv);
6145 rv = callback.WaitForResult();
6147 const HttpResponseInfo* response = trans->GetResponseInfo();
6149 scoped_ptr<HttpTransaction> push_trans(
6150 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6151 rv = push_trans->Start(&push_request, callback.callback(), log.bound());
6152 EXPECT_EQ(ERR_IO_PENDING, rv);
6154 rv = callback.WaitForResult();
6156 const HttpResponseInfo* push_response = push_trans->GetResponseInfo();
6158 ASSERT_TRUE(response != NULL);
6159 EXPECT_TRUE(response->headers->IsKeepAlive());
6161 EXPECT_EQ(200, response->headers->response_code());
6162 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6164 std::string response_data;
6165 rv = ReadTransaction(trans.get(), &response_data);
6167 EXPECT_EQ("hello!", response_data);
6169 LoadTimingInfo load_timing_info;
6170 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6171 TestLoadTimingNotReusedWithPac(load_timing_info,
6172 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6174 // Verify the pushed stream.
6175 EXPECT_TRUE(push_response->headers.get() != NULL);
6176 EXPECT_EQ(200, push_response->headers->response_code());
6178 rv = ReadTransaction(push_trans.get(), &response_data);
6180 EXPECT_EQ("pushed", response_data);
6182 LoadTimingInfo push_load_timing_info;
6183 EXPECT_TRUE(push_trans->GetLoadTimingInfo(&push_load_timing_info));
6184 TestLoadTimingReusedWithPac(push_load_timing_info);
6185 // The transactions should share a socket ID, despite being for different
6187 EXPECT_EQ(load_timing_info.socket_log_id,
6188 push_load_timing_info.socket_log_id);
6192 session->CloseAllConnections();
6195 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6196 TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) {
6197 HttpRequestInfo request;
6199 request.method = "GET";
6200 request.url = GURL("http://www.google.com/");
6202 // Configure against https proxy server "myproxy:70".
6203 session_deps_.proxy_service.reset(
6204 ProxyService::CreateFixed("https://myproxy:70"));
6205 CapturingBoundNetLog log;
6206 session_deps_.net_log = log.bound().net_log();
6208 // Enable cross-origin push.
6209 session_deps_.trusted_spdy_proxy = "myproxy:70";
6211 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6213 scoped_ptr<SpdyFrame> stream1_syn(
6214 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
6216 scoped_ptr<SpdyFrame> push_rst(
6217 spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM));
6219 MockWrite spdy_writes[] = {
6220 CreateMockWrite(*stream1_syn, 1, ASYNC),
6221 CreateMockWrite(*push_rst, 4),
6224 scoped_ptr<SpdyFrame>
6225 stream1_reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
6227 scoped_ptr<SpdyFrame>
6228 stream1_body(spdy_util_.ConstructSpdyBodyFrame(1, true));
6230 scoped_ptr<SpdyFrame>
6231 stream2_syn(spdy_util_.ConstructSpdyPush(NULL,
6235 "https://www.another-origin.com/foo.dat"));
6237 MockRead spdy_reads[] = {
6238 CreateMockRead(*stream1_reply, 2, ASYNC),
6239 CreateMockRead(*stream2_syn, 3, ASYNC),
6240 CreateMockRead(*stream1_body, 5, ASYNC),
6241 MockRead(ASYNC, ERR_IO_PENDING, 6), // Force a pause
6244 OrderedSocketData spdy_data(
6245 spdy_reads, arraysize(spdy_reads),
6246 spdy_writes, arraysize(spdy_writes));
6247 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6248 // Negotiate SPDY to the proxy
6249 SSLSocketDataProvider proxy(ASYNC, OK);
6250 proxy.SetNextProto(GetParam());
6251 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
6253 scoped_ptr<HttpTransaction> trans(
6254 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
6255 TestCompletionCallback callback;
6256 int rv = trans->Start(&request, callback.callback(), log.bound());
6257 EXPECT_EQ(ERR_IO_PENDING, rv);
6259 rv = callback.WaitForResult();
6261 const HttpResponseInfo* response = trans->GetResponseInfo();
6263 ASSERT_TRUE(response != NULL);
6264 EXPECT_TRUE(response->headers->IsKeepAlive());
6266 EXPECT_EQ(200, response->headers->response_code());
6267 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6269 std::string response_data;
6270 rv = ReadTransaction(trans.get(), &response_data);
6272 EXPECT_EQ("hello!", response_data);
6275 session->CloseAllConnections();
6278 // Test HTTPS connections to a site with a bad certificate, going through an
6280 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
6281 session_deps_.proxy_service.reset(ProxyService::CreateFixed(
6282 "https://proxy:70"));
6284 HttpRequestInfo request;
6285 request.method = "GET";
6286 request.url = GURL("https://www.google.com/");
6287 request.load_flags = 0;
6289 // Attempt to fetch the URL from a server with a bad cert
6290 MockWrite bad_cert_writes[] = {
6291 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6292 "Host: www.google.com\r\n"
6293 "Proxy-Connection: keep-alive\r\n\r\n"),
6296 MockRead bad_cert_reads[] = {
6297 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6298 MockRead(SYNCHRONOUS, OK)
6301 // Attempt to fetch the URL with a good cert
6302 MockWrite good_data_writes[] = {
6303 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6304 "Host: www.google.com\r\n"
6305 "Proxy-Connection: keep-alive\r\n\r\n"),
6306 MockWrite("GET / HTTP/1.1\r\n"
6307 "Host: www.google.com\r\n"
6308 "Connection: keep-alive\r\n\r\n"),
6311 MockRead good_cert_reads[] = {
6312 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6313 MockRead("HTTP/1.0 200 OK\r\n"),
6314 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6315 MockRead("Content-Length: 100\r\n\r\n"),
6316 MockRead(SYNCHRONOUS, OK),
6319 StaticSocketDataProvider ssl_bad_certificate(
6320 bad_cert_reads, arraysize(bad_cert_reads),
6321 bad_cert_writes, arraysize(bad_cert_writes));
6322 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
6323 good_data_writes, arraysize(good_data_writes));
6324 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
6325 SSLSocketDataProvider ssl(ASYNC, OK);
6327 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6328 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6329 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
6330 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
6332 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6334 session_deps_.socket_factory->AddSocketDataProvider(&data);
6335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6337 TestCompletionCallback callback;
6339 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6340 scoped_ptr<HttpTransaction> trans(
6341 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6343 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6344 EXPECT_EQ(ERR_IO_PENDING, rv);
6346 rv = callback.WaitForResult();
6347 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
6349 rv = trans->RestartIgnoringLastError(callback.callback());
6350 EXPECT_EQ(ERR_IO_PENDING, rv);
6352 rv = callback.WaitForResult();
6355 const HttpResponseInfo* response = trans->GetResponseInfo();
6357 ASSERT_TRUE(response != NULL);
6358 EXPECT_EQ(100, response->headers->GetContentLength());
6361 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
6362 HttpRequestInfo request;
6363 request.method = "GET";
6364 request.url = GURL("http://www.google.com/");
6365 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6366 "Chromium Ultra Awesome X Edition");
6368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6369 scoped_ptr<HttpTransaction> trans(
6370 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6372 MockWrite data_writes[] = {
6373 MockWrite("GET / HTTP/1.1\r\n"
6374 "Host: www.google.com\r\n"
6375 "Connection: keep-alive\r\n"
6376 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6379 // Lastly, the server responds with the actual content.
6380 MockRead data_reads[] = {
6381 MockRead("HTTP/1.0 200 OK\r\n"),
6382 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6383 MockRead("Content-Length: 100\r\n\r\n"),
6384 MockRead(SYNCHRONOUS, OK),
6387 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6388 data_writes, arraysize(data_writes));
6389 session_deps_.socket_factory->AddSocketDataProvider(&data);
6391 TestCompletionCallback callback;
6393 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6394 EXPECT_EQ(ERR_IO_PENDING, rv);
6396 rv = callback.WaitForResult();
6400 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
6401 HttpRequestInfo request;
6402 request.method = "GET";
6403 request.url = GURL("https://www.google.com/");
6404 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
6405 "Chromium Ultra Awesome X Edition");
6407 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
6408 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6409 scoped_ptr<HttpTransaction> trans(
6410 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6412 MockWrite data_writes[] = {
6413 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6414 "Host: www.google.com\r\n"
6415 "Proxy-Connection: keep-alive\r\n"
6416 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6418 MockRead data_reads[] = {
6419 // Return an error, so the transaction stops here (this test isn't
6420 // interested in the rest).
6421 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6422 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6423 MockRead("Proxy-Connection: close\r\n\r\n"),
6426 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6427 data_writes, arraysize(data_writes));
6428 session_deps_.socket_factory->AddSocketDataProvider(&data);
6430 TestCompletionCallback callback;
6432 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6433 EXPECT_EQ(ERR_IO_PENDING, rv);
6435 rv = callback.WaitForResult();
6439 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
6440 HttpRequestInfo request;
6441 request.method = "GET";
6442 request.url = GURL("http://www.google.com/");
6443 request.load_flags = 0;
6444 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
6445 "http://the.previous.site.com/");
6447 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6448 scoped_ptr<HttpTransaction> trans(
6449 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6451 MockWrite data_writes[] = {
6452 MockWrite("GET / HTTP/1.1\r\n"
6453 "Host: www.google.com\r\n"
6454 "Connection: keep-alive\r\n"
6455 "Referer: http://the.previous.site.com/\r\n\r\n"),
6458 // Lastly, the server responds with the actual content.
6459 MockRead data_reads[] = {
6460 MockRead("HTTP/1.0 200 OK\r\n"),
6461 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6462 MockRead("Content-Length: 100\r\n\r\n"),
6463 MockRead(SYNCHRONOUS, OK),
6466 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6467 data_writes, arraysize(data_writes));
6468 session_deps_.socket_factory->AddSocketDataProvider(&data);
6470 TestCompletionCallback callback;
6472 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6473 EXPECT_EQ(ERR_IO_PENDING, rv);
6475 rv = callback.WaitForResult();
6479 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
6480 HttpRequestInfo request;
6481 request.method = "POST";
6482 request.url = GURL("http://www.google.com/");
6484 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6485 scoped_ptr<HttpTransaction> trans(
6486 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6488 MockWrite data_writes[] = {
6489 MockWrite("POST / HTTP/1.1\r\n"
6490 "Host: www.google.com\r\n"
6491 "Connection: keep-alive\r\n"
6492 "Content-Length: 0\r\n\r\n"),
6495 // Lastly, the server responds with the actual content.
6496 MockRead data_reads[] = {
6497 MockRead("HTTP/1.0 200 OK\r\n"),
6498 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6499 MockRead("Content-Length: 100\r\n\r\n"),
6500 MockRead(SYNCHRONOUS, OK),
6503 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6504 data_writes, arraysize(data_writes));
6505 session_deps_.socket_factory->AddSocketDataProvider(&data);
6507 TestCompletionCallback callback;
6509 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6510 EXPECT_EQ(ERR_IO_PENDING, rv);
6512 rv = callback.WaitForResult();
6516 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
6517 HttpRequestInfo request;
6518 request.method = "PUT";
6519 request.url = GURL("http://www.google.com/");
6521 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6522 scoped_ptr<HttpTransaction> trans(
6523 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6525 MockWrite data_writes[] = {
6526 MockWrite("PUT / HTTP/1.1\r\n"
6527 "Host: www.google.com\r\n"
6528 "Connection: keep-alive\r\n"
6529 "Content-Length: 0\r\n\r\n"),
6532 // Lastly, the server responds with the actual content.
6533 MockRead data_reads[] = {
6534 MockRead("HTTP/1.0 200 OK\r\n"),
6535 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6536 MockRead("Content-Length: 100\r\n\r\n"),
6537 MockRead(SYNCHRONOUS, OK),
6540 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6541 data_writes, arraysize(data_writes));
6542 session_deps_.socket_factory->AddSocketDataProvider(&data);
6544 TestCompletionCallback callback;
6546 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6547 EXPECT_EQ(ERR_IO_PENDING, rv);
6549 rv = callback.WaitForResult();
6553 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
6554 HttpRequestInfo request;
6555 request.method = "HEAD";
6556 request.url = GURL("http://www.google.com/");
6558 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6559 scoped_ptr<HttpTransaction> trans(
6560 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6562 MockWrite data_writes[] = {
6563 MockWrite("HEAD / HTTP/1.1\r\n"
6564 "Host: www.google.com\r\n"
6565 "Connection: keep-alive\r\n"
6566 "Content-Length: 0\r\n\r\n"),
6569 // Lastly, the server responds with the actual content.
6570 MockRead data_reads[] = {
6571 MockRead("HTTP/1.0 200 OK\r\n"),
6572 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6573 MockRead("Content-Length: 100\r\n\r\n"),
6574 MockRead(SYNCHRONOUS, OK),
6577 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6578 data_writes, arraysize(data_writes));
6579 session_deps_.socket_factory->AddSocketDataProvider(&data);
6581 TestCompletionCallback callback;
6583 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6584 EXPECT_EQ(ERR_IO_PENDING, rv);
6586 rv = callback.WaitForResult();
6590 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
6591 HttpRequestInfo request;
6592 request.method = "GET";
6593 request.url = GURL("http://www.google.com/");
6594 request.load_flags = LOAD_BYPASS_CACHE;
6596 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6597 scoped_ptr<HttpTransaction> trans(
6598 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6600 MockWrite data_writes[] = {
6601 MockWrite("GET / HTTP/1.1\r\n"
6602 "Host: www.google.com\r\n"
6603 "Connection: keep-alive\r\n"
6604 "Pragma: no-cache\r\n"
6605 "Cache-Control: no-cache\r\n\r\n"),
6608 // Lastly, the server responds with the actual content.
6609 MockRead data_reads[] = {
6610 MockRead("HTTP/1.0 200 OK\r\n"),
6611 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6612 MockRead("Content-Length: 100\r\n\r\n"),
6613 MockRead(SYNCHRONOUS, OK),
6616 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6617 data_writes, arraysize(data_writes));
6618 session_deps_.socket_factory->AddSocketDataProvider(&data);
6620 TestCompletionCallback callback;
6622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6623 EXPECT_EQ(ERR_IO_PENDING, rv);
6625 rv = callback.WaitForResult();
6629 TEST_P(HttpNetworkTransactionTest,
6630 BuildRequest_CacheControlValidateCache) {
6631 HttpRequestInfo request;
6632 request.method = "GET";
6633 request.url = GURL("http://www.google.com/");
6634 request.load_flags = LOAD_VALIDATE_CACHE;
6636 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6637 scoped_ptr<HttpTransaction> trans(
6638 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6640 MockWrite data_writes[] = {
6641 MockWrite("GET / HTTP/1.1\r\n"
6642 "Host: www.google.com\r\n"
6643 "Connection: keep-alive\r\n"
6644 "Cache-Control: max-age=0\r\n\r\n"),
6647 // Lastly, the server responds with the actual content.
6648 MockRead data_reads[] = {
6649 MockRead("HTTP/1.0 200 OK\r\n"),
6650 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6651 MockRead("Content-Length: 100\r\n\r\n"),
6652 MockRead(SYNCHRONOUS, OK),
6655 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6656 data_writes, arraysize(data_writes));
6657 session_deps_.socket_factory->AddSocketDataProvider(&data);
6659 TestCompletionCallback callback;
6661 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6662 EXPECT_EQ(ERR_IO_PENDING, rv);
6664 rv = callback.WaitForResult();
6668 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
6669 HttpRequestInfo request;
6670 request.method = "GET";
6671 request.url = GURL("http://www.google.com/");
6672 request.extra_headers.SetHeader("FooHeader", "Bar");
6674 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6675 scoped_ptr<HttpTransaction> trans(
6676 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6678 MockWrite data_writes[] = {
6679 MockWrite("GET / HTTP/1.1\r\n"
6680 "Host: www.google.com\r\n"
6681 "Connection: keep-alive\r\n"
6682 "FooHeader: Bar\r\n\r\n"),
6685 // Lastly, the server responds with the actual content.
6686 MockRead data_reads[] = {
6687 MockRead("HTTP/1.0 200 OK\r\n"),
6688 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6689 MockRead("Content-Length: 100\r\n\r\n"),
6690 MockRead(SYNCHRONOUS, OK),
6693 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6694 data_writes, arraysize(data_writes));
6695 session_deps_.socket_factory->AddSocketDataProvider(&data);
6697 TestCompletionCallback callback;
6699 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6700 EXPECT_EQ(ERR_IO_PENDING, rv);
6702 rv = callback.WaitForResult();
6706 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
6707 HttpRequestInfo request;
6708 request.method = "GET";
6709 request.url = GURL("http://www.google.com/");
6710 request.extra_headers.SetHeader("referer", "www.foo.com");
6711 request.extra_headers.SetHeader("hEllo", "Kitty");
6712 request.extra_headers.SetHeader("FoO", "bar");
6714 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6715 scoped_ptr<HttpTransaction> trans(
6716 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6718 MockWrite data_writes[] = {
6719 MockWrite("GET / HTTP/1.1\r\n"
6720 "Host: www.google.com\r\n"
6721 "Connection: keep-alive\r\n"
6722 "referer: www.foo.com\r\n"
6724 "FoO: bar\r\n\r\n"),
6727 // Lastly, the server responds with the actual content.
6728 MockRead data_reads[] = {
6729 MockRead("HTTP/1.0 200 OK\r\n"),
6730 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6731 MockRead("Content-Length: 100\r\n\r\n"),
6732 MockRead(SYNCHRONOUS, OK),
6735 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6736 data_writes, arraysize(data_writes));
6737 session_deps_.socket_factory->AddSocketDataProvider(&data);
6739 TestCompletionCallback callback;
6741 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6742 EXPECT_EQ(ERR_IO_PENDING, rv);
6744 rv = callback.WaitForResult();
6748 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
6749 HttpRequestInfo request;
6750 request.method = "GET";
6751 request.url = GURL("http://www.google.com/");
6752 request.load_flags = 0;
6754 session_deps_.proxy_service.reset(
6755 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6756 CapturingNetLog net_log;
6757 session_deps_.net_log = &net_log;
6759 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6760 scoped_ptr<HttpTransaction> trans(
6761 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6763 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6764 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6766 MockWrite data_writes[] = {
6767 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6768 MockWrite("GET / HTTP/1.1\r\n"
6769 "Host: www.google.com\r\n"
6770 "Connection: keep-alive\r\n\r\n")
6773 MockRead data_reads[] = {
6774 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6775 MockRead("HTTP/1.0 200 OK\r\n"),
6776 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6777 MockRead("Payload"),
6778 MockRead(SYNCHRONOUS, OK)
6781 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6782 data_writes, arraysize(data_writes));
6783 session_deps_.socket_factory->AddSocketDataProvider(&data);
6785 TestCompletionCallback callback;
6787 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6788 EXPECT_EQ(ERR_IO_PENDING, rv);
6790 rv = callback.WaitForResult();
6793 const HttpResponseInfo* response = trans->GetResponseInfo();
6794 ASSERT_TRUE(response != NULL);
6796 LoadTimingInfo load_timing_info;
6797 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6798 TestLoadTimingNotReusedWithPac(load_timing_info,
6799 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6801 std::string response_text;
6802 rv = ReadTransaction(trans.get(), &response_text);
6804 EXPECT_EQ("Payload", response_text);
6807 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
6808 HttpRequestInfo request;
6809 request.method = "GET";
6810 request.url = GURL("https://www.google.com/");
6811 request.load_flags = 0;
6813 session_deps_.proxy_service.reset(
6814 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
6815 CapturingNetLog net_log;
6816 session_deps_.net_log = &net_log;
6818 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6819 scoped_ptr<HttpTransaction> trans(
6820 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6822 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
6823 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6825 MockWrite data_writes[] = {
6826 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
6827 arraysize(write_buffer)),
6828 MockWrite("GET / HTTP/1.1\r\n"
6829 "Host: www.google.com\r\n"
6830 "Connection: keep-alive\r\n\r\n")
6833 MockRead data_reads[] = {
6834 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
6835 arraysize(read_buffer)),
6836 MockRead("HTTP/1.0 200 OK\r\n"),
6837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6838 MockRead("Payload"),
6839 MockRead(SYNCHRONOUS, OK)
6842 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6843 data_writes, arraysize(data_writes));
6844 session_deps_.socket_factory->AddSocketDataProvider(&data);
6846 SSLSocketDataProvider ssl(ASYNC, OK);
6847 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6849 TestCompletionCallback callback;
6851 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6852 EXPECT_EQ(ERR_IO_PENDING, rv);
6854 rv = callback.WaitForResult();
6857 LoadTimingInfo load_timing_info;
6858 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6859 TestLoadTimingNotReusedWithPac(load_timing_info,
6860 CONNECT_TIMING_HAS_SSL_TIMES);
6862 const HttpResponseInfo* response = trans->GetResponseInfo();
6863 ASSERT_TRUE(response != NULL);
6865 std::string response_text;
6866 rv = ReadTransaction(trans.get(), &response_text);
6868 EXPECT_EQ("Payload", response_text);
6871 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
6872 HttpRequestInfo request;
6873 request.method = "GET";
6874 request.url = GURL("http://www.google.com/");
6875 request.load_flags = 0;
6877 session_deps_.proxy_service.reset(
6878 ProxyService::CreateFixed("socks4://myproxy:1080"));
6879 CapturingNetLog net_log;
6880 session_deps_.net_log = &net_log;
6882 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6883 scoped_ptr<HttpTransaction> trans(
6884 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6886 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
6887 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
6889 MockWrite data_writes[] = {
6890 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
6891 MockWrite("GET / HTTP/1.1\r\n"
6892 "Host: www.google.com\r\n"
6893 "Connection: keep-alive\r\n\r\n")
6896 MockRead data_reads[] = {
6897 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
6898 MockRead("HTTP/1.0 200 OK\r\n"),
6899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6900 MockRead("Payload"),
6901 MockRead(SYNCHRONOUS, OK)
6904 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6905 data_writes, arraysize(data_writes));
6906 session_deps_.socket_factory->AddSocketDataProvider(&data);
6908 TestCompletionCallback callback;
6910 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6911 EXPECT_EQ(ERR_IO_PENDING, rv);
6913 rv = callback.WaitForResult();
6916 const HttpResponseInfo* response = trans->GetResponseInfo();
6917 ASSERT_TRUE(response != NULL);
6919 LoadTimingInfo load_timing_info;
6920 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6921 TestLoadTimingNotReused(load_timing_info,
6922 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6924 std::string response_text;
6925 rv = ReadTransaction(trans.get(), &response_text);
6927 EXPECT_EQ("Payload", response_text);
6930 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
6931 HttpRequestInfo request;
6932 request.method = "GET";
6933 request.url = GURL("http://www.google.com/");
6934 request.load_flags = 0;
6936 session_deps_.proxy_service.reset(
6937 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
6938 CapturingNetLog net_log;
6939 session_deps_.net_log = &net_log;
6941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6942 scoped_ptr<HttpTransaction> trans(
6943 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
6945 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
6946 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
6947 const char kSOCKS5OkRequest[] = {
6949 0x01, // Command (CONNECT)
6951 0x03, // Address type (DOMAINNAME).
6952 0x0E, // Length of domain (14)
6954 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
6955 0x00, 0x50, // 16-bit port (80)
6957 const char kSOCKS5OkResponse[] =
6958 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
6960 MockWrite data_writes[] = {
6961 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
6962 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
6963 MockWrite("GET / HTTP/1.1\r\n"
6964 "Host: www.google.com\r\n"
6965 "Connection: keep-alive\r\n\r\n")
6968 MockRead data_reads[] = {
6969 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
6970 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
6971 MockRead("HTTP/1.0 200 OK\r\n"),
6972 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
6973 MockRead("Payload"),
6974 MockRead(SYNCHRONOUS, OK)
6977 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6978 data_writes, arraysize(data_writes));
6979 session_deps_.socket_factory->AddSocketDataProvider(&data);
6981 TestCompletionCallback callback;
6983 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6984 EXPECT_EQ(ERR_IO_PENDING, rv);
6986 rv = callback.WaitForResult();
6989 const HttpResponseInfo* response = trans->GetResponseInfo();
6990 ASSERT_TRUE(response != NULL);
6992 LoadTimingInfo load_timing_info;
6993 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
6994 TestLoadTimingNotReusedWithPac(load_timing_info,
6995 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6997 std::string response_text;
6998 rv = ReadTransaction(trans.get(), &response_text);
7000 EXPECT_EQ("Payload", response_text);
7003 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
7004 HttpRequestInfo request;
7005 request.method = "GET";
7006 request.url = GURL("https://www.google.com/");
7007 request.load_flags = 0;
7009 session_deps_.proxy_service.reset(
7010 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7011 CapturingNetLog net_log;
7012 session_deps_.net_log = &net_log;
7014 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7015 scoped_ptr<HttpTransaction> trans(
7016 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7018 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
7019 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
7020 const unsigned char kSOCKS5OkRequest[] = {
7022 0x01, // Command (CONNECT)
7024 0x03, // Address type (DOMAINNAME).
7025 0x0E, // Length of domain (14)
7027 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7028 0x01, 0xBB, // 16-bit port (443)
7031 const char kSOCKS5OkResponse[] =
7032 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7034 MockWrite data_writes[] = {
7035 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
7036 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
7037 arraysize(kSOCKS5OkRequest)),
7038 MockWrite("GET / HTTP/1.1\r\n"
7039 "Host: www.google.com\r\n"
7040 "Connection: keep-alive\r\n\r\n")
7043 MockRead data_reads[] = {
7044 MockRead(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
7045 MockRead(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
7046 MockRead("HTTP/1.0 200 OK\r\n"),
7047 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7048 MockRead("Payload"),
7049 MockRead(SYNCHRONOUS, OK)
7052 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7053 data_writes, arraysize(data_writes));
7054 session_deps_.socket_factory->AddSocketDataProvider(&data);
7056 SSLSocketDataProvider ssl(ASYNC, OK);
7057 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7059 TestCompletionCallback callback;
7061 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7062 EXPECT_EQ(ERR_IO_PENDING, rv);
7064 rv = callback.WaitForResult();
7067 const HttpResponseInfo* response = trans->GetResponseInfo();
7068 ASSERT_TRUE(response != NULL);
7070 LoadTimingInfo load_timing_info;
7071 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
7072 TestLoadTimingNotReusedWithPac(load_timing_info,
7073 CONNECT_TIMING_HAS_SSL_TIMES);
7075 std::string response_text;
7076 rv = ReadTransaction(trans.get(), &response_text);
7078 EXPECT_EQ("Payload", response_text);
7083 // Tests that for connection endpoints the group names are correctly set.
7085 struct GroupNameTest {
7086 std::string proxy_server;
7088 std::string expected_group_name;
7092 scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
7093 NextProto next_proto,
7094 SpdySessionDependencies* session_deps_) {
7095 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps_));
7097 base::WeakPtr<HttpServerProperties> http_server_properties =
7098 session->http_server_properties();
7099 http_server_properties->SetAlternateProtocol(
7100 HostPortPair("host.with.alternate", 80), 443,
7101 AlternateProtocolFromNextProto(next_proto));
7106 int GroupNameTransactionHelper(
7107 const std::string& url,
7108 const scoped_refptr<HttpNetworkSession>& session) {
7109 HttpRequestInfo request;
7110 request.method = "GET";
7111 request.url = GURL(url);
7112 request.load_flags = 0;
7114 scoped_ptr<HttpTransaction> trans(
7115 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7117 TestCompletionCallback callback;
7119 // We do not complete this request, the dtor will clean the transaction up.
7120 return trans->Start(&request, callback.callback(), BoundNetLog());
7125 TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
7126 const GroupNameTest tests[] = {
7129 "http://www.google.com/direct",
7130 "www.google.com:80",
7135 "http://[2001:1418:13:1::25]/direct",
7136 "[2001:1418:13:1::25]:80",
7143 "https://www.google.com/direct_ssl",
7144 "ssl/www.google.com:443",
7149 "https://[2001:1418:13:1::25]/direct",
7150 "ssl/[2001:1418:13:1::25]:443",
7155 "http://host.with.alternate/direct",
7156 "ssl/host.with.alternate:443",
7161 HttpStreamFactory::set_use_alternate_protocols(true);
7163 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7164 session_deps_.proxy_service.reset(
7165 ProxyService::CreateFixed(tests[i].proxy_server));
7166 scoped_refptr<HttpNetworkSession> session(
7167 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7169 HttpNetworkSessionPeer peer(session);
7170 CaptureGroupNameTransportSocketPool* transport_conn_pool =
7171 new CaptureGroupNameTransportSocketPool(NULL, NULL);
7172 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7173 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7174 MockClientSocketPoolManager* mock_pool_manager =
7175 new MockClientSocketPoolManager;
7176 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
7177 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
7178 peer.SetClientSocketPoolManager(mock_pool_manager);
7180 EXPECT_EQ(ERR_IO_PENDING,
7181 GroupNameTransactionHelper(tests[i].url, session));
7183 EXPECT_EQ(tests[i].expected_group_name,
7184 ssl_conn_pool->last_group_name_received());
7186 EXPECT_EQ(tests[i].expected_group_name,
7187 transport_conn_pool->last_group_name_received());
7192 TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
7193 const GroupNameTest tests[] = {
7196 "http://www.google.com/http_proxy_normal",
7197 "www.google.com:80",
7204 "https://www.google.com/http_connect_ssl",
7205 "ssl/www.google.com:443",
7211 "http://host.with.alternate/direct",
7212 "ssl/host.with.alternate:443",
7218 "ftp://ftp.google.com/http_proxy_normal",
7219 "ftp/ftp.google.com:21",
7224 HttpStreamFactory::set_use_alternate_protocols(true);
7226 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7227 session_deps_.proxy_service.reset(
7228 ProxyService::CreateFixed(tests[i].proxy_server));
7229 scoped_refptr<HttpNetworkSession> session(
7230 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7232 HttpNetworkSessionPeer peer(session);
7234 HostPortPair proxy_host("http_proxy", 80);
7235 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
7236 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
7237 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7238 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7240 MockClientSocketPoolManager* mock_pool_manager =
7241 new MockClientSocketPoolManager;
7242 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
7243 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7244 peer.SetClientSocketPoolManager(mock_pool_manager);
7246 EXPECT_EQ(ERR_IO_PENDING,
7247 GroupNameTransactionHelper(tests[i].url, session));
7249 EXPECT_EQ(tests[i].expected_group_name,
7250 ssl_conn_pool->last_group_name_received());
7252 EXPECT_EQ(tests[i].expected_group_name,
7253 http_proxy_pool->last_group_name_received());
7257 TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
7258 const GroupNameTest tests[] = {
7260 "socks4://socks_proxy:1080",
7261 "http://www.google.com/socks4_direct",
7262 "socks4/www.google.com:80",
7266 "socks5://socks_proxy:1080",
7267 "http://www.google.com/socks5_direct",
7268 "socks5/www.google.com:80",
7274 "socks4://socks_proxy:1080",
7275 "https://www.google.com/socks4_ssl",
7276 "socks4/ssl/www.google.com:443",
7280 "socks5://socks_proxy:1080",
7281 "https://www.google.com/socks5_ssl",
7282 "socks5/ssl/www.google.com:443",
7287 "socks4://socks_proxy:1080",
7288 "http://host.with.alternate/direct",
7289 "socks4/ssl/host.with.alternate:443",
7294 HttpStreamFactory::set_use_alternate_protocols(true);
7296 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
7297 session_deps_.proxy_service.reset(
7298 ProxyService::CreateFixed(tests[i].proxy_server));
7299 scoped_refptr<HttpNetworkSession> session(
7300 SetupSessionForGroupNameTests(GetParam(), &session_deps_));
7302 HttpNetworkSessionPeer peer(session);
7304 HostPortPair proxy_host("socks_proxy", 1080);
7305 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
7306 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
7307 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
7308 new CaptureGroupNameSSLSocketPool(NULL, NULL);
7310 MockClientSocketPoolManager* mock_pool_manager =
7311 new MockClientSocketPoolManager;
7312 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
7313 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
7314 peer.SetClientSocketPoolManager(mock_pool_manager);
7316 scoped_ptr<HttpTransaction> trans(
7317 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7319 EXPECT_EQ(ERR_IO_PENDING,
7320 GroupNameTransactionHelper(tests[i].url, session));
7322 EXPECT_EQ(tests[i].expected_group_name,
7323 ssl_conn_pool->last_group_name_received());
7325 EXPECT_EQ(tests[i].expected_group_name,
7326 socks_conn_pool->last_group_name_received());
7330 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
7331 HttpRequestInfo request;
7332 request.method = "GET";
7333 request.url = GURL("http://www.google.com/");
7335 session_deps_.proxy_service.reset(
7336 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7338 // This simulates failure resolving all hostnames; that means we will fail
7339 // connecting to both proxies (myproxy:70 and foobar:80).
7340 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
7342 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7343 scoped_ptr<HttpTransaction> trans(
7344 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7346 TestCompletionCallback callback;
7348 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7349 EXPECT_EQ(ERR_IO_PENDING, rv);
7351 rv = callback.WaitForResult();
7352 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
7355 // Base test to make sure that when the load flags for a request specify to
7356 // bypass the cache, the DNS cache is not used.
7357 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7359 // Issue a request, asking to bypass the cache(s).
7360 HttpRequestInfo request;
7361 request.method = "GET";
7362 request.load_flags = load_flags;
7363 request.url = GURL("http://www.google.com/");
7365 // Select a host resolver that does caching.
7366 session_deps_.host_resolver.reset(new MockCachingHostResolver);
7368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7369 scoped_ptr<HttpTransaction> trans(
7370 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7372 // Warm up the host cache so it has an entry for "www.google.com".
7373 AddressList addrlist;
7374 TestCompletionCallback callback;
7375 int rv = session_deps_.host_resolver->Resolve(
7376 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7379 callback.callback(),
7382 EXPECT_EQ(ERR_IO_PENDING, rv);
7383 rv = callback.WaitForResult();
7386 // Verify that it was added to host cache, by doing a subsequent async lookup
7387 // and confirming it completes synchronously.
7388 rv = session_deps_.host_resolver->Resolve(
7389 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7392 callback.callback(),
7397 // Inject a failure the next time that "www.google.com" is resolved. This way
7398 // we can tell if the next lookup hit the cache, or the "network".
7399 // (cache --> success, "network" --> failure).
7400 session_deps_.host_resolver->rules()->AddSimulatedFailure("www.google.com");
7402 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7403 // first read -- this won't be reached as the host resolution will fail first.
7404 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
7405 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7406 session_deps_.socket_factory->AddSocketDataProvider(&data);
7409 rv = trans->Start(&request, callback.callback(), BoundNetLog());
7410 ASSERT_EQ(ERR_IO_PENDING, rv);
7411 rv = callback.WaitForResult();
7413 // If we bypassed the cache, we would have gotten a failure while resolving
7414 // "www.google.com".
7415 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
7418 // There are multiple load flags that should trigger the host cache bypass.
7419 // Test each in isolation:
7420 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
7421 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
7424 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
7425 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
7428 TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
7429 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
7432 // Make sure we can handle an error when writing the request.
7433 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
7434 HttpRequestInfo request;
7435 request.method = "GET";
7436 request.url = GURL("http://www.foo.com/");
7437 request.load_flags = 0;
7439 MockWrite write_failure[] = {
7440 MockWrite(ASYNC, ERR_CONNECTION_RESET),
7442 StaticSocketDataProvider data(NULL, 0,
7443 write_failure, arraysize(write_failure));
7444 session_deps_.socket_factory->AddSocketDataProvider(&data);
7445 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7447 TestCompletionCallback callback;
7449 scoped_ptr<HttpTransaction> trans(
7450 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7452 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7453 EXPECT_EQ(ERR_IO_PENDING, rv);
7455 rv = callback.WaitForResult();
7456 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
7459 // Check that a connection closed after the start of the headers finishes ok.
7460 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
7461 HttpRequestInfo request;
7462 request.method = "GET";
7463 request.url = GURL("http://www.foo.com/");
7464 request.load_flags = 0;
7466 MockRead data_reads[] = {
7467 MockRead("HTTP/1."),
7468 MockRead(SYNCHRONOUS, OK),
7471 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7472 session_deps_.socket_factory->AddSocketDataProvider(&data);
7473 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7475 TestCompletionCallback callback;
7477 scoped_ptr<HttpTransaction> trans(
7478 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7480 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7481 EXPECT_EQ(ERR_IO_PENDING, rv);
7483 rv = callback.WaitForResult();
7486 const HttpResponseInfo* response = trans->GetResponseInfo();
7487 ASSERT_TRUE(response != NULL);
7489 EXPECT_TRUE(response->headers.get() != NULL);
7490 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7492 std::string response_data;
7493 rv = ReadTransaction(trans.get(), &response_data);
7495 EXPECT_EQ("", response_data);
7498 // Make sure that a dropped connection while draining the body for auth
7499 // restart does the right thing.
7500 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
7501 HttpRequestInfo request;
7502 request.method = "GET";
7503 request.url = GURL("http://www.google.com/");
7504 request.load_flags = 0;
7506 MockWrite data_writes1[] = {
7507 MockWrite("GET / HTTP/1.1\r\n"
7508 "Host: www.google.com\r\n"
7509 "Connection: keep-alive\r\n\r\n"),
7512 MockRead data_reads1[] = {
7513 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7514 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7515 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7516 MockRead("Content-Length: 14\r\n\r\n"),
7518 MockRead(ASYNC, ERR_CONNECTION_RESET),
7521 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7522 data_writes1, arraysize(data_writes1));
7523 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7525 // After calling trans->RestartWithAuth(), this is the request we should
7526 // be issuing -- the final header line contains the credentials.
7527 MockWrite data_writes2[] = {
7528 MockWrite("GET / HTTP/1.1\r\n"
7529 "Host: www.google.com\r\n"
7530 "Connection: keep-alive\r\n"
7531 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7534 // Lastly, the server responds with the actual content.
7535 MockRead data_reads2[] = {
7536 MockRead("HTTP/1.1 200 OK\r\n"),
7537 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7538 MockRead("Content-Length: 100\r\n\r\n"),
7539 MockRead(SYNCHRONOUS, OK),
7542 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7543 data_writes2, arraysize(data_writes2));
7544 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7545 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7547 TestCompletionCallback callback1;
7549 scoped_ptr<HttpTransaction> trans(
7550 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
7552 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7553 EXPECT_EQ(ERR_IO_PENDING, rv);
7555 rv = callback1.WaitForResult();
7558 const HttpResponseInfo* response = trans->GetResponseInfo();
7559 ASSERT_TRUE(response != NULL);
7560 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7562 TestCompletionCallback callback2;
7564 rv = trans->RestartWithAuth(
7565 AuthCredentials(kFoo, kBar), callback2.callback());
7566 EXPECT_EQ(ERR_IO_PENDING, rv);
7568 rv = callback2.WaitForResult();
7571 response = trans->GetResponseInfo();
7572 ASSERT_TRUE(response != NULL);
7573 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7574 EXPECT_EQ(100, response->headers->GetContentLength());
7577 // Test HTTPS connections going through a proxy that sends extra data.
7578 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
7579 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
7581 HttpRequestInfo request;
7582 request.method = "GET";
7583 request.url = GURL("https://www.google.com/");
7584 request.load_flags = 0;
7586 MockRead proxy_reads[] = {
7587 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7588 MockRead(SYNCHRONOUS, OK)
7591 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
7592 SSLSocketDataProvider ssl(ASYNC, OK);
7594 session_deps_.socket_factory->AddSocketDataProvider(&data);
7595 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7597 TestCompletionCallback callback;
7599 session_deps_.socket_factory->ResetNextMockIndexes();
7601 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7602 scoped_ptr<HttpTransaction> trans(
7603 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7605 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7606 EXPECT_EQ(ERR_IO_PENDING, rv);
7608 rv = callback.WaitForResult();
7609 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
7612 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
7613 HttpRequestInfo request;
7614 request.method = "GET";
7615 request.url = GURL("http://www.google.com/");
7616 request.load_flags = 0;
7618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7619 scoped_ptr<HttpTransaction> trans(
7620 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7622 MockRead data_reads[] = {
7623 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7624 MockRead(SYNCHRONOUS, OK),
7627 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7628 session_deps_.socket_factory->AddSocketDataProvider(&data);
7630 TestCompletionCallback callback;
7632 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7633 EXPECT_EQ(ERR_IO_PENDING, rv);
7635 EXPECT_EQ(OK, callback.WaitForResult());
7637 const HttpResponseInfo* response = trans->GetResponseInfo();
7638 ASSERT_TRUE(response != NULL);
7640 EXPECT_TRUE(response->headers.get() != NULL);
7641 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7643 std::string response_data;
7644 rv = ReadTransaction(trans.get(), &response_data);
7645 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH, rv);
7648 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
7649 base::FilePath temp_file_path;
7650 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
7651 const uint64 kFakeSize = 100000; // file is actually blank
7652 UploadFileElementReader::ScopedOverridingContentLengthForTests
7653 overriding_content_length(kFakeSize);
7655 ScopedVector<UploadElementReader> element_readers;
7656 element_readers.push_back(
7657 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7662 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7664 HttpRequestInfo request;
7665 request.method = "POST";
7666 request.url = GURL("http://www.google.com/upload");
7667 request.upload_data_stream = &upload_data_stream;
7668 request.load_flags = 0;
7670 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7671 scoped_ptr<HttpTransaction> trans(
7672 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7674 MockRead data_reads[] = {
7675 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7676 MockRead("hello world"),
7677 MockRead(SYNCHRONOUS, OK),
7679 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7680 session_deps_.socket_factory->AddSocketDataProvider(&data);
7682 TestCompletionCallback callback;
7684 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7685 EXPECT_EQ(ERR_IO_PENDING, rv);
7687 rv = callback.WaitForResult();
7690 const HttpResponseInfo* response = trans->GetResponseInfo();
7691 ASSERT_TRUE(response != NULL);
7693 EXPECT_TRUE(response->headers.get() != NULL);
7694 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7696 std::string response_data;
7697 rv = ReadTransaction(trans.get(), &response_data);
7699 EXPECT_EQ("hello world", response_data);
7701 base::DeleteFile(temp_file_path, false);
7704 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
7705 base::FilePath temp_file;
7706 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
7707 std::string temp_file_content("Unreadable file.");
7708 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
7709 temp_file_content.length()));
7710 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7712 ScopedVector<UploadElementReader> element_readers;
7713 element_readers.push_back(
7714 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7719 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7721 HttpRequestInfo request;
7722 request.method = "POST";
7723 request.url = GURL("http://www.google.com/upload");
7724 request.upload_data_stream = &upload_data_stream;
7725 request.load_flags = 0;
7727 // If we try to upload an unreadable file, the network stack should report
7728 // the file size as zero and upload zero bytes for that file.
7729 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7730 scoped_ptr<HttpTransaction> trans(
7731 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7733 MockRead data_reads[] = {
7734 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7735 MockRead(SYNCHRONOUS, OK),
7737 MockWrite data_writes[] = {
7738 MockWrite("POST /upload HTTP/1.1\r\n"
7739 "Host: www.google.com\r\n"
7740 "Connection: keep-alive\r\n"
7741 "Content-Length: 0\r\n\r\n"),
7742 MockWrite(SYNCHRONOUS, OK),
7744 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
7745 arraysize(data_writes));
7746 session_deps_.socket_factory->AddSocketDataProvider(&data);
7748 TestCompletionCallback callback;
7750 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7751 EXPECT_EQ(ERR_IO_PENDING, rv);
7753 rv = callback.WaitForResult();
7756 const HttpResponseInfo* response = trans->GetResponseInfo();
7757 ASSERT_TRUE(response != NULL);
7758 EXPECT_TRUE(response->headers.get() != NULL);
7759 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
7761 base::DeleteFile(temp_file, false);
7764 TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
7765 base::FilePath temp_file;
7766 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
7767 std::string temp_file_contents("Unreadable file.");
7768 std::string unreadable_contents(temp_file_contents.length(), '\0');
7769 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
7770 temp_file_contents.length()));
7772 ScopedVector<UploadElementReader> element_readers;
7773 element_readers.push_back(
7774 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7779 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7781 HttpRequestInfo request;
7782 request.method = "POST";
7783 request.url = GURL("http://www.google.com/upload");
7784 request.upload_data_stream = &upload_data_stream;
7785 request.load_flags = 0;
7787 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7788 scoped_ptr<HttpTransaction> trans(
7789 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7791 MockRead data_reads[] = {
7792 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7793 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7794 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
7796 MockRead("HTTP/1.1 200 OK\r\n"),
7797 MockRead("Content-Length: 0\r\n\r\n"),
7798 MockRead(SYNCHRONOUS, OK),
7800 MockWrite data_writes[] = {
7801 MockWrite("POST /upload HTTP/1.1\r\n"
7802 "Host: www.google.com\r\n"
7803 "Connection: keep-alive\r\n"
7804 "Content-Length: 16\r\n\r\n"),
7805 MockWrite(SYNCHRONOUS, temp_file_contents.c_str()),
7807 MockWrite("POST /upload HTTP/1.1\r\n"
7808 "Host: www.google.com\r\n"
7809 "Connection: keep-alive\r\n"
7810 "Content-Length: 0\r\n"
7811 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7812 MockWrite(SYNCHRONOUS, unreadable_contents.c_str(),
7813 temp_file_contents.length()),
7814 MockWrite(SYNCHRONOUS, OK),
7816 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
7817 arraysize(data_writes));
7818 session_deps_.socket_factory->AddSocketDataProvider(&data);
7820 TestCompletionCallback callback1;
7822 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
7823 EXPECT_EQ(ERR_IO_PENDING, rv);
7825 rv = callback1.WaitForResult();
7828 const HttpResponseInfo* response = trans->GetResponseInfo();
7829 ASSERT_TRUE(response != NULL);
7830 ASSERT_TRUE(response->headers.get() != NULL);
7831 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
7832 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
7834 // Now make the file unreadable and try again.
7835 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
7837 TestCompletionCallback callback2;
7839 rv = trans->RestartWithAuth(
7840 AuthCredentials(kFoo, kBar), callback2.callback());
7841 EXPECT_EQ(ERR_IO_PENDING, rv);
7843 rv = callback2.WaitForResult();
7846 response = trans->GetResponseInfo();
7847 ASSERT_TRUE(response != NULL);
7848 EXPECT_TRUE(response->headers.get() != NULL);
7849 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7850 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7852 base::DeleteFile(temp_file, false);
7855 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
7856 class FakeUploadElementReader : public UploadElementReader {
7858 FakeUploadElementReader() {}
7859 virtual ~FakeUploadElementReader() {}
7861 const CompletionCallback& callback() const { return callback_; }
7863 // UploadElementReader overrides:
7864 virtual int Init(const CompletionCallback& callback) OVERRIDE {
7865 callback_ = callback;
7866 return ERR_IO_PENDING;
7868 virtual uint64 GetContentLength() const OVERRIDE { return 0; }
7869 virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
7870 virtual int Read(IOBuffer* buf,
7872 const CompletionCallback& callback) OVERRIDE {
7877 CompletionCallback callback_;
7880 FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
7881 ScopedVector<UploadElementReader> element_readers;
7882 element_readers.push_back(fake_reader);
7883 UploadDataStream upload_data_stream(element_readers.Pass(), 0);
7885 HttpRequestInfo request;
7886 request.method = "POST";
7887 request.url = GURL("http://www.google.com/upload");
7888 request.upload_data_stream = &upload_data_stream;
7889 request.load_flags = 0;
7891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7892 scoped_ptr<HttpTransaction> trans(
7893 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7895 StaticSocketDataProvider data;
7896 session_deps_.socket_factory->AddSocketDataProvider(&data);
7898 TestCompletionCallback callback;
7899 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
7900 EXPECT_EQ(ERR_IO_PENDING, rv);
7901 base::MessageLoop::current()->RunUntilIdle();
7903 // Transaction is pending on request body initialization.
7904 ASSERT_FALSE(fake_reader->callback().is_null());
7906 // Return Init()'s result after the transaction gets destroyed.
7908 fake_reader->callback().Run(OK); // Should not crash.
7911 // Tests that changes to Auth realms are treated like auth rejections.
7912 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
7914 HttpRequestInfo request;
7915 request.method = "GET";
7916 request.url = GURL("http://www.google.com/");
7917 request.load_flags = 0;
7919 // First transaction will request a resource and receive a Basic challenge
7920 // with realm="first_realm".
7921 MockWrite data_writes1[] = {
7922 MockWrite("GET / HTTP/1.1\r\n"
7923 "Host: www.google.com\r\n"
7924 "Connection: keep-alive\r\n"
7927 MockRead data_reads1[] = {
7928 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7929 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7933 // After calling trans->RestartWithAuth(), provide an Authentication header
7934 // for first_realm. The server will reject and provide a challenge with
7936 MockWrite data_writes2[] = {
7937 MockWrite("GET / HTTP/1.1\r\n"
7938 "Host: www.google.com\r\n"
7939 "Connection: keep-alive\r\n"
7940 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
7943 MockRead data_reads2[] = {
7944 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7945 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
7949 // This again fails, and goes back to first_realm. Make sure that the
7950 // entry is removed from cache.
7951 MockWrite data_writes3[] = {
7952 MockWrite("GET / HTTP/1.1\r\n"
7953 "Host: www.google.com\r\n"
7954 "Connection: keep-alive\r\n"
7955 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
7958 MockRead data_reads3[] = {
7959 MockRead("HTTP/1.1 401 Unauthorized\r\n"
7960 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
7964 // Try one last time (with the correct password) and get the resource.
7965 MockWrite data_writes4[] = {
7966 MockWrite("GET / HTTP/1.1\r\n"
7967 "Host: www.google.com\r\n"
7968 "Connection: keep-alive\r\n"
7969 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
7972 MockRead data_reads4[] = {
7973 MockRead("HTTP/1.1 200 OK\r\n"
7974 "Content-Type: text/html; charset=iso-8859-1\r\n"
7975 "Content-Length: 5\r\n"
7980 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7981 data_writes1, arraysize(data_writes1));
7982 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
7983 data_writes2, arraysize(data_writes2));
7984 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
7985 data_writes3, arraysize(data_writes3));
7986 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
7987 data_writes4, arraysize(data_writes4));
7988 session_deps_.socket_factory->AddSocketDataProvider(&data1);
7989 session_deps_.socket_factory->AddSocketDataProvider(&data2);
7990 session_deps_.socket_factory->AddSocketDataProvider(&data3);
7991 session_deps_.socket_factory->AddSocketDataProvider(&data4);
7993 TestCompletionCallback callback1;
7995 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7996 scoped_ptr<HttpTransaction> trans(
7997 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
7999 // Issue the first request with Authorize headers. There should be a
8000 // password prompt for first_realm waiting to be filled in after the
8001 // transaction completes.
8002 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
8003 EXPECT_EQ(ERR_IO_PENDING, rv);
8004 rv = callback1.WaitForResult();
8006 const HttpResponseInfo* response = trans->GetResponseInfo();
8007 ASSERT_TRUE(response != NULL);
8008 const AuthChallengeInfo* challenge = response->auth_challenge.get();
8009 ASSERT_FALSE(challenge == NULL);
8010 EXPECT_FALSE(challenge->is_proxy);
8011 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8012 EXPECT_EQ("first_realm", challenge->realm);
8013 EXPECT_EQ("basic", challenge->scheme);
8015 // Issue the second request with an incorrect password. There should be a
8016 // password prompt for second_realm waiting to be filled in after the
8017 // transaction completes.
8018 TestCompletionCallback callback2;
8019 rv = trans->RestartWithAuth(
8020 AuthCredentials(kFirst, kBaz), callback2.callback());
8021 EXPECT_EQ(ERR_IO_PENDING, rv);
8022 rv = callback2.WaitForResult();
8024 response = trans->GetResponseInfo();
8025 ASSERT_TRUE(response != NULL);
8026 challenge = response->auth_challenge.get();
8027 ASSERT_FALSE(challenge == NULL);
8028 EXPECT_FALSE(challenge->is_proxy);
8029 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8030 EXPECT_EQ("second_realm", challenge->realm);
8031 EXPECT_EQ("basic", challenge->scheme);
8033 // Issue the third request with another incorrect password. There should be
8034 // a password prompt for first_realm waiting to be filled in. If the password
8035 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8036 // first_realm was not correctly removed.
8037 TestCompletionCallback callback3;
8038 rv = trans->RestartWithAuth(
8039 AuthCredentials(kSecond, kFou), callback3.callback());
8040 EXPECT_EQ(ERR_IO_PENDING, rv);
8041 rv = callback3.WaitForResult();
8043 response = trans->GetResponseInfo();
8044 ASSERT_TRUE(response != NULL);
8045 challenge = response->auth_challenge.get();
8046 ASSERT_FALSE(challenge == NULL);
8047 EXPECT_FALSE(challenge->is_proxy);
8048 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
8049 EXPECT_EQ("first_realm", challenge->realm);
8050 EXPECT_EQ("basic", challenge->scheme);
8052 // Issue the fourth request with the correct password and username.
8053 TestCompletionCallback callback4;
8054 rv = trans->RestartWithAuth(
8055 AuthCredentials(kFirst, kBar), callback4.callback());
8056 EXPECT_EQ(ERR_IO_PENDING, rv);
8057 rv = callback4.WaitForResult();
8059 response = trans->GetResponseInfo();
8060 ASSERT_TRUE(response != NULL);
8061 EXPECT_TRUE(response->auth_challenge.get() == NULL);
8064 TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
8065 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8066 HttpStreamFactory::set_use_alternate_protocols(true);
8068 std::string alternate_protocol_http_header =
8069 GetAlternateProtocolHttpHeader();
8071 MockRead data_reads[] = {
8072 MockRead("HTTP/1.1 200 OK\r\n"),
8073 MockRead(alternate_protocol_http_header.c_str()),
8074 MockRead("hello world"),
8075 MockRead(SYNCHRONOUS, OK),
8078 HttpRequestInfo request;
8079 request.method = "GET";
8080 request.url = GURL("http://www.google.com/");
8081 request.load_flags = 0;
8083 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8085 session_deps_.socket_factory->AddSocketDataProvider(&data);
8087 TestCompletionCallback callback;
8089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8090 scoped_ptr<HttpTransaction> trans(
8091 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8093 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8094 EXPECT_EQ(ERR_IO_PENDING, rv);
8096 HostPortPair http_host_port_pair("www.google.com", 80);
8097 const HttpServerProperties& http_server_properties =
8098 *session->http_server_properties();
8100 http_server_properties.HasAlternateProtocol(http_host_port_pair));
8102 EXPECT_EQ(OK, callback.WaitForResult());
8104 const HttpResponseInfo* response = trans->GetResponseInfo();
8105 ASSERT_TRUE(response != NULL);
8106 ASSERT_TRUE(response->headers.get() != NULL);
8107 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8108 EXPECT_FALSE(response->was_fetched_via_spdy);
8109 EXPECT_FALSE(response->was_npn_negotiated);
8111 std::string response_data;
8112 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8113 EXPECT_EQ("hello world", response_data);
8115 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
8116 const PortAlternateProtocolPair alternate =
8117 http_server_properties.GetAlternateProtocol(http_host_port_pair);
8118 PortAlternateProtocolPair expected_alternate;
8119 expected_alternate.port = 443;
8120 expected_alternate.protocol = AlternateProtocolFromNextProto(GetParam());
8121 EXPECT_TRUE(expected_alternate.Equals(alternate));
8124 TEST_P(HttpNetworkTransactionTest,
8125 MarkBrokenAlternateProtocolAndFallback) {
8126 HttpStreamFactory::set_use_alternate_protocols(true);
8128 HttpRequestInfo request;
8129 request.method = "GET";
8130 request.url = GURL("http://www.google.com/");
8131 request.load_flags = 0;
8133 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8134 StaticSocketDataProvider first_data;
8135 first_data.set_connect_data(mock_connect);
8136 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8138 MockRead data_reads[] = {
8139 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8140 MockRead("hello world"),
8141 MockRead(ASYNC, OK),
8143 StaticSocketDataProvider second_data(
8144 data_reads, arraysize(data_reads), NULL, 0);
8145 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8147 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8149 base::WeakPtr<HttpServerProperties> http_server_properties =
8150 session->http_server_properties();
8151 // Port must be < 1024, or the header will be ignored (since initial port was
8152 // port 80 (another restricted port).
8153 http_server_properties->SetAlternateProtocol(
8154 HostPortPair::FromURL(request.url),
8155 666 /* port is ignored by MockConnect anyway */,
8156 AlternateProtocolFromNextProto(GetParam()));
8158 scoped_ptr<HttpTransaction> trans(
8159 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8160 TestCompletionCallback callback;
8162 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8163 EXPECT_EQ(ERR_IO_PENDING, rv);
8164 EXPECT_EQ(OK, callback.WaitForResult());
8166 const HttpResponseInfo* response = trans->GetResponseInfo();
8167 ASSERT_TRUE(response != NULL);
8168 ASSERT_TRUE(response->headers.get() != NULL);
8169 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8171 std::string response_data;
8172 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8173 EXPECT_EQ("hello world", response_data);
8175 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
8176 HostPortPair::FromURL(request.url)));
8177 const PortAlternateProtocolPair alternate =
8178 http_server_properties->GetAlternateProtocol(
8179 HostPortPair::FromURL(request.url));
8180 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
8183 TEST_P(HttpNetworkTransactionTest,
8184 AlternateProtocolPortRestrictedBlocked) {
8185 // Ensure that we're not allowed to redirect traffic via an alternate
8186 // protocol to an unrestricted (port >= 1024) when the original traffic was
8187 // on a restricted port (port < 1024). Ensure that we can redirect in all
8189 HttpStreamFactory::set_use_alternate_protocols(true);
8191 HttpRequestInfo restricted_port_request;
8192 restricted_port_request.method = "GET";
8193 restricted_port_request.url = GURL("http://www.google.com:1023/");
8194 restricted_port_request.load_flags = 0;
8196 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8197 StaticSocketDataProvider first_data;
8198 first_data.set_connect_data(mock_connect);
8199 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8201 MockRead data_reads[] = {
8202 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8203 MockRead("hello world"),
8204 MockRead(ASYNC, OK),
8206 StaticSocketDataProvider second_data(
8207 data_reads, arraysize(data_reads), NULL, 0);
8208 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8210 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8212 base::WeakPtr<HttpServerProperties> http_server_properties =
8213 session->http_server_properties();
8214 const int kUnrestrictedAlternatePort = 1024;
8215 http_server_properties->SetAlternateProtocol(
8216 HostPortPair::FromURL(restricted_port_request.url),
8217 kUnrestrictedAlternatePort,
8218 AlternateProtocolFromNextProto(GetParam()));
8220 scoped_ptr<HttpTransaction> trans(
8221 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8222 TestCompletionCallback callback;
8224 int rv = trans->Start(
8225 &restricted_port_request,
8226 callback.callback(), BoundNetLog());
8227 EXPECT_EQ(ERR_IO_PENDING, rv);
8228 // Invalid change to unrestricted port should fail.
8229 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
8232 TEST_P(HttpNetworkTransactionTest,
8233 AlternateProtocolPortRestrictedPermitted) {
8234 // Ensure that we're allowed to redirect traffic via an alternate
8235 // protocol to an unrestricted (port >= 1024) when the original traffic was
8236 // on a restricted port (port < 1024) if we set
8237 // enable_user_alternate_protocol_ports.
8239 HttpStreamFactory::set_use_alternate_protocols(true);
8240 session_deps_.enable_user_alternate_protocol_ports = true;
8242 HttpRequestInfo restricted_port_request;
8243 restricted_port_request.method = "GET";
8244 restricted_port_request.url = GURL("http://www.google.com:1023/");
8245 restricted_port_request.load_flags = 0;
8247 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8248 StaticSocketDataProvider first_data;
8249 first_data.set_connect_data(mock_connect);
8250 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8252 MockRead data_reads[] = {
8253 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8254 MockRead("hello world"),
8255 MockRead(ASYNC, OK),
8257 StaticSocketDataProvider second_data(
8258 data_reads, arraysize(data_reads), NULL, 0);
8259 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8261 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8263 base::WeakPtr<HttpServerProperties> http_server_properties =
8264 session->http_server_properties();
8265 const int kUnrestrictedAlternatePort = 1024;
8266 http_server_properties->SetAlternateProtocol(
8267 HostPortPair::FromURL(restricted_port_request.url),
8268 kUnrestrictedAlternatePort,
8269 AlternateProtocolFromNextProto(GetParam()));
8271 scoped_ptr<HttpTransaction> trans(
8272 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8273 TestCompletionCallback callback;
8275 EXPECT_EQ(ERR_IO_PENDING, trans->Start(
8276 &restricted_port_request,
8277 callback.callback(), BoundNetLog()));
8278 // Change to unrestricted port should succeed.
8279 EXPECT_EQ(OK, callback.WaitForResult());
8282 TEST_P(HttpNetworkTransactionTest,
8283 AlternateProtocolPortRestrictedAllowed) {
8284 // Ensure that we're not allowed to redirect traffic via an alternate
8285 // protocol to an unrestricted (port >= 1024) when the original traffic was
8286 // on a restricted port (port < 1024). Ensure that we can redirect in all
8288 HttpStreamFactory::set_use_alternate_protocols(true);
8290 HttpRequestInfo restricted_port_request;
8291 restricted_port_request.method = "GET";
8292 restricted_port_request.url = GURL("http://www.google.com:1023/");
8293 restricted_port_request.load_flags = 0;
8295 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8296 StaticSocketDataProvider first_data;
8297 first_data.set_connect_data(mock_connect);
8298 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8300 MockRead data_reads[] = {
8301 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8302 MockRead("hello world"),
8303 MockRead(ASYNC, OK),
8305 StaticSocketDataProvider second_data(
8306 data_reads, arraysize(data_reads), NULL, 0);
8307 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8309 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8311 base::WeakPtr<HttpServerProperties> http_server_properties =
8312 session->http_server_properties();
8313 const int kRestrictedAlternatePort = 80;
8314 http_server_properties->SetAlternateProtocol(
8315 HostPortPair::FromURL(restricted_port_request.url),
8316 kRestrictedAlternatePort,
8317 AlternateProtocolFromNextProto(GetParam()));
8319 scoped_ptr<HttpTransaction> trans(
8320 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8321 TestCompletionCallback callback;
8323 int rv = trans->Start(
8324 &restricted_port_request,
8325 callback.callback(), BoundNetLog());
8326 EXPECT_EQ(ERR_IO_PENDING, rv);
8327 // Valid change to restricted port should pass.
8328 EXPECT_EQ(OK, callback.WaitForResult());
8331 TEST_P(HttpNetworkTransactionTest,
8332 AlternateProtocolPortUnrestrictedAllowed1) {
8333 // Ensure that we're not allowed to redirect traffic via an alternate
8334 // protocol to an unrestricted (port >= 1024) when the original traffic was
8335 // on a restricted port (port < 1024). Ensure that we can redirect in all
8337 HttpStreamFactory::set_use_alternate_protocols(true);
8339 HttpRequestInfo unrestricted_port_request;
8340 unrestricted_port_request.method = "GET";
8341 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8342 unrestricted_port_request.load_flags = 0;
8344 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8345 StaticSocketDataProvider first_data;
8346 first_data.set_connect_data(mock_connect);
8347 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8349 MockRead data_reads[] = {
8350 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8351 MockRead("hello world"),
8352 MockRead(ASYNC, OK),
8354 StaticSocketDataProvider second_data(
8355 data_reads, arraysize(data_reads), NULL, 0);
8356 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8358 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8360 base::WeakPtr<HttpServerProperties> http_server_properties =
8361 session->http_server_properties();
8362 const int kRestrictedAlternatePort = 80;
8363 http_server_properties->SetAlternateProtocol(
8364 HostPortPair::FromURL(unrestricted_port_request.url),
8365 kRestrictedAlternatePort,
8366 AlternateProtocolFromNextProto(GetParam()));
8368 scoped_ptr<HttpTransaction> trans(
8369 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8370 TestCompletionCallback callback;
8372 int rv = trans->Start(
8373 &unrestricted_port_request, callback.callback(), BoundNetLog());
8374 EXPECT_EQ(ERR_IO_PENDING, rv);
8375 // Valid change to restricted port should pass.
8376 EXPECT_EQ(OK, callback.WaitForResult());
8379 TEST_P(HttpNetworkTransactionTest,
8380 AlternateProtocolPortUnrestrictedAllowed2) {
8381 // Ensure that we're not allowed to redirect traffic via an alternate
8382 // protocol to an unrestricted (port >= 1024) when the original traffic was
8383 // on a restricted port (port < 1024). Ensure that we can redirect in all
8385 HttpStreamFactory::set_use_alternate_protocols(true);
8387 HttpRequestInfo unrestricted_port_request;
8388 unrestricted_port_request.method = "GET";
8389 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
8390 unrestricted_port_request.load_flags = 0;
8392 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
8393 StaticSocketDataProvider first_data;
8394 first_data.set_connect_data(mock_connect);
8395 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
8397 MockRead data_reads[] = {
8398 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8399 MockRead("hello world"),
8400 MockRead(ASYNC, OK),
8402 StaticSocketDataProvider second_data(
8403 data_reads, arraysize(data_reads), NULL, 0);
8404 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
8406 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8408 base::WeakPtr<HttpServerProperties> http_server_properties =
8409 session->http_server_properties();
8410 const int kUnrestrictedAlternatePort = 1024;
8411 http_server_properties->SetAlternateProtocol(
8412 HostPortPair::FromURL(unrestricted_port_request.url),
8413 kUnrestrictedAlternatePort,
8414 AlternateProtocolFromNextProto(GetParam()));
8416 scoped_ptr<HttpTransaction> trans(
8417 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8418 TestCompletionCallback callback;
8420 int rv = trans->Start(
8421 &unrestricted_port_request, callback.callback(), BoundNetLog());
8422 EXPECT_EQ(ERR_IO_PENDING, rv);
8423 // Valid change to an unrestricted port should pass.
8424 EXPECT_EQ(OK, callback.WaitForResult());
8427 TEST_P(HttpNetworkTransactionTest,
8428 AlternateProtocolUnsafeBlocked) {
8429 // Ensure that we're not allowed to redirect traffic via an alternate
8430 // protocol to an unsafe port, and that we resume the second
8431 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8432 HttpStreamFactory::set_use_alternate_protocols(true);
8434 HttpRequestInfo request;
8435 request.method = "GET";
8436 request.url = GURL("http://www.google.com/");
8437 request.load_flags = 0;
8439 // The alternate protocol request will error out before we attempt to connect,
8440 // so only the standard HTTP request will try to connect.
8441 MockRead data_reads[] = {
8442 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8443 MockRead("hello world"),
8444 MockRead(ASYNC, OK),
8446 StaticSocketDataProvider data(
8447 data_reads, arraysize(data_reads), NULL, 0);
8448 session_deps_.socket_factory->AddSocketDataProvider(&data);
8450 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8452 base::WeakPtr<HttpServerProperties> http_server_properties =
8453 session->http_server_properties();
8454 const int kUnsafePort = 7;
8455 http_server_properties->SetAlternateProtocol(
8456 HostPortPair::FromURL(request.url),
8458 AlternateProtocolFromNextProto(GetParam()));
8460 scoped_ptr<HttpTransaction> trans(
8461 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8462 TestCompletionCallback callback;
8464 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8465 EXPECT_EQ(ERR_IO_PENDING, rv);
8466 // The HTTP request should succeed.
8467 EXPECT_EQ(OK, callback.WaitForResult());
8469 // Disable alternate protocol before the asserts.
8470 HttpStreamFactory::set_use_alternate_protocols(false);
8472 const HttpResponseInfo* response = trans->GetResponseInfo();
8473 ASSERT_TRUE(response != NULL);
8474 ASSERT_TRUE(response->headers.get() != NULL);
8475 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8477 std::string response_data;
8478 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8479 EXPECT_EQ("hello world", response_data);
8482 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
8483 HttpStreamFactory::set_use_alternate_protocols(true);
8484 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8486 HttpRequestInfo request;
8487 request.method = "GET";
8488 request.url = GURL("http://www.google.com/");
8489 request.load_flags = 0;
8491 std::string alternate_protocol_http_header =
8492 GetAlternateProtocolHttpHeader();
8494 MockRead data_reads[] = {
8495 MockRead("HTTP/1.1 200 OK\r\n"),
8496 MockRead(alternate_protocol_http_header.c_str()),
8497 MockRead("hello world"),
8498 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8502 StaticSocketDataProvider first_transaction(
8503 data_reads, arraysize(data_reads), NULL, 0);
8504 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8506 SSLSocketDataProvider ssl(ASYNC, OK);
8507 ssl.SetNextProto(GetParam());
8508 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8510 scoped_ptr<SpdyFrame> req(
8511 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8512 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8514 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8515 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8516 MockRead spdy_reads[] = {
8517 CreateMockRead(*resp),
8518 CreateMockRead(*data),
8519 MockRead(ASYNC, 0, 0),
8522 DelayedSocketData spdy_data(
8523 1, // wait for one write to finish before reading.
8524 spdy_reads, arraysize(spdy_reads),
8525 spdy_writes, arraysize(spdy_writes));
8526 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8528 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8529 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8531 hanging_non_alternate_protocol_socket.set_connect_data(
8532 never_finishing_connect);
8533 session_deps_.socket_factory->AddSocketDataProvider(
8534 &hanging_non_alternate_protocol_socket);
8536 TestCompletionCallback callback;
8538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8539 scoped_ptr<HttpTransaction> trans(
8540 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8542 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8543 EXPECT_EQ(ERR_IO_PENDING, rv);
8544 EXPECT_EQ(OK, callback.WaitForResult());
8546 const HttpResponseInfo* response = trans->GetResponseInfo();
8547 ASSERT_TRUE(response != NULL);
8548 ASSERT_TRUE(response->headers.get() != NULL);
8549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8551 std::string response_data;
8552 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8553 EXPECT_EQ("hello world", response_data);
8555 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8557 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8558 EXPECT_EQ(ERR_IO_PENDING, rv);
8559 EXPECT_EQ(OK, callback.WaitForResult());
8561 response = trans->GetResponseInfo();
8562 ASSERT_TRUE(response != NULL);
8563 ASSERT_TRUE(response->headers.get() != NULL);
8564 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8565 EXPECT_TRUE(response->was_fetched_via_spdy);
8566 EXPECT_TRUE(response->was_npn_negotiated);
8568 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8569 EXPECT_EQ("hello!", response_data);
8572 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
8573 HttpStreamFactory::set_use_alternate_protocols(true);
8574 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8576 HttpRequestInfo request;
8577 request.method = "GET";
8578 request.url = GURL("http://www.google.com/");
8579 request.load_flags = 0;
8581 std::string alternate_protocol_http_header =
8582 GetAlternateProtocolHttpHeader();
8584 MockRead data_reads[] = {
8585 MockRead("HTTP/1.1 200 OK\r\n"),
8586 MockRead(alternate_protocol_http_header.c_str()),
8587 MockRead("hello world"),
8588 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8589 MockRead(ASYNC, OK),
8592 StaticSocketDataProvider first_transaction(
8593 data_reads, arraysize(data_reads), NULL, 0);
8594 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8595 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8597 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8598 StaticSocketDataProvider hanging_socket(
8600 hanging_socket.set_connect_data(never_finishing_connect);
8601 // Socket 2 and 3 are the hanging Alternate-Protocol and
8602 // non-Alternate-Protocol jobs from the 2nd transaction.
8603 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8604 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8606 SSLSocketDataProvider ssl(ASYNC, OK);
8607 ssl.SetNextProto(GetParam());
8608 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8610 scoped_ptr<SpdyFrame> req1(
8611 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8612 scoped_ptr<SpdyFrame> req2(
8613 spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true));
8614 MockWrite spdy_writes[] = {
8615 CreateMockWrite(*req1),
8616 CreateMockWrite(*req2),
8618 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8619 scoped_ptr<SpdyFrame> data1(spdy_util_.ConstructSpdyBodyFrame(1, true));
8620 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
8621 scoped_ptr<SpdyFrame> data2(spdy_util_.ConstructSpdyBodyFrame(3, true));
8622 MockRead spdy_reads[] = {
8623 CreateMockRead(*resp1),
8624 CreateMockRead(*data1),
8625 CreateMockRead(*resp2),
8626 CreateMockRead(*data2),
8627 MockRead(ASYNC, 0, 0),
8630 DelayedSocketData spdy_data(
8631 2, // wait for writes to finish before reading.
8632 spdy_reads, arraysize(spdy_reads),
8633 spdy_writes, arraysize(spdy_writes));
8634 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8635 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8637 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8638 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket);
8640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8641 TestCompletionCallback callback1;
8642 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8644 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
8645 EXPECT_EQ(ERR_IO_PENDING, rv);
8646 EXPECT_EQ(OK, callback1.WaitForResult());
8648 const HttpResponseInfo* response = trans1.GetResponseInfo();
8649 ASSERT_TRUE(response != NULL);
8650 ASSERT_TRUE(response->headers.get() != NULL);
8651 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8653 std::string response_data;
8654 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8655 EXPECT_EQ("hello world", response_data);
8657 TestCompletionCallback callback2;
8658 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8659 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
8660 EXPECT_EQ(ERR_IO_PENDING, rv);
8662 TestCompletionCallback callback3;
8663 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
8664 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
8665 EXPECT_EQ(ERR_IO_PENDING, rv);
8667 EXPECT_EQ(OK, callback2.WaitForResult());
8668 EXPECT_EQ(OK, callback3.WaitForResult());
8670 response = trans2.GetResponseInfo();
8671 ASSERT_TRUE(response != NULL);
8672 ASSERT_TRUE(response->headers.get() != NULL);
8673 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8674 EXPECT_TRUE(response->was_fetched_via_spdy);
8675 EXPECT_TRUE(response->was_npn_negotiated);
8676 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8677 EXPECT_EQ("hello!", response_data);
8679 response = trans3.GetResponseInfo();
8680 ASSERT_TRUE(response != NULL);
8681 ASSERT_TRUE(response->headers.get() != NULL);
8682 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8683 EXPECT_TRUE(response->was_fetched_via_spdy);
8684 EXPECT_TRUE(response->was_npn_negotiated);
8685 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
8686 EXPECT_EQ("hello!", response_data);
8689 TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
8690 HttpStreamFactory::set_use_alternate_protocols(true);
8691 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8693 HttpRequestInfo request;
8694 request.method = "GET";
8695 request.url = GURL("http://www.google.com/");
8696 request.load_flags = 0;
8698 std::string alternate_protocol_http_header =
8699 GetAlternateProtocolHttpHeader();
8701 MockRead data_reads[] = {
8702 MockRead("HTTP/1.1 200 OK\r\n"),
8703 MockRead(alternate_protocol_http_header.c_str()),
8704 MockRead("hello world"),
8705 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8706 MockRead(ASYNC, OK),
8709 StaticSocketDataProvider first_transaction(
8710 data_reads, arraysize(data_reads), NULL, 0);
8711 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8713 SSLSocketDataProvider ssl(ASYNC, OK);
8714 ssl.SetNextProto(GetParam());
8715 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8717 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8718 StaticSocketDataProvider hanging_alternate_protocol_socket(
8720 hanging_alternate_protocol_socket.set_connect_data(
8721 never_finishing_connect);
8722 session_deps_.socket_factory->AddSocketDataProvider(
8723 &hanging_alternate_protocol_socket);
8725 // 2nd request is just a copy of the first one, over HTTP again.
8726 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8728 TestCompletionCallback callback;
8730 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8731 scoped_ptr<HttpTransaction> trans(
8732 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8734 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8735 EXPECT_EQ(ERR_IO_PENDING, rv);
8736 EXPECT_EQ(OK, callback.WaitForResult());
8738 const HttpResponseInfo* response = trans->GetResponseInfo();
8739 ASSERT_TRUE(response != NULL);
8740 ASSERT_TRUE(response->headers.get() != NULL);
8741 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8743 std::string response_data;
8744 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8745 EXPECT_EQ("hello world", response_data);
8747 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8749 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8750 EXPECT_EQ(ERR_IO_PENDING, rv);
8751 EXPECT_EQ(OK, callback.WaitForResult());
8753 response = trans->GetResponseInfo();
8754 ASSERT_TRUE(response != NULL);
8755 ASSERT_TRUE(response->headers.get() != NULL);
8756 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8757 EXPECT_FALSE(response->was_fetched_via_spdy);
8758 EXPECT_FALSE(response->was_npn_negotiated);
8760 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8761 EXPECT_EQ("hello world", response_data);
8764 class CapturingProxyResolver : public ProxyResolver {
8766 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8767 virtual ~CapturingProxyResolver() {}
8769 virtual int GetProxyForURL(const GURL& url,
8771 const CompletionCallback& callback,
8772 RequestHandle* request,
8773 const BoundNetLog& net_log) OVERRIDE {
8774 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
8775 HostPortPair("myproxy", 80));
8776 results->UseProxyServer(proxy_server);
8777 resolved_.push_back(url);
8781 virtual void CancelRequest(RequestHandle request) OVERRIDE {
8785 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
8787 return LOAD_STATE_IDLE;
8790 virtual void CancelSetPacScript() OVERRIDE {
8794 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
8795 const CompletionCallback& /*callback*/) OVERRIDE {
8799 const std::vector<GURL>& resolved() const { return resolved_; }
8802 std::vector<GURL> resolved_;
8804 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
8807 TEST_P(HttpNetworkTransactionTest,
8808 UseAlternateProtocolForTunneledNpnSpdy) {
8809 HttpStreamFactory::set_use_alternate_protocols(true);
8810 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8812 ProxyConfig proxy_config;
8813 proxy_config.set_auto_detect(true);
8814 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
8816 CapturingProxyResolver* capturing_proxy_resolver =
8817 new CapturingProxyResolver();
8818 session_deps_.proxy_service.reset(new ProxyService(
8819 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
8821 CapturingNetLog net_log;
8822 session_deps_.net_log = &net_log;
8824 HttpRequestInfo request;
8825 request.method = "GET";
8826 request.url = GURL("http://www.google.com/");
8827 request.load_flags = 0;
8829 std::string alternate_protocol_http_header =
8830 GetAlternateProtocolHttpHeader();
8832 MockRead data_reads[] = {
8833 MockRead("HTTP/1.1 200 OK\r\n"),
8834 MockRead(alternate_protocol_http_header.c_str()),
8835 MockRead("hello world"),
8836 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8837 MockRead(ASYNC, OK),
8840 StaticSocketDataProvider first_transaction(
8841 data_reads, arraysize(data_reads), NULL, 0);
8842 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8844 SSLSocketDataProvider ssl(ASYNC, OK);
8845 ssl.SetNextProto(GetParam());
8846 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8848 scoped_ptr<SpdyFrame> req(
8849 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8850 MockWrite spdy_writes[] = {
8851 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8852 "Host: www.google.com\r\n"
8853 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
8854 CreateMockWrite(*req), // 3
8857 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8859 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8860 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8861 MockRead spdy_reads[] = {
8862 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
8863 CreateMockRead(*resp.get(), 4), // 2, 4
8864 CreateMockRead(*data.get(), 4), // 5
8865 MockRead(ASYNC, 0, 0, 4), // 6
8868 OrderedSocketData spdy_data(
8869 spdy_reads, arraysize(spdy_reads),
8870 spdy_writes, arraysize(spdy_writes));
8871 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8873 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
8874 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8876 hanging_non_alternate_protocol_socket.set_connect_data(
8877 never_finishing_connect);
8878 session_deps_.socket_factory->AddSocketDataProvider(
8879 &hanging_non_alternate_protocol_socket);
8881 TestCompletionCallback callback;
8883 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8884 scoped_ptr<HttpTransaction> trans(
8885 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8887 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8888 EXPECT_EQ(ERR_IO_PENDING, rv);
8889 EXPECT_EQ(OK, callback.WaitForResult());
8891 const HttpResponseInfo* response = trans->GetResponseInfo();
8892 ASSERT_TRUE(response != NULL);
8893 ASSERT_TRUE(response->headers.get() != NULL);
8894 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8895 EXPECT_FALSE(response->was_fetched_via_spdy);
8896 EXPECT_FALSE(response->was_npn_negotiated);
8898 std::string response_data;
8899 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8900 EXPECT_EQ("hello world", response_data);
8902 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8904 rv = trans->Start(&request, callback.callback(), BoundNetLog());
8905 EXPECT_EQ(ERR_IO_PENDING, rv);
8906 EXPECT_EQ(OK, callback.WaitForResult());
8908 response = trans->GetResponseInfo();
8909 ASSERT_TRUE(response != NULL);
8910 ASSERT_TRUE(response->headers.get() != NULL);
8911 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8912 EXPECT_TRUE(response->was_fetched_via_spdy);
8913 EXPECT_TRUE(response->was_npn_negotiated);
8915 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8916 EXPECT_EQ("hello!", response_data);
8917 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
8918 EXPECT_EQ("http://www.google.com/",
8919 capturing_proxy_resolver->resolved()[0].spec());
8920 EXPECT_EQ("https://www.google.com/",
8921 capturing_proxy_resolver->resolved()[1].spec());
8923 LoadTimingInfo load_timing_info;
8924 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
8925 TestLoadTimingNotReusedWithPac(load_timing_info,
8926 CONNECT_TIMING_HAS_SSL_TIMES);
8929 TEST_P(HttpNetworkTransactionTest,
8930 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
8931 HttpStreamFactory::set_use_alternate_protocols(true);
8932 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8934 HttpRequestInfo request;
8935 request.method = "GET";
8936 request.url = GURL("http://www.google.com/");
8937 request.load_flags = 0;
8939 std::string alternate_protocol_http_header =
8940 GetAlternateProtocolHttpHeader();
8942 MockRead data_reads[] = {
8943 MockRead("HTTP/1.1 200 OK\r\n"),
8944 MockRead(alternate_protocol_http_header.c_str()),
8945 MockRead("hello world"),
8946 MockRead(ASYNC, OK),
8949 StaticSocketDataProvider first_transaction(
8950 data_reads, arraysize(data_reads), NULL, 0);
8951 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
8953 SSLSocketDataProvider ssl(ASYNC, OK);
8954 ssl.SetNextProto(GetParam());
8955 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8957 scoped_ptr<SpdyFrame> req(
8958 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
8959 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8961 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
8962 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
8963 MockRead spdy_reads[] = {
8964 CreateMockRead(*resp),
8965 CreateMockRead(*data),
8966 MockRead(ASYNC, 0, 0),
8969 DelayedSocketData spdy_data(
8970 1, // wait for one write to finish before reading.
8971 spdy_reads, arraysize(spdy_reads),
8972 spdy_writes, arraysize(spdy_writes));
8973 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8975 TestCompletionCallback callback;
8977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8979 scoped_ptr<HttpTransaction> trans(
8980 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
8982 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
8983 EXPECT_EQ(ERR_IO_PENDING, rv);
8984 EXPECT_EQ(OK, callback.WaitForResult());
8986 const HttpResponseInfo* response = trans->GetResponseInfo();
8987 ASSERT_TRUE(response != NULL);
8988 ASSERT_TRUE(response->headers.get() != NULL);
8989 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8991 std::string response_data;
8992 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8993 EXPECT_EQ("hello world", response_data);
8995 // Set up an initial SpdySession in the pool to reuse.
8996 HostPortPair host_port_pair("www.google.com", 443);
8997 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
8998 kPrivacyModeDisabled);
8999 base::WeakPtr<SpdySession> spdy_session =
9000 CreateSecureSpdySession(session, key, BoundNetLog());
9002 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9004 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9005 EXPECT_EQ(ERR_IO_PENDING, rv);
9006 EXPECT_EQ(OK, callback.WaitForResult());
9008 response = trans->GetResponseInfo();
9009 ASSERT_TRUE(response != NULL);
9010 ASSERT_TRUE(response->headers.get() != NULL);
9011 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9012 EXPECT_TRUE(response->was_fetched_via_spdy);
9013 EXPECT_TRUE(response->was_npn_negotiated);
9015 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9016 EXPECT_EQ("hello!", response_data);
9019 // GenerateAuthToken is a mighty big test.
9020 // It tests all permutation of GenerateAuthToken behavior:
9021 // - Synchronous and Asynchronous completion.
9022 // - OK or error on completion.
9023 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9024 // - HTTP or HTTPS backend (to include proxy tunneling).
9025 // - Non-authenticating and authenticating backend.
9027 // In all, there are 44 reasonable permuations (for example, if there are
9028 // problems generating an auth token for an authenticating proxy, we don't
9029 // need to test all permutations of the backend server).
9031 // The test proceeds by going over each of the configuration cases, and
9032 // potentially running up to three rounds in each of the tests. The TestConfig
9033 // specifies both the configuration for the test as well as the expectations
9035 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
9036 static const char kServer[] = "http://www.example.com";
9037 static const char kSecureServer[] = "https://www.example.com";
9038 static const char kProxy[] = "myproxy:70";
9039 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
9047 const MockWrite kGet(
9048 "GET / HTTP/1.1\r\n"
9049 "Host: www.example.com\r\n"
9050 "Connection: keep-alive\r\n\r\n");
9051 const MockWrite kGetProxy(
9052 "GET http://www.example.com/ HTTP/1.1\r\n"
9053 "Host: www.example.com\r\n"
9054 "Proxy-Connection: keep-alive\r\n\r\n");
9055 const MockWrite kGetAuth(
9056 "GET / HTTP/1.1\r\n"
9057 "Host: www.example.com\r\n"
9058 "Connection: keep-alive\r\n"
9059 "Authorization: auth_token\r\n\r\n");
9060 const MockWrite kGetProxyAuth(
9061 "GET http://www.example.com/ HTTP/1.1\r\n"
9062 "Host: www.example.com\r\n"
9063 "Proxy-Connection: keep-alive\r\n"
9064 "Proxy-Authorization: auth_token\r\n\r\n");
9065 const MockWrite kGetAuthThroughProxy(
9066 "GET http://www.example.com/ HTTP/1.1\r\n"
9067 "Host: www.example.com\r\n"
9068 "Proxy-Connection: keep-alive\r\n"
9069 "Authorization: auth_token\r\n\r\n");
9070 const MockWrite kGetAuthWithProxyAuth(
9071 "GET http://www.example.com/ HTTP/1.1\r\n"
9072 "Host: www.example.com\r\n"
9073 "Proxy-Connection: keep-alive\r\n"
9074 "Proxy-Authorization: auth_token\r\n"
9075 "Authorization: auth_token\r\n\r\n");
9076 const MockWrite kConnect(
9077 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9078 "Host: www.example.com\r\n"
9079 "Proxy-Connection: keep-alive\r\n\r\n");
9080 const MockWrite kConnectProxyAuth(
9081 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9082 "Host: www.example.com\r\n"
9083 "Proxy-Connection: keep-alive\r\n"
9084 "Proxy-Authorization: auth_token\r\n\r\n");
9086 const MockRead kSuccess(
9087 "HTTP/1.1 200 OK\r\n"
9088 "Content-Type: text/html; charset=iso-8859-1\r\n"
9089 "Content-Length: 3\r\n\r\n"
9091 const MockRead kFailure(
9092 "Should not be called.");
9093 const MockRead kServerChallenge(
9094 "HTTP/1.1 401 Unauthorized\r\n"
9095 "WWW-Authenticate: Mock realm=server\r\n"
9096 "Content-Type: text/html; charset=iso-8859-1\r\n"
9097 "Content-Length: 14\r\n\r\n"
9098 "Unauthorized\r\n");
9099 const MockRead kProxyChallenge(
9100 "HTTP/1.1 407 Unauthorized\r\n"
9101 "Proxy-Authenticate: Mock realm=proxy\r\n"
9102 "Proxy-Connection: close\r\n"
9103 "Content-Type: text/html; charset=iso-8859-1\r\n"
9104 "Content-Length: 14\r\n\r\n"
9105 "Unauthorized\r\n");
9106 const MockRead kProxyConnected(
9107 "HTTP/1.1 200 Connection Established\r\n\r\n");
9109 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9110 // no constructors, but the C++ compiler on Windows warns about
9111 // unspecified data in compound literals. So, moved to using constructors,
9112 // and TestRound's created with the default constructor should not be used.
9115 : expected_rv(ERR_UNEXPECTED),
9119 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9120 int expected_rv_arg)
9123 expected_rv(expected_rv_arg),
9127 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
9128 int expected_rv_arg, const MockWrite* extra_write_arg,
9129 const MockRead* extra_read_arg)
9132 expected_rv(expected_rv_arg),
9133 extra_write(extra_write_arg),
9134 extra_read(extra_read_arg) {
9139 const MockWrite* extra_write;
9140 const MockRead* extra_read;
9143 static const int kNoSSL = 500;
9146 const char* proxy_url;
9147 AuthTiming proxy_auth_timing;
9149 const char* server_url;
9150 AuthTiming server_auth_timing;
9152 int num_auth_rounds;
9153 int first_ssl_round;
9154 TestRound rounds[3];
9155 } test_configs[] = {
9156 // Non-authenticating HTTP server with a direct connection.
9157 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9158 { TestRound(kGet, kSuccess, OK)}},
9159 // Authenticating HTTP server with a direct connection.
9160 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9161 { TestRound(kGet, kServerChallenge, OK),
9162 TestRound(kGetAuth, kSuccess, OK)}},
9163 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9164 { TestRound(kGet, kServerChallenge, OK),
9165 TestRound(kGetAuth, kFailure, kAuthErr)}},
9166 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9167 { TestRound(kGet, kServerChallenge, OK),
9168 TestRound(kGetAuth, kSuccess, OK)}},
9169 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9170 { TestRound(kGet, kServerChallenge, OK),
9171 TestRound(kGetAuth, kFailure, kAuthErr)}},
9172 // Non-authenticating HTTP server through a non-authenticating proxy.
9173 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
9174 { TestRound(kGetProxy, kSuccess, OK)}},
9175 // Authenticating HTTP server through a non-authenticating proxy.
9176 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
9177 { TestRound(kGetProxy, kServerChallenge, OK),
9178 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9179 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
9180 { TestRound(kGetProxy, kServerChallenge, OK),
9181 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9182 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
9183 { TestRound(kGetProxy, kServerChallenge, OK),
9184 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
9185 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
9186 { TestRound(kGetProxy, kServerChallenge, OK),
9187 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
9188 // Non-authenticating HTTP server through an authenticating proxy.
9189 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9190 { TestRound(kGetProxy, kProxyChallenge, OK),
9191 TestRound(kGetProxyAuth, kSuccess, OK)}},
9192 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9193 { TestRound(kGetProxy, kProxyChallenge, OK),
9194 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9195 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
9196 { TestRound(kGetProxy, kProxyChallenge, OK),
9197 TestRound(kGetProxyAuth, kSuccess, OK)}},
9198 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
9199 { TestRound(kGetProxy, kProxyChallenge, OK),
9200 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
9201 // Authenticating HTTP server through an authenticating proxy.
9202 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9203 { TestRound(kGetProxy, kProxyChallenge, OK),
9204 TestRound(kGetProxyAuth, kServerChallenge, OK),
9205 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9206 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9207 { TestRound(kGetProxy, kProxyChallenge, OK),
9208 TestRound(kGetProxyAuth, kServerChallenge, OK),
9209 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9210 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
9211 { TestRound(kGetProxy, kProxyChallenge, OK),
9212 TestRound(kGetProxyAuth, kServerChallenge, OK),
9213 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9214 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
9215 { TestRound(kGetProxy, kProxyChallenge, OK),
9216 TestRound(kGetProxyAuth, kServerChallenge, OK),
9217 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9218 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9219 { TestRound(kGetProxy, kProxyChallenge, OK),
9220 TestRound(kGetProxyAuth, kServerChallenge, OK),
9221 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9222 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9223 { TestRound(kGetProxy, kProxyChallenge, OK),
9224 TestRound(kGetProxyAuth, kServerChallenge, OK),
9225 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9226 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
9227 { TestRound(kGetProxy, kProxyChallenge, OK),
9228 TestRound(kGetProxyAuth, kServerChallenge, OK),
9229 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
9230 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
9231 { TestRound(kGetProxy, kProxyChallenge, OK),
9232 TestRound(kGetProxyAuth, kServerChallenge, OK),
9233 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
9234 // Non-authenticating HTTPS server with a direct connection.
9235 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9236 { TestRound(kGet, kSuccess, OK)}},
9237 // Authenticating HTTPS server with a direct connection.
9238 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9239 { TestRound(kGet, kServerChallenge, OK),
9240 TestRound(kGetAuth, kSuccess, OK)}},
9241 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9242 { TestRound(kGet, kServerChallenge, OK),
9243 TestRound(kGetAuth, kFailure, kAuthErr)}},
9244 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9245 { TestRound(kGet, kServerChallenge, OK),
9246 TestRound(kGetAuth, kSuccess, OK)}},
9247 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9248 { TestRound(kGet, kServerChallenge, OK),
9249 TestRound(kGetAuth, kFailure, kAuthErr)}},
9250 // Non-authenticating HTTPS server with a non-authenticating proxy.
9251 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
9252 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
9253 // Authenticating HTTPS server through a non-authenticating proxy.
9254 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
9255 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9256 TestRound(kGetAuth, kSuccess, OK)}},
9257 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
9258 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9259 TestRound(kGetAuth, kFailure, kAuthErr)}},
9260 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
9261 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9262 TestRound(kGetAuth, kSuccess, OK)}},
9263 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
9264 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
9265 TestRound(kGetAuth, kFailure, kAuthErr)}},
9266 // Non-Authenticating HTTPS server through an authenticating proxy.
9267 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9268 { TestRound(kConnect, kProxyChallenge, OK),
9269 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9270 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9271 { TestRound(kConnect, kProxyChallenge, OK),
9272 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9273 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
9274 { TestRound(kConnect, kProxyChallenge, OK),
9275 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
9276 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
9277 { TestRound(kConnect, kProxyChallenge, OK),
9278 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
9279 // Authenticating HTTPS server through an authenticating proxy.
9280 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9281 { TestRound(kConnect, kProxyChallenge, OK),
9282 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9283 &kGet, &kServerChallenge),
9284 TestRound(kGetAuth, kSuccess, OK)}},
9285 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9286 { TestRound(kConnect, kProxyChallenge, OK),
9287 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9288 &kGet, &kServerChallenge),
9289 TestRound(kGetAuth, kFailure, kAuthErr)}},
9290 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
9291 { TestRound(kConnect, kProxyChallenge, OK),
9292 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9293 &kGet, &kServerChallenge),
9294 TestRound(kGetAuth, kSuccess, OK)}},
9295 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
9296 { TestRound(kConnect, kProxyChallenge, OK),
9297 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9298 &kGet, &kServerChallenge),
9299 TestRound(kGetAuth, kFailure, kAuthErr)}},
9300 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9301 { TestRound(kConnect, kProxyChallenge, OK),
9302 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9303 &kGet, &kServerChallenge),
9304 TestRound(kGetAuth, kSuccess, OK)}},
9305 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9306 { TestRound(kConnect, kProxyChallenge, OK),
9307 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9308 &kGet, &kServerChallenge),
9309 TestRound(kGetAuth, kFailure, kAuthErr)}},
9310 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
9311 { TestRound(kConnect, kProxyChallenge, OK),
9312 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9313 &kGet, &kServerChallenge),
9314 TestRound(kGetAuth, kSuccess, OK)}},
9315 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
9316 { TestRound(kConnect, kProxyChallenge, OK),
9317 TestRound(kConnectProxyAuth, kProxyConnected, OK,
9318 &kGet, &kServerChallenge),
9319 TestRound(kGetAuth, kFailure, kAuthErr)}},
9322 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
9323 HttpAuthHandlerMock::Factory* auth_factory(
9324 new HttpAuthHandlerMock::Factory());
9325 session_deps_.http_auth_handler_factory.reset(auth_factory);
9326 const TestConfig& test_config = test_configs[i];
9328 // Set up authentication handlers as necessary.
9329 if (test_config.proxy_auth_timing != AUTH_NONE) {
9330 for (int n = 0; n < 2; n++) {
9331 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9332 std::string auth_challenge = "Mock realm=proxy";
9333 GURL origin(test_config.proxy_url);
9334 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9335 auth_challenge.end());
9336 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
9337 origin, BoundNetLog());
9338 auth_handler->SetGenerateExpectation(
9339 test_config.proxy_auth_timing == AUTH_ASYNC,
9340 test_config.proxy_auth_rv);
9341 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9344 if (test_config.server_auth_timing != AUTH_NONE) {
9345 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9346 std::string auth_challenge = "Mock realm=server";
9347 GURL origin(test_config.server_url);
9348 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9349 auth_challenge.end());
9350 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9351 origin, BoundNetLog());
9352 auth_handler->SetGenerateExpectation(
9353 test_config.server_auth_timing == AUTH_ASYNC,
9354 test_config.server_auth_rv);
9355 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9357 if (test_config.proxy_url) {
9358 session_deps_.proxy_service.reset(
9359 ProxyService::CreateFixed(test_config.proxy_url));
9361 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9364 HttpRequestInfo request;
9365 request.method = "GET";
9366 request.url = GURL(test_config.server_url);
9367 request.load_flags = 0;
9369 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9370 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
9372 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
9373 const TestRound& read_write_round = test_config.rounds[round];
9375 // Set up expected reads and writes.
9377 reads[0] = read_write_round.read;
9378 size_t length_reads = 1;
9379 if (read_write_round.extra_read) {
9380 reads[1] = *read_write_round.extra_read;
9384 MockWrite writes[2];
9385 writes[0] = read_write_round.write;
9386 size_t length_writes = 1;
9387 if (read_write_round.extra_write) {
9388 writes[1] = *read_write_round.extra_write;
9391 StaticSocketDataProvider data_provider(
9392 reads, length_reads, writes, length_writes);
9393 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9395 // Add an SSL sequence if necessary.
9396 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
9397 if (round >= test_config.first_ssl_round)
9398 session_deps_.socket_factory->AddSSLSocketDataProvider(
9399 &ssl_socket_data_provider);
9401 // Start or restart the transaction.
9402 TestCompletionCallback callback;
9405 rv = trans.Start(&request, callback.callback(), BoundNetLog());
9407 rv = trans.RestartWithAuth(
9408 AuthCredentials(kFoo, kBar), callback.callback());
9410 if (rv == ERR_IO_PENDING)
9411 rv = callback.WaitForResult();
9413 // Compare results with expected data.
9414 EXPECT_EQ(read_write_round.expected_rv, rv);
9415 const HttpResponseInfo* response = trans.GetResponseInfo();
9416 if (read_write_round.expected_rv == OK) {
9417 ASSERT_TRUE(response != NULL);
9419 EXPECT_TRUE(response == NULL);
9420 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
9423 if (round + 1 < test_config.num_auth_rounds) {
9424 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9426 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9432 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
9433 // Do multi-round authentication and make sure it works correctly.
9434 HttpAuthHandlerMock::Factory* auth_factory(
9435 new HttpAuthHandlerMock::Factory());
9436 session_deps_.http_auth_handler_factory.reset(auth_factory);
9437 session_deps_.proxy_service.reset(ProxyService::CreateDirect());
9438 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
9439 session_deps_.host_resolver->set_synchronous_mode(true);
9441 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
9442 auth_handler->set_connection_based(true);
9443 std::string auth_challenge = "Mock realm=server";
9444 GURL origin("http://www.example.com");
9445 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
9446 auth_challenge.end());
9447 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
9448 origin, BoundNetLog());
9449 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
9452 const HttpResponseInfo* response = NULL;
9453 HttpRequestInfo request;
9454 request.method = "GET";
9455 request.url = origin;
9456 request.load_flags = 0;
9458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9460 // Use a TCP Socket Pool with only one connection per group. This is used
9461 // to validate that the TCP socket is not released to the pool between
9462 // each round of multi-round authentication.
9463 HttpNetworkSessionPeer session_peer(session);
9464 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
9465 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
9466 50, // Max sockets for pool
9467 1, // Max sockets per group
9468 &transport_pool_histograms,
9469 session_deps_.host_resolver.get(),
9470 session_deps_.socket_factory.get(),
9471 session_deps_.net_log);
9472 MockClientSocketPoolManager* mock_pool_manager =
9473 new MockClientSocketPoolManager;
9474 mock_pool_manager->SetTransportSocketPool(transport_pool);
9475 session_peer.SetClientSocketPoolManager(mock_pool_manager);
9477 scoped_ptr<HttpTransaction> trans(
9478 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9479 TestCompletionCallback callback;
9481 const MockWrite kGet(
9482 "GET / HTTP/1.1\r\n"
9483 "Host: www.example.com\r\n"
9484 "Connection: keep-alive\r\n\r\n");
9485 const MockWrite kGetAuth(
9486 "GET / HTTP/1.1\r\n"
9487 "Host: www.example.com\r\n"
9488 "Connection: keep-alive\r\n"
9489 "Authorization: auth_token\r\n\r\n");
9491 const MockRead kServerChallenge(
9492 "HTTP/1.1 401 Unauthorized\r\n"
9493 "WWW-Authenticate: Mock realm=server\r\n"
9494 "Content-Type: text/html; charset=iso-8859-1\r\n"
9495 "Content-Length: 14\r\n\r\n"
9496 "Unauthorized\r\n");
9497 const MockRead kSuccess(
9498 "HTTP/1.1 200 OK\r\n"
9499 "Content-Type: text/html; charset=iso-8859-1\r\n"
9500 "Content-Length: 3\r\n\r\n"
9503 MockWrite writes[] = {
9512 // Competing request
9515 MockRead reads[] = {
9524 // Competing response
9527 StaticSocketDataProvider data_provider(reads, arraysize(reads),
9528 writes, arraysize(writes));
9529 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
9531 const char* const kSocketGroup = "www.example.com:80";
9533 // First round of authentication.
9534 auth_handler->SetGenerateExpectation(false, OK);
9535 rv = trans->Start(&request, callback.callback(), BoundNetLog());
9536 if (rv == ERR_IO_PENDING)
9537 rv = callback.WaitForResult();
9539 response = trans->GetResponseInfo();
9540 ASSERT_TRUE(response != NULL);
9541 EXPECT_FALSE(response->auth_challenge.get() == NULL);
9542 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9544 // In between rounds, another request comes in for the same domain.
9545 // It should not be able to grab the TCP socket that trans has already
9547 scoped_ptr<HttpTransaction> trans_compete(
9548 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9549 TestCompletionCallback callback_compete;
9550 rv = trans_compete->Start(
9551 &request, callback_compete.callback(), BoundNetLog());
9552 EXPECT_EQ(ERR_IO_PENDING, rv);
9553 // callback_compete.WaitForResult at this point would stall forever,
9554 // since the HttpNetworkTransaction does not release the request back to
9555 // the pool until after authentication completes.
9557 // Second round of authentication.
9558 auth_handler->SetGenerateExpectation(false, OK);
9559 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9560 if (rv == ERR_IO_PENDING)
9561 rv = callback.WaitForResult();
9563 response = trans->GetResponseInfo();
9564 ASSERT_TRUE(response != NULL);
9565 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9566 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9568 // Third round of authentication.
9569 auth_handler->SetGenerateExpectation(false, OK);
9570 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9571 if (rv == ERR_IO_PENDING)
9572 rv = callback.WaitForResult();
9574 response = trans->GetResponseInfo();
9575 ASSERT_TRUE(response != NULL);
9576 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9577 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9579 // Fourth round of authentication, which completes successfully.
9580 auth_handler->SetGenerateExpectation(false, OK);
9581 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
9582 if (rv == ERR_IO_PENDING)
9583 rv = callback.WaitForResult();
9585 response = trans->GetResponseInfo();
9586 ASSERT_TRUE(response != NULL);
9587 EXPECT_TRUE(response->auth_challenge.get() == NULL);
9588 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9590 // Read the body since the fourth round was successful. This will also
9591 // release the socket back to the pool.
9592 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
9593 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9594 if (rv == ERR_IO_PENDING)
9595 rv = callback.WaitForResult();
9597 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
9599 // There are still 0 idle sockets, since the trans_compete transaction
9600 // will be handed it immediately after trans releases it to the group.
9601 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9603 // The competing request can now finish. Wait for the headers and then
9605 rv = callback_compete.WaitForResult();
9607 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9608 if (rv == ERR_IO_PENDING)
9609 rv = callback.WaitForResult();
9611 rv = trans_compete->Read(io_buf.get(), io_buf->size(), callback.callback());
9614 // Finally, the socket is released to the group.
9615 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
9618 // This tests the case that a request is issued via http instead of spdy after
9619 // npn is negotiated.
9620 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
9621 HttpStreamFactory::set_use_alternate_protocols(true);
9622 std::vector<NextProto> next_protos;
9623 next_protos.push_back(kProtoHTTP11);
9624 HttpStreamFactory::SetNextProtos(next_protos);
9625 HttpRequestInfo request;
9626 request.method = "GET";
9627 request.url = GURL("https://www.google.com/");
9628 request.load_flags = 0;
9630 MockWrite data_writes[] = {
9631 MockWrite("GET / HTTP/1.1\r\n"
9632 "Host: www.google.com\r\n"
9633 "Connection: keep-alive\r\n\r\n"),
9636 std::string alternate_protocol_http_header =
9637 GetAlternateProtocolHttpHeader();
9639 MockRead data_reads[] = {
9640 MockRead("HTTP/1.1 200 OK\r\n"),
9641 MockRead(alternate_protocol_http_header.c_str()),
9642 MockRead("hello world"),
9643 MockRead(SYNCHRONOUS, OK),
9646 SSLSocketDataProvider ssl(ASYNC, OK);
9647 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9648 ssl.next_proto = "http/1.1";
9649 ssl.protocol_negotiated = kProtoHTTP11;
9651 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9653 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
9654 data_writes, arraysize(data_writes));
9655 session_deps_.socket_factory->AddSocketDataProvider(&data);
9657 TestCompletionCallback callback;
9659 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9660 scoped_ptr<HttpTransaction> trans(
9661 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9663 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9665 EXPECT_EQ(ERR_IO_PENDING, rv);
9666 EXPECT_EQ(OK, callback.WaitForResult());
9668 const HttpResponseInfo* response = trans->GetResponseInfo();
9669 ASSERT_TRUE(response != NULL);
9670 ASSERT_TRUE(response->headers.get() != NULL);
9671 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9673 std::string response_data;
9674 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
9675 EXPECT_EQ("hello world", response_data);
9677 EXPECT_FALSE(response->was_fetched_via_spdy);
9678 EXPECT_TRUE(response->was_npn_negotiated);
9681 TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
9682 // Simulate the SSL handshake completing with an NPN negotiation
9683 // followed by an immediate server closing of the socket.
9684 // Fix crash: http://crbug.com/46369
9685 HttpStreamFactory::set_use_alternate_protocols(true);
9686 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9688 HttpRequestInfo request;
9689 request.method = "GET";
9690 request.url = GURL("https://www.google.com/");
9691 request.load_flags = 0;
9693 SSLSocketDataProvider ssl(ASYNC, OK);
9694 ssl.SetNextProto(GetParam());
9695 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9697 scoped_ptr<SpdyFrame> req(
9698 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9699 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
9701 MockRead spdy_reads[] = {
9702 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
9705 DelayedSocketData spdy_data(
9706 0, // don't wait in this case, immediate hangup.
9707 spdy_reads, arraysize(spdy_reads),
9708 spdy_writes, arraysize(spdy_writes));
9709 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9711 TestCompletionCallback callback;
9713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9714 scoped_ptr<HttpTransaction> trans(
9715 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9717 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
9718 EXPECT_EQ(ERR_IO_PENDING, rv);
9719 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
9722 // A subclass of HttpAuthHandlerMock that records the request URL when
9723 // it gets it. This is needed since the auth handler may get destroyed
9724 // before we get a chance to query it.
9725 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
9727 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
9729 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9732 virtual int GenerateAuthTokenImpl(const AuthCredentials* credentials,
9733 const HttpRequestInfo* request,
9734 const CompletionCallback& callback,
9735 std::string* auth_token) OVERRIDE {
9736 *url_ = request->url;
9737 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9738 credentials, request, callback, auth_token);
9745 TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
9746 // This test ensures that the URL passed into the proxy is upgraded
9747 // to https when doing an Alternate Protocol upgrade.
9748 HttpStreamFactory::set_use_alternate_protocols(true);
9749 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9751 session_deps_.proxy_service.reset(
9752 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9753 CapturingNetLog net_log;
9754 session_deps_.net_log = &net_log;
9757 HttpAuthHandlerMock::Factory* auth_factory =
9758 new HttpAuthHandlerMock::Factory();
9759 UrlRecordingHttpAuthHandlerMock* auth_handler =
9760 new UrlRecordingHttpAuthHandlerMock(&request_url);
9761 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
9762 auth_factory->set_do_init_from_challenge(true);
9763 session_deps_.http_auth_handler_factory.reset(auth_factory);
9766 HttpRequestInfo request;
9767 request.method = "GET";
9768 request.url = GURL("http://www.google.com");
9769 request.load_flags = 0;
9771 // First round goes unauthenticated through the proxy.
9772 MockWrite data_writes_1[] = {
9773 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9774 "Host: www.google.com\r\n"
9775 "Proxy-Connection: keep-alive\r\n"
9778 MockRead data_reads_1[] = {
9779 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
9780 MockRead("HTTP/1.1 200 OK\r\n"
9781 "Alternate-Protocol: 443:npn-spdy/2\r\n"
9782 "Proxy-Connection: close\r\n"
9785 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
9786 data_writes_1, arraysize(data_writes_1));
9788 // Second round tries to tunnel to www.google.com due to the
9789 // Alternate-Protocol announcement in the first round. It fails due
9790 // to a proxy authentication challenge.
9791 // After the failure, a tunnel is established to www.google.com using
9792 // Proxy-Authorization headers. There is then a SPDY request round.
9794 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
9795 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
9796 // does a Disconnect and Connect on the same socket, rather than trying
9797 // to obtain a new one.
9799 // NOTE: Originally, the proxy response to the second CONNECT request
9800 // simply returned another 407 so the unit test could skip the SSL connection
9801 // establishment and SPDY framing issues. Alas, the
9802 // retry-http-when-alternate-protocol fails logic kicks in, which was more
9803 // complicated to set up expectations for than the SPDY session.
9805 scoped_ptr<SpdyFrame> req(
9806 spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
9807 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
9808 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
9810 MockWrite data_writes_2[] = {
9811 // First connection attempt without Proxy-Authorization.
9812 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9813 "Host: www.google.com\r\n"
9814 "Proxy-Connection: keep-alive\r\n"
9817 // Second connection attempt with Proxy-Authorization.
9818 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9819 "Host: www.google.com\r\n"
9820 "Proxy-Connection: keep-alive\r\n"
9821 "Proxy-Authorization: auth_token\r\n"
9825 CreateMockWrite(*req),
9827 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
9828 "Proxy-Authenticate: Mock\r\n"
9829 "Proxy-Connection: close\r\n"
9831 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
9832 MockRead data_reads_2[] = {
9833 // First connection attempt fails
9834 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
9835 MockRead(ASYNC, kRejectConnectResponse,
9836 arraysize(kRejectConnectResponse) - 1, 1),
9838 // Second connection attempt passes
9839 MockRead(ASYNC, kAcceptConnectResponse,
9840 arraysize(kAcceptConnectResponse) -1, 4),
9843 CreateMockRead(*resp.get(), 6),
9844 CreateMockRead(*data.get(), 6),
9845 MockRead(ASYNC, 0, 0, 6),
9847 OrderedSocketData data_2(
9848 data_reads_2, arraysize(data_reads_2),
9849 data_writes_2, arraysize(data_writes_2));
9851 SSLSocketDataProvider ssl(ASYNC, OK);
9852 ssl.SetNextProto(GetParam());
9854 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
9855 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
9857 hanging_non_alternate_protocol_socket.set_connect_data(
9858 never_finishing_connect);
9860 session_deps_.socket_factory->AddSocketDataProvider(&data_1);
9861 session_deps_.socket_factory->AddSocketDataProvider(&data_2);
9862 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9863 session_deps_.socket_factory->AddSocketDataProvider(
9864 &hanging_non_alternate_protocol_socket);
9865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9867 // First round should work and provide the Alternate-Protocol state.
9868 TestCompletionCallback callback_1;
9869 scoped_ptr<HttpTransaction> trans_1(
9870 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9871 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
9872 EXPECT_EQ(ERR_IO_PENDING, rv);
9873 EXPECT_EQ(OK, callback_1.WaitForResult());
9875 // Second round should attempt a tunnel connect and get an auth challenge.
9876 TestCompletionCallback callback_2;
9877 scoped_ptr<HttpTransaction> trans_2(
9878 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9879 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
9880 EXPECT_EQ(ERR_IO_PENDING, rv);
9881 EXPECT_EQ(OK, callback_2.WaitForResult());
9882 const HttpResponseInfo* response = trans_2->GetResponseInfo();
9883 ASSERT_TRUE(response != NULL);
9884 ASSERT_FALSE(response->auth_challenge.get() == NULL);
9886 // Restart with auth. Tunnel should work and response received.
9887 TestCompletionCallback callback_3;
9888 rv = trans_2->RestartWithAuth(
9889 AuthCredentials(kFoo, kBar), callback_3.callback());
9890 EXPECT_EQ(ERR_IO_PENDING, rv);
9891 EXPECT_EQ(OK, callback_3.WaitForResult());
9893 // After all that work, these two lines (or actually, just the scheme) are
9894 // what this test is all about. Make sure it happens correctly.
9895 EXPECT_EQ("https", request_url.scheme());
9896 EXPECT_EQ("www.google.com", request_url.host());
9898 LoadTimingInfo load_timing_info;
9899 EXPECT_TRUE(trans_2->GetLoadTimingInfo(&load_timing_info));
9900 TestLoadTimingNotReusedWithPac(load_timing_info,
9901 CONNECT_TIMING_HAS_SSL_TIMES);
9904 // Test that if we cancel the transaction as the connection is completing, that
9905 // everything tears down correctly.
9906 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
9907 // Setup everything about the connection to complete synchronously, so that
9908 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
9909 // for is the callback from the HttpStreamRequest.
9910 // Then cancel the transaction.
9911 // Verify that we don't crash.
9912 MockConnect mock_connect(SYNCHRONOUS, OK);
9913 MockRead data_reads[] = {
9914 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
9915 MockRead(SYNCHRONOUS, "hello world"),
9916 MockRead(SYNCHRONOUS, OK),
9919 HttpRequestInfo request;
9920 request.method = "GET";
9921 request.url = GURL("http://www.google.com/");
9922 request.load_flags = 0;
9924 session_deps_.host_resolver->set_synchronous_mode(true);
9925 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9926 scoped_ptr<HttpTransaction> trans(
9927 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
9929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
9930 data.set_connect_data(mock_connect);
9931 session_deps_.socket_factory->AddSocketDataProvider(&data);
9933 TestCompletionCallback callback;
9935 CapturingBoundNetLog log;
9936 int rv = trans->Start(&request, callback.callback(), log.bound());
9937 EXPECT_EQ(ERR_IO_PENDING, rv);
9938 trans.reset(); // Cancel the transaction here.
9940 base::MessageLoop::current()->RunUntilIdle();
9943 // Test a basic GET request through a proxy.
9944 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
9945 session_deps_.proxy_service.reset(
9946 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9947 CapturingBoundNetLog log;
9948 session_deps_.net_log = log.bound().net_log();
9949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9951 HttpRequestInfo request;
9952 request.method = "GET";
9953 request.url = GURL("http://www.google.com/");
9955 MockWrite data_writes1[] = {
9956 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9957 "Host: www.google.com\r\n"
9958 "Proxy-Connection: keep-alive\r\n\r\n"),
9961 MockRead data_reads1[] = {
9962 MockRead("HTTP/1.1 200 OK\r\n"),
9963 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
9964 MockRead("Content-Length: 100\r\n\r\n"),
9965 MockRead(SYNCHRONOUS, OK),
9968 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
9969 data_writes1, arraysize(data_writes1));
9970 session_deps_.socket_factory->AddSocketDataProvider(&data1);
9972 TestCompletionCallback callback1;
9974 scoped_ptr<HttpTransaction> trans(
9975 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
9977 int rv = trans->Start(&request, callback1.callback(), log.bound());
9978 EXPECT_EQ(ERR_IO_PENDING, rv);
9980 rv = callback1.WaitForResult();
9983 const HttpResponseInfo* response = trans->GetResponseInfo();
9984 ASSERT_TRUE(response != NULL);
9986 EXPECT_TRUE(response->headers->IsKeepAlive());
9987 EXPECT_EQ(200, response->headers->response_code());
9988 EXPECT_EQ(100, response->headers->GetContentLength());
9989 EXPECT_TRUE(response->was_fetched_via_proxy);
9990 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9992 LoadTimingInfo load_timing_info;
9993 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9994 TestLoadTimingNotReusedWithPac(load_timing_info,
9995 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
9998 // Test a basic HTTPS GET request through a proxy.
9999 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
10000 session_deps_.proxy_service.reset(
10001 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10002 CapturingBoundNetLog log;
10003 session_deps_.net_log = log.bound().net_log();
10004 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10006 HttpRequestInfo request;
10007 request.method = "GET";
10008 request.url = GURL("https://www.google.com/");
10010 // Since we have proxy, should try to establish tunnel.
10011 MockWrite data_writes1[] = {
10012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10013 "Host: www.google.com\r\n"
10014 "Proxy-Connection: keep-alive\r\n\r\n"),
10016 MockWrite("GET / HTTP/1.1\r\n"
10017 "Host: www.google.com\r\n"
10018 "Connection: keep-alive\r\n\r\n"),
10021 MockRead data_reads1[] = {
10022 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10024 MockRead("HTTP/1.1 200 OK\r\n"),
10025 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10026 MockRead("Content-Length: 100\r\n\r\n"),
10027 MockRead(SYNCHRONOUS, OK),
10030 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10031 data_writes1, arraysize(data_writes1));
10032 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10033 SSLSocketDataProvider ssl(ASYNC, OK);
10034 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10036 TestCompletionCallback callback1;
10038 scoped_ptr<HttpTransaction> trans(
10039 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10041 int rv = trans->Start(&request, callback1.callback(), log.bound());
10042 EXPECT_EQ(ERR_IO_PENDING, rv);
10044 rv = callback1.WaitForResult();
10046 net::CapturingNetLog::CapturedEntryList entries;
10047 log.GetEntries(&entries);
10048 size_t pos = ExpectLogContainsSomewhere(
10049 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10050 NetLog::PHASE_NONE);
10051 ExpectLogContainsSomewhere(
10053 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10054 NetLog::PHASE_NONE);
10056 const HttpResponseInfo* response = trans->GetResponseInfo();
10057 ASSERT_TRUE(response != NULL);
10059 EXPECT_TRUE(response->headers->IsKeepAlive());
10060 EXPECT_EQ(200, response->headers->response_code());
10061 EXPECT_EQ(100, response->headers->GetContentLength());
10062 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10063 EXPECT_TRUE(response->was_fetched_via_proxy);
10065 LoadTimingInfo load_timing_info;
10066 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10067 TestLoadTimingNotReusedWithPac(load_timing_info,
10068 CONNECT_TIMING_HAS_SSL_TIMES);
10071 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10072 // while establishing the tunnel.
10073 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
10074 session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
10075 CapturingBoundNetLog log;
10076 session_deps_.net_log = log.bound().net_log();
10077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10079 HttpRequestInfo request;
10080 request.method = "GET";
10081 request.url = GURL("https://www.google.com/");
10083 // Since we have proxy, should try to establish tunnel.
10084 MockWrite data_writes1[] = {
10085 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10086 "Host: www.google.com\r\n"
10087 "Proxy-Connection: keep-alive\r\n\r\n"),
10089 MockWrite("GET / HTTP/1.1\r\n"
10090 "Host: www.google.com\r\n"
10091 "Connection: keep-alive\r\n\r\n"),
10094 MockRead data_reads1[] = {
10095 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
10096 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10097 MockRead(ASYNC, 0, 0), // EOF
10100 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
10101 data_writes1, arraysize(data_writes1));
10102 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10103 SSLSocketDataProvider ssl(ASYNC, OK);
10104 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10106 TestCompletionCallback callback1;
10108 scoped_ptr<HttpTransaction> trans(
10109 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10111 int rv = trans->Start(&request, callback1.callback(), log.bound());
10112 EXPECT_EQ(ERR_IO_PENDING, rv);
10114 rv = callback1.WaitForResult();
10115 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
10116 net::CapturingNetLog::CapturedEntryList entries;
10117 log.GetEntries(&entries);
10118 size_t pos = ExpectLogContainsSomewhere(
10119 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
10120 NetLog::PHASE_NONE);
10121 ExpectLogContainsSomewhere(
10123 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
10124 NetLog::PHASE_NONE);
10127 // Test for crbug.com/55424.
10128 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
10129 scoped_ptr<SpdyFrame> req(
10130 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10131 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
10133 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10134 scoped_ptr<SpdyFrame> data(spdy_util_.ConstructSpdyBodyFrame(1, true));
10135 MockRead spdy_reads[] = {
10136 CreateMockRead(*resp),
10137 CreateMockRead(*data),
10138 MockRead(ASYNC, 0, 0),
10141 DelayedSocketData spdy_data(
10142 1, // wait for one write to finish before reading.
10143 spdy_reads, arraysize(spdy_reads),
10144 spdy_writes, arraysize(spdy_writes));
10145 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10147 SSLSocketDataProvider ssl(ASYNC, OK);
10148 ssl.SetNextProto(GetParam());
10149 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10151 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10153 // Set up an initial SpdySession in the pool to reuse.
10154 HostPortPair host_port_pair("www.google.com", 443);
10155 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
10156 kPrivacyModeDisabled);
10157 base::WeakPtr<SpdySession> spdy_session =
10158 CreateInsecureSpdySession(session, key, BoundNetLog());
10160 HttpRequestInfo request;
10161 request.method = "GET";
10162 request.url = GURL("https://www.google.com/");
10163 request.load_flags = 0;
10165 // This is the important line that marks this as a preconnect.
10166 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
10168 scoped_ptr<HttpTransaction> trans(
10169 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10171 TestCompletionCallback callback;
10172 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
10173 EXPECT_EQ(ERR_IO_PENDING, rv);
10174 EXPECT_EQ(OK, callback.WaitForResult());
10177 // Given a net error, cause that error to be returned from the first Write()
10178 // call and verify that the HttpTransaction fails with that error.
10179 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10180 int error, IoMode mode) {
10181 net::HttpRequestInfo request_info;
10182 request_info.url = GURL("https://www.example.com/");
10183 request_info.method = "GET";
10184 request_info.load_flags = net::LOAD_NORMAL;
10186 SSLSocketDataProvider ssl_data(mode, OK);
10187 net::MockWrite data_writes[] = {
10188 net::MockWrite(mode, error),
10190 net::StaticSocketDataProvider data(NULL, 0,
10191 data_writes, arraysize(data_writes));
10192 session_deps_.socket_factory->AddSocketDataProvider(&data);
10193 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
10195 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10196 scoped_ptr<HttpTransaction> trans(
10197 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10199 TestCompletionCallback callback;
10200 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10201 if (rv == net::ERR_IO_PENDING)
10202 rv = callback.WaitForResult();
10203 ASSERT_EQ(error, rv);
10206 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
10207 // Just check a grab bag of cert errors.
10208 static const int kErrors[] = {
10209 ERR_CERT_COMMON_NAME_INVALID,
10210 ERR_CERT_AUTHORITY_INVALID,
10211 ERR_CERT_DATE_INVALID,
10213 for (size_t i = 0; i < arraysize(kErrors); i++) {
10214 CheckErrorIsPassedBack(kErrors[i], ASYNC);
10215 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
10219 // Ensure that a client certificate is removed from the SSL client auth
10221 // 1) No proxy is involved.
10222 // 2) TLS False Start is disabled.
10223 // 3) The initial TLS handshake requests a client certificate.
10224 // 4) The client supplies an invalid/unacceptable certificate.
10225 TEST_P(HttpNetworkTransactionTest,
10226 ClientAuthCertCache_Direct_NoFalseStart) {
10227 net::HttpRequestInfo request_info;
10228 request_info.url = GURL("https://www.example.com/");
10229 request_info.method = "GET";
10230 request_info.load_flags = net::LOAD_NORMAL;
10232 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10233 cert_request->host_and_port = "www.example.com:443";
10235 // [ssl_]data1 contains the data for the first SSL handshake. When a
10236 // CertificateRequest is received for the first time, the handshake will
10237 // be aborted to allow the caller to provide a certificate.
10238 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10239 ssl_data1.cert_request_info = cert_request.get();
10240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10241 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10242 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10244 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10245 // False Start is not being used, the result of the SSL handshake will be
10246 // returned as part of the SSLClientSocket::Connect() call. This test
10247 // matches the result of a server sending a handshake_failure alert,
10248 // rather than a Finished message, because it requires a client
10249 // certificate and none was supplied.
10250 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10251 ssl_data2.cert_request_info = cert_request.get();
10252 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10253 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10254 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10256 // [ssl_]data3 contains the data for the third SSL handshake. When a
10257 // connection to a server fails during an SSL handshake,
10258 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10259 // connection was attempted with TLSv1.1. This is transparent to the caller
10260 // of the HttpNetworkTransaction. Because this test failure is due to
10261 // requiring a client certificate, this fallback handshake should also
10263 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10264 ssl_data3.cert_request_info = cert_request.get();
10265 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10266 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10267 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10269 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10270 // connection to a server fails during an SSL handshake,
10271 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10272 // connection was attempted with TLSv1. This is transparent to the caller
10273 // of the HttpNetworkTransaction. Because this test failure is due to
10274 // requiring a client certificate, this fallback handshake should also
10276 SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10277 ssl_data4.cert_request_info = cert_request.get();
10278 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10279 net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
10280 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10282 // Need one more if TLSv1.2 is enabled.
10283 SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10284 ssl_data5.cert_request_info = cert_request.get();
10285 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10286 net::StaticSocketDataProvider data5(NULL, 0, NULL, 0);
10287 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10290 scoped_ptr<HttpTransaction> trans(
10291 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10293 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10294 TestCompletionCallback callback;
10295 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10296 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10298 // Complete the SSL handshake, which should abort due to requiring a
10299 // client certificate.
10300 rv = callback.WaitForResult();
10301 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10303 // Indicate that no certificate should be supplied. From the perspective
10304 // of SSLClientCertCache, NULL is just as meaningful as a real
10305 // certificate, so this is the same as supply a
10306 // legitimate-but-unacceptable certificate.
10307 rv = trans->RestartWithCertificate(NULL, callback.callback());
10308 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10310 // Ensure the certificate was added to the client auth cache before
10311 // allowing the connection to continue restarting.
10312 scoped_refptr<X509Certificate> client_cert;
10313 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10315 ASSERT_EQ(NULL, client_cert.get());
10317 // Restart the handshake. This will consume ssl_data2, which fails, and
10318 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10319 // The result code is checked against what ssl_data4 should return.
10320 rv = callback.WaitForResult();
10321 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10323 // Ensure that the client certificate is removed from the cache on a
10324 // handshake failure.
10325 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10329 // Ensure that a client certificate is removed from the SSL client auth
10331 // 1) No proxy is involved.
10332 // 2) TLS False Start is enabled.
10333 // 3) The initial TLS handshake requests a client certificate.
10334 // 4) The client supplies an invalid/unacceptable certificate.
10335 TEST_P(HttpNetworkTransactionTest,
10336 ClientAuthCertCache_Direct_FalseStart) {
10337 net::HttpRequestInfo request_info;
10338 request_info.url = GURL("https://www.example.com/");
10339 request_info.method = "GET";
10340 request_info.load_flags = net::LOAD_NORMAL;
10342 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10343 cert_request->host_and_port = "www.example.com:443";
10345 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10346 // return successfully after reading up to the peer's Certificate message.
10347 // This is to allow the caller to call SSLClientSocket::Write(), which can
10348 // enqueue application data to be sent in the same packet as the
10349 // ChangeCipherSpec and Finished messages.
10350 // The actual handshake will be finished when SSLClientSocket::Read() is
10351 // called, which expects to process the peer's ChangeCipherSpec and
10352 // Finished messages. If there was an error negotiating with the peer,
10353 // such as due to the peer requiring a client certificate when none was
10354 // supplied, the alert sent by the peer won't be processed until Read() is
10357 // Like the non-False Start case, when a client certificate is requested by
10358 // the peer, the handshake is aborted during the Connect() call.
10359 // [ssl_]data1 represents the initial SSL handshake with the peer.
10360 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10361 ssl_data1.cert_request_info = cert_request.get();
10362 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10363 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10364 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10366 // When a client certificate is supplied, Connect() will not be aborted
10367 // when the peer requests the certificate. Instead, the handshake will
10368 // artificially succeed, allowing the caller to write the HTTP request to
10369 // the socket. The handshake messages are not processed until Read() is
10370 // called, which then detects that the handshake was aborted, due to the
10371 // peer sending a handshake_failure because it requires a client
10373 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
10374 ssl_data2.cert_request_info = cert_request.get();
10375 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10376 net::MockRead data2_reads[] = {
10377 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
10379 net::StaticSocketDataProvider data2(
10380 data2_reads, arraysize(data2_reads), NULL, 0);
10381 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10383 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10384 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10385 // TLSv1. It has the same behaviour as [ssl_]data2.
10386 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
10387 ssl_data3.cert_request_info = cert_request.get();
10388 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10389 net::StaticSocketDataProvider data3(
10390 data2_reads, arraysize(data2_reads), NULL, 0);
10391 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10393 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10394 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10395 SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
10396 ssl_data4.cert_request_info = cert_request.get();
10397 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
10398 net::StaticSocketDataProvider data4(
10399 data2_reads, arraysize(data2_reads), NULL, 0);
10400 session_deps_.socket_factory->AddSocketDataProvider(&data4);
10402 // Need one more if TLSv1.2 is enabled.
10403 SSLSocketDataProvider ssl_data5(ASYNC, net::OK);
10404 ssl_data5.cert_request_info = cert_request.get();
10405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
10406 net::StaticSocketDataProvider data5(
10407 data2_reads, arraysize(data2_reads), NULL, 0);
10408 session_deps_.socket_factory->AddSocketDataProvider(&data5);
10410 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10411 scoped_ptr<HttpTransaction> trans(
10412 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10414 // Begin the initial SSL handshake.
10415 TestCompletionCallback callback;
10416 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
10417 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10419 // Complete the SSL handshake, which should abort due to requiring a
10420 // client certificate.
10421 rv = callback.WaitForResult();
10422 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10424 // Indicate that no certificate should be supplied. From the perspective
10425 // of SSLClientCertCache, NULL is just as meaningful as a real
10426 // certificate, so this is the same as supply a
10427 // legitimate-but-unacceptable certificate.
10428 rv = trans->RestartWithCertificate(NULL, callback.callback());
10429 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10431 // Ensure the certificate was added to the client auth cache before
10432 // allowing the connection to continue restarting.
10433 scoped_refptr<X509Certificate> client_cert;
10434 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10436 ASSERT_EQ(NULL, client_cert.get());
10438 // Restart the handshake. This will consume ssl_data2, which fails, and
10439 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10440 // The result code is checked against what ssl_data4 should return.
10441 rv = callback.WaitForResult();
10442 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
10444 // Ensure that the client certificate is removed from the cache on a
10445 // handshake failure.
10446 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10450 // Ensure that a client certificate is removed from the SSL client auth
10452 // 1) An HTTPS proxy is involved.
10453 // 3) The HTTPS proxy requests a client certificate.
10454 // 4) The client supplies an invalid/unacceptable certificate for the
10456 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10457 // then for connecting to an HTTP endpoint.
10458 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
10459 session_deps_.proxy_service.reset(
10460 ProxyService::CreateFixed("https://proxy:70"));
10461 CapturingBoundNetLog log;
10462 session_deps_.net_log = log.bound().net_log();
10464 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
10465 cert_request->host_and_port = "proxy:70";
10467 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10468 // [ssl_]data[1-3]. Rather than represending the endpoint
10469 // (www.example.com:443), they represent failures with the HTTPS proxy
10471 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
10472 ssl_data1.cert_request_info = cert_request.get();
10473 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
10474 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
10475 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10477 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10478 ssl_data2.cert_request_info = cert_request.get();
10479 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
10480 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
10481 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10483 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10485 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
10486 ssl_data3.cert_request_info = cert_request.get();
10487 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
10488 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
10489 session_deps_.socket_factory->AddSocketDataProvider(&data3);
10492 net::HttpRequestInfo requests[2];
10493 requests[0].url = GURL("https://www.example.com/");
10494 requests[0].method = "GET";
10495 requests[0].load_flags = net::LOAD_NORMAL;
10497 requests[1].url = GURL("http://www.example.com/");
10498 requests[1].method = "GET";
10499 requests[1].load_flags = net::LOAD_NORMAL;
10501 for (size_t i = 0; i < arraysize(requests); ++i) {
10502 session_deps_.socket_factory->ResetNextMockIndexes();
10503 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10504 scoped_ptr<HttpNetworkTransaction> trans(
10505 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
10507 // Begin the SSL handshake with the proxy.
10508 TestCompletionCallback callback;
10509 int rv = trans->Start(
10510 &requests[i], callback.callback(), net::BoundNetLog());
10511 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10513 // Complete the SSL handshake, which should abort due to requiring a
10514 // client certificate.
10515 rv = callback.WaitForResult();
10516 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
10518 // Indicate that no certificate should be supplied. From the perspective
10519 // of SSLClientCertCache, NULL is just as meaningful as a real
10520 // certificate, so this is the same as supply a
10521 // legitimate-but-unacceptable certificate.
10522 rv = trans->RestartWithCertificate(NULL, callback.callback());
10523 ASSERT_EQ(net::ERR_IO_PENDING, rv);
10525 // Ensure the certificate was added to the client auth cache before
10526 // allowing the connection to continue restarting.
10527 scoped_refptr<X509Certificate> client_cert;
10528 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
10530 ASSERT_EQ(NULL, client_cert.get());
10531 // Ensure the certificate was NOT cached for the endpoint. This only
10532 // applies to HTTPS requests, but is fine to check for HTTP requests.
10533 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10536 // Restart the handshake. This will consume ssl_data2, which fails, and
10537 // then consume ssl_data3, which should also fail. The result code is
10538 // checked against what ssl_data3 should return.
10539 rv = callback.WaitForResult();
10540 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
10542 // Now that the new handshake has failed, ensure that the client
10543 // certificate was removed from the client auth cache.
10544 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
10546 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
10551 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10552 // TEST_P is a macro that expands directly to code that stringizes the
10553 // arguments. As a result, macros passed as parameters (such as prefix
10554 // or test_case_name) will not be expanded by the preprocessor. To
10555 // work around this, indirect the macro for TEST_P, so that the
10556 // pre-processor will expand macros such as MAYBE_test_name before
10557 // instantiating the test.
10558 #define WRAPPED_TEST_P(test_case_name, test_name) \
10559 TEST_P(test_case_name, test_name)
10561 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10562 #if defined(OS_WIN)
10563 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10565 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10567 WRAPPED_TEST_P(HttpNetworkTransactionTest, MAYBE_UseIPConnectionPooling) {
10568 HttpStreamFactory::set_use_alternate_protocols(true);
10569 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10571 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10572 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10573 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10574 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10575 pool_peer.DisableDomainAuthenticationVerification();
10577 SSLSocketDataProvider ssl(ASYNC, OK);
10578 ssl.SetNextProto(GetParam());
10579 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10581 scoped_ptr<SpdyFrame> host1_req(
10582 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10583 scoped_ptr<SpdyFrame> host2_req(
10584 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10585 MockWrite spdy_writes[] = {
10586 CreateMockWrite(*host1_req, 1),
10587 CreateMockWrite(*host2_req, 4),
10589 scoped_ptr<SpdyFrame> host1_resp(
10590 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10591 scoped_ptr<SpdyFrame> host1_resp_body(
10592 spdy_util_.ConstructSpdyBodyFrame(1, true));
10593 scoped_ptr<SpdyFrame> host2_resp(
10594 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10595 scoped_ptr<SpdyFrame> host2_resp_body(
10596 spdy_util_.ConstructSpdyBodyFrame(3, true));
10597 MockRead spdy_reads[] = {
10598 CreateMockRead(*host1_resp, 2),
10599 CreateMockRead(*host1_resp_body, 3),
10600 CreateMockRead(*host2_resp, 5),
10601 CreateMockRead(*host2_resp_body, 6),
10602 MockRead(ASYNC, 0, 7),
10605 IPAddressNumber ip;
10606 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10607 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10608 MockConnect connect(ASYNC, OK, peer_addr);
10609 OrderedSocketData spdy_data(
10611 spdy_reads, arraysize(spdy_reads),
10612 spdy_writes, arraysize(spdy_writes));
10613 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10615 TestCompletionCallback callback;
10616 HttpRequestInfo request1;
10617 request1.method = "GET";
10618 request1.url = GURL("https://www.google.com/");
10619 request1.load_flags = 0;
10620 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10622 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10623 EXPECT_EQ(ERR_IO_PENDING, rv);
10624 EXPECT_EQ(OK, callback.WaitForResult());
10626 const HttpResponseInfo* response = trans1.GetResponseInfo();
10627 ASSERT_TRUE(response != NULL);
10628 ASSERT_TRUE(response->headers.get() != NULL);
10629 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10631 std::string response_data;
10632 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10633 EXPECT_EQ("hello!", response_data);
10635 // Preload www.gmail.com into HostCache.
10636 HostPortPair host_port("www.gmail.com", 443);
10637 HostResolver::RequestInfo resolve_info(host_port);
10638 AddressList ignored;
10639 rv = session_deps_.host_resolver->Resolve(resolve_info,
10642 callback.callback(),
10645 EXPECT_EQ(ERR_IO_PENDING, rv);
10646 rv = callback.WaitForResult();
10649 HttpRequestInfo request2;
10650 request2.method = "GET";
10651 request2.url = GURL("https://www.gmail.com/");
10652 request2.load_flags = 0;
10653 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10655 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10656 EXPECT_EQ(ERR_IO_PENDING, rv);
10657 EXPECT_EQ(OK, callback.WaitForResult());
10659 response = trans2.GetResponseInfo();
10660 ASSERT_TRUE(response != NULL);
10661 ASSERT_TRUE(response->headers.get() != NULL);
10662 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10663 EXPECT_TRUE(response->was_fetched_via_spdy);
10664 EXPECT_TRUE(response->was_npn_negotiated);
10665 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10666 EXPECT_EQ("hello!", response_data);
10668 #undef MAYBE_UseIPConnectionPooling
10670 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
10671 HttpStreamFactory::set_use_alternate_protocols(true);
10672 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10674 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10675 session_deps_.host_resolver.reset(new MockCachingHostResolver());
10676 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10677 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10678 pool_peer.DisableDomainAuthenticationVerification();
10680 SSLSocketDataProvider ssl(ASYNC, OK);
10681 ssl.SetNextProto(GetParam());
10682 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10684 scoped_ptr<SpdyFrame> host1_req(
10685 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10686 scoped_ptr<SpdyFrame> host2_req(
10687 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10688 MockWrite spdy_writes[] = {
10689 CreateMockWrite(*host1_req, 1),
10690 CreateMockWrite(*host2_req, 4),
10692 scoped_ptr<SpdyFrame> host1_resp(
10693 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10694 scoped_ptr<SpdyFrame> host1_resp_body(
10695 spdy_util_.ConstructSpdyBodyFrame(1, true));
10696 scoped_ptr<SpdyFrame> host2_resp(
10697 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10698 scoped_ptr<SpdyFrame> host2_resp_body(
10699 spdy_util_.ConstructSpdyBodyFrame(3, true));
10700 MockRead spdy_reads[] = {
10701 CreateMockRead(*host1_resp, 2),
10702 CreateMockRead(*host1_resp_body, 3),
10703 CreateMockRead(*host2_resp, 5),
10704 CreateMockRead(*host2_resp_body, 6),
10705 MockRead(ASYNC, 0, 7),
10708 IPAddressNumber ip;
10709 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10710 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10711 MockConnect connect(ASYNC, OK, peer_addr);
10712 OrderedSocketData spdy_data(
10714 spdy_reads, arraysize(spdy_reads),
10715 spdy_writes, arraysize(spdy_writes));
10716 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10718 TestCompletionCallback callback;
10719 HttpRequestInfo request1;
10720 request1.method = "GET";
10721 request1.url = GURL("https://www.google.com/");
10722 request1.load_flags = 0;
10723 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10725 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10726 EXPECT_EQ(ERR_IO_PENDING, rv);
10727 EXPECT_EQ(OK, callback.WaitForResult());
10729 const HttpResponseInfo* response = trans1.GetResponseInfo();
10730 ASSERT_TRUE(response != NULL);
10731 ASSERT_TRUE(response->headers.get() != NULL);
10732 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10734 std::string response_data;
10735 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10736 EXPECT_EQ("hello!", response_data);
10738 HttpRequestInfo request2;
10739 request2.method = "GET";
10740 request2.url = GURL("https://www.gmail.com/");
10741 request2.load_flags = 0;
10742 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10744 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10745 EXPECT_EQ(ERR_IO_PENDING, rv);
10746 EXPECT_EQ(OK, callback.WaitForResult());
10748 response = trans2.GetResponseInfo();
10749 ASSERT_TRUE(response != NULL);
10750 ASSERT_TRUE(response->headers.get() != NULL);
10751 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10752 EXPECT_TRUE(response->was_fetched_via_spdy);
10753 EXPECT_TRUE(response->was_npn_negotiated);
10754 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10755 EXPECT_EQ("hello!", response_data);
10758 class OneTimeCachingHostResolver : public net::HostResolver {
10760 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
10761 : host_port_(host_port) {}
10762 virtual ~OneTimeCachingHostResolver() {}
10764 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
10766 // HostResolver methods:
10767 virtual int Resolve(const RequestInfo& info,
10768 RequestPriority priority,
10769 AddressList* addresses,
10770 const CompletionCallback& callback,
10771 RequestHandle* out_req,
10772 const BoundNetLog& net_log) OVERRIDE {
10773 return host_resolver_.Resolve(
10774 info, priority, addresses, callback, out_req, net_log);
10777 virtual int ResolveFromCache(const RequestInfo& info,
10778 AddressList* addresses,
10779 const BoundNetLog& net_log) OVERRIDE {
10780 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
10781 if (rv == OK && info.host_port_pair().Equals(host_port_))
10782 host_resolver_.GetHostCache()->clear();
10786 virtual void CancelRequest(RequestHandle req) OVERRIDE {
10787 host_resolver_.CancelRequest(req);
10790 MockCachingHostResolver* GetMockHostResolver() {
10791 return &host_resolver_;
10795 MockCachingHostResolver host_resolver_;
10796 const HostPortPair host_port_;
10799 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10800 #if defined(OS_WIN)
10801 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10802 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
10804 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
10805 UseIPConnectionPoolingWithHostCacheExpiration
10807 WRAPPED_TEST_P(HttpNetworkTransactionTest,
10808 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration) {
10809 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
10810 // prefix doesn't work with parametrized tests).
10811 #if defined(OS_WIN)
10815 HttpStreamFactory::set_use_alternate_protocols(true);
10816 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10818 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
10819 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
10820 HttpNetworkSession::Params params =
10821 SpdySessionDependencies::CreateSessionParams(&session_deps_);
10822 params.host_resolver = &host_resolver;
10823 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10824 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
10825 pool_peer.DisableDomainAuthenticationVerification();
10827 SSLSocketDataProvider ssl(ASYNC, OK);
10828 ssl.SetNextProto(GetParam());
10829 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10831 scoped_ptr<SpdyFrame> host1_req(
10832 spdy_util_.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST));
10833 scoped_ptr<SpdyFrame> host2_req(
10834 spdy_util_.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST));
10835 MockWrite spdy_writes[] = {
10836 CreateMockWrite(*host1_req, 1),
10837 CreateMockWrite(*host2_req, 4),
10839 scoped_ptr<SpdyFrame> host1_resp(
10840 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10841 scoped_ptr<SpdyFrame> host1_resp_body(
10842 spdy_util_.ConstructSpdyBodyFrame(1, true));
10843 scoped_ptr<SpdyFrame> host2_resp(
10844 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
10845 scoped_ptr<SpdyFrame> host2_resp_body(
10846 spdy_util_.ConstructSpdyBodyFrame(3, true));
10847 MockRead spdy_reads[] = {
10848 CreateMockRead(*host1_resp, 2),
10849 CreateMockRead(*host1_resp_body, 3),
10850 CreateMockRead(*host2_resp, 5),
10851 CreateMockRead(*host2_resp_body, 6),
10852 MockRead(ASYNC, 0, 7),
10855 IPAddressNumber ip;
10856 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip));
10857 IPEndPoint peer_addr = IPEndPoint(ip, 443);
10858 MockConnect connect(ASYNC, OK, peer_addr);
10859 OrderedSocketData spdy_data(
10861 spdy_reads, arraysize(spdy_reads),
10862 spdy_writes, arraysize(spdy_writes));
10863 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10865 TestCompletionCallback callback;
10866 HttpRequestInfo request1;
10867 request1.method = "GET";
10868 request1.url = GURL("https://www.google.com/");
10869 request1.load_flags = 0;
10870 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
10872 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
10873 EXPECT_EQ(ERR_IO_PENDING, rv);
10874 EXPECT_EQ(OK, callback.WaitForResult());
10876 const HttpResponseInfo* response = trans1.GetResponseInfo();
10877 ASSERT_TRUE(response != NULL);
10878 ASSERT_TRUE(response->headers.get() != NULL);
10879 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10881 std::string response_data;
10882 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
10883 EXPECT_EQ("hello!", response_data);
10885 // Preload cache entries into HostCache.
10886 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
10887 AddressList ignored;
10888 rv = host_resolver.Resolve(resolve_info,
10891 callback.callback(),
10894 EXPECT_EQ(ERR_IO_PENDING, rv);
10895 rv = callback.WaitForResult();
10898 HttpRequestInfo request2;
10899 request2.method = "GET";
10900 request2.url = GURL("https://www.gmail.com/");
10901 request2.load_flags = 0;
10902 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10904 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
10905 EXPECT_EQ(ERR_IO_PENDING, rv);
10906 EXPECT_EQ(OK, callback.WaitForResult());
10908 response = trans2.GetResponseInfo();
10909 ASSERT_TRUE(response != NULL);
10910 ASSERT_TRUE(response->headers.get() != NULL);
10911 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
10912 EXPECT_TRUE(response->was_fetched_via_spdy);
10913 EXPECT_TRUE(response->was_npn_negotiated);
10914 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
10915 EXPECT_EQ("hello!", response_data);
10917 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
10919 TEST_P(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
10920 MockRead data_reads1[] = {
10921 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10923 MockRead data_reads2[] = {
10924 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10925 MockRead("hello world"),
10926 MockRead(SYNCHRONOUS, OK),
10928 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
10929 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
10930 StaticSocketDataProvider* data[] = { &data1, &data2 };
10932 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10934 EXPECT_EQ(OK, out.rv);
10935 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10936 EXPECT_EQ("hello world", out.response_data);
10939 TEST_P(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
10940 MockWrite data_writes1[] = {
10941 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
10943 MockWrite data_writes2[] = {
10944 MockWrite("GET / HTTP/1.1\r\n"
10945 "Host: www.google.com\r\n"
10946 "Connection: keep-alive\r\n\r\n"),
10948 MockRead data_reads2[] = {
10949 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
10950 MockRead("hello world"),
10951 MockRead(SYNCHRONOUS, OK),
10953 StaticSocketDataProvider data1(NULL, 0,
10954 data_writes1, arraysize(data_writes1));
10955 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
10956 data_writes2, arraysize(data_writes2));
10957 StaticSocketDataProvider* data[] = { &data1, &data2 };
10959 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
10961 EXPECT_EQ(OK, out.rv);
10962 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
10963 EXPECT_EQ("hello world", out.response_data);
10966 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
10967 const std::string https_url = "https://www.google.com/";
10968 const std::string http_url = "http://www.google.com:443/";
10970 // SPDY GET for HTTPS URL
10971 scoped_ptr<SpdyFrame> req1(
10972 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
10974 MockWrite writes1[] = {
10975 CreateMockWrite(*req1, 0),
10978 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
10979 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
10980 MockRead reads1[] = {
10981 CreateMockRead(*resp1, 1),
10982 CreateMockRead(*body1, 2),
10983 MockRead(ASYNC, ERR_IO_PENDING, 3)
10986 DelayedSocketData data1(
10987 1, reads1, arraysize(reads1),
10988 writes1, arraysize(writes1));
10989 MockConnect connect_data1(ASYNC, OK);
10990 data1.set_connect_data(connect_data1);
10992 // HTTP GET for the HTTP URL
10993 MockWrite writes2[] = {
10994 MockWrite(ASYNC, 4,
10995 "GET / HTTP/1.1\r\n"
10996 "Host: www.google.com:443\r\n"
10997 "Connection: keep-alive\r\n\r\n"),
11000 MockRead reads2[] = {
11001 MockRead(ASYNC, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11002 MockRead(ASYNC, 6, "hello"),
11003 MockRead(ASYNC, 7, OK),
11006 DelayedSocketData data2(
11007 1, reads2, arraysize(reads2),
11008 writes2, arraysize(writes2));
11010 SSLSocketDataProvider ssl(ASYNC, OK);
11011 ssl.SetNextProto(GetParam());
11012 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11013 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11014 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11016 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11018 // Start the first transaction to set up the SpdySession
11019 HttpRequestInfo request1;
11020 request1.method = "GET";
11021 request1.url = GURL(https_url);
11022 request1.load_flags = 0;
11023 HttpNetworkTransaction trans1(LOWEST, session.get());
11024 TestCompletionCallback callback1;
11025 EXPECT_EQ(ERR_IO_PENDING,
11026 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11027 base::MessageLoop::current()->RunUntilIdle();
11029 EXPECT_EQ(OK, callback1.WaitForResult());
11030 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11032 // Now, start the HTTP request
11033 HttpRequestInfo request2;
11034 request2.method = "GET";
11035 request2.url = GURL(http_url);
11036 request2.load_flags = 0;
11037 HttpNetworkTransaction trans2(MEDIUM, session.get());
11038 TestCompletionCallback callback2;
11039 EXPECT_EQ(ERR_IO_PENDING,
11040 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11041 base::MessageLoop::current()->RunUntilIdle();
11043 EXPECT_EQ(OK, callback2.WaitForResult());
11044 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11047 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
11048 const std::string https_url = "https://www.google.com/";
11049 const std::string http_url = "http://www.google.com:443/";
11051 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11052 scoped_ptr<SpdyFrame> connect(spdy_util_.ConstructSpdyConnect(NULL, 0, 1,
11054 scoped_ptr<SpdyFrame> req1(
11055 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11057 // SPDY GET for HTTP URL (through the proxy, but not the tunnel)
11058 scoped_ptr<SpdyFrame> wrapped_req1(
11059 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
11060 const char* const headers[] = {
11061 spdy_util_.GetMethodKey(), "GET",
11062 spdy_util_.GetPathKey(), spdy_util_.is_spdy2() ? http_url.c_str() : "/",
11063 spdy_util_.GetHostKey(), "www.google.com:443",
11064 spdy_util_.GetSchemeKey(), "http",
11065 spdy_util_.GetVersionKey(), "HTTP/1.1"
11067 scoped_ptr<SpdyFrame> req2(spdy_util_.ConstructSpdyControlFrame(
11068 NULL, 0, false, 3, MEDIUM, SYN_STREAM, CONTROL_FLAG_FIN,
11069 headers, arraysize(headers), 0));
11071 MockWrite writes1[] = {
11072 CreateMockWrite(*connect, 0),
11073 CreateMockWrite(*wrapped_req1, 2),
11074 CreateMockWrite(*req2, 5),
11077 scoped_ptr<SpdyFrame> conn_resp(
11078 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11079 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11080 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11081 scoped_ptr<SpdyFrame> wrapped_resp1(
11082 spdy_util_.ConstructWrappedSpdyFrame(resp1, 1));
11083 scoped_ptr<SpdyFrame> wrapped_body1(
11084 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
11085 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11086 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11087 MockRead reads1[] = {
11088 CreateMockRead(*conn_resp, 1),
11089 CreateMockRead(*wrapped_resp1, 3),
11090 CreateMockRead(*wrapped_body1, 4),
11091 CreateMockRead(*resp2, 6),
11092 CreateMockRead(*body2, 7),
11093 MockRead(ASYNC, ERR_IO_PENDING, 8)
11096 DeterministicSocketData data1(reads1, arraysize(reads1),
11097 writes1, arraysize(writes1));
11098 MockConnect connect_data1(ASYNC, OK);
11099 data1.set_connect_data(connect_data1);
11101 session_deps_.proxy_service.reset(
11102 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11103 CapturingNetLog log;
11104 session_deps_.net_log = &log;
11105 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11106 ssl1.SetNextProto(GetParam());
11107 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11108 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11109 ssl2.SetNextProto(GetParam());
11110 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11111 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data1);
11113 scoped_refptr<HttpNetworkSession> session(
11114 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11116 // Start the first transaction to set up the SpdySession
11117 HttpRequestInfo request1;
11118 request1.method = "GET";
11119 request1.url = GURL(https_url);
11120 request1.load_flags = 0;
11121 HttpNetworkTransaction trans1(LOWEST, session.get());
11122 TestCompletionCallback callback1;
11123 EXPECT_EQ(ERR_IO_PENDING,
11124 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11125 base::MessageLoop::current()->RunUntilIdle();
11128 EXPECT_EQ(OK, callback1.WaitForResult());
11129 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11131 LoadTimingInfo load_timing_info1;
11132 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
11133 TestLoadTimingNotReusedWithPac(load_timing_info1,
11134 CONNECT_TIMING_HAS_SSL_TIMES);
11136 // Now, start the HTTP request
11137 HttpRequestInfo request2;
11138 request2.method = "GET";
11139 request2.url = GURL(http_url);
11140 request2.load_flags = 0;
11141 HttpNetworkTransaction trans2(MEDIUM, session.get());
11142 TestCompletionCallback callback2;
11143 EXPECT_EQ(ERR_IO_PENDING,
11144 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11145 base::MessageLoop::current()->RunUntilIdle();
11148 EXPECT_EQ(OK, callback2.WaitForResult());
11149 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11151 LoadTimingInfo load_timing_info2;
11152 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
11153 // The established SPDY sessions is considered reused by the HTTP request.
11154 TestLoadTimingReusedWithPac(load_timing_info2);
11155 // HTTP requests over a SPDY session should have a different connection
11156 // socket_log_id than requests over a tunnel.
11157 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
11160 TEST_P(HttpNetworkTransactionTest, UseSpdySessionForHttpWhenForced) {
11161 HttpStreamFactory::set_force_spdy_always(true);
11162 const std::string https_url = "https://www.google.com/";
11163 const std::string http_url = "http://www.google.com:443/";
11165 // SPDY GET for HTTPS URL
11166 scoped_ptr<SpdyFrame> req1(
11167 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, LOWEST));
11168 // SPDY GET for the HTTP URL
11169 scoped_ptr<SpdyFrame> req2(
11170 spdy_util_.ConstructSpdyGet(http_url.c_str(), false, 3, MEDIUM));
11172 MockWrite writes[] = {
11173 CreateMockWrite(*req1, 1),
11174 CreateMockWrite(*req2, 4),
11177 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11178 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11179 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
11180 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(3, true));
11181 MockRead reads[] = {
11182 CreateMockRead(*resp1, 2),
11183 CreateMockRead(*body1, 3),
11184 CreateMockRead(*resp2, 5),
11185 CreateMockRead(*body2, 6),
11186 MockRead(ASYNC, ERR_IO_PENDING, 7)
11189 OrderedSocketData data(reads, arraysize(reads),
11190 writes, arraysize(writes));
11192 SSLSocketDataProvider ssl(ASYNC, OK);
11193 ssl.SetNextProto(GetParam());
11194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
11195 session_deps_.socket_factory->AddSocketDataProvider(&data);
11197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11199 // Start the first transaction to set up the SpdySession
11200 HttpRequestInfo request1;
11201 request1.method = "GET";
11202 request1.url = GURL(https_url);
11203 request1.load_flags = 0;
11204 HttpNetworkTransaction trans1(LOWEST, session.get());
11205 TestCompletionCallback callback1;
11206 EXPECT_EQ(ERR_IO_PENDING,
11207 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11208 base::MessageLoop::current()->RunUntilIdle();
11210 EXPECT_EQ(OK, callback1.WaitForResult());
11211 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11213 // Now, start the HTTP request
11214 HttpRequestInfo request2;
11215 request2.method = "GET";
11216 request2.url = GURL(http_url);
11217 request2.load_flags = 0;
11218 HttpNetworkTransaction trans2(MEDIUM, session.get());
11219 TestCompletionCallback callback2;
11220 EXPECT_EQ(ERR_IO_PENDING,
11221 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11222 base::MessageLoop::current()->RunUntilIdle();
11224 EXPECT_EQ(OK, callback2.WaitForResult());
11225 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11228 // Test that in the case where we have a SPDY session to a SPDY proxy
11229 // that we do not pool other origins that resolve to the same IP when
11230 // the certificate does not match the new origin.
11231 // http://crbug.com/134690
11232 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
11233 const std::string url1 = "http://www.google.com/";
11234 const std::string url2 = "https://mail.google.com/";
11235 const std::string ip_addr = "1.2.3.4";
11237 // SPDY GET for HTTP URL (through SPDY proxy)
11238 scoped_ptr<SpdyHeaderBlock> headers(
11239 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11240 scoped_ptr<SpdyFrame> req1(spdy_util_.ConstructSpdyControlFrame(
11241 headers.Pass(), false, 1, LOWEST, SYN_STREAM, CONTROL_FLAG_FIN, 0));
11243 MockWrite writes1[] = {
11244 CreateMockWrite(*req1, 0),
11247 scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11248 scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true));
11249 MockRead reads1[] = {
11250 CreateMockRead(*resp1, 1),
11251 CreateMockRead(*body1, 2),
11252 MockRead(ASYNC, OK, 3) // EOF
11255 scoped_ptr<DeterministicSocketData> data1(
11256 new DeterministicSocketData(reads1, arraysize(reads1),
11257 writes1, arraysize(writes1)));
11258 IPAddressNumber ip;
11259 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr, &ip));
11260 IPEndPoint peer_addr = IPEndPoint(ip, 443);
11261 MockConnect connect_data1(ASYNC, OK, peer_addr);
11262 data1->set_connect_data(connect_data1);
11264 // SPDY GET for HTTPS URL (direct)
11265 scoped_ptr<SpdyFrame> req2(
11266 spdy_util_.ConstructSpdyGet(url2.c_str(), false, 1, MEDIUM));
11268 MockWrite writes2[] = {
11269 CreateMockWrite(*req2, 0),
11272 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11273 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11274 MockRead reads2[] = {
11275 CreateMockRead(*resp2, 1),
11276 CreateMockRead(*body2, 2),
11277 MockRead(ASYNC, OK, 3) // EOF
11280 scoped_ptr<DeterministicSocketData> data2(
11281 new DeterministicSocketData(reads2, arraysize(reads2),
11282 writes2, arraysize(writes2)));
11283 MockConnect connect_data2(ASYNC, OK);
11284 data2->set_connect_data(connect_data2);
11286 // Set up a proxy config that sends HTTP requests to a proxy, and
11287 // all others direct.
11288 ProxyConfig proxy_config;
11289 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
11290 CapturingProxyResolver* capturing_proxy_resolver =
11291 new CapturingProxyResolver();
11292 session_deps_.proxy_service.reset(new ProxyService(
11293 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
11296 // Load a valid cert. Note, that this does not need to
11297 // be valid for proxy because the MockSSLClientSocket does
11298 // not actually verify it. But SpdySession will use this
11299 // to see if it is valid for the new origin
11300 base::FilePath certs_dir = GetTestCertsDirectory();
11301 scoped_refptr<X509Certificate> server_cert(
11302 ImportCertFromFile(certs_dir, "ok_cert.pem"));
11303 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert);
11305 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
11306 ssl1.SetNextProto(GetParam());
11307 ssl1.cert = server_cert;
11308 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11309 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11312 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
11313 ssl2.SetNextProto(GetParam());
11314 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11315 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11318 session_deps_.host_resolver.reset(new MockCachingHostResolver());
11319 session_deps_.host_resolver->rules()->AddRule("mail.google.com", ip_addr);
11320 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
11322 scoped_refptr<HttpNetworkSession> session(
11323 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11325 // Start the first transaction to set up the SpdySession
11326 HttpRequestInfo request1;
11327 request1.method = "GET";
11328 request1.url = GURL(url1);
11329 request1.load_flags = 0;
11330 HttpNetworkTransaction trans1(LOWEST, session.get());
11331 TestCompletionCallback callback1;
11332 ASSERT_EQ(ERR_IO_PENDING,
11333 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11336 ASSERT_TRUE(callback1.have_result());
11337 EXPECT_EQ(OK, callback1.WaitForResult());
11338 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
11340 // Now, start the HTTP request
11341 HttpRequestInfo request2;
11342 request2.method = "GET";
11343 request2.url = GURL(url2);
11344 request2.load_flags = 0;
11345 HttpNetworkTransaction trans2(MEDIUM, session.get());
11346 TestCompletionCallback callback2;
11347 EXPECT_EQ(ERR_IO_PENDING,
11348 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11349 base::MessageLoop::current()->RunUntilIdle();
11352 ASSERT_TRUE(callback2.have_result());
11353 EXPECT_EQ(OK, callback2.WaitForResult());
11354 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11357 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11358 // error) in SPDY session, removes the socket from pool and closes the SPDY
11359 // session. Verify that new url's from the same HttpNetworkSession (and a new
11360 // SpdySession) do work. http://crbug.com/224701
11361 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
11362 const std::string https_url = "https://www.google.com/";
11364 MockRead reads1[] = {
11365 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)
11368 scoped_ptr<DeterministicSocketData> data1(
11369 new DeterministicSocketData(reads1, arraysize(reads1), NULL, 0));
11372 scoped_ptr<SpdyFrame> req2(
11373 spdy_util_.ConstructSpdyGet(https_url.c_str(), false, 1, MEDIUM));
11374 MockWrite writes2[] = {
11375 CreateMockWrite(*req2, 0),
11378 scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11379 scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true));
11380 MockRead reads2[] = {
11381 CreateMockRead(*resp2, 1),
11382 CreateMockRead(*body2, 2),
11383 MockRead(ASYNC, OK, 3) // EOF
11386 scoped_ptr<DeterministicSocketData> data2(
11387 new DeterministicSocketData(reads2, arraysize(reads2),
11388 writes2, arraysize(writes2)));
11390 SSLSocketDataProvider ssl1(ASYNC, OK);
11391 ssl1.SetNextProto(GetParam());
11392 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl1);
11393 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11396 SSLSocketDataProvider ssl2(ASYNC, OK);
11397 ssl2.SetNextProto(GetParam());
11398 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2);
11399 session_deps_.deterministic_socket_factory->AddSocketDataProvider(
11402 scoped_refptr<HttpNetworkSession> session(
11403 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_));
11405 // Start the first transaction to set up the SpdySession and verify that
11406 // connection was closed.
11407 HttpRequestInfo request1;
11408 request1.method = "GET";
11409 request1.url = GURL(https_url);
11410 request1.load_flags = 0;
11411 HttpNetworkTransaction trans1(MEDIUM, session.get());
11412 TestCompletionCallback callback1;
11413 EXPECT_EQ(ERR_IO_PENDING,
11414 trans1.Start(&request1, callback1.callback(), BoundNetLog()));
11415 base::MessageLoop::current()->RunUntilIdle();
11416 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback1.WaitForResult());
11418 // Now, start the second request and make sure it succeeds.
11419 HttpRequestInfo request2;
11420 request2.method = "GET";
11421 request2.url = GURL(https_url);
11422 request2.load_flags = 0;
11423 HttpNetworkTransaction trans2(MEDIUM, session.get());
11424 TestCompletionCallback callback2;
11425 EXPECT_EQ(ERR_IO_PENDING,
11426 trans2.Start(&request2, callback2.callback(), BoundNetLog()));
11427 base::MessageLoop::current()->RunUntilIdle();
11430 ASSERT_TRUE(callback2.have_result());
11431 EXPECT_EQ(OK, callback2.WaitForResult());
11432 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
11435 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
11436 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11437 ClientSocketPoolManager::set_max_sockets_per_group(
11438 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11439 ClientSocketPoolManager::set_max_sockets_per_pool(
11440 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
11442 // Use two different hosts with different IPs so they don't get pooled.
11443 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
11444 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
11445 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11447 SSLSocketDataProvider ssl1(ASYNC, OK);
11448 ssl1.SetNextProto(GetParam());
11449 SSLSocketDataProvider ssl2(ASYNC, OK);
11450 ssl2.SetNextProto(GetParam());
11451 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11452 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11454 scoped_ptr<SpdyFrame> host1_req(spdy_util_.ConstructSpdyGet(
11455 "https://www.a.com", false, 1, DEFAULT_PRIORITY));
11456 MockWrite spdy1_writes[] = {
11457 CreateMockWrite(*host1_req, 1),
11459 scoped_ptr<SpdyFrame> host1_resp(
11460 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11461 scoped_ptr<SpdyFrame> host1_resp_body(
11462 spdy_util_.ConstructSpdyBodyFrame(1, true));
11463 MockRead spdy1_reads[] = {
11464 CreateMockRead(*host1_resp, 2),
11465 CreateMockRead(*host1_resp_body, 3),
11466 MockRead(ASYNC, ERR_IO_PENDING, 4),
11469 scoped_ptr<OrderedSocketData> spdy1_data(
11470 new OrderedSocketData(
11471 spdy1_reads, arraysize(spdy1_reads),
11472 spdy1_writes, arraysize(spdy1_writes)));
11473 session_deps_.socket_factory->AddSocketDataProvider(spdy1_data.get());
11475 scoped_ptr<SpdyFrame> host2_req(spdy_util_.ConstructSpdyGet(
11476 "https://www.b.com", false, 1, DEFAULT_PRIORITY));
11477 MockWrite spdy2_writes[] = {
11478 CreateMockWrite(*host2_req, 1),
11480 scoped_ptr<SpdyFrame> host2_resp(
11481 spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
11482 scoped_ptr<SpdyFrame> host2_resp_body(
11483 spdy_util_.ConstructSpdyBodyFrame(1, true));
11484 MockRead spdy2_reads[] = {
11485 CreateMockRead(*host2_resp, 2),
11486 CreateMockRead(*host2_resp_body, 3),
11487 MockRead(ASYNC, ERR_IO_PENDING, 4),
11490 scoped_ptr<OrderedSocketData> spdy2_data(
11491 new OrderedSocketData(
11492 spdy2_reads, arraysize(spdy2_reads),
11493 spdy2_writes, arraysize(spdy2_writes)));
11494 session_deps_.socket_factory->AddSocketDataProvider(spdy2_data.get());
11496 MockWrite http_write[] = {
11497 MockWrite("GET / HTTP/1.1\r\n"
11498 "Host: www.a.com\r\n"
11499 "Connection: keep-alive\r\n\r\n"),
11502 MockRead http_read[] = {
11503 MockRead("HTTP/1.1 200 OK\r\n"),
11504 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11505 MockRead("Content-Length: 6\r\n\r\n"),
11506 MockRead("hello!"),
11508 StaticSocketDataProvider http_data(http_read, arraysize(http_read),
11509 http_write, arraysize(http_write));
11510 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
11512 HostPortPair host_port_pair_a("www.a.com", 443);
11513 SpdySessionKey spdy_session_key_a(
11514 host_port_pair_a, ProxyServer::Direct(), kPrivacyModeDisabled);
11516 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11518 TestCompletionCallback callback;
11519 HttpRequestInfo request1;
11520 request1.method = "GET";
11521 request1.url = GURL("https://www.a.com/");
11522 request1.load_flags = 0;
11523 scoped_ptr<HttpNetworkTransaction> trans(
11524 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11526 int rv = trans->Start(&request1, callback.callback(), BoundNetLog());
11527 EXPECT_EQ(ERR_IO_PENDING, rv);
11528 EXPECT_EQ(OK, callback.WaitForResult());
11530 const HttpResponseInfo* response = trans->GetResponseInfo();
11531 ASSERT_TRUE(response != NULL);
11532 ASSERT_TRUE(response->headers.get() != NULL);
11533 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11534 EXPECT_TRUE(response->was_fetched_via_spdy);
11535 EXPECT_TRUE(response->was_npn_negotiated);
11537 std::string response_data;
11538 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11539 EXPECT_EQ("hello!", response_data);
11542 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11544 HostPortPair host_port_pair_b("www.b.com", 443);
11545 SpdySessionKey spdy_session_key_b(
11546 host_port_pair_b, ProxyServer::Direct(), kPrivacyModeDisabled);
11548 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11549 HttpRequestInfo request2;
11550 request2.method = "GET";
11551 request2.url = GURL("https://www.b.com/");
11552 request2.load_flags = 0;
11553 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11555 rv = trans->Start(&request2, callback.callback(), BoundNetLog());
11556 EXPECT_EQ(ERR_IO_PENDING, rv);
11557 EXPECT_EQ(OK, callback.WaitForResult());
11559 response = trans->GetResponseInfo();
11560 ASSERT_TRUE(response != NULL);
11561 ASSERT_TRUE(response->headers.get() != NULL);
11562 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11563 EXPECT_TRUE(response->was_fetched_via_spdy);
11564 EXPECT_TRUE(response->was_npn_negotiated);
11565 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11566 EXPECT_EQ("hello!", response_data);
11568 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11570 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11572 HostPortPair host_port_pair_a1("www.a.com", 80);
11573 SpdySessionKey spdy_session_key_a1(
11574 host_port_pair_a1, ProxyServer::Direct(), kPrivacyModeDisabled);
11576 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
11577 HttpRequestInfo request3;
11578 request3.method = "GET";
11579 request3.url = GURL("http://www.a.com/");
11580 request3.load_flags = 0;
11581 trans.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
11583 rv = trans->Start(&request3, callback.callback(), BoundNetLog());
11584 EXPECT_EQ(ERR_IO_PENDING, rv);
11585 EXPECT_EQ(OK, callback.WaitForResult());
11587 response = trans->GetResponseInfo();
11588 ASSERT_TRUE(response != NULL);
11589 ASSERT_TRUE(response->headers.get() != NULL);
11590 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
11591 EXPECT_FALSE(response->was_fetched_via_spdy);
11592 EXPECT_FALSE(response->was_npn_negotiated);
11593 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
11594 EXPECT_EQ("hello!", response_data);
11596 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
11598 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
11601 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
11602 HttpRequestInfo request;
11603 request.method = "GET";
11604 request.url = GURL("http://www.google.com/");
11605 request.load_flags = 0;
11607 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11608 scoped_ptr<HttpTransaction> trans(
11609 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11611 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
11612 StaticSocketDataProvider data;
11613 data.set_connect_data(mock_connect);
11614 session_deps_.socket_factory->AddSocketDataProvider(&data);
11616 TestCompletionCallback callback;
11618 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11619 EXPECT_EQ(ERR_IO_PENDING, rv);
11621 rv = callback.WaitForResult();
11622 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11624 EXPECT_EQ(NULL, trans->GetResponseInfo());
11626 // We don't care whether this succeeds or fails, but it shouldn't crash.
11627 HttpRequestHeaders request_headers;
11628 trans->GetFullRequestHeaders(&request_headers);
11631 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
11632 HttpRequestInfo request;
11633 request.method = "GET";
11634 request.url = GURL("http://www.google.com/");
11635 request.load_flags = 0;
11637 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11638 scoped_ptr<HttpTransaction> trans(
11639 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11641 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
11642 StaticSocketDataProvider data;
11643 data.set_connect_data(mock_connect);
11644 session_deps_.socket_factory->AddSocketDataProvider(&data);
11646 TestCompletionCallback callback;
11648 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11649 EXPECT_EQ(ERR_IO_PENDING, rv);
11651 rv = callback.WaitForResult();
11652 EXPECT_EQ(ERR_CONNECTION_REFUSED, rv);
11654 EXPECT_EQ(NULL, trans->GetResponseInfo());
11656 // We don't care whether this succeeds or fails, but it shouldn't crash.
11657 HttpRequestHeaders request_headers;
11658 trans->GetFullRequestHeaders(&request_headers);
11661 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
11662 HttpRequestInfo request;
11663 request.method = "GET";
11664 request.url = GURL("http://www.google.com/");
11665 request.load_flags = 0;
11667 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11668 scoped_ptr<HttpTransaction> trans(
11669 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11671 MockWrite data_writes[] = {
11672 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
11674 MockRead data_reads[] = {
11675 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11678 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11679 data_writes, arraysize(data_writes));
11680 session_deps_.socket_factory->AddSocketDataProvider(&data);
11682 TestCompletionCallback callback;
11684 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11685 EXPECT_EQ(ERR_IO_PENDING, rv);
11687 rv = callback.WaitForResult();
11688 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11690 EXPECT_EQ(NULL, trans->GetResponseInfo());
11692 HttpRequestHeaders request_headers;
11693 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11694 EXPECT_TRUE(request_headers.HasHeader("Host"));
11697 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
11698 HttpRequestInfo request;
11699 request.method = "GET";
11700 request.url = GURL("http://www.google.com/");
11701 request.load_flags = 0;
11703 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11704 scoped_ptr<HttpTransaction> trans(
11705 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11707 MockWrite data_writes[] = {
11708 MockWrite(ASYNC, ERR_CONNECTION_RESET),
11710 MockRead data_reads[] = {
11711 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
11714 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11715 data_writes, arraysize(data_writes));
11716 session_deps_.socket_factory->AddSocketDataProvider(&data);
11718 TestCompletionCallback callback;
11720 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11721 EXPECT_EQ(ERR_IO_PENDING, rv);
11723 rv = callback.WaitForResult();
11724 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11726 EXPECT_EQ(NULL, trans->GetResponseInfo());
11728 HttpRequestHeaders request_headers;
11729 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11730 EXPECT_TRUE(request_headers.HasHeader("Host"));
11733 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
11734 HttpRequestInfo request;
11735 request.method = "GET";
11736 request.url = GURL("http://www.google.com/");
11737 request.load_flags = 0;
11739 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11740 scoped_ptr<HttpTransaction> trans(
11741 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11743 MockWrite data_writes[] = {
11744 MockWrite("GET / HTTP/1.1\r\n"
11745 "Host: www.google.com\r\n"
11746 "Connection: keep-alive\r\n\r\n"),
11748 MockRead data_reads[] = {
11749 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
11752 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11753 data_writes, arraysize(data_writes));
11754 session_deps_.socket_factory->AddSocketDataProvider(&data);
11756 TestCompletionCallback callback;
11758 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11759 EXPECT_EQ(ERR_IO_PENDING, rv);
11761 rv = callback.WaitForResult();
11762 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11764 EXPECT_EQ(NULL, trans->GetResponseInfo());
11766 HttpRequestHeaders request_headers;
11767 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11768 EXPECT_TRUE(request_headers.HasHeader("Host"));
11771 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
11772 HttpRequestInfo request;
11773 request.method = "GET";
11774 request.url = GURL("http://www.google.com/");
11775 request.load_flags = 0;
11777 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11778 scoped_ptr<HttpTransaction> trans(
11779 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11781 MockWrite data_writes[] = {
11782 MockWrite("GET / HTTP/1.1\r\n"
11783 "Host: www.google.com\r\n"
11784 "Connection: keep-alive\r\n\r\n"),
11786 MockRead data_reads[] = {
11787 MockRead(ASYNC, ERR_CONNECTION_RESET),
11790 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11791 data_writes, arraysize(data_writes));
11792 session_deps_.socket_factory->AddSocketDataProvider(&data);
11794 TestCompletionCallback callback;
11796 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11797 EXPECT_EQ(ERR_IO_PENDING, rv);
11799 rv = callback.WaitForResult();
11800 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
11802 EXPECT_EQ(NULL, trans->GetResponseInfo());
11804 HttpRequestHeaders request_headers;
11805 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11806 EXPECT_TRUE(request_headers.HasHeader("Host"));
11809 TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
11810 HttpRequestInfo request;
11811 request.method = "GET";
11812 request.url = GURL("http://www.google.com/");
11813 request.load_flags = 0;
11814 request.extra_headers.SetHeader("X-Foo", "bar");
11816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11817 scoped_ptr<HttpTransaction> trans(
11818 new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
11820 MockWrite data_writes[] = {
11821 MockWrite("GET / HTTP/1.1\r\n"
11822 "Host: www.google.com\r\n"
11823 "Connection: keep-alive\r\n"
11824 "X-Foo: bar\r\n\r\n"),
11826 MockRead data_reads[] = {
11827 MockRead("HTTP/1.1 200 OK\r\n"
11828 "Content-Length: 5\r\n\r\n"
11830 MockRead(ASYNC, ERR_UNEXPECTED),
11833 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
11834 data_writes, arraysize(data_writes));
11835 session_deps_.socket_factory->AddSocketDataProvider(&data);
11837 TestCompletionCallback callback;
11839 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
11840 EXPECT_EQ(ERR_IO_PENDING, rv);
11842 rv = callback.WaitForResult();
11845 HttpRequestHeaders request_headers;
11846 EXPECT_TRUE(trans->GetFullRequestHeaders(&request_headers));
11848 EXPECT_TRUE(request_headers.GetHeader("X-Foo", &foo));
11849 EXPECT_EQ("bar", foo);
11854 // Fake HttpStreamBase that simply records calls to SetPriority().
11855 class FakeStream : public HttpStreamBase,
11856 public base::SupportsWeakPtr<FakeStream> {
11858 explicit FakeStream(RequestPriority priority) : priority_(priority) {}
11859 virtual ~FakeStream() {}
11861 RequestPriority priority() const { return priority_; }
11863 virtual int InitializeStream(const HttpRequestInfo* request_info,
11864 RequestPriority priority,
11865 const BoundNetLog& net_log,
11866 const CompletionCallback& callback) OVERRIDE {
11867 return ERR_IO_PENDING;
11870 virtual int SendRequest(const HttpRequestHeaders& request_headers,
11871 HttpResponseInfo* response,
11872 const CompletionCallback& callback) OVERRIDE {
11874 return ERR_UNEXPECTED;
11877 virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
11879 return ERR_UNEXPECTED;
11882 virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
11887 virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
11888 const CompletionCallback& callback) OVERRIDE {
11890 return ERR_UNEXPECTED;
11893 virtual void Close(bool not_reusable) OVERRIDE {}
11895 virtual bool IsResponseBodyComplete() const OVERRIDE {
11900 virtual bool CanFindEndOfResponse() const OVERRIDE {
11904 virtual bool IsConnectionReused() const OVERRIDE {
11909 virtual void SetConnectionReused() OVERRIDE {
11913 virtual bool IsConnectionReusable() const OVERRIDE {
11918 virtual bool GetLoadTimingInfo(
11919 LoadTimingInfo* load_timing_info) const OVERRIDE {
11924 virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
11928 virtual void GetSSLCertRequestInfo(
11929 SSLCertRequestInfo* cert_request_info) OVERRIDE {
11933 virtual bool IsSpdyHttpStream() const OVERRIDE {
11938 virtual void Drain(HttpNetworkSession* session) OVERRIDE {
11942 virtual void SetPriority(RequestPriority priority) OVERRIDE {
11943 priority_ = priority;
11947 RequestPriority priority_;
11949 DISALLOW_COPY_AND_ASSIGN(FakeStream);
11952 // Fake HttpStreamRequest that simply records calls to SetPriority()
11953 // and vends FakeStreams with its current priority.
11954 class FakeStreamRequest : public HttpStreamRequest,
11955 public base::SupportsWeakPtr<FakeStreamRequest> {
11957 FakeStreamRequest(RequestPriority priority,
11958 HttpStreamRequest::Delegate* delegate)
11959 : priority_(priority),
11960 delegate_(delegate) {}
11962 virtual ~FakeStreamRequest() {}
11964 RequestPriority priority() const { return priority_; }
11966 // Create a new FakeStream and pass it to the request's
11967 // delegate. Returns a weak pointer to the FakeStream.
11968 base::WeakPtr<FakeStream> FinishStreamRequest() {
11969 FakeStream* fake_stream = new FakeStream(priority_);
11970 // Do this before calling OnStreamReady() as OnStreamReady() may
11971 // immediately delete |fake_stream|.
11972 base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
11973 delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
11974 return weak_stream;
11977 virtual int RestartTunnelWithProxyAuth(
11978 const AuthCredentials& credentials) OVERRIDE {
11980 return ERR_UNEXPECTED;
11983 virtual LoadState GetLoadState() const OVERRIDE {
11985 return LoadState();
11988 virtual void SetPriority(RequestPriority priority) OVERRIDE {
11989 priority_ = priority;
11992 virtual bool was_npn_negotiated() const OVERRIDE {
11996 virtual NextProto protocol_negotiated() const OVERRIDE {
11997 return kProtoUnknown;
12000 virtual bool using_spdy() const OVERRIDE {
12005 RequestPriority priority_;
12006 HttpStreamRequest::Delegate* const delegate_;
12008 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
12011 // Fake HttpStreamFactory that vends FakeStreamRequests.
12012 class FakeStreamFactory : public HttpStreamFactory {
12014 FakeStreamFactory() {}
12015 virtual ~FakeStreamFactory() {}
12017 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12018 // RequestStream() (which may be NULL if it was destroyed already).
12019 base::WeakPtr<FakeStreamRequest> last_stream_request() {
12020 return last_stream_request_;
12023 virtual HttpStreamRequest* RequestStream(
12024 const HttpRequestInfo& info,
12025 RequestPriority priority,
12026 const SSLConfig& server_ssl_config,
12027 const SSLConfig& proxy_ssl_config,
12028 HttpStreamRequest::Delegate* delegate,
12029 const BoundNetLog& net_log) OVERRIDE {
12030 FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
12031 last_stream_request_ = fake_request->AsWeakPtr();
12032 return fake_request;
12035 virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
12036 const HttpRequestInfo& info,
12037 RequestPriority priority,
12038 const SSLConfig& server_ssl_config,
12039 const SSLConfig& proxy_ssl_config,
12040 HttpStreamRequest::Delegate* delegate,
12041 WebSocketHandshakeStreamBase::Factory* factory,
12042 const BoundNetLog& net_log) OVERRIDE {
12047 virtual void PreconnectStreams(int num_streams,
12048 const HttpRequestInfo& info,
12049 RequestPriority priority,
12050 const SSLConfig& server_ssl_config,
12051 const SSLConfig& proxy_ssl_config) OVERRIDE {
12055 virtual base::Value* PipelineInfoToValue() const OVERRIDE {
12060 virtual const HostMappingRules* GetHostMappingRules() const OVERRIDE {
12066 base::WeakPtr<FakeStreamRequest> last_stream_request_;
12068 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
12073 // Make sure that HttpNetworkTransaction passes on its priority to its
12074 // stream request on start.
12075 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
12076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12077 HttpNetworkSessionPeer peer(session);
12078 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12079 peer.SetHttpStreamFactory(fake_factory);
12081 HttpNetworkTransaction trans(LOW, session);
12083 ASSERT_TRUE(fake_factory->last_stream_request() == NULL);
12085 HttpRequestInfo request;
12086 TestCompletionCallback callback;
12087 EXPECT_EQ(ERR_IO_PENDING,
12088 trans.Start(&request, callback.callback(), BoundNetLog()));
12090 base::WeakPtr<FakeStreamRequest> fake_request =
12091 fake_factory->last_stream_request();
12092 ASSERT_TRUE(fake_request != NULL);
12093 EXPECT_EQ(LOW, fake_request->priority());
12096 // Make sure that HttpNetworkTransaction passes on its priority
12097 // updates to its stream request.
12098 TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
12099 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12100 HttpNetworkSessionPeer peer(session);
12101 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12102 peer.SetHttpStreamFactory(fake_factory);
12104 HttpNetworkTransaction trans(LOW, session);
12106 HttpRequestInfo request;
12107 TestCompletionCallback callback;
12108 EXPECT_EQ(ERR_IO_PENDING,
12109 trans.Start(&request, callback.callback(), BoundNetLog()));
12111 base::WeakPtr<FakeStreamRequest> fake_request =
12112 fake_factory->last_stream_request();
12113 ASSERT_TRUE(fake_request != NULL);
12114 EXPECT_EQ(LOW, fake_request->priority());
12116 trans.SetPriority(LOWEST);
12117 ASSERT_TRUE(fake_request != NULL);
12118 EXPECT_EQ(LOWEST, fake_request->priority());
12121 // Make sure that HttpNetworkTransaction passes on its priority
12122 // updates to its stream.
12123 TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
12124 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12125 HttpNetworkSessionPeer peer(session);
12126 FakeStreamFactory* fake_factory = new FakeStreamFactory();
12127 peer.SetHttpStreamFactory(fake_factory);
12129 HttpNetworkTransaction trans(LOW, session);
12131 HttpRequestInfo request;
12132 TestCompletionCallback callback;
12133 EXPECT_EQ(ERR_IO_PENDING,
12134 trans.Start(&request, callback.callback(), BoundNetLog()));
12136 base::WeakPtr<FakeStreamRequest> fake_request =
12137 fake_factory->last_stream_request();
12138 ASSERT_TRUE(fake_request != NULL);
12139 base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
12140 ASSERT_TRUE(fake_stream != NULL);
12141 EXPECT_EQ(LOW, fake_stream->priority());
12143 trans.SetPriority(LOWEST);
12144 EXPECT_EQ(LOWEST, fake_stream->priority());
12147 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12148 // if the transport socket pool is stalled on the global socket limit.
12149 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
12150 ClientSocketPoolManager::set_max_sockets_per_group(
12151 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12152 ClientSocketPoolManager::set_max_sockets_per_pool(
12153 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12155 // Set up SSL request.
12157 HttpRequestInfo ssl_request;
12158 ssl_request.method = "GET";
12159 ssl_request.url = GURL("https://www.google.com/");
12161 MockWrite ssl_writes[] = {
12162 MockWrite("GET / HTTP/1.1\r\n"
12163 "Host: www.google.com\r\n"
12164 "Connection: keep-alive\r\n\r\n"),
12166 MockRead ssl_reads[] = {
12167 MockRead("HTTP/1.1 200 OK\r\n"),
12168 MockRead("Content-Length: 11\r\n\r\n"),
12169 MockRead("hello world"),
12170 MockRead(SYNCHRONOUS, OK),
12172 StaticSocketDataProvider ssl_data(ssl_reads, arraysize(ssl_reads),
12173 ssl_writes, arraysize(ssl_writes));
12174 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12176 SSLSocketDataProvider ssl(ASYNC, OK);
12177 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12179 // Set up HTTP request.
12181 HttpRequestInfo http_request;
12182 http_request.method = "GET";
12183 http_request.url = GURL("http://www.google.com/");
12185 MockWrite http_writes[] = {
12186 MockWrite("GET / HTTP/1.1\r\n"
12187 "Host: www.google.com\r\n"
12188 "Connection: keep-alive\r\n\r\n"),
12190 MockRead http_reads[] = {
12191 MockRead("HTTP/1.1 200 OK\r\n"),
12192 MockRead("Content-Length: 7\r\n\r\n"),
12193 MockRead("falafel"),
12194 MockRead(SYNCHRONOUS, OK),
12196 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12197 http_writes, arraysize(http_writes));
12198 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12200 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12202 // Start the SSL request.
12203 TestCompletionCallback ssl_callback;
12204 scoped_ptr<HttpTransaction> ssl_trans(
12205 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12206 ASSERT_EQ(ERR_IO_PENDING,
12207 ssl_trans->Start(&ssl_request, ssl_callback.callback(),
12210 // Start the HTTP request. Pool should stall.
12211 TestCompletionCallback http_callback;
12212 scoped_ptr<HttpTransaction> http_trans(
12213 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12214 ASSERT_EQ(ERR_IO_PENDING,
12215 http_trans->Start(&http_request, http_callback.callback(),
12217 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12219 // Wait for response from SSL request.
12220 ASSERT_EQ(OK, ssl_callback.WaitForResult());
12221 std::string response_data;
12222 ASSERT_EQ(OK, ReadTransaction(ssl_trans.get(), &response_data));
12223 EXPECT_EQ("hello world", response_data);
12225 // The SSL socket should automatically be closed, so the HTTP request can
12227 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12228 ASSERT_FALSE(IsTransportSocketPoolStalled(session));
12230 // The HTTP request can now complete.
12231 ASSERT_EQ(OK, http_callback.WaitForResult());
12232 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12233 EXPECT_EQ("falafel", response_data);
12235 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));
12238 // Tests that when a SSL connection is established but there's no corresponding
12239 // request that needs it, the new socket is closed if the transport socket pool
12240 // is stalled on the global socket limit.
12241 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
12242 ClientSocketPoolManager::set_max_sockets_per_group(
12243 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12244 ClientSocketPoolManager::set_max_sockets_per_pool(
12245 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
12247 // Set up an ssl request.
12249 HttpRequestInfo ssl_request;
12250 ssl_request.method = "GET";
12251 ssl_request.url = GURL("https://www.foopy.com/");
12253 // No data will be sent on the SSL socket.
12254 StaticSocketDataProvider ssl_data;
12255 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
12257 SSLSocketDataProvider ssl(ASYNC, OK);
12258 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12260 // Set up HTTP request.
12262 HttpRequestInfo http_request;
12263 http_request.method = "GET";
12264 http_request.url = GURL("http://www.google.com/");
12266 MockWrite http_writes[] = {
12267 MockWrite("GET / HTTP/1.1\r\n"
12268 "Host: www.google.com\r\n"
12269 "Connection: keep-alive\r\n\r\n"),
12271 MockRead http_reads[] = {
12272 MockRead("HTTP/1.1 200 OK\r\n"),
12273 MockRead("Content-Length: 7\r\n\r\n"),
12274 MockRead("falafel"),
12275 MockRead(SYNCHRONOUS, OK),
12277 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
12278 http_writes, arraysize(http_writes));
12279 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
12281 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12283 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12284 // cancelled when a normal transaction is cancelled.
12285 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory();
12286 net::SSLConfig ssl_config;
12287 session->ssl_config_service()->GetSSLConfig(&ssl_config);
12288 http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY,
12289 ssl_config, ssl_config);
12290 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session));
12292 // Start the HTTP request. Pool should stall.
12293 TestCompletionCallback http_callback;
12294 scoped_ptr<HttpTransaction> http_trans(
12295 new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
12296 ASSERT_EQ(ERR_IO_PENDING,
12297 http_trans->Start(&http_request, http_callback.callback(),
12299 EXPECT_TRUE(IsTransportSocketPoolStalled(session));
12301 // The SSL connection will automatically be closed once the connection is
12302 // established, to let the HTTP request start.
12303 ASSERT_EQ(OK, http_callback.WaitForResult());
12304 std::string response_data;
12305 ASSERT_EQ(OK, ReadTransaction(http_trans.get(), &response_data));
12306 EXPECT_EQ("falafel", response_data);
12308 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session));