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/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/test_file_util.h"
23 #include "net/base/auth.h"
24 #include "net/base/capturing_net_log.h"
25 #include "net/base/completion_callback.h"
26 #include "net/base/load_timing_info.h"
27 #include "net/base/load_timing_info_test_util.h"
28 #include "net/base/net_log.h"
29 #include "net/base/net_log_unittest.h"
30 #include "net/base/request_priority.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/test_data_directory.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/upload_data_stream.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_stream.h"
44 #include "net/http/http_network_session.h"
45 #include "net/http/http_network_session_peer.h"
46 #include "net/http/http_server_properties_impl.h"
47 #include "net/http/http_stream.h"
48 #include "net/http/http_stream_factory.h"
49 #include "net/http/http_transaction_test_util.h"
50 #include "net/proxy/proxy_config_service_fixed.h"
51 #include "net/proxy/proxy_info.h"
52 #include "net/proxy/proxy_resolver.h"
53 #include "net/proxy/proxy_service.h"
54 #include "net/socket/client_socket_factory.h"
55 #include "net/socket/client_socket_pool_manager.h"
56 #include "net/socket/mock_client_socket_pool_manager.h"
57 #include "net/socket/next_proto.h"
58 #include "net/socket/socket_test_util.h"
59 #include "net/socket/ssl_client_socket.h"
60 #include "net/spdy/spdy_framer.h"
61 #include "net/spdy/spdy_session.h"
62 #include "net/spdy/spdy_session_pool.h"
63 #include "net/spdy/spdy_test_util_common.h"
64 #include "net/ssl/ssl_cert_request_info.h"
65 #include "net/ssl/ssl_config_service.h"
66 #include "net/ssl/ssl_config_service_defaults.h"
67 #include "net/ssl/ssl_info.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/websockets/websocket_handshake_stream_base.h"
70 #include "testing/gtest/include/gtest/gtest.h"
71 #include "testing/platform_test.h"
74 using base::ASCIIToUTF16
;
76 //-----------------------------------------------------------------------------
80 const base::string16
kBar(ASCIIToUTF16("bar"));
81 const base::string16
kBar2(ASCIIToUTF16("bar2"));
82 const base::string16
kBar3(ASCIIToUTF16("bar3"));
83 const base::string16
kBaz(ASCIIToUTF16("baz"));
84 const base::string16
kFirst(ASCIIToUTF16("first"));
85 const base::string16
kFoo(ASCIIToUTF16("foo"));
86 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
87 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
88 const base::string16
kFou(ASCIIToUTF16("fou"));
89 const base::string16
kSecond(ASCIIToUTF16("second"));
90 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession
* session
) {
94 return session
->GetTransportSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession
* session
) {
99 return session
->GetSSLSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession
* session
) {
104 return session
->GetTransportSocketPool(
105 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IsStalled();
108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
109 // a JSONified list of headers as a single string. Uses single quotes instead
110 // of double quotes for easier comparison. Returns false on failure.
111 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
114 base::ListValue
* header_list
;
115 if (!params
->GetList("headers", &header_list
))
117 std::string double_quote_headers
;
118 base::JSONWriter::Write(header_list
, &double_quote_headers
);
119 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
125 void TestLoadTimingReused(const net::LoadTimingInfo
& load_timing_info
) {
126 EXPECT_TRUE(load_timing_info
.socket_reused
);
127 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
129 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
130 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
132 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
133 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
135 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
137 // Set at a higher level.
138 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
139 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
140 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
145 void TestLoadTimingNotReused(const net::LoadTimingInfo
& load_timing_info
,
146 int connect_timing_flags
) {
147 EXPECT_FALSE(load_timing_info
.socket_reused
);
148 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
150 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
151 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
153 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
154 connect_timing_flags
);
155 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
156 load_timing_info
.send_start
);
158 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
160 // Set at a higher level.
161 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
162 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
163 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo
& load_timing_info
) {
169 EXPECT_TRUE(load_timing_info
.socket_reused
);
170 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
172 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
174 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
175 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
176 load_timing_info
.proxy_resolve_end
);
177 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
178 load_timing_info
.send_start
);
179 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
181 // Set at a higher level.
182 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
183 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
184 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo
& load_timing_info
,
190 int connect_timing_flags
) {
191 EXPECT_FALSE(load_timing_info
.socket_reused
);
192 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
194 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
195 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
196 load_timing_info
.proxy_resolve_end
);
197 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
198 load_timing_info
.connect_timing
.connect_start
);
199 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
200 connect_timing_flags
);
201 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
202 load_timing_info
.send_start
);
204 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
206 // Set at a higher level.
207 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
208 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
209 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
218 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
219 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
224 class HttpNetworkTransactionTest
225 : public PlatformTest
,
226 public ::testing::WithParamInterface
<NextProto
> {
228 virtual ~HttpNetworkTransactionTest() {
229 // Important to restore the per-pool limit first, since the pool limit must
230 // always be greater than group limit, and the tests reduce both limits.
231 ClientSocketPoolManager::set_max_sockets_per_pool(
232 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
233 ClientSocketPoolManager::set_max_sockets_per_group(
234 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
238 HttpNetworkTransactionTest()
239 : spdy_util_(GetParam()),
240 session_deps_(GetParam()),
241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
247 struct SimpleGetHelperResult
{
249 std::string status_line
;
250 std::string response_data
;
251 int64 totalReceivedBytes
;
252 LoadTimingInfo load_timing_info
;
255 virtual void SetUp() {
256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257 base::MessageLoop::current()->RunUntilIdle();
260 virtual void TearDown() {
261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262 base::MessageLoop::current()->RunUntilIdle();
263 // Empty the current queue.
264 base::MessageLoop::current()->RunUntilIdle();
265 PlatformTest::TearDown();
266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267 base::MessageLoop::current()->RunUntilIdle();
270 // This is the expected return from a current server advertising SPDY.
271 std::string
GetAlternateProtocolHttpHeader() {
273 std::string("Alternate-Protocol: 443:") +
274 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
278 // Either |write_failure| specifies a write failure or |read_failure|
279 // specifies a read failure when using a reused socket. In either case, the
280 // failure should cause the network transaction to resend the request, and the
281 // other argument should be NULL.
282 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
283 const MockRead
* read_failure
);
285 // Either |write_failure| specifies a write failure or |read_failure|
286 // specifies a read failure when using a reused socket. In either case, the
287 // failure should cause the network transaction to resend the request, and the
288 // other argument should be NULL.
289 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
290 const MockRead
* read_failure
,
293 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
295 SimpleGetHelperResult out
;
297 HttpRequestInfo request
;
298 request
.method
= "GET";
299 request
.url
= GURL("http://www.google.com/");
300 request
.load_flags
= 0;
302 CapturingBoundNetLog log
;
303 session_deps_
.net_log
= log
.bound().net_log();
304 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
305 scoped_ptr
<HttpTransaction
> trans(
306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
308 for (size_t i
= 0; i
< data_count
; ++i
) {
309 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
312 TestCompletionCallback callback
;
314 EXPECT_TRUE(log
.bound().IsLogging());
315 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
316 EXPECT_EQ(ERR_IO_PENDING
, rv
);
318 out
.rv
= callback
.WaitForResult();
320 // Even in the failure cases that use this function, connections are always
321 // successfully established before the error.
322 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
323 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
328 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
329 // Can't use ASSERT_* inside helper functions like this, so
331 if (response
== NULL
|| response
->headers
.get() == NULL
) {
332 out
.rv
= ERR_UNEXPECTED
;
335 out
.status_line
= response
->headers
->GetStatusLine();
337 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
338 EXPECT_EQ(80, response
->socket_address
.port());
340 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
343 net::CapturingNetLog::CapturedEntryList entries
;
344 log
.GetEntries(&entries
);
345 size_t pos
= ExpectLogContainsSomewhere(
346 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
348 ExpectLogContainsSomewhere(
350 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
354 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
355 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
357 HttpRequestHeaders request_headers
;
358 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
360 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
361 EXPECT_EQ("www.google.com", value
);
362 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
363 EXPECT_EQ("keep-alive", value
);
365 std::string response_headers
;
366 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
367 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
370 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
374 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
375 size_t reads_count
) {
376 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
377 StaticSocketDataProvider
* data
[] = { &reads
};
378 return SimpleGetHelperForData(data
, 1);
381 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
383 for (size_t i
= 0; i
< reads_count
; ++i
)
384 size
+= data_reads
[i
].data_len
;
388 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
389 int expected_status
);
391 void ConnectStatusHelper(const MockRead
& status
);
393 void BypassHostCacheOnRefreshHelper(int load_flags
);
395 void CheckErrorIsPassedBack(int error
, IoMode mode
);
397 SpdyTestUtil spdy_util_
;
398 SpdySessionDependencies session_deps_
;
400 // Original socket limits. Some tests set these. Safest to always restore
401 // them once each test has been run.
402 int old_max_group_sockets_
;
403 int old_max_pool_sockets_
;
406 INSTANTIATE_TEST_CASE_P(
408 HttpNetworkTransactionTest
,
409 testing::Values(kProtoDeprecatedSPDY2
,
410 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4
));
414 class BeforeNetworkStartHandler
{
416 explicit BeforeNetworkStartHandler(bool defer
)
417 : defer_on_before_network_start_(defer
),
418 observed_before_network_start_(false) {}
420 void OnBeforeNetworkStart(bool* defer
) {
421 *defer
= defer_on_before_network_start_
;
422 observed_before_network_start_
= true;
425 bool observed_before_network_start() const {
426 return observed_before_network_start_
;
430 const bool defer_on_before_network_start_
;
431 bool observed_before_network_start_
;
433 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
436 class BeforeProxyHeadersSentHandler
{
438 BeforeProxyHeadersSentHandler()
439 : observed_before_proxy_headers_sent_(false) {}
441 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
442 HttpRequestHeaders
* request_headers
) {
443 observed_before_proxy_headers_sent_
= true;
444 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
447 bool observed_before_proxy_headers_sent() const {
448 return observed_before_proxy_headers_sent_
;
451 std::string
observed_proxy_server_uri() const {
452 return observed_proxy_server_uri_
;
456 bool observed_before_proxy_headers_sent_
;
457 std::string observed_proxy_server_uri_
;
459 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
462 // Fill |str| with a long header list that consumes >= |size| bytes.
463 void FillLargeHeadersString(std::string
* str
, int size
) {
465 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
466 const int sizeof_row
= strlen(row
);
467 const int num_rows
= static_cast<int>(
468 ceil(static_cast<float>(size
) / sizeof_row
));
469 const int sizeof_data
= num_rows
* sizeof_row
;
470 DCHECK(sizeof_data
>= size
);
471 str
->reserve(sizeof_data
);
473 for (int i
= 0; i
< num_rows
; ++i
)
474 str
->append(row
, sizeof_row
);
477 // Alternative functions that eliminate randomness and dependency on the local
478 // host name so that the generated NTLM messages are reproducible.
479 void MockGenerateRandom1(uint8
* output
, size_t n
) {
480 static const uint8 bytes
[] = {
481 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
483 static size_t current_byte
= 0;
484 for (size_t i
= 0; i
< n
; ++i
) {
485 output
[i
] = bytes
[current_byte
++];
486 current_byte
%= arraysize(bytes
);
490 void MockGenerateRandom2(uint8
* output
, size_t n
) {
491 static const uint8 bytes
[] = {
492 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
493 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
495 static size_t current_byte
= 0;
496 for (size_t i
= 0; i
< n
; ++i
) {
497 output
[i
] = bytes
[current_byte
++];
498 current_byte
%= arraysize(bytes
);
502 std::string
MockGetHostName() {
506 template<typename ParentPool
>
507 class CaptureGroupNameSocketPool
: public ParentPool
{
509 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
510 CertVerifier
* cert_verifier
);
512 const std::string
last_group_name_received() const {
513 return last_group_name_
;
516 virtual int RequestSocket(const std::string
& group_name
,
517 const void* socket_params
,
518 RequestPriority priority
,
519 ClientSocketHandle
* handle
,
520 const CompletionCallback
& callback
,
521 const BoundNetLog
& net_log
) {
522 last_group_name_
= group_name
;
523 return ERR_IO_PENDING
;
525 virtual void CancelRequest(const std::string
& group_name
,
526 ClientSocketHandle
* handle
) {}
527 virtual void ReleaseSocket(const std::string
& group_name
,
528 scoped_ptr
<StreamSocket
> socket
,
530 virtual void CloseIdleSockets() {}
531 virtual int IdleSocketCount() const {
534 virtual int IdleSocketCountInGroup(const std::string
& group_name
) const {
537 virtual LoadState
GetLoadState(const std::string
& group_name
,
538 const ClientSocketHandle
* handle
) const {
539 return LOAD_STATE_IDLE
;
541 virtual base::TimeDelta
ConnectionTimeout() const {
542 return base::TimeDelta();
546 std::string last_group_name_
;
549 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
550 CaptureGroupNameTransportSocketPool
;
551 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
552 CaptureGroupNameHttpProxySocketPool
;
553 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
554 CaptureGroupNameSOCKSSocketPool
;
555 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
556 CaptureGroupNameSSLSocketPool
;
558 template<typename ParentPool
>
559 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
560 HostResolver
* host_resolver
,
561 CertVerifier
* /* cert_verifier */)
562 : ParentPool(0, 0, NULL
, host_resolver
, NULL
, NULL
) {}
565 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
566 HostResolver
* host_resolver
,
567 CertVerifier
* /* cert_verifier */)
568 : HttpProxyClientSocketPool(0, 0, NULL
, host_resolver
, NULL
, NULL
, NULL
) {}
571 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
572 HostResolver
* host_resolver
,
573 CertVerifier
* cert_verifier
)
574 : SSLClientSocketPool(0,
592 //-----------------------------------------------------------------------------
594 // Helper functions for validating that AuthChallengeInfo's are correctly
595 // configured for common cases.
596 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
599 EXPECT_FALSE(auth_challenge
->is_proxy
);
600 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
601 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
602 EXPECT_EQ("basic", auth_challenge
->scheme
);
606 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
609 EXPECT_TRUE(auth_challenge
->is_proxy
);
610 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
611 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
612 EXPECT_EQ("basic", auth_challenge
->scheme
);
616 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
619 EXPECT_FALSE(auth_challenge
->is_proxy
);
620 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
621 EXPECT_EQ("digestive", auth_challenge
->realm
);
622 EXPECT_EQ("digest", auth_challenge
->scheme
);
626 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
629 EXPECT_FALSE(auth_challenge
->is_proxy
);
630 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
631 EXPECT_EQ(std::string(), auth_challenge
->realm
);
632 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
638 TEST_P(HttpNetworkTransactionTest
, Basic
) {
639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
640 scoped_ptr
<HttpTransaction
> trans(
641 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
644 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
645 MockRead data_reads
[] = {
646 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
647 MockRead("hello world"),
648 MockRead(SYNCHRONOUS
, OK
),
650 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
651 arraysize(data_reads
));
652 EXPECT_EQ(OK
, out
.rv
);
653 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
654 EXPECT_EQ("hello world", out
.response_data
);
655 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
656 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
659 // Response with no status line.
660 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
661 MockRead data_reads
[] = {
662 MockRead("hello world"),
663 MockRead(SYNCHRONOUS
, OK
),
665 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
666 arraysize(data_reads
));
667 EXPECT_EQ(OK
, out
.rv
);
668 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
669 EXPECT_EQ("hello world", out
.response_data
);
670 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
671 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
674 // Allow up to 4 bytes of junk to precede status line.
675 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
676 MockRead data_reads
[] = {
677 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
678 MockRead(SYNCHRONOUS
, OK
),
680 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
681 arraysize(data_reads
));
682 EXPECT_EQ(OK
, out
.rv
);
683 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
684 EXPECT_EQ("DATA", out
.response_data
);
685 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
686 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
689 // Allow up to 4 bytes of junk to precede status line.
690 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
691 MockRead data_reads
[] = {
692 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
693 MockRead(SYNCHRONOUS
, OK
),
695 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
696 arraysize(data_reads
));
697 EXPECT_EQ(OK
, out
.rv
);
698 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
699 EXPECT_EQ("DATA", out
.response_data
);
700 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
701 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
704 // Beyond 4 bytes of slop and it should fail to find a status line.
705 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
706 MockRead data_reads
[] = {
707 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
708 MockRead(SYNCHRONOUS
, OK
),
710 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
711 arraysize(data_reads
));
712 EXPECT_EQ(OK
, out
.rv
);
713 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
714 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
715 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
716 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
719 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
720 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
721 MockRead data_reads
[] = {
726 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
727 MockRead(SYNCHRONOUS
, OK
),
729 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
730 arraysize(data_reads
));
731 EXPECT_EQ(OK
, out
.rv
);
732 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
733 EXPECT_EQ("DATA", out
.response_data
);
734 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
735 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
738 // Close the connection before enough bytes to have a status line.
739 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
740 MockRead data_reads
[] = {
742 MockRead(SYNCHRONOUS
, OK
),
744 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
745 arraysize(data_reads
));
746 EXPECT_EQ(OK
, out
.rv
);
747 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
748 EXPECT_EQ("HTT", out
.response_data
);
749 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
750 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
753 // Simulate a 204 response, lacking a Content-Length header, sent over a
754 // persistent connection. The response should still terminate since a 204
755 // cannot have a response body.
756 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
757 char junk
[] = "junk";
758 MockRead data_reads
[] = {
759 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
760 MockRead(junk
), // Should not be read!!
761 MockRead(SYNCHRONOUS
, OK
),
763 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
764 arraysize(data_reads
));
765 EXPECT_EQ(OK
, out
.rv
);
766 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
767 EXPECT_EQ("", out
.response_data
);
768 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
769 int64 response_size
= reads_size
- strlen(junk
);
770 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
773 // A simple request using chunked encoding with some extra data after.
774 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
775 std::string final_chunk
= "0\r\n\r\n";
776 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
777 std::string last_read
= final_chunk
+ extra_data
;
778 MockRead data_reads
[] = {
779 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
780 MockRead("5\r\nHello\r\n"),
783 MockRead("5\r\nworld\r\n"),
784 MockRead(last_read
.data()),
785 MockRead(SYNCHRONOUS
, OK
),
787 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
788 arraysize(data_reads
));
789 EXPECT_EQ(OK
, out
.rv
);
790 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
791 EXPECT_EQ("Hello world", out
.response_data
);
792 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
793 int64 response_size
= reads_size
- extra_data
.size();
794 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
797 // Next tests deal with http://crbug.com/56344.
799 TEST_P(HttpNetworkTransactionTest
,
800 MultipleContentLengthHeadersNoTransferEncoding
) {
801 MockRead data_reads
[] = {
802 MockRead("HTTP/1.1 200 OK\r\n"),
803 MockRead("Content-Length: 10\r\n"),
804 MockRead("Content-Length: 5\r\n\r\n"),
806 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
807 arraysize(data_reads
));
808 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
811 TEST_P(HttpNetworkTransactionTest
,
812 DuplicateContentLengthHeadersNoTransferEncoding
) {
813 MockRead data_reads
[] = {
814 MockRead("HTTP/1.1 200 OK\r\n"),
815 MockRead("Content-Length: 5\r\n"),
816 MockRead("Content-Length: 5\r\n\r\n"),
819 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
820 arraysize(data_reads
));
821 EXPECT_EQ(OK
, out
.rv
);
822 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
823 EXPECT_EQ("Hello", out
.response_data
);
826 TEST_P(HttpNetworkTransactionTest
,
827 ComplexContentLengthHeadersNoTransferEncoding
) {
828 // More than 2 dupes.
830 MockRead data_reads
[] = {
831 MockRead("HTTP/1.1 200 OK\r\n"),
832 MockRead("Content-Length: 5\r\n"),
833 MockRead("Content-Length: 5\r\n"),
834 MockRead("Content-Length: 5\r\n\r\n"),
837 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
838 arraysize(data_reads
));
839 EXPECT_EQ(OK
, out
.rv
);
840 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
841 EXPECT_EQ("Hello", out
.response_data
);
845 MockRead data_reads
[] = {
846 MockRead("HTTP/1.0 200 OK\r\n"),
847 MockRead("Content-Length: 5\r\n"),
848 MockRead("Content-Length: 5\r\n"),
849 MockRead("Content-Length: 5\r\n\r\n"),
852 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
853 arraysize(data_reads
));
854 EXPECT_EQ(OK
, out
.rv
);
855 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
856 EXPECT_EQ("Hello", out
.response_data
);
858 // 2 dupes and one mismatched.
860 MockRead data_reads
[] = {
861 MockRead("HTTP/1.1 200 OK\r\n"),
862 MockRead("Content-Length: 10\r\n"),
863 MockRead("Content-Length: 10\r\n"),
864 MockRead("Content-Length: 5\r\n\r\n"),
866 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
867 arraysize(data_reads
));
868 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
872 TEST_P(HttpNetworkTransactionTest
,
873 MultipleContentLengthHeadersTransferEncoding
) {
874 MockRead data_reads
[] = {
875 MockRead("HTTP/1.1 200 OK\r\n"),
876 MockRead("Content-Length: 666\r\n"),
877 MockRead("Content-Length: 1337\r\n"),
878 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
879 MockRead("5\r\nHello\r\n"),
882 MockRead("5\r\nworld\r\n"),
883 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
884 MockRead(SYNCHRONOUS
, OK
),
886 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
887 arraysize(data_reads
));
888 EXPECT_EQ(OK
, out
.rv
);
889 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
890 EXPECT_EQ("Hello world", out
.response_data
);
893 // Next tests deal with http://crbug.com/98895.
895 // Checks that a single Content-Disposition header results in no error.
896 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
897 MockRead data_reads
[] = {
898 MockRead("HTTP/1.1 200 OK\r\n"),
899 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
900 MockRead("Content-Length: 5\r\n\r\n"),
903 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
904 arraysize(data_reads
));
905 EXPECT_EQ(OK
, out
.rv
);
906 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
907 EXPECT_EQ("Hello", out
.response_data
);
910 // Checks that two identical Content-Disposition headers result in no error.
911 TEST_P(HttpNetworkTransactionTest
,
912 TwoIdenticalContentDispositionHeaders
) {
913 MockRead data_reads
[] = {
914 MockRead("HTTP/1.1 200 OK\r\n"),
915 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
916 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
917 MockRead("Content-Length: 5\r\n\r\n"),
920 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
921 arraysize(data_reads
));
922 EXPECT_EQ(OK
, out
.rv
);
923 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
924 EXPECT_EQ("Hello", out
.response_data
);
927 // Checks that two distinct Content-Disposition headers result in an error.
928 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
929 MockRead data_reads
[] = {
930 MockRead("HTTP/1.1 200 OK\r\n"),
931 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
932 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
933 MockRead("Content-Length: 5\r\n\r\n"),
936 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
937 arraysize(data_reads
));
938 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
941 // Checks that two identical Location headers result in no error.
942 // Also tests Location header behavior.
943 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
944 MockRead data_reads
[] = {
945 MockRead("HTTP/1.1 302 Redirect\r\n"),
946 MockRead("Location: http://good.com/\r\n"),
947 MockRead("Location: http://good.com/\r\n"),
948 MockRead("Content-Length: 0\r\n\r\n"),
949 MockRead(SYNCHRONOUS
, OK
),
952 HttpRequestInfo request
;
953 request
.method
= "GET";
954 request
.url
= GURL("http://redirect.com/");
955 request
.load_flags
= 0;
957 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
958 scoped_ptr
<HttpTransaction
> trans(
959 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
961 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
962 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
964 TestCompletionCallback callback
;
966 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
967 EXPECT_EQ(ERR_IO_PENDING
, rv
);
969 EXPECT_EQ(OK
, callback
.WaitForResult());
971 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
972 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
973 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
975 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
976 EXPECT_EQ("http://good.com/", url
);
977 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
980 // Checks that two distinct Location headers result in an error.
981 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
982 MockRead data_reads
[] = {
983 MockRead("HTTP/1.1 302 Redirect\r\n"),
984 MockRead("Location: http://good.com/\r\n"),
985 MockRead("Location: http://evil.com/\r\n"),
986 MockRead("Content-Length: 0\r\n\r\n"),
987 MockRead(SYNCHRONOUS
, OK
),
989 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
990 arraysize(data_reads
));
991 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
994 // Do a request using the HEAD method. Verify that we don't try to read the
995 // message body (since HEAD has none).
996 TEST_P(HttpNetworkTransactionTest
, Head
) {
997 HttpRequestInfo request
;
998 request
.method
= "HEAD";
999 request
.url
= GURL("http://www.google.com/");
1000 request
.load_flags
= 0;
1002 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1003 scoped_ptr
<HttpTransaction
> trans(
1004 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1005 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1006 trans
->SetBeforeProxyHeadersSentCallback(
1007 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1008 base::Unretained(&proxy_headers_handler
)));
1010 MockWrite data_writes1
[] = {
1011 MockWrite("HEAD / HTTP/1.1\r\n"
1012 "Host: www.google.com\r\n"
1013 "Connection: keep-alive\r\n"
1014 "Content-Length: 0\r\n\r\n"),
1016 MockRead data_reads1
[] = {
1017 MockRead("HTTP/1.1 404 Not Found\r\n"),
1018 MockRead("Server: Blah\r\n"),
1019 MockRead("Content-Length: 1234\r\n\r\n"),
1021 // No response body because the test stops reading here.
1022 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1025 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1026 data_writes1
, arraysize(data_writes1
));
1027 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1029 TestCompletionCallback callback1
;
1031 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1034 rv
= callback1
.WaitForResult();
1037 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1038 ASSERT_TRUE(response
!= NULL
);
1040 // Check that the headers got parsed.
1041 EXPECT_TRUE(response
->headers
.get() != NULL
);
1042 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1043 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1044 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1045 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1047 std::string server_header
;
1049 bool has_server_header
= response
->headers
->EnumerateHeader(
1050 &iter
, "Server", &server_header
);
1051 EXPECT_TRUE(has_server_header
);
1052 EXPECT_EQ("Blah", server_header
);
1054 // Reading should give EOF right away, since there is no message body
1055 // (despite non-zero content-length).
1056 std::string response_data
;
1057 rv
= ReadTransaction(trans
.get(), &response_data
);
1059 EXPECT_EQ("", response_data
);
1062 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1065 MockRead data_reads
[] = {
1066 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1068 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1070 MockRead(SYNCHRONOUS
, OK
),
1072 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1073 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1075 const char* const kExpectedResponseData
[] = {
1079 for (int i
= 0; i
< 2; ++i
) {
1080 HttpRequestInfo request
;
1081 request
.method
= "GET";
1082 request
.url
= GURL("http://www.google.com/");
1083 request
.load_flags
= 0;
1085 scoped_ptr
<HttpTransaction
> trans(
1086 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1088 TestCompletionCallback callback
;
1090 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1091 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1093 rv
= callback
.WaitForResult();
1096 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1097 ASSERT_TRUE(response
!= NULL
);
1099 EXPECT_TRUE(response
->headers
.get() != NULL
);
1100 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1101 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1103 std::string response_data
;
1104 rv
= ReadTransaction(trans
.get(), &response_data
);
1106 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1110 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1111 ScopedVector
<UploadElementReader
> element_readers
;
1112 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1113 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1115 HttpRequestInfo request
;
1116 request
.method
= "POST";
1117 request
.url
= GURL("http://www.foo.com/");
1118 request
.upload_data_stream
= &upload_data_stream
;
1119 request
.load_flags
= 0;
1121 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1122 scoped_ptr
<HttpTransaction
> trans(
1123 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1125 MockRead data_reads
[] = {
1126 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1127 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1128 MockRead("hello world"),
1129 MockRead(SYNCHRONOUS
, OK
),
1131 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1132 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1134 TestCompletionCallback callback
;
1136 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1137 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1139 rv
= callback
.WaitForResult();
1142 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1143 ASSERT_TRUE(response
!= NULL
);
1145 EXPECT_TRUE(response
->headers
.get() != NULL
);
1146 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1148 std::string response_data
;
1149 rv
= ReadTransaction(trans
.get(), &response_data
);
1151 EXPECT_EQ("hello world", response_data
);
1154 // This test is almost the same as Ignores100 above, but the response contains
1155 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1156 // HTTP/1.1 and the two status headers are read in one read.
1157 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1158 HttpRequestInfo request
;
1159 request
.method
= "GET";
1160 request
.url
= GURL("http://www.foo.com/");
1161 request
.load_flags
= 0;
1163 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1164 scoped_ptr
<HttpTransaction
> trans(
1165 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1167 MockRead data_reads
[] = {
1168 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1169 "HTTP/1.1 200 OK\r\n\r\n"),
1170 MockRead("hello world"),
1171 MockRead(SYNCHRONOUS
, OK
),
1173 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1174 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1176 TestCompletionCallback callback
;
1178 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1181 rv
= callback
.WaitForResult();
1184 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1185 ASSERT_TRUE(response
!= NULL
);
1187 EXPECT_TRUE(response
->headers
.get() != NULL
);
1188 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1190 std::string response_data
;
1191 rv
= ReadTransaction(trans
.get(), &response_data
);
1193 EXPECT_EQ("hello world", response_data
);
1196 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1197 HttpRequestInfo request
;
1198 request
.method
= "POST";
1199 request
.url
= GURL("http://www.foo.com/");
1200 request
.load_flags
= 0;
1202 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1203 scoped_ptr
<HttpTransaction
> trans(
1204 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1206 MockRead data_reads
[] = {
1207 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1210 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1211 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1213 TestCompletionCallback callback
;
1215 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1216 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1218 rv
= callback
.WaitForResult();
1221 std::string response_data
;
1222 rv
= ReadTransaction(trans
.get(), &response_data
);
1224 EXPECT_EQ("", response_data
);
1227 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1228 HttpRequestInfo request
;
1229 request
.method
= "POST";
1230 request
.url
= GURL("http://www.foo.com/");
1231 request
.load_flags
= 0;
1233 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1234 scoped_ptr
<HttpTransaction
> trans(
1235 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1237 MockRead data_reads
[] = {
1240 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1241 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1243 TestCompletionCallback callback
;
1245 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1246 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1248 rv
= callback
.WaitForResult();
1249 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1252 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1253 const MockWrite
* write_failure
,
1254 const MockRead
* read_failure
) {
1255 HttpRequestInfo request
;
1256 request
.method
= "GET";
1257 request
.url
= GURL("http://www.foo.com/");
1258 request
.load_flags
= 0;
1260 CapturingNetLog net_log
;
1261 session_deps_
.net_log
= &net_log
;
1262 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1264 // Written data for successfully sending both requests.
1265 MockWrite data1_writes
[] = {
1266 MockWrite("GET / HTTP/1.1\r\n"
1267 "Host: www.foo.com\r\n"
1268 "Connection: keep-alive\r\n\r\n"),
1269 MockWrite("GET / HTTP/1.1\r\n"
1270 "Host: www.foo.com\r\n"
1271 "Connection: keep-alive\r\n\r\n")
1274 // Read results for the first request.
1275 MockRead data1_reads
[] = {
1276 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1278 MockRead(ASYNC
, OK
),
1281 if (write_failure
) {
1282 ASSERT_FALSE(read_failure
);
1283 data1_writes
[1] = *write_failure
;
1285 ASSERT_TRUE(read_failure
);
1286 data1_reads
[2] = *read_failure
;
1289 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1290 data1_writes
, arraysize(data1_writes
));
1291 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1293 MockRead data2_reads
[] = {
1294 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1296 MockRead(ASYNC
, OK
),
1298 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1299 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1301 const char* kExpectedResponseData
[] = {
1305 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1306 for (int i
= 0; i
< 2; ++i
) {
1307 TestCompletionCallback callback
;
1309 scoped_ptr
<HttpTransaction
> trans(
1310 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1312 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1313 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1315 rv
= callback
.WaitForResult();
1318 LoadTimingInfo load_timing_info
;
1319 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1320 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1322 first_socket_log_id
= load_timing_info
.socket_log_id
;
1324 // The second request should be using a new socket.
1325 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1328 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1329 ASSERT_TRUE(response
!= NULL
);
1331 EXPECT_TRUE(response
->headers
.get() != NULL
);
1332 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1334 std::string response_data
;
1335 rv
= ReadTransaction(trans
.get(), &response_data
);
1337 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1341 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1342 const MockWrite
* write_failure
,
1343 const MockRead
* read_failure
,
1345 HttpRequestInfo request
;
1346 request
.method
= "GET";
1347 request
.url
= GURL("https://www.foo.com/");
1348 request
.load_flags
= 0;
1350 CapturingNetLog net_log
;
1351 session_deps_
.net_log
= &net_log
;
1352 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1354 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1355 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1357 ssl1
.SetNextProto(GetParam());
1358 ssl2
.SetNextProto(GetParam());
1360 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1361 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1363 // SPDY versions of the request and response.
1364 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1365 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1366 scoped_ptr
<SpdyFrame
> spdy_response(
1367 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1368 scoped_ptr
<SpdyFrame
> spdy_data(
1369 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1371 // HTTP/1.1 versions of the request and response.
1372 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1373 "Host: www.foo.com\r\n"
1374 "Connection: keep-alive\r\n\r\n";
1375 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1376 const char kHttpData
[] = "hello";
1378 std::vector
<MockRead
> data1_reads
;
1379 std::vector
<MockWrite
> data1_writes
;
1380 if (write_failure
) {
1381 ASSERT_FALSE(read_failure
);
1382 data1_writes
.push_back(*write_failure
);
1383 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1385 ASSERT_TRUE(read_failure
);
1387 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1389 data1_writes
.push_back(MockWrite(kHttpRequest
));
1391 data1_reads
.push_back(*read_failure
);
1394 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1395 &data1_writes
[0], data1_writes
.size());
1396 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1398 std::vector
<MockRead
> data2_reads
;
1399 std::vector
<MockWrite
> data2_writes
;
1402 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1404 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1405 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1406 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1408 data2_writes
.push_back(
1409 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1411 data2_reads
.push_back(
1412 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1413 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1414 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1416 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1417 &data2_writes
[0], data2_writes
.size());
1418 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1420 // Preconnect a socket.
1421 net::SSLConfig ssl_config
;
1422 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1423 session
->GetNextProtos(&ssl_config
.next_protos
);
1424 session
->http_stream_factory()->PreconnectStreams(
1425 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1426 // Wait for the preconnect to complete.
1427 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1428 base::RunLoop().RunUntilIdle();
1429 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1431 // Make the request.
1432 TestCompletionCallback callback
;
1434 scoped_ptr
<HttpTransaction
> trans(
1435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1437 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1440 rv
= callback
.WaitForResult();
1443 LoadTimingInfo load_timing_info
;
1444 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1445 TestLoadTimingNotReused(
1447 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1449 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1450 ASSERT_TRUE(response
!= NULL
);
1452 EXPECT_TRUE(response
->headers
.get() != NULL
);
1453 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1455 std::string response_data
;
1456 rv
= ReadTransaction(trans
.get(), &response_data
);
1458 EXPECT_EQ(kHttpData
, response_data
);
1461 TEST_P(HttpNetworkTransactionTest
,
1462 KeepAliveConnectionNotConnectedOnWrite
) {
1463 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1464 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1467 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1468 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1469 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1472 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1473 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1474 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1477 // Make sure that on a 408 response (Request Timeout), the request is retried,
1478 // if the socket was a reused keep alive socket.
1479 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1480 MockRead
read_failure(SYNCHRONOUS
,
1481 "HTTP/1.1 408 Request Timeout\r\n"
1482 "Connection: Keep-Alive\r\n"
1483 "Content-Length: 6\r\n\r\n"
1485 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1488 TEST_P(HttpNetworkTransactionTest
,
1489 PreconnectErrorNotConnectedOnWrite
) {
1490 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1491 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1494 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1495 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1496 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1499 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1500 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1501 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1504 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1505 MockRead
read_failure(ASYNC
, OK
); // EOF
1506 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1509 // Make sure that on a 408 response (Request Timeout), the request is retried,
1510 // if the socket was a preconnected (UNUSED_IDLE) socket.
1511 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1512 MockRead
read_failure(SYNCHRONOUS
,
1513 "HTTP/1.1 408 Request Timeout\r\n"
1514 "Connection: Keep-Alive\r\n"
1515 "Content-Length: 6\r\n\r\n"
1517 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1518 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1521 TEST_P(HttpNetworkTransactionTest
,
1522 SpdyPreconnectErrorNotConnectedOnWrite
) {
1523 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1524 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1527 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1528 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1529 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1532 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1533 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1534 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1537 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1538 MockRead
read_failure(ASYNC
, OK
); // EOF
1539 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1542 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1543 HttpRequestInfo request
;
1544 request
.method
= "GET";
1545 request
.url
= GURL("http://www.google.com/");
1546 request
.load_flags
= 0;
1548 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1549 scoped_ptr
<HttpTransaction
> trans(
1550 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1552 MockRead data_reads
[] = {
1553 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1554 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1555 MockRead("hello world"),
1556 MockRead(SYNCHRONOUS
, OK
),
1558 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1559 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1561 TestCompletionCallback callback
;
1563 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1564 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1566 rv
= callback
.WaitForResult();
1567 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1569 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1570 EXPECT_TRUE(response
== NULL
);
1573 // What do various browsers do when the server closes a non-keepalive
1574 // connection without sending any response header or body?
1577 // Safari 3.1.2 (Windows): error page
1578 // Firefox 3.0.1: blank page
1579 // Opera 9.52: after five attempts, blank page
1580 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1581 // Us: error page (EMPTY_RESPONSE)
1582 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1583 MockRead data_reads
[] = {
1584 MockRead(SYNCHRONOUS
, OK
), // EOF
1585 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1586 MockRead("hello world"),
1587 MockRead(SYNCHRONOUS
, OK
),
1589 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1590 arraysize(data_reads
));
1591 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1594 // Test that network access can be deferred and resumed.
1595 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1596 HttpRequestInfo request
;
1597 request
.method
= "GET";
1598 request
.url
= GURL("http://www.google.com/");
1599 request
.load_flags
= 0;
1601 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1602 scoped_ptr
<HttpTransaction
> trans(
1603 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1605 // Defer on OnBeforeNetworkStart.
1606 BeforeNetworkStartHandler
net_start_handler(true); // defer
1607 trans
->SetBeforeNetworkStartCallback(
1608 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1609 base::Unretained(&net_start_handler
)));
1611 MockRead data_reads
[] = {
1612 MockRead("HTTP/1.0 200 OK\r\n"),
1613 MockRead("Content-Length: 5\r\n\r\n"),
1615 MockRead(SYNCHRONOUS
, 0),
1617 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1618 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1620 TestCompletionCallback callback
;
1622 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1623 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1624 base::MessageLoop::current()->RunUntilIdle();
1626 // Should have deferred for network start.
1627 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1628 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1629 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1631 trans
->ResumeNetworkStart();
1632 rv
= callback
.WaitForResult();
1634 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1636 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1637 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1638 if (rv
== ERR_IO_PENDING
)
1639 rv
= callback
.WaitForResult();
1644 // Test that network use can be deferred and canceled.
1645 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1646 HttpRequestInfo request
;
1647 request
.method
= "GET";
1648 request
.url
= GURL("http://www.google.com/");
1649 request
.load_flags
= 0;
1651 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1652 scoped_ptr
<HttpTransaction
> trans(
1653 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1655 // Defer on OnBeforeNetworkStart.
1656 BeforeNetworkStartHandler
net_start_handler(true); // defer
1657 trans
->SetBeforeNetworkStartCallback(
1658 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1659 base::Unretained(&net_start_handler
)));
1661 TestCompletionCallback callback
;
1663 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1664 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1665 base::MessageLoop::current()->RunUntilIdle();
1667 // Should have deferred for network start.
1668 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1669 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1670 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1673 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1674 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1675 // destructor in such situations.
1676 // See http://crbug.com/154712 and http://crbug.com/156609.
1677 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1678 HttpRequestInfo request
;
1679 request
.method
= "GET";
1680 request
.url
= GURL("http://www.google.com/");
1681 request
.load_flags
= 0;
1683 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1684 scoped_ptr
<HttpTransaction
> trans(
1685 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1687 MockRead data_reads
[] = {
1688 MockRead("HTTP/1.0 200 OK\r\n"),
1689 MockRead("Connection: keep-alive\r\n"),
1690 MockRead("Content-Length: 100\r\n\r\n"),
1692 MockRead(SYNCHRONOUS
, 0),
1694 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1695 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1697 TestCompletionCallback callback
;
1699 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1700 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1702 rv
= callback
.WaitForResult();
1705 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1706 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1707 if (rv
== ERR_IO_PENDING
)
1708 rv
= callback
.WaitForResult();
1710 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1711 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1714 base::MessageLoop::current()->RunUntilIdle();
1715 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1718 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1719 HttpRequestInfo request
;
1720 request
.method
= "GET";
1721 request
.url
= GURL("http://www.google.com/");
1722 request
.load_flags
= 0;
1724 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1725 scoped_ptr
<HttpTransaction
> trans(
1726 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1728 MockRead data_reads
[] = {
1729 MockRead("HTTP/1.0 200 OK\r\n"),
1730 MockRead("Connection: keep-alive\r\n"),
1731 MockRead("Content-Length: 100\r\n\r\n"),
1732 MockRead(SYNCHRONOUS
, 0),
1734 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1735 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1737 TestCompletionCallback callback
;
1739 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1740 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1742 rv
= callback
.WaitForResult();
1745 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1746 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1747 if (rv
== ERR_IO_PENDING
)
1748 rv
= callback
.WaitForResult();
1749 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1752 base::MessageLoop::current()->RunUntilIdle();
1753 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1756 // Test that we correctly reuse a keep-alive connection after not explicitly
1757 // reading the body.
1758 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1759 HttpRequestInfo request
;
1760 request
.method
= "GET";
1761 request
.url
= GURL("http://www.foo.com/");
1762 request
.load_flags
= 0;
1764 CapturingNetLog net_log
;
1765 session_deps_
.net_log
= &net_log
;
1766 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1768 // Note that because all these reads happen in the same
1769 // StaticSocketDataProvider, it shows that the same socket is being reused for
1770 // all transactions.
1771 MockRead data1_reads
[] = {
1772 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1773 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1774 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1775 MockRead("HTTP/1.1 302 Found\r\n"
1776 "Content-Length: 0\r\n\r\n"),
1777 MockRead("HTTP/1.1 302 Found\r\n"
1778 "Content-Length: 5\r\n\r\n"
1780 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1781 "Content-Length: 0\r\n\r\n"),
1782 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1783 "Content-Length: 5\r\n\r\n"
1785 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1788 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1789 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1791 MockRead data2_reads
[] = {
1792 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1794 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1795 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1797 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1798 std::string response_lines
[kNumUnreadBodies
];
1800 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1801 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1802 TestCompletionCallback callback
;
1804 scoped_ptr
<HttpTransaction
> trans(
1805 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1807 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1808 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1810 rv
= callback
.WaitForResult();
1813 LoadTimingInfo load_timing_info
;
1814 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1816 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1817 first_socket_log_id
= load_timing_info
.socket_log_id
;
1819 TestLoadTimingReused(load_timing_info
);
1820 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1823 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1824 ASSERT_TRUE(response
!= NULL
);
1826 ASSERT_TRUE(response
->headers
.get() != NULL
);
1827 response_lines
[i
] = response
->headers
->GetStatusLine();
1829 // We intentionally don't read the response bodies.
1832 const char* const kStatusLines
[] = {
1833 "HTTP/1.1 204 No Content",
1834 "HTTP/1.1 205 Reset Content",
1835 "HTTP/1.1 304 Not Modified",
1836 "HTTP/1.1 302 Found",
1837 "HTTP/1.1 302 Found",
1838 "HTTP/1.1 301 Moved Permanently",
1839 "HTTP/1.1 301 Moved Permanently",
1842 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1843 forgot_to_update_kStatusLines
);
1845 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1846 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1848 TestCompletionCallback callback
;
1849 scoped_ptr
<HttpTransaction
> trans(
1850 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1851 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1852 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1853 rv
= callback
.WaitForResult();
1855 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1856 ASSERT_TRUE(response
!= NULL
);
1857 ASSERT_TRUE(response
->headers
.get() != NULL
);
1858 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1859 std::string response_data
;
1860 rv
= ReadTransaction(trans
.get(), &response_data
);
1862 EXPECT_EQ("hello", response_data
);
1865 // Test the request-challenge-retry sequence for basic auth.
1866 // (basic auth is the easiest to mock, because it has no randomness).
1867 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1868 HttpRequestInfo request
;
1869 request
.method
= "GET";
1870 request
.url
= GURL("http://www.google.com/");
1871 request
.load_flags
= 0;
1873 CapturingNetLog log
;
1874 session_deps_
.net_log
= &log
;
1875 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1876 scoped_ptr
<HttpTransaction
> trans(
1877 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1879 MockWrite data_writes1
[] = {
1880 MockWrite("GET / HTTP/1.1\r\n"
1881 "Host: www.google.com\r\n"
1882 "Connection: keep-alive\r\n\r\n"),
1885 MockRead data_reads1
[] = {
1886 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1887 // Give a couple authenticate options (only the middle one is actually
1889 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1890 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1891 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1892 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1893 // Large content-length -- won't matter, as connection will be reset.
1894 MockRead("Content-Length: 10000\r\n\r\n"),
1895 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1898 // After calling trans->RestartWithAuth(), this is the request we should
1899 // be issuing -- the final header line contains the credentials.
1900 MockWrite data_writes2
[] = {
1901 MockWrite("GET / HTTP/1.1\r\n"
1902 "Host: www.google.com\r\n"
1903 "Connection: keep-alive\r\n"
1904 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1907 // Lastly, the server responds with the actual content.
1908 MockRead data_reads2
[] = {
1909 MockRead("HTTP/1.0 200 OK\r\n"),
1910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1911 MockRead("Content-Length: 100\r\n\r\n"),
1912 MockRead(SYNCHRONOUS
, OK
),
1915 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1916 data_writes1
, arraysize(data_writes1
));
1917 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1918 data_writes2
, arraysize(data_writes2
));
1919 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1920 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1922 TestCompletionCallback callback1
;
1924 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1925 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1927 rv
= callback1
.WaitForResult();
1930 LoadTimingInfo load_timing_info1
;
1931 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1932 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1934 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1935 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1937 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1938 ASSERT_TRUE(response
!= NULL
);
1939 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1941 TestCompletionCallback callback2
;
1943 rv
= trans
->RestartWithAuth(
1944 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1947 rv
= callback2
.WaitForResult();
1950 LoadTimingInfo load_timing_info2
;
1951 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1952 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1953 // The load timing after restart should have a new socket ID, and times after
1954 // those of the first load timing.
1955 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1956 load_timing_info2
.connect_timing
.connect_start
);
1957 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1959 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1960 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1962 response
= trans
->GetResponseInfo();
1963 ASSERT_TRUE(response
!= NULL
);
1964 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1965 EXPECT_EQ(100, response
->headers
->GetContentLength());
1968 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1969 HttpRequestInfo request
;
1970 request
.method
= "GET";
1971 request
.url
= GURL("http://www.google.com/");
1972 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1974 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1975 scoped_ptr
<HttpTransaction
> trans(
1976 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1978 MockWrite data_writes
[] = {
1979 MockWrite("GET / HTTP/1.1\r\n"
1980 "Host: www.google.com\r\n"
1981 "Connection: keep-alive\r\n\r\n"),
1984 MockRead data_reads
[] = {
1985 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1986 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1987 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1988 // Large content-length -- won't matter, as connection will be reset.
1989 MockRead("Content-Length: 10000\r\n\r\n"),
1990 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1993 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1994 data_writes
, arraysize(data_writes
));
1995 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1996 TestCompletionCallback callback
;
1998 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1999 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2001 rv
= callback
.WaitForResult();
2004 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2005 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2007 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2008 ASSERT_TRUE(response
!= NULL
);
2009 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2012 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2014 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2015 HttpRequestInfo request
;
2016 request
.method
= "GET";
2017 request
.url
= GURL("http://www.google.com/");
2018 request
.load_flags
= 0;
2020 CapturingNetLog log
;
2021 session_deps_
.net_log
= &log
;
2022 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2024 MockWrite data_writes1
[] = {
2025 MockWrite("GET / HTTP/1.1\r\n"
2026 "Host: www.google.com\r\n"
2027 "Connection: keep-alive\r\n\r\n"),
2029 // After calling trans->RestartWithAuth(), this is the request we should
2030 // be issuing -- the final header line contains the credentials.
2031 MockWrite("GET / HTTP/1.1\r\n"
2032 "Host: www.google.com\r\n"
2033 "Connection: keep-alive\r\n"
2034 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2037 MockRead data_reads1
[] = {
2038 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2039 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2041 MockRead("Content-Length: 14\r\n\r\n"),
2042 MockRead("Unauthorized\r\n"),
2044 // Lastly, the server responds with the actual content.
2045 MockRead("HTTP/1.1 200 OK\r\n"),
2046 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2047 MockRead("Content-Length: 5\r\n\r\n"),
2051 // If there is a regression where we disconnect a Keep-Alive
2052 // connection during an auth roundtrip, we'll end up reading this.
2053 MockRead data_reads2
[] = {
2054 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2057 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2058 data_writes1
, arraysize(data_writes1
));
2059 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2061 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2062 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2064 TestCompletionCallback callback1
;
2066 scoped_ptr
<HttpTransaction
> trans(
2067 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2068 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2071 rv
= callback1
.WaitForResult();
2074 LoadTimingInfo load_timing_info1
;
2075 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2076 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2078 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2079 ASSERT_TRUE(response
!= NULL
);
2080 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2082 TestCompletionCallback callback2
;
2084 rv
= trans
->RestartWithAuth(
2085 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2086 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2088 rv
= callback2
.WaitForResult();
2091 LoadTimingInfo load_timing_info2
;
2092 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2093 TestLoadTimingReused(load_timing_info2
);
2094 // The load timing after restart should have the same socket ID, and times
2095 // those of the first load timing.
2096 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2097 load_timing_info2
.send_start
);
2098 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2100 response
= trans
->GetResponseInfo();
2101 ASSERT_TRUE(response
!= NULL
);
2102 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2103 EXPECT_EQ(5, response
->headers
->GetContentLength());
2105 std::string response_data
;
2106 rv
= ReadTransaction(trans
.get(), &response_data
);
2108 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2109 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2112 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2113 // connection and with no response body to drain.
2114 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2115 HttpRequestInfo request
;
2116 request
.method
= "GET";
2117 request
.url
= GURL("http://www.google.com/");
2118 request
.load_flags
= 0;
2120 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2122 MockWrite data_writes1
[] = {
2123 MockWrite("GET / HTTP/1.1\r\n"
2124 "Host: www.google.com\r\n"
2125 "Connection: keep-alive\r\n\r\n"),
2127 // After calling trans->RestartWithAuth(), this is the request we should
2128 // be issuing -- the final header line contains the credentials.
2129 MockWrite("GET / HTTP/1.1\r\n"
2130 "Host: www.google.com\r\n"
2131 "Connection: keep-alive\r\n"
2132 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2135 MockRead data_reads1
[] = {
2136 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2137 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2138 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2140 // Lastly, the server responds with the actual content.
2141 MockRead("HTTP/1.1 200 OK\r\n"),
2142 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2143 MockRead("Content-Length: 5\r\n\r\n"),
2147 // An incorrect reconnect would cause this to be read.
2148 MockRead data_reads2
[] = {
2149 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2152 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2153 data_writes1
, arraysize(data_writes1
));
2154 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2156 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2157 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2159 TestCompletionCallback callback1
;
2161 scoped_ptr
<HttpTransaction
> trans(
2162 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2163 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2164 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2166 rv
= callback1
.WaitForResult();
2169 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2170 ASSERT_TRUE(response
!= NULL
);
2171 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2173 TestCompletionCallback callback2
;
2175 rv
= trans
->RestartWithAuth(
2176 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2177 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2179 rv
= callback2
.WaitForResult();
2182 response
= trans
->GetResponseInfo();
2183 ASSERT_TRUE(response
!= NULL
);
2184 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2185 EXPECT_EQ(5, response
->headers
->GetContentLength());
2188 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2189 // connection and with a large response body to drain.
2190 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2191 HttpRequestInfo request
;
2192 request
.method
= "GET";
2193 request
.url
= GURL("http://www.google.com/");
2194 request
.load_flags
= 0;
2196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2198 MockWrite data_writes1
[] = {
2199 MockWrite("GET / HTTP/1.1\r\n"
2200 "Host: www.google.com\r\n"
2201 "Connection: keep-alive\r\n\r\n"),
2203 // After calling trans->RestartWithAuth(), this is the request we should
2204 // be issuing -- the final header line contains the credentials.
2205 MockWrite("GET / HTTP/1.1\r\n"
2206 "Host: www.google.com\r\n"
2207 "Connection: keep-alive\r\n"
2208 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2211 // Respond with 5 kb of response body.
2212 std::string
large_body_string("Unauthorized");
2213 large_body_string
.append(5 * 1024, ' ');
2214 large_body_string
.append("\r\n");
2216 MockRead data_reads1
[] = {
2217 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2218 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2219 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2220 // 5134 = 12 + 5 * 1024 + 2
2221 MockRead("Content-Length: 5134\r\n\r\n"),
2222 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2224 // Lastly, the server responds with the actual content.
2225 MockRead("HTTP/1.1 200 OK\r\n"),
2226 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2227 MockRead("Content-Length: 5\r\n\r\n"),
2231 // An incorrect reconnect would cause this to be read.
2232 MockRead data_reads2
[] = {
2233 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2236 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2237 data_writes1
, arraysize(data_writes1
));
2238 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2240 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2241 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2243 TestCompletionCallback callback1
;
2245 scoped_ptr
<HttpTransaction
> trans(
2246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2247 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2248 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2250 rv
= callback1
.WaitForResult();
2253 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2254 ASSERT_TRUE(response
!= NULL
);
2255 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2257 TestCompletionCallback callback2
;
2259 rv
= trans
->RestartWithAuth(
2260 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2261 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2263 rv
= callback2
.WaitForResult();
2266 response
= trans
->GetResponseInfo();
2267 ASSERT_TRUE(response
!= NULL
);
2268 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2269 EXPECT_EQ(5, response
->headers
->GetContentLength());
2272 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2273 // connection, but the server gets impatient and closes the connection.
2274 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2275 HttpRequestInfo request
;
2276 request
.method
= "GET";
2277 request
.url
= GURL("http://www.google.com/");
2278 request
.load_flags
= 0;
2280 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2282 MockWrite data_writes1
[] = {
2283 MockWrite("GET / HTTP/1.1\r\n"
2284 "Host: www.google.com\r\n"
2285 "Connection: keep-alive\r\n\r\n"),
2286 // This simulates the seemingly successful write to a closed connection
2287 // if the bug is not fixed.
2288 MockWrite("GET / HTTP/1.1\r\n"
2289 "Host: www.google.com\r\n"
2290 "Connection: keep-alive\r\n"
2291 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2294 MockRead data_reads1
[] = {
2295 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2296 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2297 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2298 MockRead("Content-Length: 14\r\n\r\n"),
2299 // Tell MockTCPClientSocket to simulate the server closing the connection.
2300 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2301 MockRead("Unauthorized\r\n"),
2302 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2305 // After calling trans->RestartWithAuth(), this is the request we should
2306 // be issuing -- the final header line contains the credentials.
2307 MockWrite data_writes2
[] = {
2308 MockWrite("GET / HTTP/1.1\r\n"
2309 "Host: www.google.com\r\n"
2310 "Connection: keep-alive\r\n"
2311 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2314 // Lastly, the server responds with the actual content.
2315 MockRead data_reads2
[] = {
2316 MockRead("HTTP/1.1 200 OK\r\n"),
2317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2318 MockRead("Content-Length: 5\r\n\r\n"),
2322 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2323 data_writes1
, arraysize(data_writes1
));
2324 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2325 data_writes2
, arraysize(data_writes2
));
2326 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2327 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2329 TestCompletionCallback callback1
;
2331 scoped_ptr
<HttpTransaction
> trans(
2332 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2333 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2336 rv
= callback1
.WaitForResult();
2339 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2340 ASSERT_TRUE(response
!= NULL
);
2341 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2343 TestCompletionCallback callback2
;
2345 rv
= trans
->RestartWithAuth(
2346 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2347 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2349 rv
= callback2
.WaitForResult();
2352 response
= trans
->GetResponseInfo();
2353 ASSERT_TRUE(response
!= NULL
);
2354 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2355 EXPECT_EQ(5, response
->headers
->GetContentLength());
2358 // Test the request-challenge-retry sequence for basic auth, over a connection
2359 // that requires a restart when setting up an SSL tunnel.
2360 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
2361 HttpRequestInfo request
;
2362 request
.method
= "GET";
2363 request
.url
= GURL("https://www.google.com/");
2364 // when the no authentication data flag is set.
2365 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2367 // Configure against proxy server "myproxy:70".
2368 session_deps_
.proxy_service
.reset(
2369 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2370 CapturingBoundNetLog log
;
2371 session_deps_
.net_log
= log
.bound().net_log();
2372 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2374 // Since we have proxy, should try to establish tunnel.
2375 MockWrite data_writes1
[] = {
2376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2377 "Host: www.google.com\r\n"
2378 "Proxy-Connection: keep-alive\r\n\r\n"),
2380 // After calling trans->RestartWithAuth(), this is the request we should
2381 // be issuing -- the final header line contains the credentials.
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"
2385 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2387 MockWrite("GET / HTTP/1.1\r\n"
2388 "Host: www.google.com\r\n"
2389 "Connection: keep-alive\r\n\r\n"),
2392 // The proxy responds to the connect with a 407, using a persistent
2394 MockRead data_reads1
[] = {
2396 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2397 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2398 MockRead("Proxy-Connection: close\r\n\r\n"),
2400 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2402 MockRead("HTTP/1.1 200 OK\r\n"),
2403 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2404 MockRead("Content-Length: 5\r\n\r\n"),
2405 MockRead(SYNCHRONOUS
, "hello"),
2408 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2409 data_writes1
, arraysize(data_writes1
));
2410 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2411 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2412 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2414 TestCompletionCallback callback1
;
2416 scoped_ptr
<HttpTransaction
> trans(
2417 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2419 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2420 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2422 rv
= callback1
.WaitForResult();
2424 net::CapturingNetLog::CapturedEntryList entries
;
2425 log
.GetEntries(&entries
);
2426 size_t pos
= ExpectLogContainsSomewhere(
2427 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2428 NetLog::PHASE_NONE
);
2429 ExpectLogContainsSomewhere(
2431 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2432 NetLog::PHASE_NONE
);
2434 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2435 ASSERT_TRUE(response
!= NULL
);
2436 ASSERT_FALSE(response
->headers
.get() == NULL
);
2437 EXPECT_EQ(407, response
->headers
->response_code());
2438 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2439 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2441 LoadTimingInfo load_timing_info
;
2442 // CONNECT requests and responses are handled at the connect job level, so
2443 // the transaction does not yet have a connection.
2444 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2446 TestCompletionCallback callback2
;
2448 rv
= trans
->RestartWithAuth(
2449 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2450 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2452 rv
= callback2
.WaitForResult();
2455 response
= trans
->GetResponseInfo();
2456 ASSERT_TRUE(response
!= NULL
);
2458 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2459 EXPECT_EQ(200, response
->headers
->response_code());
2460 EXPECT_EQ(5, response
->headers
->GetContentLength());
2461 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2463 // The password prompt info should not be set.
2464 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2466 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2467 TestLoadTimingNotReusedWithPac(load_timing_info
,
2468 CONNECT_TIMING_HAS_SSL_TIMES
);
2471 session
->CloseAllConnections();
2474 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2475 // proxy connection, when setting up an SSL tunnel.
2476 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2477 HttpRequestInfo request
;
2478 request
.method
= "GET";
2479 request
.url
= GURL("https://www.google.com/");
2480 // Ensure that proxy authentication is attempted even
2481 // when the no authentication data flag is set.
2482 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2484 // Configure against proxy server "myproxy:70".
2485 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2486 CapturingBoundNetLog log
;
2487 session_deps_
.net_log
= log
.bound().net_log();
2488 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2490 scoped_ptr
<HttpTransaction
> trans(
2491 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2493 // Since we have proxy, should try to establish tunnel.
2494 MockWrite data_writes1
[] = {
2495 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2496 "Host: www.google.com\r\n"
2497 "Proxy-Connection: keep-alive\r\n\r\n"),
2499 // After calling trans->RestartWithAuth(), this is the request we should
2500 // be issuing -- the final header line contains the credentials.
2501 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2502 "Host: www.google.com\r\n"
2503 "Proxy-Connection: keep-alive\r\n"
2504 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2507 // The proxy responds to the connect with a 407, using a persistent
2509 MockRead data_reads1
[] = {
2511 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2512 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2513 MockRead("Content-Length: 10\r\n\r\n"),
2514 MockRead("0123456789"),
2516 // Wrong credentials (wrong password).
2517 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2518 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2519 MockRead("Content-Length: 10\r\n\r\n"),
2520 // No response body because the test stops reading here.
2521 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2524 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2525 data_writes1
, arraysize(data_writes1
));
2526 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2528 TestCompletionCallback callback1
;
2530 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2531 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2533 rv
= callback1
.WaitForResult();
2535 net::CapturingNetLog::CapturedEntryList entries
;
2536 log
.GetEntries(&entries
);
2537 size_t pos
= ExpectLogContainsSomewhere(
2538 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2539 NetLog::PHASE_NONE
);
2540 ExpectLogContainsSomewhere(
2542 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2543 NetLog::PHASE_NONE
);
2545 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2546 ASSERT_TRUE(response
!= NULL
);
2547 ASSERT_FALSE(response
->headers
.get() == NULL
);
2548 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2549 EXPECT_EQ(407, response
->headers
->response_code());
2550 EXPECT_EQ(10, response
->headers
->GetContentLength());
2551 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2552 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2554 TestCompletionCallback callback2
;
2556 // Wrong password (should be "bar").
2557 rv
= trans
->RestartWithAuth(
2558 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2559 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2561 rv
= callback2
.WaitForResult();
2564 response
= trans
->GetResponseInfo();
2565 ASSERT_TRUE(response
!= NULL
);
2566 ASSERT_FALSE(response
->headers
.get() == NULL
);
2567 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2568 EXPECT_EQ(407, response
->headers
->response_code());
2569 EXPECT_EQ(10, response
->headers
->GetContentLength());
2570 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2571 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2573 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2575 session
->CloseAllConnections();
2578 // Test that we don't read the response body when we fail to establish a tunnel,
2579 // even if the user cancels the proxy's auth attempt.
2580 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2581 HttpRequestInfo request
;
2582 request
.method
= "GET";
2583 request
.url
= GURL("https://www.google.com/");
2584 request
.load_flags
= 0;
2586 // Configure against proxy server "myproxy:70".
2587 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2589 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2591 scoped_ptr
<HttpTransaction
> trans(
2592 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2594 // Since we have proxy, should try to establish tunnel.
2595 MockWrite data_writes
[] = {
2596 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2597 "Host: www.google.com\r\n"
2598 "Proxy-Connection: keep-alive\r\n\r\n"),
2601 // The proxy responds to the connect with a 407.
2602 MockRead data_reads
[] = {
2603 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2604 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2605 MockRead("Content-Length: 10\r\n\r\n"),
2606 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2609 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2610 data_writes
, arraysize(data_writes
));
2611 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2613 TestCompletionCallback callback
;
2615 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2616 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2618 rv
= callback
.WaitForResult();
2621 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2622 ASSERT_TRUE(response
!= NULL
);
2624 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2625 EXPECT_EQ(407, response
->headers
->response_code());
2626 EXPECT_EQ(10, response
->headers
->GetContentLength());
2627 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2629 std::string response_data
;
2630 rv
= ReadTransaction(trans
.get(), &response_data
);
2631 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2633 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2634 session
->CloseAllConnections();
2637 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2638 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2639 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2640 HttpRequestInfo request
;
2641 request
.method
= "GET";
2642 request
.url
= GURL("http://www.google.com/");
2643 request
.load_flags
= 0;
2645 // We are using a DIRECT connection (i.e. no proxy) for this session.
2646 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2647 scoped_ptr
<HttpTransaction
> trans(
2648 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2650 MockWrite data_writes1
[] = {
2651 MockWrite("GET / HTTP/1.1\r\n"
2652 "Host: www.google.com\r\n"
2653 "Connection: keep-alive\r\n\r\n"),
2656 MockRead data_reads1
[] = {
2657 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2658 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2659 // Large content-length -- won't matter, as connection will be reset.
2660 MockRead("Content-Length: 10000\r\n\r\n"),
2661 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2664 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2665 data_writes1
, arraysize(data_writes1
));
2666 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2668 TestCompletionCallback callback
;
2670 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2673 rv
= callback
.WaitForResult();
2674 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2677 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2678 // through a non-authenticating proxy. The request should fail with
2679 // ERR_UNEXPECTED_PROXY_AUTH.
2680 // Note that it is impossible to detect if an HTTP server returns a 407 through
2681 // a non-authenticating proxy - there is nothing to indicate whether the
2682 // response came from the proxy or the server, so it is treated as if the proxy
2683 // issued the challenge.
2684 TEST_P(HttpNetworkTransactionTest
,
2685 HttpsServerRequestsProxyAuthThroughProxy
) {
2686 HttpRequestInfo request
;
2687 request
.method
= "GET";
2688 request
.url
= GURL("https://www.google.com/");
2690 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2691 CapturingBoundNetLog log
;
2692 session_deps_
.net_log
= log
.bound().net_log();
2693 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2695 // Since we have proxy, should try to establish tunnel.
2696 MockWrite data_writes1
[] = {
2697 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2698 "Host: www.google.com\r\n"
2699 "Proxy-Connection: keep-alive\r\n\r\n"),
2701 MockWrite("GET / HTTP/1.1\r\n"
2702 "Host: www.google.com\r\n"
2703 "Connection: keep-alive\r\n\r\n"),
2706 MockRead data_reads1
[] = {
2707 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2709 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2710 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2712 MockRead(SYNCHRONOUS
, OK
),
2715 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2716 data_writes1
, arraysize(data_writes1
));
2717 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2718 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2719 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2721 TestCompletionCallback callback1
;
2723 scoped_ptr
<HttpTransaction
> trans(
2724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2726 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2727 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2729 rv
= callback1
.WaitForResult();
2730 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2731 net::CapturingNetLog::CapturedEntryList entries
;
2732 log
.GetEntries(&entries
);
2733 size_t pos
= ExpectLogContainsSomewhere(
2734 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2735 NetLog::PHASE_NONE
);
2736 ExpectLogContainsSomewhere(
2738 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2739 NetLog::PHASE_NONE
);
2742 // Test the load timing for HTTPS requests with an HTTP proxy.
2743 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2744 HttpRequestInfo request1
;
2745 request1
.method
= "GET";
2746 request1
.url
= GURL("https://www.google.com/1");
2748 HttpRequestInfo request2
;
2749 request2
.method
= "GET";
2750 request2
.url
= GURL("https://www.google.com/2");
2752 // Configure against proxy server "myproxy:70".
2753 session_deps_
.proxy_service
.reset(
2754 ProxyService::CreateFixed("PROXY myproxy:70"));
2755 CapturingBoundNetLog log
;
2756 session_deps_
.net_log
= log
.bound().net_log();
2757 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2759 // Since we have proxy, should try to establish tunnel.
2760 MockWrite data_writes1
[] = {
2761 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2762 "Host: www.google.com\r\n"
2763 "Proxy-Connection: keep-alive\r\n\r\n"),
2765 MockWrite("GET /1 HTTP/1.1\r\n"
2766 "Host: www.google.com\r\n"
2767 "Connection: keep-alive\r\n\r\n"),
2769 MockWrite("GET /2 HTTP/1.1\r\n"
2770 "Host: www.google.com\r\n"
2771 "Connection: keep-alive\r\n\r\n"),
2774 // The proxy responds to the connect with a 407, using a persistent
2776 MockRead data_reads1
[] = {
2777 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2779 MockRead("HTTP/1.1 200 OK\r\n"),
2780 MockRead("Content-Length: 1\r\n\r\n"),
2781 MockRead(SYNCHRONOUS
, "1"),
2783 MockRead("HTTP/1.1 200 OK\r\n"),
2784 MockRead("Content-Length: 2\r\n\r\n"),
2785 MockRead(SYNCHRONOUS
, "22"),
2788 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2789 data_writes1
, arraysize(data_writes1
));
2790 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2791 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2792 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2794 TestCompletionCallback callback1
;
2795 scoped_ptr
<HttpTransaction
> trans1(
2796 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2798 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2799 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2801 rv
= callback1
.WaitForResult();
2804 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2805 ASSERT_TRUE(response1
!= NULL
);
2806 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2807 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2809 LoadTimingInfo load_timing_info1
;
2810 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2811 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2815 TestCompletionCallback callback2
;
2816 scoped_ptr
<HttpTransaction
> trans2(
2817 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2819 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2820 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2822 rv
= callback2
.WaitForResult();
2825 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2826 ASSERT_TRUE(response2
!= NULL
);
2827 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2828 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2830 LoadTimingInfo load_timing_info2
;
2831 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2832 TestLoadTimingReused(load_timing_info2
);
2834 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2837 session
->CloseAllConnections();
2840 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2841 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2842 HttpRequestInfo request1
;
2843 request1
.method
= "GET";
2844 request1
.url
= GURL("https://www.google.com/1");
2846 HttpRequestInfo request2
;
2847 request2
.method
= "GET";
2848 request2
.url
= GURL("https://www.google.com/2");
2850 // Configure against proxy server "myproxy:70".
2851 session_deps_
.proxy_service
.reset(
2852 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2853 CapturingBoundNetLog log
;
2854 session_deps_
.net_log
= log
.bound().net_log();
2855 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2857 // Since we have proxy, should try to establish tunnel.
2858 MockWrite data_writes1
[] = {
2859 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2860 "Host: www.google.com\r\n"
2861 "Proxy-Connection: keep-alive\r\n\r\n"),
2863 MockWrite("GET /1 HTTP/1.1\r\n"
2864 "Host: www.google.com\r\n"
2865 "Connection: keep-alive\r\n\r\n"),
2867 MockWrite("GET /2 HTTP/1.1\r\n"
2868 "Host: www.google.com\r\n"
2869 "Connection: keep-alive\r\n\r\n"),
2872 // The proxy responds to the connect with a 407, using a persistent
2874 MockRead data_reads1
[] = {
2875 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2877 MockRead("HTTP/1.1 200 OK\r\n"),
2878 MockRead("Content-Length: 1\r\n\r\n"),
2879 MockRead(SYNCHRONOUS
, "1"),
2881 MockRead("HTTP/1.1 200 OK\r\n"),
2882 MockRead("Content-Length: 2\r\n\r\n"),
2883 MockRead(SYNCHRONOUS
, "22"),
2886 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2887 data_writes1
, arraysize(data_writes1
));
2888 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2889 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2890 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2892 TestCompletionCallback callback1
;
2893 scoped_ptr
<HttpTransaction
> trans1(
2894 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2896 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2897 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2899 rv
= callback1
.WaitForResult();
2902 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2903 ASSERT_TRUE(response1
!= NULL
);
2904 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2905 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2907 LoadTimingInfo load_timing_info1
;
2908 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2909 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2910 CONNECT_TIMING_HAS_SSL_TIMES
);
2914 TestCompletionCallback callback2
;
2915 scoped_ptr
<HttpTransaction
> trans2(
2916 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2918 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2919 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2921 rv
= callback2
.WaitForResult();
2924 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2925 ASSERT_TRUE(response2
!= NULL
);
2926 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2927 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2929 LoadTimingInfo load_timing_info2
;
2930 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2931 TestLoadTimingReusedWithPac(load_timing_info2
);
2933 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2936 session
->CloseAllConnections();
2939 // Test a simple get through an HTTPS Proxy.
2940 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2941 HttpRequestInfo request
;
2942 request
.method
= "GET";
2943 request
.url
= GURL("http://www.google.com/");
2945 // Configure against https proxy server "proxy:70".
2946 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2947 "https://proxy:70"));
2948 CapturingBoundNetLog log
;
2949 session_deps_
.net_log
= log
.bound().net_log();
2950 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2952 // Since we have proxy, should use full url
2953 MockWrite data_writes1
[] = {
2954 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2955 "Host: www.google.com\r\n"
2956 "Proxy-Connection: keep-alive\r\n\r\n"),
2959 MockRead data_reads1
[] = {
2960 MockRead("HTTP/1.1 200 OK\r\n"),
2961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2962 MockRead("Content-Length: 100\r\n\r\n"),
2963 MockRead(SYNCHRONOUS
, OK
),
2966 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2967 data_writes1
, arraysize(data_writes1
));
2968 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2969 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2970 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2972 TestCompletionCallback callback1
;
2974 scoped_ptr
<HttpTransaction
> trans(
2975 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2977 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2980 rv
= callback1
.WaitForResult();
2983 LoadTimingInfo load_timing_info
;
2984 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2985 TestLoadTimingNotReused(load_timing_info
,
2986 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2988 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2989 ASSERT_TRUE(response
!= NULL
);
2991 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2992 EXPECT_EQ(200, response
->headers
->response_code());
2993 EXPECT_EQ(100, response
->headers
->GetContentLength());
2994 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2996 // The password prompt info should not be set.
2997 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3000 // Test a SPDY get through an HTTPS Proxy.
3001 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3002 HttpRequestInfo request
;
3003 request
.method
= "GET";
3004 request
.url
= GURL("http://www.google.com/");
3005 request
.load_flags
= 0;
3007 // Configure against https proxy server "proxy:70".
3008 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3009 "https://proxy:70"));
3010 CapturingBoundNetLog log
;
3011 session_deps_
.net_log
= log
.bound().net_log();
3012 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3014 // fetch http://www.google.com/ via SPDY
3015 scoped_ptr
<SpdyFrame
> req(
3016 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3017 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
3019 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3020 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3021 MockRead spdy_reads
[] = {
3022 CreateMockRead(*resp
),
3023 CreateMockRead(*data
),
3024 MockRead(ASYNC
, 0, 0),
3027 DelayedSocketData
spdy_data(
3028 1, // wait for one write to finish before reading.
3029 spdy_reads
, arraysize(spdy_reads
),
3030 spdy_writes
, arraysize(spdy_writes
));
3031 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3033 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3034 ssl
.SetNextProto(GetParam());
3035 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3037 TestCompletionCallback callback1
;
3039 scoped_ptr
<HttpTransaction
> trans(
3040 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3042 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3045 rv
= callback1
.WaitForResult();
3048 LoadTimingInfo load_timing_info
;
3049 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3050 TestLoadTimingNotReused(load_timing_info
,
3051 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3053 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3054 ASSERT_TRUE(response
!= NULL
);
3055 ASSERT_TRUE(response
->headers
.get() != NULL
);
3056 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3058 std::string response_data
;
3059 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3060 EXPECT_EQ(kUploadData
, response_data
);
3063 // Verifies that a session which races and wins against the owning transaction
3064 // (completing prior to host resolution), doesn't fail the transaction.
3065 // Regression test for crbug.com/334413.
3066 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3067 HttpRequestInfo request
;
3068 request
.method
= "GET";
3069 request
.url
= GURL("http://www.google.com/");
3070 request
.load_flags
= 0;
3072 // Configure SPDY proxy server "proxy:70".
3073 session_deps_
.proxy_service
.reset(
3074 ProxyService::CreateFixed("https://proxy:70"));
3075 CapturingBoundNetLog log
;
3076 session_deps_
.net_log
= log
.bound().net_log();
3077 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3079 // Fetch http://www.google.com/ through the SPDY proxy.
3080 scoped_ptr
<SpdyFrame
> req(
3081 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3082 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3084 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3085 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3086 MockRead spdy_reads
[] = {
3087 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3090 DelayedSocketData
spdy_data(
3091 1, // wait for one write to finish before reading.
3093 arraysize(spdy_reads
),
3095 arraysize(spdy_writes
));
3096 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3098 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3099 ssl
.SetNextProto(GetParam());
3100 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3102 TestCompletionCallback callback1
;
3104 scoped_ptr
<HttpTransaction
> trans(
3105 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3107 // Stall the hostname resolution begun by the transaction.
3108 session_deps_
.host_resolver
->set_synchronous_mode(false);
3109 session_deps_
.host_resolver
->set_ondemand_mode(true);
3111 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3114 // Race a session to the proxy, which completes first.
3115 session_deps_
.host_resolver
->set_ondemand_mode(false);
3117 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3118 base::WeakPtr
<SpdySession
> spdy_session
=
3119 CreateSecureSpdySession(session
, key
, log
.bound());
3121 // Unstall the resolution begun by the transaction.
3122 session_deps_
.host_resolver
->set_ondemand_mode(true);
3123 session_deps_
.host_resolver
->ResolveAllPending();
3125 EXPECT_FALSE(callback1
.have_result());
3126 rv
= callback1
.WaitForResult();
3129 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3130 ASSERT_TRUE(response
!= NULL
);
3131 ASSERT_TRUE(response
->headers
.get() != NULL
);
3132 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3134 std::string response_data
;
3135 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3136 EXPECT_EQ(kUploadData
, response_data
);
3139 // Test a SPDY get through an HTTPS Proxy.
3140 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3141 HttpRequestInfo request
;
3142 request
.method
= "GET";
3143 request
.url
= GURL("http://www.google.com/");
3144 request
.load_flags
= 0;
3146 // Configure against https proxy server "myproxy:70".
3147 session_deps_
.proxy_service
.reset(
3148 ProxyService::CreateFixed("https://myproxy:70"));
3149 CapturingBoundNetLog log
;
3150 session_deps_
.net_log
= log
.bound().net_log();
3151 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3153 // The first request will be a bare GET, the second request will be a
3154 // GET with a Proxy-Authorization header.
3155 scoped_ptr
<SpdyFrame
> req_get(
3156 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3157 const char* const kExtraAuthorizationHeaders
[] = {
3158 "proxy-authorization", "Basic Zm9vOmJhcg=="
3160 scoped_ptr
<SpdyFrame
> req_get_authorization(
3161 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3162 arraysize(kExtraAuthorizationHeaders
) / 2,
3167 MockWrite spdy_writes
[] = {
3168 CreateMockWrite(*req_get
, 1),
3169 CreateMockWrite(*req_get_authorization
, 4),
3172 // The first response is a 407 proxy authentication challenge, and the second
3173 // response will be a 200 response since the second request includes a valid
3174 // Authorization header.
3175 const char* const kExtraAuthenticationHeaders
[] = {
3176 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3178 scoped_ptr
<SpdyFrame
> resp_authentication(
3179 spdy_util_
.ConstructSpdySynReplyError(
3180 "407 Proxy Authentication Required",
3181 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3183 scoped_ptr
<SpdyFrame
> body_authentication(
3184 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3185 scoped_ptr
<SpdyFrame
> resp_data(
3186 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3187 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3188 MockRead spdy_reads
[] = {
3189 CreateMockRead(*resp_authentication
, 2),
3190 CreateMockRead(*body_authentication
, 3),
3191 CreateMockRead(*resp_data
, 5),
3192 CreateMockRead(*body_data
, 6),
3193 MockRead(ASYNC
, 0, 7),
3196 OrderedSocketData
data(
3197 spdy_reads
, arraysize(spdy_reads
),
3198 spdy_writes
, arraysize(spdy_writes
));
3199 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3201 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3202 ssl
.SetNextProto(GetParam());
3203 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3205 TestCompletionCallback callback1
;
3207 scoped_ptr
<HttpTransaction
> trans(
3208 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3210 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3211 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3213 rv
= callback1
.WaitForResult();
3216 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3218 ASSERT_TRUE(response
!= NULL
);
3219 ASSERT_TRUE(response
->headers
.get() != NULL
);
3220 EXPECT_EQ(407, response
->headers
->response_code());
3221 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3222 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3224 TestCompletionCallback callback2
;
3226 rv
= trans
->RestartWithAuth(
3227 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3228 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3230 rv
= callback2
.WaitForResult();
3233 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3235 ASSERT_TRUE(response_restart
!= NULL
);
3236 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3237 EXPECT_EQ(200, response_restart
->headers
->response_code());
3238 // The password prompt info should not be set.
3239 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3242 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3243 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3244 HttpRequestInfo request
;
3245 request
.method
= "GET";
3246 request
.url
= GURL("https://www.google.com/");
3247 request
.load_flags
= 0;
3249 // Configure against https proxy server "proxy:70".
3250 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3251 "https://proxy:70"));
3252 CapturingBoundNetLog log
;
3253 session_deps_
.net_log
= log
.bound().net_log();
3254 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3256 scoped_ptr
<HttpTransaction
> trans(
3257 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3259 // CONNECT to www.google.com:443 via SPDY
3260 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3262 // fetch https://www.google.com/ via HTTP
3264 const char get
[] = "GET / HTTP/1.1\r\n"
3265 "Host: www.google.com\r\n"
3266 "Connection: keep-alive\r\n\r\n";
3267 scoped_ptr
<SpdyFrame
> wrapped_get(
3268 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3269 scoped_ptr
<SpdyFrame
> conn_resp(
3270 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3271 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3272 "Content-Length: 10\r\n\r\n";
3273 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3274 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3275 scoped_ptr
<SpdyFrame
> wrapped_body(
3276 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3277 scoped_ptr
<SpdyFrame
> window_update(
3278 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3280 MockWrite spdy_writes
[] = {
3281 CreateMockWrite(*connect
, 1),
3282 CreateMockWrite(*wrapped_get
, 3),
3283 CreateMockWrite(*window_update
, 5),
3286 MockRead spdy_reads
[] = {
3287 CreateMockRead(*conn_resp
, 2, ASYNC
),
3288 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3289 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3290 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3291 MockRead(ASYNC
, 0, 8),
3294 OrderedSocketData
spdy_data(
3295 spdy_reads
, arraysize(spdy_reads
),
3296 spdy_writes
, arraysize(spdy_writes
));
3297 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3299 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3300 ssl
.SetNextProto(GetParam());
3301 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3302 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3303 ssl2
.was_npn_negotiated
= false;
3304 ssl2
.protocol_negotiated
= kProtoUnknown
;
3305 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3307 TestCompletionCallback callback1
;
3309 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3312 rv
= callback1
.WaitForResult();
3315 LoadTimingInfo load_timing_info
;
3316 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3317 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3319 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3320 ASSERT_TRUE(response
!= NULL
);
3321 ASSERT_TRUE(response
->headers
.get() != NULL
);
3322 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3324 std::string response_data
;
3325 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3326 EXPECT_EQ("1234567890", response_data
);
3329 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3330 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3331 HttpRequestInfo request
;
3332 request
.method
= "GET";
3333 request
.url
= GURL("https://www.google.com/");
3334 request
.load_flags
= 0;
3336 // Configure against https proxy server "proxy:70".
3337 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3338 "https://proxy:70"));
3339 CapturingBoundNetLog log
;
3340 session_deps_
.net_log
= log
.bound().net_log();
3341 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3343 scoped_ptr
<HttpTransaction
> trans(
3344 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3346 // CONNECT to www.google.com:443 via SPDY
3347 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3349 // fetch https://www.google.com/ via SPDY
3350 const char* const kMyUrl
= "https://www.google.com/";
3351 scoped_ptr
<SpdyFrame
> get(
3352 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3353 scoped_ptr
<SpdyFrame
> wrapped_get(
3354 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3355 scoped_ptr
<SpdyFrame
> conn_resp(
3356 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3357 scoped_ptr
<SpdyFrame
> get_resp(
3358 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3359 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3360 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3361 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3362 scoped_ptr
<SpdyFrame
> wrapped_body(
3363 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3364 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3365 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3366 scoped_ptr
<SpdyFrame
> window_update_body(
3367 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3369 MockWrite spdy_writes
[] = {
3370 CreateMockWrite(*connect
, 1),
3371 CreateMockWrite(*wrapped_get
, 3),
3372 CreateMockWrite(*window_update_get_resp
, 5),
3373 CreateMockWrite(*window_update_body
, 7),
3376 MockRead spdy_reads
[] = {
3377 CreateMockRead(*conn_resp
, 2, ASYNC
),
3378 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3379 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3380 MockRead(ASYNC
, 0, 8),
3383 OrderedSocketData
spdy_data(
3384 spdy_reads
, arraysize(spdy_reads
),
3385 spdy_writes
, arraysize(spdy_writes
));
3386 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3388 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3389 ssl
.SetNextProto(GetParam());
3390 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3391 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3392 ssl2
.SetNextProto(GetParam());
3393 ssl2
.protocol_negotiated
= GetParam();
3394 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3396 TestCompletionCallback callback1
;
3398 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3399 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3401 rv
= callback1
.WaitForResult();
3404 LoadTimingInfo load_timing_info
;
3405 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3406 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3408 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3409 ASSERT_TRUE(response
!= NULL
);
3410 ASSERT_TRUE(response
->headers
.get() != NULL
);
3411 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3413 std::string response_data
;
3414 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3415 EXPECT_EQ(kUploadData
, response_data
);
3418 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3419 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3420 HttpRequestInfo request
;
3421 request
.method
= "GET";
3422 request
.url
= GURL("https://www.google.com/");
3423 request
.load_flags
= 0;
3425 // Configure against https proxy server "proxy:70".
3426 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3427 "https://proxy:70"));
3428 CapturingBoundNetLog log
;
3429 session_deps_
.net_log
= log
.bound().net_log();
3430 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3432 scoped_ptr
<HttpTransaction
> trans(
3433 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3435 // CONNECT to www.google.com:443 via SPDY
3436 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3438 scoped_ptr
<SpdyFrame
> get(
3439 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3441 MockWrite spdy_writes
[] = {
3442 CreateMockWrite(*connect
, 1),
3443 CreateMockWrite(*get
, 3),
3446 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3447 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3448 MockRead spdy_reads
[] = {
3449 CreateMockRead(*resp
, 2, ASYNC
),
3450 MockRead(ASYNC
, 0, 4),
3453 OrderedSocketData
spdy_data(
3454 spdy_reads
, arraysize(spdy_reads
),
3455 spdy_writes
, arraysize(spdy_writes
));
3456 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3458 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3459 ssl
.SetNextProto(GetParam());
3460 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3461 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3462 ssl2
.SetNextProto(GetParam());
3463 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3465 TestCompletionCallback callback1
;
3467 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3470 rv
= callback1
.WaitForResult();
3471 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3473 // TODO(ttuttle): Anything else to check here?
3476 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3477 // HTTPS Proxy to different servers.
3478 TEST_P(HttpNetworkTransactionTest
,
3479 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3480 // Configure against https proxy server "proxy:70".
3481 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3482 "https://proxy:70"));
3483 CapturingBoundNetLog log
;
3484 session_deps_
.net_log
= log
.bound().net_log();
3485 scoped_refptr
<HttpNetworkSession
> session(
3486 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3488 HttpRequestInfo request1
;
3489 request1
.method
= "GET";
3490 request1
.url
= GURL("https://www.google.com/");
3491 request1
.load_flags
= 0;
3493 HttpRequestInfo request2
;
3494 request2
.method
= "GET";
3495 request2
.url
= GURL("https://news.google.com/");
3496 request2
.load_flags
= 0;
3498 // CONNECT to www.google.com:443 via SPDY.
3499 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3501 scoped_ptr
<SpdyFrame
> conn_resp1(
3502 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3504 // Fetch https://www.google.com/ via HTTP.
3505 const char get1
[] = "GET / HTTP/1.1\r\n"
3506 "Host: www.google.com\r\n"
3507 "Connection: keep-alive\r\n\r\n";
3508 scoped_ptr
<SpdyFrame
> wrapped_get1(
3509 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3510 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3511 "Content-Length: 1\r\n\r\n";
3512 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3513 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3514 scoped_ptr
<SpdyFrame
> wrapped_body1(
3515 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3516 scoped_ptr
<SpdyFrame
> window_update(
3517 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3519 // CONNECT to news.google.com:443 via SPDY.
3520 SpdyHeaderBlock connect2_block
;
3521 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3522 connect2_block
[spdy_util_
.GetPathKey()] = "news.google.com:443";
3523 connect2_block
[spdy_util_
.GetHostKey()] = "news.google.com";
3524 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3525 scoped_ptr
<SpdyFrame
> connect2(
3526 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3528 scoped_ptr
<SpdyFrame
> conn_resp2(
3529 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3531 // Fetch https://news.google.com/ via HTTP.
3532 const char get2
[] = "GET / HTTP/1.1\r\n"
3533 "Host: news.google.com\r\n"
3534 "Connection: keep-alive\r\n\r\n";
3535 scoped_ptr
<SpdyFrame
> wrapped_get2(
3536 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3537 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3538 "Content-Length: 2\r\n\r\n";
3539 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3540 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3541 scoped_ptr
<SpdyFrame
> wrapped_body2(
3542 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3544 MockWrite spdy_writes
[] = {
3545 CreateMockWrite(*connect1
, 0),
3546 CreateMockWrite(*wrapped_get1
, 2),
3547 CreateMockWrite(*connect2
, 5),
3548 CreateMockWrite(*wrapped_get2
, 7),
3551 MockRead spdy_reads
[] = {
3552 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3553 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3554 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3555 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3556 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3557 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3558 MockRead(ASYNC
, 0, 10),
3561 DeterministicSocketData
spdy_data(
3562 spdy_reads
, arraysize(spdy_reads
),
3563 spdy_writes
, arraysize(spdy_writes
));
3564 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3566 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3567 ssl
.SetNextProto(GetParam());
3568 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3569 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3570 ssl2
.was_npn_negotiated
= false;
3571 ssl2
.protocol_negotiated
= kProtoUnknown
;
3572 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3573 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3574 ssl3
.was_npn_negotiated
= false;
3575 ssl3
.protocol_negotiated
= kProtoUnknown
;
3576 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3578 TestCompletionCallback callback
;
3580 scoped_ptr
<HttpTransaction
> trans(
3581 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3582 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3583 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3584 // The first connect and request, each of their responses, and the body.
3585 spdy_data
.RunFor(5);
3587 rv
= callback
.WaitForResult();
3590 LoadTimingInfo load_timing_info
;
3591 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3592 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3594 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3595 ASSERT_TRUE(response
!= NULL
);
3596 ASSERT_TRUE(response
->headers
.get() != NULL
);
3597 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3599 std::string response_data
;
3600 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3601 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3603 scoped_ptr
<HttpTransaction
> trans2(
3604 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3605 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3608 // The second connect and request, each of their responses, and the body.
3609 spdy_data
.RunFor(5);
3610 rv
= callback
.WaitForResult();
3613 LoadTimingInfo load_timing_info2
;
3614 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3615 // Even though the SPDY connection is reused, a new tunnelled connection has
3616 // to be created, so the socket's load timing looks like a fresh connection.
3617 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3619 // The requests should have different IDs, since they each are using their own
3621 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3623 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3626 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3627 // HTTPS Proxy to the same server.
3628 TEST_P(HttpNetworkTransactionTest
,
3629 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3630 // Configure against https proxy server "proxy:70".
3631 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3632 "https://proxy:70"));
3633 CapturingBoundNetLog log
;
3634 session_deps_
.net_log
= log
.bound().net_log();
3635 scoped_refptr
<HttpNetworkSession
> session(
3636 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3638 HttpRequestInfo request1
;
3639 request1
.method
= "GET";
3640 request1
.url
= GURL("https://www.google.com/");
3641 request1
.load_flags
= 0;
3643 HttpRequestInfo request2
;
3644 request2
.method
= "GET";
3645 request2
.url
= GURL("https://www.google.com/2");
3646 request2
.load_flags
= 0;
3648 // CONNECT to www.google.com:443 via SPDY.
3649 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3651 scoped_ptr
<SpdyFrame
> conn_resp1(
3652 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3654 // Fetch https://www.google.com/ via HTTP.
3655 const char get1
[] = "GET / HTTP/1.1\r\n"
3656 "Host: www.google.com\r\n"
3657 "Connection: keep-alive\r\n\r\n";
3658 scoped_ptr
<SpdyFrame
> wrapped_get1(
3659 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3660 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3661 "Content-Length: 1\r\n\r\n";
3662 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3663 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3664 scoped_ptr
<SpdyFrame
> wrapped_body1(
3665 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3666 scoped_ptr
<SpdyFrame
> window_update(
3667 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3669 // Fetch https://www.google.com/2 via HTTP.
3670 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3671 "Host: www.google.com\r\n"
3672 "Connection: keep-alive\r\n\r\n";
3673 scoped_ptr
<SpdyFrame
> wrapped_get2(
3674 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3675 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3676 "Content-Length: 2\r\n\r\n";
3677 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3678 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3679 scoped_ptr
<SpdyFrame
> wrapped_body2(
3680 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3682 MockWrite spdy_writes
[] = {
3683 CreateMockWrite(*connect1
, 0),
3684 CreateMockWrite(*wrapped_get1
, 2),
3685 CreateMockWrite(*wrapped_get2
, 5),
3688 MockRead spdy_reads
[] = {
3689 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3690 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3691 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3692 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3693 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3694 MockRead(ASYNC
, 0, 8),
3697 DeterministicSocketData
spdy_data(
3698 spdy_reads
, arraysize(spdy_reads
),
3699 spdy_writes
, arraysize(spdy_writes
));
3700 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3702 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3703 ssl
.SetNextProto(GetParam());
3704 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3705 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3706 ssl2
.was_npn_negotiated
= false;
3707 ssl2
.protocol_negotiated
= kProtoUnknown
;
3708 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3710 TestCompletionCallback callback
;
3712 scoped_ptr
<HttpTransaction
> trans(
3713 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3714 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3715 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3716 // The first connect and request, each of their responses, and the body.
3717 spdy_data
.RunFor(5);
3719 rv
= callback
.WaitForResult();
3722 LoadTimingInfo load_timing_info
;
3723 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3724 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3726 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3727 ASSERT_TRUE(response
!= NULL
);
3728 ASSERT_TRUE(response
->headers
.get() != NULL
);
3729 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3731 std::string response_data
;
3732 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3733 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3736 scoped_ptr
<HttpTransaction
> trans2(
3737 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3738 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3741 // The second request, response, and body. There should not be a second
3743 spdy_data
.RunFor(3);
3744 rv
= callback
.WaitForResult();
3747 LoadTimingInfo load_timing_info2
;
3748 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3749 TestLoadTimingReused(load_timing_info2
);
3751 // The requests should have the same ID.
3752 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3754 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3757 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3758 // Proxy to different servers.
3759 TEST_P(HttpNetworkTransactionTest
,
3760 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3761 // Configure against https proxy server "proxy:70".
3762 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3763 "https://proxy:70"));
3764 CapturingBoundNetLog log
;
3765 session_deps_
.net_log
= log
.bound().net_log();
3766 scoped_refptr
<HttpNetworkSession
> session(
3767 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3769 HttpRequestInfo request1
;
3770 request1
.method
= "GET";
3771 request1
.url
= GURL("http://www.google.com/");
3772 request1
.load_flags
= 0;
3774 HttpRequestInfo request2
;
3775 request2
.method
= "GET";
3776 request2
.url
= GURL("http://news.google.com/");
3777 request2
.load_flags
= 0;
3779 // http://www.google.com/
3780 scoped_ptr
<SpdyHeaderBlock
> headers(
3781 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3782 scoped_ptr
<SpdyFrame
> get1(
3783 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
3784 scoped_ptr
<SpdyFrame
> get_resp1(
3785 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3786 scoped_ptr
<SpdyFrame
> body1(
3787 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3789 // http://news.google.com/
3790 scoped_ptr
<SpdyHeaderBlock
> headers2(
3791 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3792 scoped_ptr
<SpdyFrame
> get2(
3793 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
3794 scoped_ptr
<SpdyFrame
> get_resp2(
3795 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3796 scoped_ptr
<SpdyFrame
> body2(
3797 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3799 MockWrite spdy_writes
[] = {
3800 CreateMockWrite(*get1
, 0),
3801 CreateMockWrite(*get2
, 3),
3804 MockRead spdy_reads
[] = {
3805 CreateMockRead(*get_resp1
, 1, ASYNC
),
3806 CreateMockRead(*body1
, 2, ASYNC
),
3807 CreateMockRead(*get_resp2
, 4, ASYNC
),
3808 CreateMockRead(*body2
, 5, ASYNC
),
3809 MockRead(ASYNC
, 0, 6),
3812 DeterministicSocketData
spdy_data(
3813 spdy_reads
, arraysize(spdy_reads
),
3814 spdy_writes
, arraysize(spdy_writes
));
3815 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3817 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3818 ssl
.SetNextProto(GetParam());
3819 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3821 TestCompletionCallback callback
;
3823 scoped_ptr
<HttpTransaction
> trans(
3824 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3825 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3826 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3827 spdy_data
.RunFor(2);
3829 rv
= callback
.WaitForResult();
3832 LoadTimingInfo load_timing_info
;
3833 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3834 TestLoadTimingNotReused(load_timing_info
,
3835 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3837 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3838 ASSERT_TRUE(response
!= NULL
);
3839 ASSERT_TRUE(response
->headers
.get() != NULL
);
3840 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3842 std::string response_data
;
3843 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3844 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3845 spdy_data
.RunFor(1);
3846 EXPECT_EQ(1, callback
.WaitForResult());
3847 // Delete the first request, so the second one can reuse the socket.
3850 scoped_ptr
<HttpTransaction
> trans2(
3851 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3852 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3853 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3855 spdy_data
.RunFor(2);
3856 rv
= callback
.WaitForResult();
3859 LoadTimingInfo load_timing_info2
;
3860 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3861 TestLoadTimingReused(load_timing_info2
);
3863 // The requests should have the same ID.
3864 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3866 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3867 spdy_data
.RunFor(1);
3868 EXPECT_EQ(2, callback
.WaitForResult());
3871 // Test the challenge-response-retry sequence through an HTTPS Proxy
3872 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3873 HttpRequestInfo request
;
3874 request
.method
= "GET";
3875 request
.url
= GURL("http://www.google.com/");
3876 // when the no authentication data flag is set.
3877 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3879 // Configure against https proxy server "myproxy:70".
3880 session_deps_
.proxy_service
.reset(
3881 ProxyService::CreateFixed("https://myproxy:70"));
3882 CapturingBoundNetLog log
;
3883 session_deps_
.net_log
= log
.bound().net_log();
3884 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3886 // Since we have proxy, should use full url
3887 MockWrite data_writes1
[] = {
3888 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3889 "Host: www.google.com\r\n"
3890 "Proxy-Connection: keep-alive\r\n\r\n"),
3892 // After calling trans->RestartWithAuth(), this is the request we should
3893 // be issuing -- the final header line contains the credentials.
3894 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3895 "Host: www.google.com\r\n"
3896 "Proxy-Connection: keep-alive\r\n"
3897 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3900 // The proxy responds to the GET with a 407, using a persistent
3902 MockRead data_reads1
[] = {
3904 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3905 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3906 MockRead("Proxy-Connection: keep-alive\r\n"),
3907 MockRead("Content-Length: 0\r\n\r\n"),
3909 MockRead("HTTP/1.1 200 OK\r\n"),
3910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3911 MockRead("Content-Length: 100\r\n\r\n"),
3912 MockRead(SYNCHRONOUS
, OK
),
3915 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3916 data_writes1
, arraysize(data_writes1
));
3917 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3918 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3919 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3921 TestCompletionCallback callback1
;
3923 scoped_ptr
<HttpTransaction
> trans(
3924 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3926 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3927 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3929 rv
= callback1
.WaitForResult();
3932 LoadTimingInfo load_timing_info
;
3933 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3934 TestLoadTimingNotReused(load_timing_info
,
3935 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3937 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3938 ASSERT_TRUE(response
!= NULL
);
3939 ASSERT_FALSE(response
->headers
.get() == NULL
);
3940 EXPECT_EQ(407, response
->headers
->response_code());
3941 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3942 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3944 TestCompletionCallback callback2
;
3946 rv
= trans
->RestartWithAuth(
3947 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3948 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3950 rv
= callback2
.WaitForResult();
3953 load_timing_info
= LoadTimingInfo();
3954 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3955 // Retrying with HTTP AUTH is considered to be reusing a socket.
3956 TestLoadTimingReused(load_timing_info
);
3958 response
= trans
->GetResponseInfo();
3959 ASSERT_TRUE(response
!= NULL
);
3961 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3962 EXPECT_EQ(200, response
->headers
->response_code());
3963 EXPECT_EQ(100, response
->headers
->GetContentLength());
3964 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3966 // The password prompt info should not be set.
3967 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3970 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3971 const MockRead
& status
, int expected_status
) {
3972 HttpRequestInfo request
;
3973 request
.method
= "GET";
3974 request
.url
= GURL("https://www.google.com/");
3975 request
.load_flags
= 0;
3977 // Configure against proxy server "myproxy:70".
3978 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3979 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3981 // Since we have proxy, should try to establish tunnel.
3982 MockWrite data_writes
[] = {
3983 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3984 "Host: www.google.com\r\n"
3985 "Proxy-Connection: keep-alive\r\n\r\n"),
3988 MockRead data_reads
[] = {
3990 MockRead("Content-Length: 10\r\n\r\n"),
3991 // No response body because the test stops reading here.
3992 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3995 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3996 data_writes
, arraysize(data_writes
));
3997 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3999 TestCompletionCallback callback
;
4001 scoped_ptr
<HttpTransaction
> trans(
4002 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4004 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4005 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4007 rv
= callback
.WaitForResult();
4008 EXPECT_EQ(expected_status
, rv
);
4011 void HttpNetworkTransactionTest::ConnectStatusHelper(
4012 const MockRead
& status
) {
4013 ConnectStatusHelperWithExpectedStatus(
4014 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4017 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4018 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4021 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4022 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4025 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4026 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4029 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4030 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4033 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4034 ConnectStatusHelper(
4035 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4038 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4039 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4042 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4043 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4046 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4047 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4050 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4051 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4054 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4055 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4058 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4059 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4062 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4063 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4066 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4067 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4070 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4071 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4074 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4075 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4078 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4079 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4082 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4083 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4086 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4087 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4090 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4091 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4094 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4095 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4098 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4099 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4102 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4103 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4106 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4107 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4110 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4111 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4114 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4115 ConnectStatusHelperWithExpectedStatus(
4116 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4117 ERR_PROXY_AUTH_UNSUPPORTED
);
4120 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4121 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4124 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4125 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4128 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4129 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4132 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4133 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4136 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4137 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4140 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4141 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4144 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4145 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4148 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4149 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4152 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4153 ConnectStatusHelper(
4154 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4157 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4158 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4161 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4162 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4165 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4166 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4169 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4170 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4173 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4174 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4177 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4178 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4181 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4182 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4185 // Test the flow when both the proxy server AND origin server require
4186 // authentication. Again, this uses basic auth for both since that is
4187 // the simplest to mock.
4188 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4189 HttpRequestInfo request
;
4190 request
.method
= "GET";
4191 request
.url
= GURL("http://www.google.com/");
4192 request
.load_flags
= 0;
4194 // Configure against proxy server "myproxy:70".
4195 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4198 scoped_ptr
<HttpTransaction
> trans(
4199 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4201 MockWrite data_writes1
[] = {
4202 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4203 "Host: www.google.com\r\n"
4204 "Proxy-Connection: keep-alive\r\n\r\n"),
4207 MockRead data_reads1
[] = {
4208 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4209 // Give a couple authenticate options (only the middle one is actually
4211 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4212 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4213 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4215 // Large content-length -- won't matter, as connection will be reset.
4216 MockRead("Content-Length: 10000\r\n\r\n"),
4217 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4220 // After calling trans->RestartWithAuth() the first time, this is the
4221 // request we should be issuing -- the final header line contains the
4222 // proxy's credentials.
4223 MockWrite data_writes2
[] = {
4224 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4225 "Host: www.google.com\r\n"
4226 "Proxy-Connection: keep-alive\r\n"
4227 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4230 // Now the proxy server lets the request pass through to origin server.
4231 // The origin server responds with a 401.
4232 MockRead data_reads2
[] = {
4233 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4234 // Note: We are using the same realm-name as the proxy server. This is
4235 // completely valid, as realms are unique across hosts.
4236 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4237 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4238 MockRead("Content-Length: 2000\r\n\r\n"),
4239 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4242 // After calling trans->RestartWithAuth() the second time, we should send
4243 // the credentials for both the proxy and origin server.
4244 MockWrite data_writes3
[] = {
4245 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4246 "Host: www.google.com\r\n"
4247 "Proxy-Connection: keep-alive\r\n"
4248 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4249 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4252 // Lastly we get the desired content.
4253 MockRead data_reads3
[] = {
4254 MockRead("HTTP/1.0 200 OK\r\n"),
4255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4256 MockRead("Content-Length: 100\r\n\r\n"),
4257 MockRead(SYNCHRONOUS
, OK
),
4260 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4261 data_writes1
, arraysize(data_writes1
));
4262 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4263 data_writes2
, arraysize(data_writes2
));
4264 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4265 data_writes3
, arraysize(data_writes3
));
4266 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4267 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4268 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4270 TestCompletionCallback callback1
;
4272 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4273 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4275 rv
= callback1
.WaitForResult();
4278 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4279 ASSERT_TRUE(response
!= NULL
);
4280 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4282 TestCompletionCallback callback2
;
4284 rv
= trans
->RestartWithAuth(
4285 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4286 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4288 rv
= callback2
.WaitForResult();
4291 response
= trans
->GetResponseInfo();
4292 ASSERT_TRUE(response
!= NULL
);
4293 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4295 TestCompletionCallback callback3
;
4297 rv
= trans
->RestartWithAuth(
4298 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4299 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4301 rv
= callback3
.WaitForResult();
4304 response
= trans
->GetResponseInfo();
4305 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4306 EXPECT_EQ(100, response
->headers
->GetContentLength());
4309 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4310 // can't hook into its internals to cause it to generate predictable NTLM
4311 // authorization headers.
4312 #if defined(NTLM_PORTABLE)
4313 // The NTLM authentication unit tests were generated by capturing the HTTP
4314 // requests and responses using Fiddler 2 and inspecting the generated random
4315 // bytes in the debugger.
4317 // Enter the correct password and authenticate successfully.
4318 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4319 HttpRequestInfo request
;
4320 request
.method
= "GET";
4321 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4323 // Ensure load is not disrupted by flags which suppress behaviour specific
4324 // to other auth schemes.
4325 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4327 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4331 MockWrite data_writes1
[] = {
4332 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4333 "Host: 172.22.68.17\r\n"
4334 "Connection: keep-alive\r\n\r\n"),
4337 MockRead data_reads1
[] = {
4338 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4339 // Negotiate and NTLM are often requested together. However, we only want
4340 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4341 // the header that requests Negotiate for this test.
4342 MockRead("WWW-Authenticate: NTLM\r\n"),
4343 MockRead("Connection: close\r\n"),
4344 MockRead("Content-Length: 42\r\n"),
4345 MockRead("Content-Type: text/html\r\n\r\n"),
4346 // Missing content -- won't matter, as connection will be reset.
4347 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4350 MockWrite data_writes2
[] = {
4351 // After restarting with a null identity, this is the
4352 // request we should be issuing -- the final header line contains a Type
4354 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4355 "Host: 172.22.68.17\r\n"
4356 "Connection: keep-alive\r\n"
4357 "Authorization: NTLM "
4358 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4360 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4361 // (the credentials for the origin server). The second request continues
4362 // on the same connection.
4363 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4364 "Host: 172.22.68.17\r\n"
4365 "Connection: keep-alive\r\n"
4366 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4367 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4368 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4369 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4370 "ahlhx5I=\r\n\r\n"),
4373 MockRead data_reads2
[] = {
4374 // The origin server responds with a Type 2 message.
4375 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4376 MockRead("WWW-Authenticate: NTLM "
4377 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4378 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4379 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4380 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4381 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4382 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4384 MockRead("Content-Length: 42\r\n"),
4385 MockRead("Content-Type: text/html\r\n\r\n"),
4386 MockRead("You are not authorized to view this page\r\n"),
4388 // Lastly we get the desired content.
4389 MockRead("HTTP/1.1 200 OK\r\n"),
4390 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4391 MockRead("Content-Length: 13\r\n\r\n"),
4392 MockRead("Please Login\r\n"),
4393 MockRead(SYNCHRONOUS
, OK
),
4396 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4397 data_writes1
, arraysize(data_writes1
));
4398 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4399 data_writes2
, arraysize(data_writes2
));
4400 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4401 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4403 TestCompletionCallback callback1
;
4405 scoped_ptr
<HttpTransaction
> trans(
4406 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4408 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4409 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4411 rv
= callback1
.WaitForResult();
4414 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4416 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4417 ASSERT_FALSE(response
== NULL
);
4418 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4420 TestCompletionCallback callback2
;
4422 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4423 callback2
.callback());
4424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4426 rv
= callback2
.WaitForResult();
4429 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4431 response
= trans
->GetResponseInfo();
4432 ASSERT_TRUE(response
!= NULL
);
4433 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4435 TestCompletionCallback callback3
;
4437 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4440 rv
= callback3
.WaitForResult();
4443 response
= trans
->GetResponseInfo();
4444 ASSERT_TRUE(response
!= NULL
);
4445 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4446 EXPECT_EQ(13, response
->headers
->GetContentLength());
4449 // Enter a wrong password, and then the correct one.
4450 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4451 HttpRequestInfo request
;
4452 request
.method
= "GET";
4453 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4454 request
.load_flags
= 0;
4456 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4458 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4460 MockWrite data_writes1
[] = {
4461 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4462 "Host: 172.22.68.17\r\n"
4463 "Connection: keep-alive\r\n\r\n"),
4466 MockRead data_reads1
[] = {
4467 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4468 // Negotiate and NTLM are often requested together. However, we only want
4469 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4470 // the header that requests Negotiate for this test.
4471 MockRead("WWW-Authenticate: NTLM\r\n"),
4472 MockRead("Connection: close\r\n"),
4473 MockRead("Content-Length: 42\r\n"),
4474 MockRead("Content-Type: text/html\r\n\r\n"),
4475 // Missing content -- won't matter, as connection will be reset.
4476 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4479 MockWrite data_writes2
[] = {
4480 // After restarting with a null identity, this is the
4481 // request we should be issuing -- the final header line contains a Type
4483 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4484 "Host: 172.22.68.17\r\n"
4485 "Connection: keep-alive\r\n"
4486 "Authorization: NTLM "
4487 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4489 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4490 // (the credentials for the origin server). The second request continues
4491 // on the same connection.
4492 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4493 "Host: 172.22.68.17\r\n"
4494 "Connection: keep-alive\r\n"
4495 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4496 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4497 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4498 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4499 "4Ww7b7E=\r\n\r\n"),
4502 MockRead data_reads2
[] = {
4503 // The origin server responds with a Type 2 message.
4504 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4505 MockRead("WWW-Authenticate: NTLM "
4506 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4507 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4508 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4509 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4510 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4511 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4513 MockRead("Content-Length: 42\r\n"),
4514 MockRead("Content-Type: text/html\r\n\r\n"),
4515 MockRead("You are not authorized to view this page\r\n"),
4518 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4519 MockRead("WWW-Authenticate: NTLM\r\n"),
4520 MockRead("Connection: close\r\n"),
4521 MockRead("Content-Length: 42\r\n"),
4522 MockRead("Content-Type: text/html\r\n\r\n"),
4523 // Missing content -- won't matter, as connection will be reset.
4524 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4527 MockWrite data_writes3
[] = {
4528 // After restarting with a null identity, this is the
4529 // request we should be issuing -- the final header line contains a Type
4531 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4532 "Host: 172.22.68.17\r\n"
4533 "Connection: keep-alive\r\n"
4534 "Authorization: NTLM "
4535 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4537 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4538 // (the credentials for the origin server). The second request continues
4539 // on the same connection.
4540 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4541 "Host: 172.22.68.17\r\n"
4542 "Connection: keep-alive\r\n"
4543 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4544 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4545 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4546 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4547 "+4MUm7c=\r\n\r\n"),
4550 MockRead data_reads3
[] = {
4551 // The origin server responds with a Type 2 message.
4552 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4553 MockRead("WWW-Authenticate: NTLM "
4554 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4555 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4556 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4557 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4558 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4559 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4561 MockRead("Content-Length: 42\r\n"),
4562 MockRead("Content-Type: text/html\r\n\r\n"),
4563 MockRead("You are not authorized to view this page\r\n"),
4565 // Lastly we get the desired content.
4566 MockRead("HTTP/1.1 200 OK\r\n"),
4567 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4568 MockRead("Content-Length: 13\r\n\r\n"),
4569 MockRead("Please Login\r\n"),
4570 MockRead(SYNCHRONOUS
, OK
),
4573 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4574 data_writes1
, arraysize(data_writes1
));
4575 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4576 data_writes2
, arraysize(data_writes2
));
4577 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4578 data_writes3
, arraysize(data_writes3
));
4579 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4580 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4581 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4583 TestCompletionCallback callback1
;
4585 scoped_ptr
<HttpTransaction
> trans(
4586 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4588 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4591 rv
= callback1
.WaitForResult();
4594 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4596 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4597 ASSERT_TRUE(response
!= NULL
);
4598 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4600 TestCompletionCallback callback2
;
4602 // Enter the wrong password.
4603 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4604 callback2
.callback());
4605 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4607 rv
= callback2
.WaitForResult();
4610 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4611 TestCompletionCallback callback3
;
4612 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4613 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4614 rv
= callback3
.WaitForResult();
4616 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4618 response
= trans
->GetResponseInfo();
4619 ASSERT_FALSE(response
== NULL
);
4620 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4622 TestCompletionCallback callback4
;
4624 // Now enter the right password.
4625 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4626 callback4
.callback());
4627 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4629 rv
= callback4
.WaitForResult();
4632 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4634 TestCompletionCallback callback5
;
4636 // One more roundtrip
4637 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4638 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4640 rv
= callback5
.WaitForResult();
4643 response
= trans
->GetResponseInfo();
4644 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4645 EXPECT_EQ(13, response
->headers
->GetContentLength());
4647 #endif // NTLM_PORTABLE
4649 // Test reading a server response which has only headers, and no body.
4650 // After some maximum number of bytes is consumed, the transaction should
4651 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4652 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4653 HttpRequestInfo request
;
4654 request
.method
= "GET";
4655 request
.url
= GURL("http://www.google.com/");
4656 request
.load_flags
= 0;
4658 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4659 scoped_ptr
<HttpTransaction
> trans(
4660 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4662 // Respond with 300 kb of headers (we should fail after 256 kb).
4663 std::string large_headers_string
;
4664 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4666 MockRead data_reads
[] = {
4667 MockRead("HTTP/1.0 200 OK\r\n"),
4668 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4669 MockRead("\r\nBODY"),
4670 MockRead(SYNCHRONOUS
, OK
),
4672 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4673 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4675 TestCompletionCallback callback
;
4677 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4678 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4680 rv
= callback
.WaitForResult();
4681 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4683 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4684 EXPECT_TRUE(response
== NULL
);
4687 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4688 // establish tunnel.
4689 // http://code.google.com/p/chromium/issues/detail?id=3772
4690 TEST_P(HttpNetworkTransactionTest
,
4691 DontRecycleTransportSocketForSSLTunnel
) {
4692 HttpRequestInfo request
;
4693 request
.method
= "GET";
4694 request
.url
= GURL("https://www.google.com/");
4695 request
.load_flags
= 0;
4697 // Configure against proxy server "myproxy:70".
4698 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4700 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4702 scoped_ptr
<HttpTransaction
> trans(
4703 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4705 // Since we have proxy, should try to establish tunnel.
4706 MockWrite data_writes1
[] = {
4707 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4708 "Host: www.google.com\r\n"
4709 "Proxy-Connection: keep-alive\r\n\r\n"),
4712 // The proxy responds to the connect with a 404, using a persistent
4713 // connection. Usually a proxy would return 501 (not implemented),
4714 // or 200 (tunnel established).
4715 MockRead data_reads1
[] = {
4716 MockRead("HTTP/1.1 404 Not Found\r\n"),
4717 MockRead("Content-Length: 10\r\n\r\n"),
4718 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4721 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4722 data_writes1
, arraysize(data_writes1
));
4723 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4725 TestCompletionCallback callback1
;
4727 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4728 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4730 rv
= callback1
.WaitForResult();
4731 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4733 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4734 EXPECT_TRUE(response
== NULL
);
4736 // Empty the current queue. This is necessary because idle sockets are
4737 // added to the connection pool asynchronously with a PostTask.
4738 base::MessageLoop::current()->RunUntilIdle();
4740 // We now check to make sure the TCPClientSocket was not added back to
4742 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4744 base::MessageLoop::current()->RunUntilIdle();
4745 // Make sure that the socket didn't get recycled after calling the destructor.
4746 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4749 // Make sure that we recycle a socket after reading all of the response body.
4750 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4751 HttpRequestInfo request
;
4752 request
.method
= "GET";
4753 request
.url
= GURL("http://www.google.com/");
4754 request
.load_flags
= 0;
4756 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4758 scoped_ptr
<HttpTransaction
> trans(
4759 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4761 MockRead data_reads
[] = {
4762 // A part of the response body is received with the response headers.
4763 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4764 // The rest of the response body is received in two parts.
4767 MockRead("junk"), // Should not be read!!
4768 MockRead(SYNCHRONOUS
, OK
),
4771 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4772 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4774 TestCompletionCallback callback
;
4776 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4779 rv
= callback
.WaitForResult();
4782 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4783 ASSERT_TRUE(response
!= NULL
);
4785 EXPECT_TRUE(response
->headers
.get() != NULL
);
4786 std::string status_line
= response
->headers
->GetStatusLine();
4787 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4789 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4791 std::string response_data
;
4792 rv
= ReadTransaction(trans
.get(), &response_data
);
4794 EXPECT_EQ("hello world", response_data
);
4796 // Empty the current queue. This is necessary because idle sockets are
4797 // added to the connection pool asynchronously with a PostTask.
4798 base::MessageLoop::current()->RunUntilIdle();
4800 // We now check to make sure the socket was added back to the pool.
4801 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4804 // Make sure that we recycle a SSL socket after reading all of the response
4806 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4807 HttpRequestInfo request
;
4808 request
.method
= "GET";
4809 request
.url
= GURL("https://www.google.com/");
4810 request
.load_flags
= 0;
4812 MockWrite data_writes
[] = {
4813 MockWrite("GET / HTTP/1.1\r\n"
4814 "Host: www.google.com\r\n"
4815 "Connection: keep-alive\r\n\r\n"),
4818 MockRead data_reads
[] = {
4819 MockRead("HTTP/1.1 200 OK\r\n"),
4820 MockRead("Content-Length: 11\r\n\r\n"),
4821 MockRead("hello world"),
4822 MockRead(SYNCHRONOUS
, OK
),
4825 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4826 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4828 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4829 data_writes
, arraysize(data_writes
));
4830 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4832 TestCompletionCallback callback
;
4834 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4835 scoped_ptr
<HttpTransaction
> trans(
4836 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4838 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4840 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4841 EXPECT_EQ(OK
, callback
.WaitForResult());
4843 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4844 ASSERT_TRUE(response
!= NULL
);
4845 ASSERT_TRUE(response
->headers
.get() != NULL
);
4846 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4848 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4850 std::string response_data
;
4851 rv
= ReadTransaction(trans
.get(), &response_data
);
4853 EXPECT_EQ("hello world", response_data
);
4855 // Empty the current queue. This is necessary because idle sockets are
4856 // added to the connection pool asynchronously with a PostTask.
4857 base::MessageLoop::current()->RunUntilIdle();
4859 // We now check to make sure the socket was added back to the pool.
4860 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4863 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4864 // from the pool and make sure that we recover okay.
4865 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4866 HttpRequestInfo request
;
4867 request
.method
= "GET";
4868 request
.url
= GURL("https://www.google.com/");
4869 request
.load_flags
= 0;
4871 MockWrite data_writes
[] = {
4872 MockWrite("GET / HTTP/1.1\r\n"
4873 "Host: www.google.com\r\n"
4874 "Connection: keep-alive\r\n\r\n"),
4875 MockWrite("GET / HTTP/1.1\r\n"
4876 "Host: www.google.com\r\n"
4877 "Connection: keep-alive\r\n\r\n"),
4880 MockRead data_reads
[] = {
4881 MockRead("HTTP/1.1 200 OK\r\n"),
4882 MockRead("Content-Length: 11\r\n\r\n"),
4883 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4884 MockRead("hello world"),
4885 MockRead(ASYNC
, 0, 0) // EOF
4888 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4889 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4890 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4893 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4894 data_writes
, arraysize(data_writes
));
4895 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4896 data_writes
, arraysize(data_writes
));
4897 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4898 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4900 TestCompletionCallback callback
;
4902 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4903 scoped_ptr
<HttpTransaction
> trans(
4904 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4906 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4908 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4909 EXPECT_EQ(OK
, callback
.WaitForResult());
4911 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4912 ASSERT_TRUE(response
!= NULL
);
4913 ASSERT_TRUE(response
->headers
.get() != NULL
);
4914 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4916 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4918 std::string response_data
;
4919 rv
= ReadTransaction(trans
.get(), &response_data
);
4921 EXPECT_EQ("hello world", response_data
);
4923 // Empty the current queue. This is necessary because idle sockets are
4924 // added to the connection pool asynchronously with a PostTask.
4925 base::MessageLoop::current()->RunUntilIdle();
4927 // We now check to make sure the socket was added back to the pool.
4928 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4930 // Now start the second transaction, which should reuse the previous socket.
4932 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4934 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4937 EXPECT_EQ(OK
, callback
.WaitForResult());
4939 response
= trans
->GetResponseInfo();
4940 ASSERT_TRUE(response
!= NULL
);
4941 ASSERT_TRUE(response
->headers
.get() != NULL
);
4942 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4944 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4946 rv
= ReadTransaction(trans
.get(), &response_data
);
4948 EXPECT_EQ("hello world", response_data
);
4950 // Empty the current queue. This is necessary because idle sockets are
4951 // added to the connection pool asynchronously with a PostTask.
4952 base::MessageLoop::current()->RunUntilIdle();
4954 // We now check to make sure the socket was added back to the pool.
4955 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4958 // Make sure that we recycle a socket after a zero-length response.
4959 // http://crbug.com/9880
4960 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4961 HttpRequestInfo request
;
4962 request
.method
= "GET";
4963 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4964 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4965 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4966 "rt=prt.2642,ol.2649,xjs.2951");
4967 request
.load_flags
= 0;
4969 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4971 scoped_ptr
<HttpTransaction
> trans(
4972 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4974 MockRead data_reads
[] = {
4975 MockRead("HTTP/1.1 204 No Content\r\n"
4976 "Content-Length: 0\r\n"
4977 "Content-Type: text/html\r\n\r\n"),
4978 MockRead("junk"), // Should not be read!!
4979 MockRead(SYNCHRONOUS
, OK
),
4982 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4983 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4985 TestCompletionCallback callback
;
4987 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4988 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4990 rv
= callback
.WaitForResult();
4993 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4994 ASSERT_TRUE(response
!= NULL
);
4996 EXPECT_TRUE(response
->headers
.get() != NULL
);
4997 std::string status_line
= response
->headers
->GetStatusLine();
4998 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5000 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5002 std::string response_data
;
5003 rv
= ReadTransaction(trans
.get(), &response_data
);
5005 EXPECT_EQ("", response_data
);
5007 // Empty the current queue. This is necessary because idle sockets are
5008 // added to the connection pool asynchronously with a PostTask.
5009 base::MessageLoop::current()->RunUntilIdle();
5011 // We now check to make sure the socket was added back to the pool.
5012 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5015 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5016 ScopedVector
<UploadElementReader
> element_readers
;
5017 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5018 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5020 HttpRequestInfo request
[2];
5021 // Transaction 1: a GET request that succeeds. The socket is recycled
5023 request
[0].method
= "GET";
5024 request
[0].url
= GURL("http://www.google.com/");
5025 request
[0].load_flags
= 0;
5026 // Transaction 2: a POST request. Reuses the socket kept alive from
5027 // transaction 1. The first attempts fails when writing the POST data.
5028 // This causes the transaction to retry with a new socket. The second
5029 // attempt succeeds.
5030 request
[1].method
= "POST";
5031 request
[1].url
= GURL("http://www.google.com/login.cgi");
5032 request
[1].upload_data_stream
= &upload_data_stream
;
5033 request
[1].load_flags
= 0;
5035 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5037 // The first socket is used for transaction 1 and the first attempt of
5040 // The response of transaction 1.
5041 MockRead data_reads1
[] = {
5042 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5043 MockRead("hello world"),
5044 MockRead(SYNCHRONOUS
, OK
),
5046 // The mock write results of transaction 1 and the first attempt of
5048 MockWrite data_writes1
[] = {
5049 MockWrite(SYNCHRONOUS
, 64), // GET
5050 MockWrite(SYNCHRONOUS
, 93), // POST
5051 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5053 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5054 data_writes1
, arraysize(data_writes1
));
5056 // The second socket is used for the second attempt of transaction 2.
5058 // The response of transaction 2.
5059 MockRead data_reads2
[] = {
5060 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5061 MockRead("welcome"),
5062 MockRead(SYNCHRONOUS
, OK
),
5064 // The mock write results of the second attempt of transaction 2.
5065 MockWrite data_writes2
[] = {
5066 MockWrite(SYNCHRONOUS
, 93), // POST
5067 MockWrite(SYNCHRONOUS
, 3), // POST data
5069 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5070 data_writes2
, arraysize(data_writes2
));
5072 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5073 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5075 const char* kExpectedResponseData
[] = {
5076 "hello world", "welcome"
5079 for (int i
= 0; i
< 2; ++i
) {
5080 scoped_ptr
<HttpTransaction
> trans(
5081 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5083 TestCompletionCallback callback
;
5085 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5086 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5088 rv
= callback
.WaitForResult();
5091 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5092 ASSERT_TRUE(response
!= NULL
);
5094 EXPECT_TRUE(response
->headers
.get() != NULL
);
5095 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5097 std::string response_data
;
5098 rv
= ReadTransaction(trans
.get(), &response_data
);
5100 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5104 // Test the request-challenge-retry sequence for basic auth when there is
5105 // an identity in the URL. The request should be sent as normal, but when
5106 // it fails the identity from the URL is used to answer the challenge.
5107 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5108 HttpRequestInfo request
;
5109 request
.method
= "GET";
5110 request
.url
= GURL("http://foo:b@r@www.google.com/");
5111 request
.load_flags
= LOAD_NORMAL
;
5113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5114 scoped_ptr
<HttpTransaction
> trans(
5115 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5117 // The password contains an escaped character -- for this test to pass it
5118 // will need to be unescaped by HttpNetworkTransaction.
5119 EXPECT_EQ("b%40r", request
.url
.password());
5121 MockWrite data_writes1
[] = {
5122 MockWrite("GET / HTTP/1.1\r\n"
5123 "Host: www.google.com\r\n"
5124 "Connection: keep-alive\r\n\r\n"),
5127 MockRead data_reads1
[] = {
5128 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5129 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5130 MockRead("Content-Length: 10\r\n\r\n"),
5131 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5134 // After the challenge above, the transaction will be restarted using the
5135 // identity from the url (foo, b@r) to answer the challenge.
5136 MockWrite data_writes2
[] = {
5137 MockWrite("GET / HTTP/1.1\r\n"
5138 "Host: www.google.com\r\n"
5139 "Connection: keep-alive\r\n"
5140 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5143 MockRead data_reads2
[] = {
5144 MockRead("HTTP/1.0 200 OK\r\n"),
5145 MockRead("Content-Length: 100\r\n\r\n"),
5146 MockRead(SYNCHRONOUS
, OK
),
5149 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5150 data_writes1
, arraysize(data_writes1
));
5151 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5152 data_writes2
, arraysize(data_writes2
));
5153 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5154 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5156 TestCompletionCallback callback1
;
5157 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5158 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5159 rv
= callback1
.WaitForResult();
5161 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5163 TestCompletionCallback callback2
;
5164 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5166 rv
= callback2
.WaitForResult();
5168 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5170 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5171 ASSERT_TRUE(response
!= NULL
);
5173 // There is no challenge info, since the identity in URL worked.
5174 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5176 EXPECT_EQ(100, response
->headers
->GetContentLength());
5178 // Empty the current queue.
5179 base::MessageLoop::current()->RunUntilIdle();
5182 // Test the request-challenge-retry sequence for basic auth when there is an
5183 // incorrect identity in the URL. The identity from the URL should be used only
5185 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5186 HttpRequestInfo request
;
5187 request
.method
= "GET";
5188 // Note: the URL has a username:password in it. The password "baz" is
5189 // wrong (should be "bar").
5190 request
.url
= GURL("http://foo:baz@www.google.com/");
5192 request
.load_flags
= LOAD_NORMAL
;
5194 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5195 scoped_ptr
<HttpTransaction
> trans(
5196 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5198 MockWrite data_writes1
[] = {
5199 MockWrite("GET / HTTP/1.1\r\n"
5200 "Host: www.google.com\r\n"
5201 "Connection: keep-alive\r\n\r\n"),
5204 MockRead data_reads1
[] = {
5205 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5206 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5207 MockRead("Content-Length: 10\r\n\r\n"),
5208 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5211 // After the challenge above, the transaction will be restarted using the
5212 // identity from the url (foo, baz) to answer the challenge.
5213 MockWrite data_writes2
[] = {
5214 MockWrite("GET / HTTP/1.1\r\n"
5215 "Host: www.google.com\r\n"
5216 "Connection: keep-alive\r\n"
5217 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5220 MockRead data_reads2
[] = {
5221 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5222 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5223 MockRead("Content-Length: 10\r\n\r\n"),
5224 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5227 // After the challenge above, the transaction will be restarted using the
5228 // identity supplied by the user (foo, bar) to answer the challenge.
5229 MockWrite data_writes3
[] = {
5230 MockWrite("GET / HTTP/1.1\r\n"
5231 "Host: www.google.com\r\n"
5232 "Connection: keep-alive\r\n"
5233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5236 MockRead data_reads3
[] = {
5237 MockRead("HTTP/1.0 200 OK\r\n"),
5238 MockRead("Content-Length: 100\r\n\r\n"),
5239 MockRead(SYNCHRONOUS
, OK
),
5242 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5243 data_writes1
, arraysize(data_writes1
));
5244 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5245 data_writes2
, arraysize(data_writes2
));
5246 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5247 data_writes3
, arraysize(data_writes3
));
5248 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5249 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5250 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5252 TestCompletionCallback callback1
;
5254 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5255 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5257 rv
= callback1
.WaitForResult();
5260 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5261 TestCompletionCallback callback2
;
5262 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5263 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5264 rv
= callback2
.WaitForResult();
5266 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5268 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5269 ASSERT_TRUE(response
!= NULL
);
5270 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5272 TestCompletionCallback callback3
;
5273 rv
= trans
->RestartWithAuth(
5274 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5275 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5276 rv
= callback3
.WaitForResult();
5278 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5280 response
= trans
->GetResponseInfo();
5281 ASSERT_TRUE(response
!= NULL
);
5283 // There is no challenge info, since the identity worked.
5284 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5286 EXPECT_EQ(100, response
->headers
->GetContentLength());
5288 // Empty the current queue.
5289 base::MessageLoop::current()->RunUntilIdle();
5293 // Test the request-challenge-retry sequence for basic auth when there is a
5294 // correct identity in the URL, but its use is being suppressed. The identity
5295 // from the URL should never be used.
5296 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5297 HttpRequestInfo request
;
5298 request
.method
= "GET";
5299 request
.url
= GURL("http://foo:bar@www.google.com/");
5300 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5302 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5303 scoped_ptr
<HttpTransaction
> trans(
5304 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5306 MockWrite data_writes1
[] = {
5307 MockWrite("GET / HTTP/1.1\r\n"
5308 "Host: www.google.com\r\n"
5309 "Connection: keep-alive\r\n\r\n"),
5312 MockRead data_reads1
[] = {
5313 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5314 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5315 MockRead("Content-Length: 10\r\n\r\n"),
5316 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5319 // After the challenge above, the transaction will be restarted using the
5320 // identity supplied by the user, not the one in the URL, to answer the
5322 MockWrite data_writes3
[] = {
5323 MockWrite("GET / HTTP/1.1\r\n"
5324 "Host: www.google.com\r\n"
5325 "Connection: keep-alive\r\n"
5326 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5329 MockRead data_reads3
[] = {
5330 MockRead("HTTP/1.0 200 OK\r\n"),
5331 MockRead("Content-Length: 100\r\n\r\n"),
5332 MockRead(SYNCHRONOUS
, OK
),
5335 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5336 data_writes1
, arraysize(data_writes1
));
5337 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5338 data_writes3
, arraysize(data_writes3
));
5339 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5340 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5342 TestCompletionCallback callback1
;
5343 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5344 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5345 rv
= callback1
.WaitForResult();
5347 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5349 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5350 ASSERT_TRUE(response
!= NULL
);
5351 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5353 TestCompletionCallback callback3
;
5354 rv
= trans
->RestartWithAuth(
5355 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5357 rv
= callback3
.WaitForResult();
5359 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5361 response
= trans
->GetResponseInfo();
5362 ASSERT_TRUE(response
!= NULL
);
5364 // There is no challenge info, since the identity worked.
5365 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5366 EXPECT_EQ(100, response
->headers
->GetContentLength());
5368 // Empty the current queue.
5369 base::MessageLoop::current()->RunUntilIdle();
5372 // Test that previously tried username/passwords for a realm get re-used.
5373 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5374 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5376 // Transaction 1: authenticate (foo, bar) on MyRealm1
5378 HttpRequestInfo request
;
5379 request
.method
= "GET";
5380 request
.url
= GURL("http://www.google.com/x/y/z");
5381 request
.load_flags
= 0;
5383 scoped_ptr
<HttpTransaction
> trans(
5384 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5386 MockWrite data_writes1
[] = {
5387 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5388 "Host: www.google.com\r\n"
5389 "Connection: keep-alive\r\n\r\n"),
5392 MockRead data_reads1
[] = {
5393 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5394 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5395 MockRead("Content-Length: 10000\r\n\r\n"),
5396 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5399 // Resend with authorization (username=foo, password=bar)
5400 MockWrite data_writes2
[] = {
5401 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5402 "Host: www.google.com\r\n"
5403 "Connection: keep-alive\r\n"
5404 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5407 // Sever accepts the authorization.
5408 MockRead data_reads2
[] = {
5409 MockRead("HTTP/1.0 200 OK\r\n"),
5410 MockRead("Content-Length: 100\r\n\r\n"),
5411 MockRead(SYNCHRONOUS
, OK
),
5414 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5415 data_writes1
, arraysize(data_writes1
));
5416 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5417 data_writes2
, arraysize(data_writes2
));
5418 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5419 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5421 TestCompletionCallback callback1
;
5423 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5426 rv
= callback1
.WaitForResult();
5429 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5430 ASSERT_TRUE(response
!= NULL
);
5431 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5433 TestCompletionCallback callback2
;
5435 rv
= trans
->RestartWithAuth(
5436 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5439 rv
= callback2
.WaitForResult();
5442 response
= trans
->GetResponseInfo();
5443 ASSERT_TRUE(response
!= NULL
);
5444 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5445 EXPECT_EQ(100, response
->headers
->GetContentLength());
5448 // ------------------------------------------------------------------------
5450 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5452 HttpRequestInfo request
;
5453 request
.method
= "GET";
5454 // Note that Transaction 1 was at /x/y/z, so this is in the same
5455 // protection space as MyRealm1.
5456 request
.url
= GURL("http://www.google.com/x/y/a/b");
5457 request
.load_flags
= 0;
5459 scoped_ptr
<HttpTransaction
> trans(
5460 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5462 MockWrite data_writes1
[] = {
5463 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5464 "Host: www.google.com\r\n"
5465 "Connection: keep-alive\r\n"
5466 // Send preemptive authorization for MyRealm1
5467 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5470 // The server didn't like the preemptive authorization, and
5471 // challenges us for a different realm (MyRealm2).
5472 MockRead data_reads1
[] = {
5473 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5474 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5475 MockRead("Content-Length: 10000\r\n\r\n"),
5476 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5479 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5480 MockWrite data_writes2
[] = {
5481 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5482 "Host: www.google.com\r\n"
5483 "Connection: keep-alive\r\n"
5484 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5487 // Sever accepts the authorization.
5488 MockRead data_reads2
[] = {
5489 MockRead("HTTP/1.0 200 OK\r\n"),
5490 MockRead("Content-Length: 100\r\n\r\n"),
5491 MockRead(SYNCHRONOUS
, OK
),
5494 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5495 data_writes1
, arraysize(data_writes1
));
5496 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5497 data_writes2
, arraysize(data_writes2
));
5498 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5499 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5501 TestCompletionCallback callback1
;
5503 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5504 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5506 rv
= callback1
.WaitForResult();
5509 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5510 ASSERT_TRUE(response
!= NULL
);
5511 ASSERT_TRUE(response
->auth_challenge
.get());
5512 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5513 EXPECT_EQ("www.google.com:80",
5514 response
->auth_challenge
->challenger
.ToString());
5515 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5516 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5518 TestCompletionCallback callback2
;
5520 rv
= trans
->RestartWithAuth(
5521 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5522 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5524 rv
= callback2
.WaitForResult();
5527 response
= trans
->GetResponseInfo();
5528 ASSERT_TRUE(response
!= NULL
);
5529 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5530 EXPECT_EQ(100, response
->headers
->GetContentLength());
5533 // ------------------------------------------------------------------------
5535 // Transaction 3: Resend a request in MyRealm's protection space --
5536 // succeed with preemptive authorization.
5538 HttpRequestInfo request
;
5539 request
.method
= "GET";
5540 request
.url
= GURL("http://www.google.com/x/y/z2");
5541 request
.load_flags
= 0;
5543 scoped_ptr
<HttpTransaction
> trans(
5544 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5546 MockWrite data_writes1
[] = {
5547 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5548 "Host: www.google.com\r\n"
5549 "Connection: keep-alive\r\n"
5550 // The authorization for MyRealm1 gets sent preemptively
5551 // (since the url is in the same protection space)
5552 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5555 // Sever accepts the preemptive authorization
5556 MockRead data_reads1
[] = {
5557 MockRead("HTTP/1.0 200 OK\r\n"),
5558 MockRead("Content-Length: 100\r\n\r\n"),
5559 MockRead(SYNCHRONOUS
, OK
),
5562 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5563 data_writes1
, arraysize(data_writes1
));
5564 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5566 TestCompletionCallback callback1
;
5568 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5569 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5571 rv
= callback1
.WaitForResult();
5574 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5575 ASSERT_TRUE(response
!= NULL
);
5577 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5578 EXPECT_EQ(100, response
->headers
->GetContentLength());
5581 // ------------------------------------------------------------------------
5583 // Transaction 4: request another URL in MyRealm (however the
5584 // url is not known to belong to the protection space, so no pre-auth).
5586 HttpRequestInfo request
;
5587 request
.method
= "GET";
5588 request
.url
= GURL("http://www.google.com/x/1");
5589 request
.load_flags
= 0;
5591 scoped_ptr
<HttpTransaction
> trans(
5592 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5594 MockWrite data_writes1
[] = {
5595 MockWrite("GET /x/1 HTTP/1.1\r\n"
5596 "Host: www.google.com\r\n"
5597 "Connection: keep-alive\r\n\r\n"),
5600 MockRead data_reads1
[] = {
5601 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5602 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5603 MockRead("Content-Length: 10000\r\n\r\n"),
5604 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5607 // Resend with authorization from MyRealm's cache.
5608 MockWrite data_writes2
[] = {
5609 MockWrite("GET /x/1 HTTP/1.1\r\n"
5610 "Host: www.google.com\r\n"
5611 "Connection: keep-alive\r\n"
5612 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5615 // Sever accepts the authorization.
5616 MockRead data_reads2
[] = {
5617 MockRead("HTTP/1.0 200 OK\r\n"),
5618 MockRead("Content-Length: 100\r\n\r\n"),
5619 MockRead(SYNCHRONOUS
, OK
),
5622 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5623 data_writes1
, arraysize(data_writes1
));
5624 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5625 data_writes2
, arraysize(data_writes2
));
5626 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5627 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5629 TestCompletionCallback callback1
;
5631 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5632 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5634 rv
= callback1
.WaitForResult();
5637 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5638 TestCompletionCallback callback2
;
5639 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5641 rv
= callback2
.WaitForResult();
5643 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5645 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5646 ASSERT_TRUE(response
!= NULL
);
5647 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5648 EXPECT_EQ(100, response
->headers
->GetContentLength());
5651 // ------------------------------------------------------------------------
5653 // Transaction 5: request a URL in MyRealm, but the server rejects the
5654 // cached identity. Should invalidate and re-prompt.
5656 HttpRequestInfo request
;
5657 request
.method
= "GET";
5658 request
.url
= GURL("http://www.google.com/p/q/t");
5659 request
.load_flags
= 0;
5661 scoped_ptr
<HttpTransaction
> trans(
5662 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5664 MockWrite data_writes1
[] = {
5665 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5666 "Host: www.google.com\r\n"
5667 "Connection: keep-alive\r\n\r\n"),
5670 MockRead data_reads1
[] = {
5671 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5672 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5673 MockRead("Content-Length: 10000\r\n\r\n"),
5674 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5677 // Resend with authorization from cache for MyRealm.
5678 MockWrite data_writes2
[] = {
5679 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5680 "Host: www.google.com\r\n"
5681 "Connection: keep-alive\r\n"
5682 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5685 // Sever rejects the authorization.
5686 MockRead data_reads2
[] = {
5687 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5688 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5689 MockRead("Content-Length: 10000\r\n\r\n"),
5690 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5693 // At this point we should prompt for new credentials for MyRealm.
5694 // Restart with username=foo3, password=foo4.
5695 MockWrite data_writes3
[] = {
5696 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5697 "Host: www.google.com\r\n"
5698 "Connection: keep-alive\r\n"
5699 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5702 // Sever accepts the authorization.
5703 MockRead data_reads3
[] = {
5704 MockRead("HTTP/1.0 200 OK\r\n"),
5705 MockRead("Content-Length: 100\r\n\r\n"),
5706 MockRead(SYNCHRONOUS
, OK
),
5709 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5710 data_writes1
, arraysize(data_writes1
));
5711 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5712 data_writes2
, arraysize(data_writes2
));
5713 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5714 data_writes3
, arraysize(data_writes3
));
5715 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5716 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5717 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5719 TestCompletionCallback callback1
;
5721 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5724 rv
= callback1
.WaitForResult();
5727 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5728 TestCompletionCallback callback2
;
5729 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5730 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5731 rv
= callback2
.WaitForResult();
5733 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5735 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5736 ASSERT_TRUE(response
!= NULL
);
5737 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5739 TestCompletionCallback callback3
;
5741 rv
= trans
->RestartWithAuth(
5742 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5743 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5745 rv
= callback3
.WaitForResult();
5748 response
= trans
->GetResponseInfo();
5749 ASSERT_TRUE(response
!= NULL
);
5750 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5751 EXPECT_EQ(100, response
->headers
->GetContentLength());
5755 // Tests that nonce count increments when multiple auth attempts
5756 // are started with the same nonce.
5757 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5758 HttpAuthHandlerDigest::Factory
* digest_factory
=
5759 new HttpAuthHandlerDigest::Factory();
5760 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5761 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5762 digest_factory
->set_nonce_generator(nonce_generator
);
5763 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5764 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5766 // Transaction 1: authenticate (foo, bar) on MyRealm1
5768 HttpRequestInfo request
;
5769 request
.method
= "GET";
5770 request
.url
= GURL("http://www.google.com/x/y/z");
5771 request
.load_flags
= 0;
5773 scoped_ptr
<HttpTransaction
> trans(
5774 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5776 MockWrite data_writes1
[] = {
5777 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5778 "Host: www.google.com\r\n"
5779 "Connection: keep-alive\r\n\r\n"),
5782 MockRead data_reads1
[] = {
5783 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5784 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5785 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5786 MockRead(SYNCHRONOUS
, OK
),
5789 // Resend with authorization (username=foo, password=bar)
5790 MockWrite data_writes2
[] = {
5791 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5792 "Host: www.google.com\r\n"
5793 "Connection: keep-alive\r\n"
5794 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5795 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5796 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5797 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5800 // Sever accepts the authorization.
5801 MockRead data_reads2
[] = {
5802 MockRead("HTTP/1.0 200 OK\r\n"),
5803 MockRead(SYNCHRONOUS
, OK
),
5806 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5807 data_writes1
, arraysize(data_writes1
));
5808 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5809 data_writes2
, arraysize(data_writes2
));
5810 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5811 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5813 TestCompletionCallback callback1
;
5815 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5816 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5818 rv
= callback1
.WaitForResult();
5821 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5822 ASSERT_TRUE(response
!= NULL
);
5823 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5825 TestCompletionCallback callback2
;
5827 rv
= trans
->RestartWithAuth(
5828 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5829 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5831 rv
= callback2
.WaitForResult();
5834 response
= trans
->GetResponseInfo();
5835 ASSERT_TRUE(response
!= NULL
);
5836 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5839 // ------------------------------------------------------------------------
5841 // Transaction 2: Request another resource in digestive's protection space.
5842 // This will preemptively add an Authorization header which should have an
5843 // "nc" value of 2 (as compared to 1 in the first use.
5845 HttpRequestInfo request
;
5846 request
.method
= "GET";
5847 // Note that Transaction 1 was at /x/y/z, so this is in the same
5848 // protection space as digest.
5849 request
.url
= GURL("http://www.google.com/x/y/a/b");
5850 request
.load_flags
= 0;
5852 scoped_ptr
<HttpTransaction
> trans(
5853 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5855 MockWrite data_writes1
[] = {
5856 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5857 "Host: www.google.com\r\n"
5858 "Connection: keep-alive\r\n"
5859 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5860 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5861 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5862 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5865 // Sever accepts the authorization.
5866 MockRead data_reads1
[] = {
5867 MockRead("HTTP/1.0 200 OK\r\n"),
5868 MockRead("Content-Length: 100\r\n\r\n"),
5869 MockRead(SYNCHRONOUS
, OK
),
5872 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5873 data_writes1
, arraysize(data_writes1
));
5874 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5876 TestCompletionCallback callback1
;
5878 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5881 rv
= callback1
.WaitForResult();
5884 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5885 ASSERT_TRUE(response
!= NULL
);
5886 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5890 // Test the ResetStateForRestart() private method.
5891 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5892 // Create a transaction (the dependencies aren't important).
5893 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5894 scoped_ptr
<HttpNetworkTransaction
> trans(
5895 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5897 // Setup some state (which we expect ResetStateForRestart() will clear).
5898 trans
->read_buf_
= new IOBuffer(15);
5899 trans
->read_buf_len_
= 15;
5900 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5902 // Setup state in response_
5903 HttpResponseInfo
* response
= &trans
->response_
;
5904 response
->auth_challenge
= new AuthChallengeInfo();
5905 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5906 response
->response_time
= base::Time::Now();
5907 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5909 { // Setup state for response_.vary_data
5910 HttpRequestInfo request
;
5911 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5912 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5913 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5914 request
.extra_headers
.SetHeader("Foo", "1");
5915 request
.extra_headers
.SetHeader("bar", "23");
5916 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5919 // Cause the above state to be reset.
5920 trans
->ResetStateForRestart();
5922 // Verify that the state that needed to be reset, has been reset.
5923 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5924 EXPECT_EQ(0, trans
->read_buf_len_
);
5925 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5926 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5927 EXPECT_TRUE(response
->headers
.get() == NULL
);
5928 EXPECT_FALSE(response
->was_cached
);
5929 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5930 EXPECT_FALSE(response
->vary_data
.is_valid());
5933 // Test HTTPS connections to a site with a bad certificate
5934 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5935 HttpRequestInfo request
;
5936 request
.method
= "GET";
5937 request
.url
= GURL("https://www.google.com/");
5938 request
.load_flags
= 0;
5940 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5941 scoped_ptr
<HttpTransaction
> trans(
5942 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5944 MockWrite data_writes
[] = {
5945 MockWrite("GET / HTTP/1.1\r\n"
5946 "Host: www.google.com\r\n"
5947 "Connection: keep-alive\r\n\r\n"),
5950 MockRead data_reads
[] = {
5951 MockRead("HTTP/1.0 200 OK\r\n"),
5952 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5953 MockRead("Content-Length: 100\r\n\r\n"),
5954 MockRead(SYNCHRONOUS
, OK
),
5957 StaticSocketDataProvider ssl_bad_certificate
;
5958 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5959 data_writes
, arraysize(data_writes
));
5960 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5961 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5963 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5964 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5965 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5966 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5968 TestCompletionCallback callback
;
5970 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5971 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5973 rv
= callback
.WaitForResult();
5974 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5976 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5977 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5979 rv
= callback
.WaitForResult();
5982 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5984 ASSERT_TRUE(response
!= NULL
);
5985 EXPECT_EQ(100, response
->headers
->GetContentLength());
5988 // Test HTTPS connections to a site with a bad certificate, going through a
5990 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5991 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5993 HttpRequestInfo request
;
5994 request
.method
= "GET";
5995 request
.url
= GURL("https://www.google.com/");
5996 request
.load_flags
= 0;
5998 MockWrite proxy_writes
[] = {
5999 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6000 "Host: www.google.com\r\n"
6001 "Proxy-Connection: keep-alive\r\n\r\n"),
6004 MockRead proxy_reads
[] = {
6005 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6006 MockRead(SYNCHRONOUS
, OK
)
6009 MockWrite data_writes
[] = {
6010 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6011 "Host: www.google.com\r\n"
6012 "Proxy-Connection: keep-alive\r\n\r\n"),
6013 MockWrite("GET / HTTP/1.1\r\n"
6014 "Host: www.google.com\r\n"
6015 "Connection: keep-alive\r\n\r\n"),
6018 MockRead data_reads
[] = {
6019 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6020 MockRead("HTTP/1.0 200 OK\r\n"),
6021 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6022 MockRead("Content-Length: 100\r\n\r\n"),
6023 MockRead(SYNCHRONOUS
, OK
),
6026 StaticSocketDataProvider
ssl_bad_certificate(
6027 proxy_reads
, arraysize(proxy_reads
),
6028 proxy_writes
, arraysize(proxy_writes
));
6029 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6030 data_writes
, arraysize(data_writes
));
6031 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6032 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6034 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6035 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6036 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6037 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6039 TestCompletionCallback callback
;
6041 for (int i
= 0; i
< 2; i
++) {
6042 session_deps_
.socket_factory
->ResetNextMockIndexes();
6044 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6045 scoped_ptr
<HttpTransaction
> trans(
6046 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6048 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6051 rv
= callback
.WaitForResult();
6052 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6054 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6055 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6057 rv
= callback
.WaitForResult();
6060 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6062 ASSERT_TRUE(response
!= NULL
);
6063 EXPECT_EQ(100, response
->headers
->GetContentLength());
6068 // Test HTTPS connections to a site, going through an HTTPS proxy
6069 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6070 session_deps_
.proxy_service
.reset(
6071 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6072 CapturingNetLog net_log
;
6073 session_deps_
.net_log
= &net_log
;
6075 HttpRequestInfo request
;
6076 request
.method
= "GET";
6077 request
.url
= GURL("https://www.google.com/");
6078 request
.load_flags
= 0;
6080 MockWrite data_writes
[] = {
6081 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6082 "Host: www.google.com\r\n"
6083 "Proxy-Connection: keep-alive\r\n\r\n"),
6084 MockWrite("GET / HTTP/1.1\r\n"
6085 "Host: www.google.com\r\n"
6086 "Connection: keep-alive\r\n\r\n"),
6089 MockRead data_reads
[] = {
6090 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6091 MockRead("HTTP/1.1 200 OK\r\n"),
6092 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6093 MockRead("Content-Length: 100\r\n\r\n"),
6094 MockRead(SYNCHRONOUS
, OK
),
6097 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6098 data_writes
, arraysize(data_writes
));
6099 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6100 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6102 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6103 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6104 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6106 TestCompletionCallback callback
;
6108 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6109 scoped_ptr
<HttpTransaction
> trans(
6110 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6112 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6113 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6115 rv
= callback
.WaitForResult();
6117 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6119 ASSERT_TRUE(response
!= NULL
);
6121 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6122 EXPECT_EQ(200, response
->headers
->response_code());
6123 EXPECT_EQ(100, response
->headers
->GetContentLength());
6124 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6126 LoadTimingInfo load_timing_info
;
6127 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6128 TestLoadTimingNotReusedWithPac(load_timing_info
,
6129 CONNECT_TIMING_HAS_SSL_TIMES
);
6132 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6133 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6134 session_deps_
.proxy_service
.reset(
6135 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6136 CapturingNetLog net_log
;
6137 session_deps_
.net_log
= &net_log
;
6139 HttpRequestInfo request
;
6140 request
.method
= "GET";
6141 request
.url
= GURL("https://www.google.com/");
6142 request
.load_flags
= 0;
6144 MockWrite data_writes
[] = {
6145 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6146 "Host: www.google.com\r\n"
6147 "Proxy-Connection: keep-alive\r\n\r\n"),
6150 MockRead data_reads
[] = {
6151 MockRead("HTTP/1.1 302 Redirect\r\n"),
6152 MockRead("Location: http://login.example.com/\r\n"),
6153 MockRead("Content-Length: 0\r\n\r\n"),
6154 MockRead(SYNCHRONOUS
, OK
),
6157 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6158 data_writes
, arraysize(data_writes
));
6159 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6161 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6162 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6164 TestCompletionCallback callback
;
6166 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6167 scoped_ptr
<HttpTransaction
> trans(
6168 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6170 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6171 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6173 rv
= callback
.WaitForResult();
6175 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6177 ASSERT_TRUE(response
!= NULL
);
6179 EXPECT_EQ(302, response
->headers
->response_code());
6181 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6182 EXPECT_EQ("http://login.example.com/", url
);
6184 // In the case of redirects from proxies, HttpNetworkTransaction returns
6185 // timing for the proxy connection instead of the connection to the host,
6186 // and no send / receive times.
6187 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6188 LoadTimingInfo load_timing_info
;
6189 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6191 EXPECT_FALSE(load_timing_info
.socket_reused
);
6192 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6194 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6195 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6196 load_timing_info
.proxy_resolve_end
);
6197 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6198 load_timing_info
.connect_timing
.connect_start
);
6199 ExpectConnectTimingHasTimes(
6200 load_timing_info
.connect_timing
,
6201 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6203 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6204 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6205 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6208 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6209 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6210 session_deps_
.proxy_service
.reset(
6211 ProxyService::CreateFixed("https://proxy:70"));
6213 HttpRequestInfo request
;
6214 request
.method
= "GET";
6215 request
.url
= GURL("https://www.google.com/");
6216 request
.load_flags
= 0;
6218 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6220 scoped_ptr
<SpdyFrame
> goaway(
6221 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6222 MockWrite data_writes
[] = {
6223 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6224 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6227 static const char* const kExtraHeaders
[] = {
6229 "http://login.example.com/",
6231 scoped_ptr
<SpdyFrame
> resp(
6232 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6233 arraysize(kExtraHeaders
)/2, 1));
6234 MockRead data_reads
[] = {
6235 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6236 MockRead(ASYNC
, 0, 2), // EOF
6239 DelayedSocketData
data(
6240 1, // wait for one write to finish before reading.
6241 data_reads
, arraysize(data_reads
),
6242 data_writes
, arraysize(data_writes
));
6243 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6244 proxy_ssl
.SetNextProto(GetParam());
6246 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6247 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6249 TestCompletionCallback callback
;
6251 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6252 scoped_ptr
<HttpTransaction
> trans(
6253 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6255 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6258 rv
= callback
.WaitForResult();
6260 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6262 ASSERT_TRUE(response
!= NULL
);
6264 EXPECT_EQ(302, response
->headers
->response_code());
6266 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6267 EXPECT_EQ("http://login.example.com/", url
);
6270 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6271 TEST_P(HttpNetworkTransactionTest
,
6272 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6273 session_deps_
.proxy_service
.reset(
6274 ProxyService::CreateFixed("https://proxy:70"));
6276 HttpRequestInfo request
;
6277 request
.method
= "GET";
6278 request
.url
= GURL("https://www.google.com/");
6279 request
.load_flags
= 0;
6281 MockWrite data_writes
[] = {
6282 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6283 "Host: www.google.com\r\n"
6284 "Proxy-Connection: keep-alive\r\n\r\n"),
6287 MockRead data_reads
[] = {
6288 MockRead("HTTP/1.1 404 Not Found\r\n"),
6289 MockRead("Content-Length: 23\r\n\r\n"),
6290 MockRead("The host does not exist"),
6291 MockRead(SYNCHRONOUS
, OK
),
6294 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6295 data_writes
, arraysize(data_writes
));
6296 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6298 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6299 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6301 TestCompletionCallback callback
;
6303 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6304 scoped_ptr
<HttpTransaction
> trans(
6305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6307 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6308 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6310 rv
= callback
.WaitForResult();
6311 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6313 // TODO(ttuttle): Anything else to check here?
6316 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6317 TEST_P(HttpNetworkTransactionTest
,
6318 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6319 session_deps_
.proxy_service
.reset(
6320 ProxyService::CreateFixed("https://proxy:70"));
6322 HttpRequestInfo request
;
6323 request
.method
= "GET";
6324 request
.url
= GURL("https://www.google.com/");
6325 request
.load_flags
= 0;
6327 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6329 scoped_ptr
<SpdyFrame
> rst(
6330 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6331 MockWrite data_writes
[] = {
6332 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6333 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6336 static const char* const kExtraHeaders
[] = {
6338 "http://login.example.com/",
6340 scoped_ptr
<SpdyFrame
> resp(
6341 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6342 arraysize(kExtraHeaders
)/2, 1));
6343 scoped_ptr
<SpdyFrame
> body(
6344 spdy_util_
.ConstructSpdyBodyFrame(
6345 1, "The host does not exist", 23, true));
6346 MockRead data_reads
[] = {
6347 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6348 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6349 MockRead(ASYNC
, 0, 4), // EOF
6352 DelayedSocketData
data(
6353 1, // wait for one write to finish before reading.
6354 data_reads
, arraysize(data_reads
),
6355 data_writes
, arraysize(data_writes
));
6356 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6357 proxy_ssl
.SetNextProto(GetParam());
6359 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6360 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6362 TestCompletionCallback callback
;
6364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6365 scoped_ptr
<HttpTransaction
> trans(
6366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6368 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6371 rv
= callback
.WaitForResult();
6372 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6374 // TODO(ttuttle): Anything else to check here?
6377 // Test the request-challenge-retry sequence for basic auth, through
6378 // a SPDY proxy over a single SPDY session.
6379 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6380 HttpRequestInfo request
;
6381 request
.method
= "GET";
6382 request
.url
= GURL("https://www.google.com/");
6383 // when the no authentication data flag is set.
6384 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6386 // Configure against https proxy server "myproxy:70".
6387 session_deps_
.proxy_service
.reset(
6388 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6389 CapturingBoundNetLog log
;
6390 session_deps_
.net_log
= log
.bound().net_log();
6391 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6393 // Since we have proxy, should try to establish tunnel.
6394 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6396 scoped_ptr
<SpdyFrame
> rst(
6397 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6399 // After calling trans->RestartWithAuth(), this is the request we should
6400 // be issuing -- the final header line contains the credentials.
6401 const char* const kAuthCredentials
[] = {
6402 "proxy-authorization", "Basic Zm9vOmJhcg==",
6404 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6405 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
));
6406 // fetch https://www.google.com/ via HTTP
6407 const char get
[] = "GET / HTTP/1.1\r\n"
6408 "Host: www.google.com\r\n"
6409 "Connection: keep-alive\r\n\r\n";
6410 scoped_ptr
<SpdyFrame
> wrapped_get(
6411 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6413 MockWrite spdy_writes
[] = {
6414 CreateMockWrite(*req
, 1, ASYNC
),
6415 CreateMockWrite(*rst
, 4, ASYNC
),
6416 CreateMockWrite(*connect2
, 5),
6417 CreateMockWrite(*wrapped_get
, 8),
6420 // The proxy responds to the connect with a 407, using a persistent
6422 const char* const kAuthStatus
= "407";
6423 const char* const kAuthChallenge
[] = {
6424 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6426 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6427 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6429 scoped_ptr
<SpdyFrame
> conn_resp(
6430 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6431 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6432 "Content-Length: 5\r\n\r\n";
6434 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6435 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6436 scoped_ptr
<SpdyFrame
> wrapped_body(
6437 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6438 MockRead spdy_reads
[] = {
6439 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6440 CreateMockRead(*conn_resp
, 6, ASYNC
),
6441 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6442 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6443 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6446 OrderedSocketData
spdy_data(
6447 spdy_reads
, arraysize(spdy_reads
),
6448 spdy_writes
, arraysize(spdy_writes
));
6449 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6450 // Negotiate SPDY to the proxy
6451 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6452 proxy
.SetNextProto(GetParam());
6453 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6454 // Vanilla SSL to the server
6455 SSLSocketDataProvider
server(ASYNC
, OK
);
6456 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6458 TestCompletionCallback callback1
;
6460 scoped_ptr
<HttpTransaction
> trans(
6461 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6463 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6464 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6466 rv
= callback1
.WaitForResult();
6468 net::CapturingNetLog::CapturedEntryList entries
;
6469 log
.GetEntries(&entries
);
6470 size_t pos
= ExpectLogContainsSomewhere(
6471 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6472 NetLog::PHASE_NONE
);
6473 ExpectLogContainsSomewhere(
6475 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6476 NetLog::PHASE_NONE
);
6478 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6479 ASSERT_TRUE(response
!= NULL
);
6480 ASSERT_FALSE(response
->headers
.get() == NULL
);
6481 EXPECT_EQ(407, response
->headers
->response_code());
6482 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6483 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6484 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6486 TestCompletionCallback callback2
;
6488 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6489 callback2
.callback());
6490 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6492 rv
= callback2
.WaitForResult();
6495 response
= trans
->GetResponseInfo();
6496 ASSERT_TRUE(response
!= NULL
);
6498 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6499 EXPECT_EQ(200, response
->headers
->response_code());
6500 EXPECT_EQ(5, response
->headers
->GetContentLength());
6501 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6503 // The password prompt info should not be set.
6504 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6506 LoadTimingInfo load_timing_info
;
6507 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6508 TestLoadTimingNotReusedWithPac(load_timing_info
,
6509 CONNECT_TIMING_HAS_SSL_TIMES
);
6512 session
->CloseAllConnections();
6515 // Test that an explicitly trusted SPDY proxy can push a resource from an
6516 // origin that is different from that of its associated resource.
6517 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6518 HttpRequestInfo request
;
6519 HttpRequestInfo push_request
;
6521 request
.method
= "GET";
6522 request
.url
= GURL("http://www.google.com/");
6523 push_request
.method
= "GET";
6524 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6526 // Configure against https proxy server "myproxy:70".
6527 session_deps_
.proxy_service
.reset(
6528 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6529 CapturingBoundNetLog log
;
6530 session_deps_
.net_log
= log
.bound().net_log();
6532 // Enable cross-origin push.
6533 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6535 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6537 scoped_ptr
<SpdyFrame
> stream1_syn(
6538 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6540 MockWrite spdy_writes
[] = {
6541 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6544 scoped_ptr
<SpdyFrame
>
6545 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6547 scoped_ptr
<SpdyFrame
>
6548 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6550 scoped_ptr
<SpdyFrame
>
6551 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6555 "http://www.another-origin.com/foo.dat"));
6556 const char kPushedData
[] = "pushed";
6557 scoped_ptr
<SpdyFrame
> stream2_body(
6558 spdy_util_
.ConstructSpdyBodyFrame(
6559 2, kPushedData
, strlen(kPushedData
), true));
6561 MockRead spdy_reads
[] = {
6562 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6563 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6564 CreateMockRead(*stream1_body
, 4, ASYNC
),
6565 CreateMockRead(*stream2_body
, 5, ASYNC
),
6566 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6569 OrderedSocketData
spdy_data(
6570 spdy_reads
, arraysize(spdy_reads
),
6571 spdy_writes
, arraysize(spdy_writes
));
6572 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6573 // Negotiate SPDY to the proxy
6574 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6575 proxy
.SetNextProto(GetParam());
6576 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6578 scoped_ptr
<HttpTransaction
> trans(
6579 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6580 TestCompletionCallback callback
;
6581 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6584 rv
= callback
.WaitForResult();
6586 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6588 scoped_ptr
<HttpTransaction
> push_trans(
6589 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6590 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6591 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6593 rv
= callback
.WaitForResult();
6595 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6597 ASSERT_TRUE(response
!= NULL
);
6598 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6600 EXPECT_EQ(200, response
->headers
->response_code());
6601 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6603 std::string response_data
;
6604 rv
= ReadTransaction(trans
.get(), &response_data
);
6606 EXPECT_EQ("hello!", response_data
);
6608 LoadTimingInfo load_timing_info
;
6609 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6610 TestLoadTimingNotReusedWithPac(load_timing_info
,
6611 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6613 // Verify the pushed stream.
6614 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6615 EXPECT_EQ(200, push_response
->headers
->response_code());
6617 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6619 EXPECT_EQ("pushed", response_data
);
6621 LoadTimingInfo push_load_timing_info
;
6622 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6623 TestLoadTimingReusedWithPac(push_load_timing_info
);
6624 // The transactions should share a socket ID, despite being for different
6626 EXPECT_EQ(load_timing_info
.socket_log_id
,
6627 push_load_timing_info
.socket_log_id
);
6631 session
->CloseAllConnections();
6634 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6635 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6636 HttpRequestInfo request
;
6638 request
.method
= "GET";
6639 request
.url
= GURL("http://www.google.com/");
6641 // Configure against https proxy server "myproxy:70".
6642 session_deps_
.proxy_service
.reset(
6643 ProxyService::CreateFixed("https://myproxy:70"));
6644 CapturingBoundNetLog log
;
6645 session_deps_
.net_log
= log
.bound().net_log();
6647 // Enable cross-origin push.
6648 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6652 scoped_ptr
<SpdyFrame
> stream1_syn(
6653 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6655 scoped_ptr
<SpdyFrame
> push_rst(
6656 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6658 MockWrite spdy_writes
[] = {
6659 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6660 CreateMockWrite(*push_rst
, 4),
6663 scoped_ptr
<SpdyFrame
>
6664 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6666 scoped_ptr
<SpdyFrame
>
6667 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6669 scoped_ptr
<SpdyFrame
>
6670 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6674 "https://www.another-origin.com/foo.dat"));
6676 MockRead spdy_reads
[] = {
6677 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6678 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6679 CreateMockRead(*stream1_body
, 5, ASYNC
),
6680 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6683 OrderedSocketData
spdy_data(
6684 spdy_reads
, arraysize(spdy_reads
),
6685 spdy_writes
, arraysize(spdy_writes
));
6686 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6687 // Negotiate SPDY to the proxy
6688 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6689 proxy
.SetNextProto(GetParam());
6690 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6692 scoped_ptr
<HttpTransaction
> trans(
6693 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6694 TestCompletionCallback callback
;
6695 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6696 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6698 rv
= callback
.WaitForResult();
6700 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6702 ASSERT_TRUE(response
!= NULL
);
6703 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6705 EXPECT_EQ(200, response
->headers
->response_code());
6706 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6708 std::string response_data
;
6709 rv
= ReadTransaction(trans
.get(), &response_data
);
6711 EXPECT_EQ("hello!", response_data
);
6714 session
->CloseAllConnections();
6717 // Test HTTPS connections to a site with a bad certificate, going through an
6719 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6720 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6721 "https://proxy:70"));
6723 HttpRequestInfo request
;
6724 request
.method
= "GET";
6725 request
.url
= GURL("https://www.google.com/");
6726 request
.load_flags
= 0;
6728 // Attempt to fetch the URL from a server with a bad cert
6729 MockWrite bad_cert_writes
[] = {
6730 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6731 "Host: www.google.com\r\n"
6732 "Proxy-Connection: keep-alive\r\n\r\n"),
6735 MockRead bad_cert_reads
[] = {
6736 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6737 MockRead(SYNCHRONOUS
, OK
)
6740 // Attempt to fetch the URL with a good cert
6741 MockWrite good_data_writes
[] = {
6742 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6743 "Host: www.google.com\r\n"
6744 "Proxy-Connection: keep-alive\r\n\r\n"),
6745 MockWrite("GET / HTTP/1.1\r\n"
6746 "Host: www.google.com\r\n"
6747 "Connection: keep-alive\r\n\r\n"),
6750 MockRead good_cert_reads
[] = {
6751 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6752 MockRead("HTTP/1.0 200 OK\r\n"),
6753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6754 MockRead("Content-Length: 100\r\n\r\n"),
6755 MockRead(SYNCHRONOUS
, OK
),
6758 StaticSocketDataProvider
ssl_bad_certificate(
6759 bad_cert_reads
, arraysize(bad_cert_reads
),
6760 bad_cert_writes
, arraysize(bad_cert_writes
));
6761 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6762 good_data_writes
, arraysize(good_data_writes
));
6763 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6764 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6766 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6767 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6768 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6769 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6771 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6772 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6773 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6774 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6776 TestCompletionCallback callback
;
6778 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6779 scoped_ptr
<HttpTransaction
> trans(
6780 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6782 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6783 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6785 rv
= callback
.WaitForResult();
6786 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6788 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6789 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6791 rv
= callback
.WaitForResult();
6794 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6796 ASSERT_TRUE(response
!= NULL
);
6797 EXPECT_EQ(100, response
->headers
->GetContentLength());
6800 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6801 HttpRequestInfo request
;
6802 request
.method
= "GET";
6803 request
.url
= GURL("http://www.google.com/");
6804 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6805 "Chromium Ultra Awesome X Edition");
6807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6808 scoped_ptr
<HttpTransaction
> trans(
6809 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6811 MockWrite data_writes
[] = {
6812 MockWrite("GET / HTTP/1.1\r\n"
6813 "Host: www.google.com\r\n"
6814 "Connection: keep-alive\r\n"
6815 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6818 // Lastly, the server responds with the actual content.
6819 MockRead data_reads
[] = {
6820 MockRead("HTTP/1.0 200 OK\r\n"),
6821 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6822 MockRead("Content-Length: 100\r\n\r\n"),
6823 MockRead(SYNCHRONOUS
, OK
),
6826 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6827 data_writes
, arraysize(data_writes
));
6828 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6830 TestCompletionCallback callback
;
6832 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6833 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6835 rv
= callback
.WaitForResult();
6839 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6840 HttpRequestInfo request
;
6841 request
.method
= "GET";
6842 request
.url
= GURL("https://www.google.com/");
6843 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6844 "Chromium Ultra Awesome X Edition");
6846 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6847 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6848 scoped_ptr
<HttpTransaction
> trans(
6849 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6851 MockWrite data_writes
[] = {
6852 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6853 "Host: www.google.com\r\n"
6854 "Proxy-Connection: keep-alive\r\n"
6855 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6857 MockRead data_reads
[] = {
6858 // Return an error, so the transaction stops here (this test isn't
6859 // interested in the rest).
6860 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6861 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6862 MockRead("Proxy-Connection: close\r\n\r\n"),
6865 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6866 data_writes
, arraysize(data_writes
));
6867 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6869 TestCompletionCallback callback
;
6871 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6872 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6874 rv
= callback
.WaitForResult();
6878 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6879 HttpRequestInfo request
;
6880 request
.method
= "GET";
6881 request
.url
= GURL("http://www.google.com/");
6882 request
.load_flags
= 0;
6883 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6884 "http://the.previous.site.com/");
6886 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6887 scoped_ptr
<HttpTransaction
> trans(
6888 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6890 MockWrite data_writes
[] = {
6891 MockWrite("GET / HTTP/1.1\r\n"
6892 "Host: www.google.com\r\n"
6893 "Connection: keep-alive\r\n"
6894 "Referer: http://the.previous.site.com/\r\n\r\n"),
6897 // Lastly, the server responds with the actual content.
6898 MockRead data_reads
[] = {
6899 MockRead("HTTP/1.0 200 OK\r\n"),
6900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6901 MockRead("Content-Length: 100\r\n\r\n"),
6902 MockRead(SYNCHRONOUS
, OK
),
6905 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6906 data_writes
, arraysize(data_writes
));
6907 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6909 TestCompletionCallback callback
;
6911 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6914 rv
= callback
.WaitForResult();
6918 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6919 HttpRequestInfo request
;
6920 request
.method
= "POST";
6921 request
.url
= GURL("http://www.google.com/");
6923 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6924 scoped_ptr
<HttpTransaction
> trans(
6925 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6927 MockWrite data_writes
[] = {
6928 MockWrite("POST / HTTP/1.1\r\n"
6929 "Host: www.google.com\r\n"
6930 "Connection: keep-alive\r\n"
6931 "Content-Length: 0\r\n\r\n"),
6934 // Lastly, the server responds with the actual content.
6935 MockRead data_reads
[] = {
6936 MockRead("HTTP/1.0 200 OK\r\n"),
6937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6938 MockRead("Content-Length: 100\r\n\r\n"),
6939 MockRead(SYNCHRONOUS
, OK
),
6942 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6943 data_writes
, arraysize(data_writes
));
6944 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6946 TestCompletionCallback callback
;
6948 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6949 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6951 rv
= callback
.WaitForResult();
6955 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6956 HttpRequestInfo request
;
6957 request
.method
= "PUT";
6958 request
.url
= GURL("http://www.google.com/");
6960 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6961 scoped_ptr
<HttpTransaction
> trans(
6962 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6964 MockWrite data_writes
[] = {
6965 MockWrite("PUT / HTTP/1.1\r\n"
6966 "Host: www.google.com\r\n"
6967 "Connection: keep-alive\r\n"
6968 "Content-Length: 0\r\n\r\n"),
6971 // Lastly, the server responds with the actual content.
6972 MockRead data_reads
[] = {
6973 MockRead("HTTP/1.0 200 OK\r\n"),
6974 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6975 MockRead("Content-Length: 100\r\n\r\n"),
6976 MockRead(SYNCHRONOUS
, OK
),
6979 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6980 data_writes
, arraysize(data_writes
));
6981 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6983 TestCompletionCallback callback
;
6985 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6986 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6988 rv
= callback
.WaitForResult();
6992 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6993 HttpRequestInfo request
;
6994 request
.method
= "HEAD";
6995 request
.url
= GURL("http://www.google.com/");
6997 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6998 scoped_ptr
<HttpTransaction
> trans(
6999 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7001 MockWrite data_writes
[] = {
7002 MockWrite("HEAD / HTTP/1.1\r\n"
7003 "Host: www.google.com\r\n"
7004 "Connection: keep-alive\r\n"
7005 "Content-Length: 0\r\n\r\n"),
7008 // Lastly, the server responds with the actual content.
7009 MockRead data_reads
[] = {
7010 MockRead("HTTP/1.0 200 OK\r\n"),
7011 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7012 MockRead("Content-Length: 100\r\n\r\n"),
7013 MockRead(SYNCHRONOUS
, OK
),
7016 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7017 data_writes
, arraysize(data_writes
));
7018 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7020 TestCompletionCallback callback
;
7022 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7023 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7025 rv
= callback
.WaitForResult();
7029 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7030 HttpRequestInfo request
;
7031 request
.method
= "GET";
7032 request
.url
= GURL("http://www.google.com/");
7033 request
.load_flags
= LOAD_BYPASS_CACHE
;
7035 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7036 scoped_ptr
<HttpTransaction
> trans(
7037 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7039 MockWrite data_writes
[] = {
7040 MockWrite("GET / HTTP/1.1\r\n"
7041 "Host: www.google.com\r\n"
7042 "Connection: keep-alive\r\n"
7043 "Pragma: no-cache\r\n"
7044 "Cache-Control: no-cache\r\n\r\n"),
7047 // Lastly, the server responds with the actual content.
7048 MockRead data_reads
[] = {
7049 MockRead("HTTP/1.0 200 OK\r\n"),
7050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7051 MockRead("Content-Length: 100\r\n\r\n"),
7052 MockRead(SYNCHRONOUS
, OK
),
7055 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7056 data_writes
, arraysize(data_writes
));
7057 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7059 TestCompletionCallback callback
;
7061 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7062 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7064 rv
= callback
.WaitForResult();
7068 TEST_P(HttpNetworkTransactionTest
,
7069 BuildRequest_CacheControlValidateCache
) {
7070 HttpRequestInfo request
;
7071 request
.method
= "GET";
7072 request
.url
= GURL("http://www.google.com/");
7073 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7075 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7076 scoped_ptr
<HttpTransaction
> trans(
7077 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7079 MockWrite data_writes
[] = {
7080 MockWrite("GET / HTTP/1.1\r\n"
7081 "Host: www.google.com\r\n"
7082 "Connection: keep-alive\r\n"
7083 "Cache-Control: max-age=0\r\n\r\n"),
7086 // Lastly, the server responds with the actual content.
7087 MockRead data_reads
[] = {
7088 MockRead("HTTP/1.0 200 OK\r\n"),
7089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7090 MockRead("Content-Length: 100\r\n\r\n"),
7091 MockRead(SYNCHRONOUS
, OK
),
7094 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7095 data_writes
, arraysize(data_writes
));
7096 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7098 TestCompletionCallback callback
;
7100 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7101 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7103 rv
= callback
.WaitForResult();
7107 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7108 HttpRequestInfo request
;
7109 request
.method
= "GET";
7110 request
.url
= GURL("http://www.google.com/");
7111 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7114 scoped_ptr
<HttpTransaction
> trans(
7115 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7117 MockWrite data_writes
[] = {
7118 MockWrite("GET / HTTP/1.1\r\n"
7119 "Host: www.google.com\r\n"
7120 "Connection: keep-alive\r\n"
7121 "FooHeader: Bar\r\n\r\n"),
7124 // Lastly, the server responds with the actual content.
7125 MockRead data_reads
[] = {
7126 MockRead("HTTP/1.0 200 OK\r\n"),
7127 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7128 MockRead("Content-Length: 100\r\n\r\n"),
7129 MockRead(SYNCHRONOUS
, OK
),
7132 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7133 data_writes
, arraysize(data_writes
));
7134 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7136 TestCompletionCallback callback
;
7138 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7139 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7141 rv
= callback
.WaitForResult();
7145 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7146 HttpRequestInfo request
;
7147 request
.method
= "GET";
7148 request
.url
= GURL("http://www.google.com/");
7149 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7150 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7151 request
.extra_headers
.SetHeader("FoO", "bar");
7153 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7154 scoped_ptr
<HttpTransaction
> trans(
7155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7157 MockWrite data_writes
[] = {
7158 MockWrite("GET / HTTP/1.1\r\n"
7159 "Host: www.google.com\r\n"
7160 "Connection: keep-alive\r\n"
7161 "referer: www.foo.com\r\n"
7163 "FoO: bar\r\n\r\n"),
7166 // Lastly, the server responds with the actual content.
7167 MockRead data_reads
[] = {
7168 MockRead("HTTP/1.0 200 OK\r\n"),
7169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7170 MockRead("Content-Length: 100\r\n\r\n"),
7171 MockRead(SYNCHRONOUS
, OK
),
7174 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7175 data_writes
, arraysize(data_writes
));
7176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7178 TestCompletionCallback callback
;
7180 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7183 rv
= callback
.WaitForResult();
7187 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7188 HttpRequestInfo request
;
7189 request
.method
= "GET";
7190 request
.url
= GURL("http://www.google.com/");
7191 request
.load_flags
= 0;
7193 session_deps_
.proxy_service
.reset(
7194 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7195 CapturingNetLog net_log
;
7196 session_deps_
.net_log
= &net_log
;
7198 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7199 scoped_ptr
<HttpTransaction
> trans(
7200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7202 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7203 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7205 MockWrite data_writes
[] = {
7206 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7207 MockWrite("GET / HTTP/1.1\r\n"
7208 "Host: www.google.com\r\n"
7209 "Connection: keep-alive\r\n\r\n")
7212 MockRead data_reads
[] = {
7213 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7214 MockRead("HTTP/1.0 200 OK\r\n"),
7215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7216 MockRead("Payload"),
7217 MockRead(SYNCHRONOUS
, OK
)
7220 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7221 data_writes
, arraysize(data_writes
));
7222 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7224 TestCompletionCallback callback
;
7226 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7229 rv
= callback
.WaitForResult();
7232 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7233 ASSERT_TRUE(response
!= NULL
);
7235 LoadTimingInfo load_timing_info
;
7236 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7237 TestLoadTimingNotReusedWithPac(load_timing_info
,
7238 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7240 std::string response_text
;
7241 rv
= ReadTransaction(trans
.get(), &response_text
);
7243 EXPECT_EQ("Payload", response_text
);
7246 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7247 HttpRequestInfo request
;
7248 request
.method
= "GET";
7249 request
.url
= GURL("https://www.google.com/");
7250 request
.load_flags
= 0;
7252 session_deps_
.proxy_service
.reset(
7253 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7254 CapturingNetLog net_log
;
7255 session_deps_
.net_log
= &net_log
;
7257 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7258 scoped_ptr
<HttpTransaction
> trans(
7259 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7261 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7262 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7264 MockWrite data_writes
[] = {
7265 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7266 arraysize(write_buffer
)),
7267 MockWrite("GET / HTTP/1.1\r\n"
7268 "Host: www.google.com\r\n"
7269 "Connection: keep-alive\r\n\r\n")
7272 MockRead data_reads
[] = {
7273 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7274 arraysize(read_buffer
)),
7275 MockRead("HTTP/1.0 200 OK\r\n"),
7276 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7277 MockRead("Payload"),
7278 MockRead(SYNCHRONOUS
, OK
)
7281 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7282 data_writes
, arraysize(data_writes
));
7283 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7285 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7286 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7288 TestCompletionCallback callback
;
7290 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7291 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7293 rv
= callback
.WaitForResult();
7296 LoadTimingInfo load_timing_info
;
7297 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7298 TestLoadTimingNotReusedWithPac(load_timing_info
,
7299 CONNECT_TIMING_HAS_SSL_TIMES
);
7301 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7302 ASSERT_TRUE(response
!= NULL
);
7304 std::string response_text
;
7305 rv
= ReadTransaction(trans
.get(), &response_text
);
7307 EXPECT_EQ("Payload", response_text
);
7310 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7311 HttpRequestInfo request
;
7312 request
.method
= "GET";
7313 request
.url
= GURL("http://www.google.com/");
7314 request
.load_flags
= 0;
7316 session_deps_
.proxy_service
.reset(
7317 ProxyService::CreateFixed("socks4://myproxy:1080"));
7318 CapturingNetLog net_log
;
7319 session_deps_
.net_log
= &net_log
;
7321 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7322 scoped_ptr
<HttpTransaction
> trans(
7323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7325 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7326 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7328 MockWrite data_writes
[] = {
7329 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7330 MockWrite("GET / HTTP/1.1\r\n"
7331 "Host: www.google.com\r\n"
7332 "Connection: keep-alive\r\n\r\n")
7335 MockRead data_reads
[] = {
7336 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7337 MockRead("HTTP/1.0 200 OK\r\n"),
7338 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7339 MockRead("Payload"),
7340 MockRead(SYNCHRONOUS
, OK
)
7343 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7344 data_writes
, arraysize(data_writes
));
7345 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7347 TestCompletionCallback callback
;
7349 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7350 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7352 rv
= callback
.WaitForResult();
7355 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7356 ASSERT_TRUE(response
!= NULL
);
7358 LoadTimingInfo load_timing_info
;
7359 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7360 TestLoadTimingNotReused(load_timing_info
,
7361 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7363 std::string response_text
;
7364 rv
= ReadTransaction(trans
.get(), &response_text
);
7366 EXPECT_EQ("Payload", response_text
);
7369 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7370 HttpRequestInfo request
;
7371 request
.method
= "GET";
7372 request
.url
= GURL("http://www.google.com/");
7373 request
.load_flags
= 0;
7375 session_deps_
.proxy_service
.reset(
7376 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7377 CapturingNetLog net_log
;
7378 session_deps_
.net_log
= &net_log
;
7380 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7381 scoped_ptr
<HttpTransaction
> trans(
7382 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7384 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7385 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7386 const char kSOCKS5OkRequest
[] = {
7388 0x01, // Command (CONNECT)
7390 0x03, // Address type (DOMAINNAME).
7391 0x0E, // Length of domain (14)
7393 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7394 0x00, 0x50, // 16-bit port (80)
7396 const char kSOCKS5OkResponse
[] =
7397 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7399 MockWrite data_writes
[] = {
7400 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7401 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7402 MockWrite("GET / HTTP/1.1\r\n"
7403 "Host: www.google.com\r\n"
7404 "Connection: keep-alive\r\n\r\n")
7407 MockRead data_reads
[] = {
7408 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7409 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7410 MockRead("HTTP/1.0 200 OK\r\n"),
7411 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7412 MockRead("Payload"),
7413 MockRead(SYNCHRONOUS
, OK
)
7416 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7417 data_writes
, arraysize(data_writes
));
7418 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7420 TestCompletionCallback callback
;
7422 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7425 rv
= callback
.WaitForResult();
7428 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7429 ASSERT_TRUE(response
!= NULL
);
7431 LoadTimingInfo load_timing_info
;
7432 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7433 TestLoadTimingNotReusedWithPac(load_timing_info
,
7434 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7436 std::string response_text
;
7437 rv
= ReadTransaction(trans
.get(), &response_text
);
7439 EXPECT_EQ("Payload", response_text
);
7442 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7443 HttpRequestInfo request
;
7444 request
.method
= "GET";
7445 request
.url
= GURL("https://www.google.com/");
7446 request
.load_flags
= 0;
7448 session_deps_
.proxy_service
.reset(
7449 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7450 CapturingNetLog net_log
;
7451 session_deps_
.net_log
= &net_log
;
7453 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7454 scoped_ptr
<HttpTransaction
> trans(
7455 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7457 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7458 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7459 const unsigned char kSOCKS5OkRequest
[] = {
7461 0x01, // Command (CONNECT)
7463 0x03, // Address type (DOMAINNAME).
7464 0x0E, // Length of domain (14)
7466 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7467 0x01, 0xBB, // 16-bit port (443)
7470 const char kSOCKS5OkResponse
[] =
7471 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7473 MockWrite data_writes
[] = {
7474 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7475 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7476 arraysize(kSOCKS5OkRequest
)),
7477 MockWrite("GET / HTTP/1.1\r\n"
7478 "Host: www.google.com\r\n"
7479 "Connection: keep-alive\r\n\r\n")
7482 MockRead data_reads
[] = {
7483 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7484 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7485 MockRead("HTTP/1.0 200 OK\r\n"),
7486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7487 MockRead("Payload"),
7488 MockRead(SYNCHRONOUS
, OK
)
7491 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7492 data_writes
, arraysize(data_writes
));
7493 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7495 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7496 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7498 TestCompletionCallback callback
;
7500 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7501 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7503 rv
= callback
.WaitForResult();
7506 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7507 ASSERT_TRUE(response
!= NULL
);
7509 LoadTimingInfo load_timing_info
;
7510 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7511 TestLoadTimingNotReusedWithPac(load_timing_info
,
7512 CONNECT_TIMING_HAS_SSL_TIMES
);
7514 std::string response_text
;
7515 rv
= ReadTransaction(trans
.get(), &response_text
);
7517 EXPECT_EQ("Payload", response_text
);
7522 // Tests that for connection endpoints the group names are correctly set.
7524 struct GroupNameTest
{
7525 std::string proxy_server
;
7527 std::string expected_group_name
;
7531 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7532 NextProto next_proto
,
7533 SpdySessionDependencies
* session_deps_
) {
7534 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7536 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7537 session
->http_server_properties();
7538 http_server_properties
->SetAlternateProtocol(
7539 HostPortPair("host.with.alternate", 80), 443,
7540 AlternateProtocolFromNextProto(next_proto
), 1);
7545 int GroupNameTransactionHelper(
7546 const std::string
& url
,
7547 const scoped_refptr
<HttpNetworkSession
>& session
) {
7548 HttpRequestInfo request
;
7549 request
.method
= "GET";
7550 request
.url
= GURL(url
);
7551 request
.load_flags
= 0;
7553 scoped_ptr
<HttpTransaction
> trans(
7554 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7556 TestCompletionCallback callback
;
7558 // We do not complete this request, the dtor will clean the transaction up.
7559 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7564 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7565 const GroupNameTest tests
[] = {
7568 "http://www.google.com/direct",
7569 "www.google.com:80",
7574 "http://[2001:1418:13:1::25]/direct",
7575 "[2001:1418:13:1::25]:80",
7582 "https://www.google.com/direct_ssl",
7583 "ssl/www.google.com:443",
7588 "https://[2001:1418:13:1::25]/direct",
7589 "ssl/[2001:1418:13:1::25]:443",
7594 "http://host.with.alternate/direct",
7595 "ssl/host.with.alternate:443",
7600 session_deps_
.use_alternate_protocols
= true;
7602 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7603 session_deps_
.proxy_service
.reset(
7604 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7605 scoped_refptr
<HttpNetworkSession
> session(
7606 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7608 HttpNetworkSessionPeer
peer(session
);
7609 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7610 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7611 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7612 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7613 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7614 new MockClientSocketPoolManager
);
7615 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7616 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7617 peer
.SetClientSocketPoolManager(
7618 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7620 EXPECT_EQ(ERR_IO_PENDING
,
7621 GroupNameTransactionHelper(tests
[i
].url
, session
));
7623 EXPECT_EQ(tests
[i
].expected_group_name
,
7624 ssl_conn_pool
->last_group_name_received());
7626 EXPECT_EQ(tests
[i
].expected_group_name
,
7627 transport_conn_pool
->last_group_name_received());
7632 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7633 const GroupNameTest tests
[] = {
7636 "http://www.google.com/http_proxy_normal",
7637 "www.google.com:80",
7644 "https://www.google.com/http_connect_ssl",
7645 "ssl/www.google.com:443",
7651 "http://host.with.alternate/direct",
7652 "ssl/host.with.alternate:443",
7658 "ftp://ftp.google.com/http_proxy_normal",
7659 "ftp/ftp.google.com:21",
7664 session_deps_
.use_alternate_protocols
= true;
7666 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7667 session_deps_
.proxy_service
.reset(
7668 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7669 scoped_refptr
<HttpNetworkSession
> session(
7670 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7672 HttpNetworkSessionPeer
peer(session
);
7674 HostPortPair
proxy_host("http_proxy", 80);
7675 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7676 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7677 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7678 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7680 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7681 new MockClientSocketPoolManager
);
7682 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7683 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7684 peer
.SetClientSocketPoolManager(
7685 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7687 EXPECT_EQ(ERR_IO_PENDING
,
7688 GroupNameTransactionHelper(tests
[i
].url
, session
));
7690 EXPECT_EQ(tests
[i
].expected_group_name
,
7691 ssl_conn_pool
->last_group_name_received());
7693 EXPECT_EQ(tests
[i
].expected_group_name
,
7694 http_proxy_pool
->last_group_name_received());
7698 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7699 const GroupNameTest tests
[] = {
7701 "socks4://socks_proxy:1080",
7702 "http://www.google.com/socks4_direct",
7703 "socks4/www.google.com:80",
7707 "socks5://socks_proxy:1080",
7708 "http://www.google.com/socks5_direct",
7709 "socks5/www.google.com:80",
7715 "socks4://socks_proxy:1080",
7716 "https://www.google.com/socks4_ssl",
7717 "socks4/ssl/www.google.com:443",
7721 "socks5://socks_proxy:1080",
7722 "https://www.google.com/socks5_ssl",
7723 "socks5/ssl/www.google.com:443",
7728 "socks4://socks_proxy:1080",
7729 "http://host.with.alternate/direct",
7730 "socks4/ssl/host.with.alternate:443",
7735 session_deps_
.use_alternate_protocols
= true;
7737 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7738 session_deps_
.proxy_service
.reset(
7739 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7740 scoped_refptr
<HttpNetworkSession
> session(
7741 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7743 HttpNetworkSessionPeer
peer(session
);
7745 HostPortPair
proxy_host("socks_proxy", 1080);
7746 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7747 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7748 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7749 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7751 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7752 new MockClientSocketPoolManager
);
7753 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7754 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7755 peer
.SetClientSocketPoolManager(
7756 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7758 scoped_ptr
<HttpTransaction
> trans(
7759 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7761 EXPECT_EQ(ERR_IO_PENDING
,
7762 GroupNameTransactionHelper(tests
[i
].url
, session
));
7764 EXPECT_EQ(tests
[i
].expected_group_name
,
7765 ssl_conn_pool
->last_group_name_received());
7767 EXPECT_EQ(tests
[i
].expected_group_name
,
7768 socks_conn_pool
->last_group_name_received());
7772 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
7773 HttpRequestInfo request
;
7774 request
.method
= "GET";
7775 request
.url
= GURL("http://www.google.com/");
7777 session_deps_
.proxy_service
.reset(
7778 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7780 // This simulates failure resolving all hostnames; that means we will fail
7781 // connecting to both proxies (myproxy:70 and foobar:80).
7782 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
7784 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7785 scoped_ptr
<HttpTransaction
> trans(
7786 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7788 TestCompletionCallback callback
;
7790 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7791 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7793 rv
= callback
.WaitForResult();
7794 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
7797 // Base test to make sure that when the load flags for a request specify to
7798 // bypass the cache, the DNS cache is not used.
7799 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7801 // Issue a request, asking to bypass the cache(s).
7802 HttpRequestInfo request
;
7803 request
.method
= "GET";
7804 request
.load_flags
= load_flags
;
7805 request
.url
= GURL("http://www.google.com/");
7807 // Select a host resolver that does caching.
7808 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
7810 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7811 scoped_ptr
<HttpTransaction
> trans(
7812 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7814 // Warm up the host cache so it has an entry for "www.google.com".
7815 AddressList addrlist
;
7816 TestCompletionCallback callback
;
7817 int rv
= session_deps_
.host_resolver
->Resolve(
7818 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7821 callback
.callback(),
7824 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7825 rv
= callback
.WaitForResult();
7828 // Verify that it was added to host cache, by doing a subsequent async lookup
7829 // and confirming it completes synchronously.
7830 rv
= session_deps_
.host_resolver
->Resolve(
7831 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7834 callback
.callback(),
7839 // Inject a failure the next time that "www.google.com" is resolved. This way
7840 // we can tell if the next lookup hit the cache, or the "network".
7841 // (cache --> success, "network" --> failure).
7842 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
7844 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7845 // first read -- this won't be reached as the host resolution will fail first.
7846 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
7847 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7848 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7851 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7852 ASSERT_EQ(ERR_IO_PENDING
, rv
);
7853 rv
= callback
.WaitForResult();
7855 // If we bypassed the cache, we would have gotten a failure while resolving
7856 // "www.google.com".
7857 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
7860 // There are multiple load flags that should trigger the host cache bypass.
7861 // Test each in isolation:
7862 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
7863 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
7866 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
7867 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
7870 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
7871 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
7874 // Make sure we can handle an error when writing the request.
7875 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
7876 HttpRequestInfo request
;
7877 request
.method
= "GET";
7878 request
.url
= GURL("http://www.foo.com/");
7879 request
.load_flags
= 0;
7881 MockWrite write_failure
[] = {
7882 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
7884 StaticSocketDataProvider
data(NULL
, 0,
7885 write_failure
, arraysize(write_failure
));
7886 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7887 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7889 TestCompletionCallback callback
;
7891 scoped_ptr
<HttpTransaction
> trans(
7892 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7894 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7895 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7897 rv
= callback
.WaitForResult();
7898 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
7901 // Check that a connection closed after the start of the headers finishes ok.
7902 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
7903 HttpRequestInfo request
;
7904 request
.method
= "GET";
7905 request
.url
= GURL("http://www.foo.com/");
7906 request
.load_flags
= 0;
7908 MockRead data_reads
[] = {
7909 MockRead("HTTP/1."),
7910 MockRead(SYNCHRONOUS
, OK
),
7913 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7914 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7915 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7917 TestCompletionCallback callback
;
7919 scoped_ptr
<HttpTransaction
> trans(
7920 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7922 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7923 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7925 rv
= callback
.WaitForResult();
7928 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7929 ASSERT_TRUE(response
!= NULL
);
7931 EXPECT_TRUE(response
->headers
.get() != NULL
);
7932 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7934 std::string response_data
;
7935 rv
= ReadTransaction(trans
.get(), &response_data
);
7937 EXPECT_EQ("", response_data
);
7940 // Make sure that a dropped connection while draining the body for auth
7941 // restart does the right thing.
7942 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
7943 HttpRequestInfo request
;
7944 request
.method
= "GET";
7945 request
.url
= GURL("http://www.google.com/");
7946 request
.load_flags
= 0;
7948 MockWrite data_writes1
[] = {
7949 MockWrite("GET / HTTP/1.1\r\n"
7950 "Host: www.google.com\r\n"
7951 "Connection: keep-alive\r\n\r\n"),
7954 MockRead data_reads1
[] = {
7955 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7956 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7957 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7958 MockRead("Content-Length: 14\r\n\r\n"),
7960 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
7963 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7964 data_writes1
, arraysize(data_writes1
));
7965 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7967 // After calling trans->RestartWithAuth(), this is the request we should
7968 // be issuing -- the final header line contains the credentials.
7969 MockWrite data_writes2
[] = {
7970 MockWrite("GET / HTTP/1.1\r\n"
7971 "Host: www.google.com\r\n"
7972 "Connection: keep-alive\r\n"
7973 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7976 // Lastly, the server responds with the actual content.
7977 MockRead data_reads2
[] = {
7978 MockRead("HTTP/1.1 200 OK\r\n"),
7979 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7980 MockRead("Content-Length: 100\r\n\r\n"),
7981 MockRead(SYNCHRONOUS
, OK
),
7984 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7985 data_writes2
, arraysize(data_writes2
));
7986 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7987 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7989 TestCompletionCallback callback1
;
7991 scoped_ptr
<HttpTransaction
> trans(
7992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7994 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7995 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7997 rv
= callback1
.WaitForResult();
8000 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8001 ASSERT_TRUE(response
!= NULL
);
8002 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8004 TestCompletionCallback callback2
;
8006 rv
= trans
->RestartWithAuth(
8007 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8008 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8010 rv
= callback2
.WaitForResult();
8013 response
= trans
->GetResponseInfo();
8014 ASSERT_TRUE(response
!= NULL
);
8015 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8016 EXPECT_EQ(100, response
->headers
->GetContentLength());
8019 // Test HTTPS connections going through a proxy that sends extra data.
8020 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8021 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8023 HttpRequestInfo request
;
8024 request
.method
= "GET";
8025 request
.url
= GURL("https://www.google.com/");
8026 request
.load_flags
= 0;
8028 MockRead proxy_reads
[] = {
8029 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8030 MockRead(SYNCHRONOUS
, OK
)
8033 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8034 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8036 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8037 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8039 TestCompletionCallback callback
;
8041 session_deps_
.socket_factory
->ResetNextMockIndexes();
8043 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8044 scoped_ptr
<HttpTransaction
> trans(
8045 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8047 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8048 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8050 rv
= callback
.WaitForResult();
8051 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8054 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8055 HttpRequestInfo request
;
8056 request
.method
= "GET";
8057 request
.url
= GURL("http://www.google.com/");
8058 request
.load_flags
= 0;
8060 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8061 scoped_ptr
<HttpTransaction
> trans(
8062 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8064 MockRead data_reads
[] = {
8065 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8066 MockRead(SYNCHRONOUS
, OK
),
8069 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8070 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8072 TestCompletionCallback callback
;
8074 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8075 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8077 EXPECT_EQ(OK
, callback
.WaitForResult());
8079 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8080 ASSERT_TRUE(response
!= NULL
);
8082 EXPECT_TRUE(response
->headers
.get() != NULL
);
8083 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8085 std::string response_data
;
8086 rv
= ReadTransaction(trans
.get(), &response_data
);
8087 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8090 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8091 base::FilePath temp_file_path
;
8092 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8093 const uint64 kFakeSize
= 100000; // file is actually blank
8094 UploadFileElementReader::ScopedOverridingContentLengthForTests
8095 overriding_content_length(kFakeSize
);
8097 ScopedVector
<UploadElementReader
> element_readers
;
8098 element_readers
.push_back(
8099 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8104 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8106 HttpRequestInfo request
;
8107 request
.method
= "POST";
8108 request
.url
= GURL("http://www.google.com/upload");
8109 request
.upload_data_stream
= &upload_data_stream
;
8110 request
.load_flags
= 0;
8112 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8113 scoped_ptr
<HttpTransaction
> trans(
8114 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8116 MockRead data_reads
[] = {
8117 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8118 MockRead("hello world"),
8119 MockRead(SYNCHRONOUS
, OK
),
8121 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8122 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8124 TestCompletionCallback callback
;
8126 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8127 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8129 rv
= callback
.WaitForResult();
8132 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8133 ASSERT_TRUE(response
!= NULL
);
8135 EXPECT_TRUE(response
->headers
.get() != NULL
);
8136 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8138 std::string response_data
;
8139 rv
= ReadTransaction(trans
.get(), &response_data
);
8141 EXPECT_EQ("hello world", response_data
);
8143 base::DeleteFile(temp_file_path
, false);
8146 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8147 base::FilePath temp_file
;
8148 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8149 std::string
temp_file_content("Unreadable file.");
8150 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8151 temp_file_content
.length()));
8152 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8154 ScopedVector
<UploadElementReader
> element_readers
;
8155 element_readers
.push_back(
8156 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8161 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8163 HttpRequestInfo request
;
8164 request
.method
= "POST";
8165 request
.url
= GURL("http://www.google.com/upload");
8166 request
.upload_data_stream
= &upload_data_stream
;
8167 request
.load_flags
= 0;
8169 // If we try to upload an unreadable file, the transaction should fail.
8170 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8171 scoped_ptr
<HttpTransaction
> trans(
8172 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8174 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8175 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8177 TestCompletionCallback callback
;
8179 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8182 rv
= callback
.WaitForResult();
8183 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8185 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8186 EXPECT_FALSE(response
);
8188 base::DeleteFile(temp_file
, false);
8191 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8192 class FakeUploadElementReader
: public UploadElementReader
{
8194 FakeUploadElementReader() {}
8195 virtual ~FakeUploadElementReader() {}
8197 const CompletionCallback
& callback() const { return callback_
; }
8199 // UploadElementReader overrides:
8200 virtual int Init(const CompletionCallback
& callback
) OVERRIDE
{
8201 callback_
= callback
;
8202 return ERR_IO_PENDING
;
8204 virtual uint64
GetContentLength() const OVERRIDE
{ return 0; }
8205 virtual uint64
BytesRemaining() const OVERRIDE
{ return 0; }
8206 virtual int Read(IOBuffer
* buf
,
8208 const CompletionCallback
& callback
) OVERRIDE
{
8213 CompletionCallback callback_
;
8216 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8217 ScopedVector
<UploadElementReader
> element_readers
;
8218 element_readers
.push_back(fake_reader
);
8219 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8221 HttpRequestInfo request
;
8222 request
.method
= "POST";
8223 request
.url
= GURL("http://www.google.com/upload");
8224 request
.upload_data_stream
= &upload_data_stream
;
8225 request
.load_flags
= 0;
8227 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8228 scoped_ptr
<HttpTransaction
> trans(
8229 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8231 StaticSocketDataProvider data
;
8232 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8234 TestCompletionCallback callback
;
8235 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8236 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8237 base::MessageLoop::current()->RunUntilIdle();
8239 // Transaction is pending on request body initialization.
8240 ASSERT_FALSE(fake_reader
->callback().is_null());
8242 // Return Init()'s result after the transaction gets destroyed.
8244 fake_reader
->callback().Run(OK
); // Should not crash.
8247 // Tests that changes to Auth realms are treated like auth rejections.
8248 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8250 HttpRequestInfo request
;
8251 request
.method
= "GET";
8252 request
.url
= GURL("http://www.google.com/");
8253 request
.load_flags
= 0;
8255 // First transaction will request a resource and receive a Basic challenge
8256 // with realm="first_realm".
8257 MockWrite data_writes1
[] = {
8258 MockWrite("GET / HTTP/1.1\r\n"
8259 "Host: www.google.com\r\n"
8260 "Connection: keep-alive\r\n"
8263 MockRead data_reads1
[] = {
8264 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8265 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8269 // After calling trans->RestartWithAuth(), provide an Authentication header
8270 // for first_realm. The server will reject and provide a challenge with
8272 MockWrite data_writes2
[] = {
8273 MockWrite("GET / HTTP/1.1\r\n"
8274 "Host: www.google.com\r\n"
8275 "Connection: keep-alive\r\n"
8276 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8279 MockRead data_reads2
[] = {
8280 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8281 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8285 // This again fails, and goes back to first_realm. Make sure that the
8286 // entry is removed from cache.
8287 MockWrite data_writes3
[] = {
8288 MockWrite("GET / HTTP/1.1\r\n"
8289 "Host: www.google.com\r\n"
8290 "Connection: keep-alive\r\n"
8291 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8294 MockRead data_reads3
[] = {
8295 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8296 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8300 // Try one last time (with the correct password) and get the resource.
8301 MockWrite data_writes4
[] = {
8302 MockWrite("GET / HTTP/1.1\r\n"
8303 "Host: www.google.com\r\n"
8304 "Connection: keep-alive\r\n"
8305 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8308 MockRead data_reads4
[] = {
8309 MockRead("HTTP/1.1 200 OK\r\n"
8310 "Content-Type: text/html; charset=iso-8859-1\r\n"
8311 "Content-Length: 5\r\n"
8316 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8317 data_writes1
, arraysize(data_writes1
));
8318 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8319 data_writes2
, arraysize(data_writes2
));
8320 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8321 data_writes3
, arraysize(data_writes3
));
8322 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8323 data_writes4
, arraysize(data_writes4
));
8324 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8325 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8326 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8327 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8329 TestCompletionCallback callback1
;
8331 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8332 scoped_ptr
<HttpTransaction
> trans(
8333 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8335 // Issue the first request with Authorize headers. There should be a
8336 // password prompt for first_realm waiting to be filled in after the
8337 // transaction completes.
8338 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8340 rv
= callback1
.WaitForResult();
8342 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8343 ASSERT_TRUE(response
!= NULL
);
8344 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8345 ASSERT_FALSE(challenge
== NULL
);
8346 EXPECT_FALSE(challenge
->is_proxy
);
8347 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8348 EXPECT_EQ("first_realm", challenge
->realm
);
8349 EXPECT_EQ("basic", challenge
->scheme
);
8351 // Issue the second request with an incorrect password. There should be a
8352 // password prompt for second_realm waiting to be filled in after the
8353 // transaction completes.
8354 TestCompletionCallback callback2
;
8355 rv
= trans
->RestartWithAuth(
8356 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8357 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8358 rv
= callback2
.WaitForResult();
8360 response
= trans
->GetResponseInfo();
8361 ASSERT_TRUE(response
!= NULL
);
8362 challenge
= response
->auth_challenge
.get();
8363 ASSERT_FALSE(challenge
== NULL
);
8364 EXPECT_FALSE(challenge
->is_proxy
);
8365 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8366 EXPECT_EQ("second_realm", challenge
->realm
);
8367 EXPECT_EQ("basic", challenge
->scheme
);
8369 // Issue the third request with another incorrect password. There should be
8370 // a password prompt for first_realm waiting to be filled in. If the password
8371 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8372 // first_realm was not correctly removed.
8373 TestCompletionCallback callback3
;
8374 rv
= trans
->RestartWithAuth(
8375 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8376 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8377 rv
= callback3
.WaitForResult();
8379 response
= trans
->GetResponseInfo();
8380 ASSERT_TRUE(response
!= NULL
);
8381 challenge
= response
->auth_challenge
.get();
8382 ASSERT_FALSE(challenge
== NULL
);
8383 EXPECT_FALSE(challenge
->is_proxy
);
8384 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8385 EXPECT_EQ("first_realm", challenge
->realm
);
8386 EXPECT_EQ("basic", challenge
->scheme
);
8388 // Issue the fourth request with the correct password and username.
8389 TestCompletionCallback callback4
;
8390 rv
= trans
->RestartWithAuth(
8391 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8393 rv
= callback4
.WaitForResult();
8395 response
= trans
->GetResponseInfo();
8396 ASSERT_TRUE(response
!= NULL
);
8397 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8400 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8401 session_deps_
.next_protos
= SpdyNextProtos();
8402 session_deps_
.use_alternate_protocols
= true;
8404 std::string alternate_protocol_http_header
=
8405 GetAlternateProtocolHttpHeader();
8407 MockRead data_reads
[] = {
8408 MockRead("HTTP/1.1 200 OK\r\n"),
8409 MockRead(alternate_protocol_http_header
.c_str()),
8410 MockRead("hello world"),
8411 MockRead(SYNCHRONOUS
, OK
),
8414 HttpRequestInfo request
;
8415 request
.method
= "GET";
8416 request
.url
= GURL("http://www.google.com/");
8417 request
.load_flags
= 0;
8419 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8421 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8423 TestCompletionCallback callback
;
8425 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8426 scoped_ptr
<HttpTransaction
> trans(
8427 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8429 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8430 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8432 HostPortPair
http_host_port_pair("www.google.com", 80);
8433 HttpServerProperties
& http_server_properties
=
8434 *session
->http_server_properties();
8436 http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8438 EXPECT_EQ(OK
, callback
.WaitForResult());
8440 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8441 ASSERT_TRUE(response
!= NULL
);
8442 ASSERT_TRUE(response
->headers
.get() != NULL
);
8443 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8444 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8445 EXPECT_FALSE(response
->was_npn_negotiated
);
8447 std::string response_data
;
8448 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8449 EXPECT_EQ("hello world", response_data
);
8451 ASSERT_TRUE(http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8452 const AlternateProtocolInfo alternate
=
8453 http_server_properties
.GetAlternateProtocol(http_host_port_pair
);
8454 AlternateProtocolInfo
expected_alternate(
8455 443, AlternateProtocolFromNextProto(GetParam()), 1);
8456 EXPECT_TRUE(expected_alternate
.Equals(alternate
));
8459 TEST_P(HttpNetworkTransactionTest
,
8460 MarkBrokenAlternateProtocolAndFallback
) {
8461 session_deps_
.use_alternate_protocols
= true;
8463 HttpRequestInfo request
;
8464 request
.method
= "GET";
8465 request
.url
= GURL("http://www.google.com/");
8466 request
.load_flags
= 0;
8468 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8469 StaticSocketDataProvider first_data
;
8470 first_data
.set_connect_data(mock_connect
);
8471 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8473 MockRead data_reads
[] = {
8474 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8475 MockRead("hello world"),
8476 MockRead(ASYNC
, OK
),
8478 StaticSocketDataProvider
second_data(
8479 data_reads
, arraysize(data_reads
), NULL
, 0);
8480 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8482 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8484 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8485 session
->http_server_properties();
8486 // Port must be < 1024, or the header will be ignored (since initial port was
8487 // port 80 (another restricted port).
8488 http_server_properties
->SetAlternateProtocol(
8489 HostPortPair::FromURL(request
.url
),
8490 666 /* port is ignored by MockConnect anyway */,
8491 AlternateProtocolFromNextProto(GetParam()), 1);
8493 scoped_ptr
<HttpTransaction
> trans(
8494 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8495 TestCompletionCallback callback
;
8497 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8498 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8499 EXPECT_EQ(OK
, callback
.WaitForResult());
8501 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8502 ASSERT_TRUE(response
!= NULL
);
8503 ASSERT_TRUE(response
->headers
.get() != NULL
);
8504 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8506 std::string response_data
;
8507 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8508 EXPECT_EQ("hello world", response_data
);
8510 ASSERT_TRUE(http_server_properties
->HasAlternateProtocol(
8511 HostPortPair::FromURL(request
.url
)));
8512 const AlternateProtocolInfo alternate
=
8513 http_server_properties
->GetAlternateProtocol(
8514 HostPortPair::FromURL(request
.url
));
8515 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN
, alternate
.protocol
);
8518 TEST_P(HttpNetworkTransactionTest
,
8519 AlternateProtocolPortRestrictedBlocked
) {
8520 // Ensure that we're not allowed to redirect traffic via an alternate
8521 // protocol to an unrestricted (port >= 1024) when the original traffic was
8522 // on a restricted port (port < 1024). Ensure that we can redirect in all
8524 session_deps_
.use_alternate_protocols
= true;
8526 HttpRequestInfo restricted_port_request
;
8527 restricted_port_request
.method
= "GET";
8528 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8529 restricted_port_request
.load_flags
= 0;
8531 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8532 StaticSocketDataProvider first_data
;
8533 first_data
.set_connect_data(mock_connect
);
8534 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8536 MockRead data_reads
[] = {
8537 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8538 MockRead("hello world"),
8539 MockRead(ASYNC
, OK
),
8541 StaticSocketDataProvider
second_data(
8542 data_reads
, arraysize(data_reads
), NULL
, 0);
8543 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8545 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8547 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8548 session
->http_server_properties();
8549 const int kUnrestrictedAlternatePort
= 1024;
8550 http_server_properties
->SetAlternateProtocol(
8551 HostPortPair::FromURL(restricted_port_request
.url
),
8552 kUnrestrictedAlternatePort
,
8553 AlternateProtocolFromNextProto(GetParam()), 1);
8555 scoped_ptr
<HttpTransaction
> trans(
8556 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8557 TestCompletionCallback callback
;
8559 int rv
= trans
->Start(
8560 &restricted_port_request
,
8561 callback
.callback(), BoundNetLog());
8562 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8563 // Invalid change to unrestricted port should fail.
8564 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8567 TEST_P(HttpNetworkTransactionTest
,
8568 AlternateProtocolPortRestrictedPermitted
) {
8569 // Ensure that we're allowed to redirect traffic via an alternate
8570 // protocol to an unrestricted (port >= 1024) when the original traffic was
8571 // on a restricted port (port < 1024) if we set
8572 // enable_user_alternate_protocol_ports.
8574 session_deps_
.use_alternate_protocols
= true;
8575 session_deps_
.enable_user_alternate_protocol_ports
= true;
8577 HttpRequestInfo restricted_port_request
;
8578 restricted_port_request
.method
= "GET";
8579 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8580 restricted_port_request
.load_flags
= 0;
8582 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8583 StaticSocketDataProvider first_data
;
8584 first_data
.set_connect_data(mock_connect
);
8585 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8587 MockRead data_reads
[] = {
8588 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8589 MockRead("hello world"),
8590 MockRead(ASYNC
, OK
),
8592 StaticSocketDataProvider
second_data(
8593 data_reads
, arraysize(data_reads
), NULL
, 0);
8594 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8596 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8598 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8599 session
->http_server_properties();
8600 const int kUnrestrictedAlternatePort
= 1024;
8601 http_server_properties
->SetAlternateProtocol(
8602 HostPortPair::FromURL(restricted_port_request
.url
),
8603 kUnrestrictedAlternatePort
,
8604 AlternateProtocolFromNextProto(GetParam()), 1);
8606 scoped_ptr
<HttpTransaction
> trans(
8607 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8608 TestCompletionCallback callback
;
8610 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8611 &restricted_port_request
,
8612 callback
.callback(), BoundNetLog()));
8613 // Change to unrestricted port should succeed.
8614 EXPECT_EQ(OK
, callback
.WaitForResult());
8617 TEST_P(HttpNetworkTransactionTest
,
8618 AlternateProtocolPortRestrictedAllowed
) {
8619 // Ensure that we're not allowed to redirect traffic via an alternate
8620 // protocol to an unrestricted (port >= 1024) when the original traffic was
8621 // on a restricted port (port < 1024). Ensure that we can redirect in all
8623 session_deps_
.use_alternate_protocols
= true;
8625 HttpRequestInfo restricted_port_request
;
8626 restricted_port_request
.method
= "GET";
8627 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8628 restricted_port_request
.load_flags
= 0;
8630 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8631 StaticSocketDataProvider first_data
;
8632 first_data
.set_connect_data(mock_connect
);
8633 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8635 MockRead data_reads
[] = {
8636 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8637 MockRead("hello world"),
8638 MockRead(ASYNC
, OK
),
8640 StaticSocketDataProvider
second_data(
8641 data_reads
, arraysize(data_reads
), NULL
, 0);
8642 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8644 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8646 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8647 session
->http_server_properties();
8648 const int kRestrictedAlternatePort
= 80;
8649 http_server_properties
->SetAlternateProtocol(
8650 HostPortPair::FromURL(restricted_port_request
.url
),
8651 kRestrictedAlternatePort
,
8652 AlternateProtocolFromNextProto(GetParam()), 1);
8654 scoped_ptr
<HttpTransaction
> trans(
8655 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8656 TestCompletionCallback callback
;
8658 int rv
= trans
->Start(
8659 &restricted_port_request
,
8660 callback
.callback(), BoundNetLog());
8661 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8662 // Valid change to restricted port should pass.
8663 EXPECT_EQ(OK
, callback
.WaitForResult());
8666 TEST_P(HttpNetworkTransactionTest
,
8667 AlternateProtocolPortUnrestrictedAllowed1
) {
8668 // Ensure that we're not allowed to redirect traffic via an alternate
8669 // protocol to an unrestricted (port >= 1024) when the original traffic was
8670 // on a restricted port (port < 1024). Ensure that we can redirect in all
8672 session_deps_
.use_alternate_protocols
= true;
8674 HttpRequestInfo unrestricted_port_request
;
8675 unrestricted_port_request
.method
= "GET";
8676 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8677 unrestricted_port_request
.load_flags
= 0;
8679 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8680 StaticSocketDataProvider first_data
;
8681 first_data
.set_connect_data(mock_connect
);
8682 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8684 MockRead data_reads
[] = {
8685 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8686 MockRead("hello world"),
8687 MockRead(ASYNC
, OK
),
8689 StaticSocketDataProvider
second_data(
8690 data_reads
, arraysize(data_reads
), NULL
, 0);
8691 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8693 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8695 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8696 session
->http_server_properties();
8697 const int kRestrictedAlternatePort
= 80;
8698 http_server_properties
->SetAlternateProtocol(
8699 HostPortPair::FromURL(unrestricted_port_request
.url
),
8700 kRestrictedAlternatePort
,
8701 AlternateProtocolFromNextProto(GetParam()), 1);
8703 scoped_ptr
<HttpTransaction
> trans(
8704 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8705 TestCompletionCallback callback
;
8707 int rv
= trans
->Start(
8708 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8709 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8710 // Valid change to restricted port should pass.
8711 EXPECT_EQ(OK
, callback
.WaitForResult());
8714 TEST_P(HttpNetworkTransactionTest
,
8715 AlternateProtocolPortUnrestrictedAllowed2
) {
8716 // Ensure that we're not allowed to redirect traffic via an alternate
8717 // protocol to an unrestricted (port >= 1024) when the original traffic was
8718 // on a restricted port (port < 1024). Ensure that we can redirect in all
8720 session_deps_
.use_alternate_protocols
= true;
8722 HttpRequestInfo unrestricted_port_request
;
8723 unrestricted_port_request
.method
= "GET";
8724 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8725 unrestricted_port_request
.load_flags
= 0;
8727 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8728 StaticSocketDataProvider first_data
;
8729 first_data
.set_connect_data(mock_connect
);
8730 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8732 MockRead data_reads
[] = {
8733 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8734 MockRead("hello world"),
8735 MockRead(ASYNC
, OK
),
8737 StaticSocketDataProvider
second_data(
8738 data_reads
, arraysize(data_reads
), NULL
, 0);
8739 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8741 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8743 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8744 session
->http_server_properties();
8745 const int kUnrestrictedAlternatePort
= 1024;
8746 http_server_properties
->SetAlternateProtocol(
8747 HostPortPair::FromURL(unrestricted_port_request
.url
),
8748 kUnrestrictedAlternatePort
,
8749 AlternateProtocolFromNextProto(GetParam()), 1);
8751 scoped_ptr
<HttpTransaction
> trans(
8752 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8753 TestCompletionCallback callback
;
8755 int rv
= trans
->Start(
8756 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8757 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8758 // Valid change to an unrestricted port should pass.
8759 EXPECT_EQ(OK
, callback
.WaitForResult());
8762 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
8763 // Ensure that we're not allowed to redirect traffic via an alternate
8764 // protocol to an unsafe port, and that we resume the second
8765 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8766 session_deps_
.use_alternate_protocols
= true;
8768 HttpRequestInfo request
;
8769 request
.method
= "GET";
8770 request
.url
= GURL("http://www.google.com/");
8771 request
.load_flags
= 0;
8773 // The alternate protocol request will error out before we attempt to connect,
8774 // so only the standard HTTP request will try to connect.
8775 MockRead data_reads
[] = {
8776 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8777 MockRead("hello world"),
8778 MockRead(ASYNC
, OK
),
8780 StaticSocketDataProvider
data(
8781 data_reads
, arraysize(data_reads
), NULL
, 0);
8782 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8784 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8786 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8787 session
->http_server_properties();
8788 const int kUnsafePort
= 7;
8789 http_server_properties
->SetAlternateProtocol(
8790 HostPortPair::FromURL(request
.url
),
8792 AlternateProtocolFromNextProto(GetParam()), 1);
8794 scoped_ptr
<HttpTransaction
> trans(
8795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8796 TestCompletionCallback callback
;
8798 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8799 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8800 // The HTTP request should succeed.
8801 EXPECT_EQ(OK
, callback
.WaitForResult());
8803 // Disable alternate protocol before the asserts.
8804 // HttpStreamFactory::set_use_alternate_protocols(false);
8806 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8807 ASSERT_TRUE(response
!= NULL
);
8808 ASSERT_TRUE(response
->headers
.get() != NULL
);
8809 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8811 std::string response_data
;
8812 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8813 EXPECT_EQ("hello world", response_data
);
8816 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
8817 session_deps_
.use_alternate_protocols
= true;
8818 session_deps_
.next_protos
= SpdyNextProtos();
8820 HttpRequestInfo request
;
8821 request
.method
= "GET";
8822 request
.url
= GURL("http://www.google.com/");
8823 request
.load_flags
= 0;
8825 std::string alternate_protocol_http_header
=
8826 GetAlternateProtocolHttpHeader();
8828 MockRead data_reads
[] = {
8829 MockRead("HTTP/1.1 200 OK\r\n"),
8830 MockRead(alternate_protocol_http_header
.c_str()),
8831 MockRead("hello world"),
8832 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8836 StaticSocketDataProvider
first_transaction(
8837 data_reads
, arraysize(data_reads
), NULL
, 0);
8838 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8840 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8841 ssl
.SetNextProto(GetParam());
8842 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8844 scoped_ptr
<SpdyFrame
> req(
8845 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8846 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8848 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8849 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8850 MockRead spdy_reads
[] = {
8851 CreateMockRead(*resp
),
8852 CreateMockRead(*data
),
8853 MockRead(ASYNC
, 0, 0),
8856 DelayedSocketData
spdy_data(
8857 1, // wait for one write to finish before reading.
8858 spdy_reads
, arraysize(spdy_reads
),
8859 spdy_writes
, arraysize(spdy_writes
));
8860 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8862 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8863 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8865 hanging_non_alternate_protocol_socket
.set_connect_data(
8866 never_finishing_connect
);
8867 session_deps_
.socket_factory
->AddSocketDataProvider(
8868 &hanging_non_alternate_protocol_socket
);
8870 TestCompletionCallback callback
;
8872 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8873 scoped_ptr
<HttpTransaction
> trans(
8874 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8876 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8877 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8878 EXPECT_EQ(OK
, callback
.WaitForResult());
8880 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8881 ASSERT_TRUE(response
!= NULL
);
8882 ASSERT_TRUE(response
->headers
.get() != NULL
);
8883 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8885 std::string response_data
;
8886 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8887 EXPECT_EQ("hello world", response_data
);
8889 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8891 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8892 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8893 EXPECT_EQ(OK
, callback
.WaitForResult());
8895 response
= trans
->GetResponseInfo();
8896 ASSERT_TRUE(response
!= NULL
);
8897 ASSERT_TRUE(response
->headers
.get() != NULL
);
8898 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8899 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8900 EXPECT_TRUE(response
->was_npn_negotiated
);
8902 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8903 EXPECT_EQ("hello!", response_data
);
8906 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
8907 session_deps_
.use_alternate_protocols
= true;
8908 session_deps_
.next_protos
= SpdyNextProtos();
8910 HttpRequestInfo request
;
8911 request
.method
= "GET";
8912 request
.url
= GURL("http://www.google.com/");
8913 request
.load_flags
= 0;
8915 std::string alternate_protocol_http_header
=
8916 GetAlternateProtocolHttpHeader();
8918 MockRead data_reads
[] = {
8919 MockRead("HTTP/1.1 200 OK\r\n"),
8920 MockRead(alternate_protocol_http_header
.c_str()),
8921 MockRead("hello world"),
8922 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8923 MockRead(ASYNC
, OK
),
8926 StaticSocketDataProvider
first_transaction(
8927 data_reads
, arraysize(data_reads
), NULL
, 0);
8928 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8929 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8931 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8932 StaticSocketDataProvider
hanging_socket(
8934 hanging_socket
.set_connect_data(never_finishing_connect
);
8935 // Socket 2 and 3 are the hanging Alternate-Protocol and
8936 // non-Alternate-Protocol jobs from the 2nd transaction.
8937 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8938 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8940 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8941 ssl
.SetNextProto(GetParam());
8942 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8944 scoped_ptr
<SpdyFrame
> req1(
8945 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8946 scoped_ptr
<SpdyFrame
> req2(
8947 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
8948 MockWrite spdy_writes
[] = {
8949 CreateMockWrite(*req1
),
8950 CreateMockWrite(*req2
),
8952 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8953 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8954 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
8955 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
8956 MockRead spdy_reads
[] = {
8957 CreateMockRead(*resp1
),
8958 CreateMockRead(*data1
),
8959 CreateMockRead(*resp2
),
8960 CreateMockRead(*data2
),
8961 MockRead(ASYNC
, 0, 0),
8964 DelayedSocketData
spdy_data(
8965 2, // wait for writes to finish before reading.
8966 spdy_reads
, arraysize(spdy_reads
),
8967 spdy_writes
, arraysize(spdy_writes
));
8968 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8969 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8971 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8972 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8974 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8975 TestCompletionCallback callback1
;
8976 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
8978 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
8979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8980 EXPECT_EQ(OK
, callback1
.WaitForResult());
8982 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
8983 ASSERT_TRUE(response
!= NULL
);
8984 ASSERT_TRUE(response
->headers
.get() != NULL
);
8985 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8987 std::string response_data
;
8988 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
8989 EXPECT_EQ("hello world", response_data
);
8991 TestCompletionCallback callback2
;
8992 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
8993 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
8994 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8996 TestCompletionCallback callback3
;
8997 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
8998 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
8999 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9001 EXPECT_EQ(OK
, callback2
.WaitForResult());
9002 EXPECT_EQ(OK
, callback3
.WaitForResult());
9004 response
= trans2
.GetResponseInfo();
9005 ASSERT_TRUE(response
!= NULL
);
9006 ASSERT_TRUE(response
->headers
.get() != NULL
);
9007 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9008 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9009 EXPECT_TRUE(response
->was_npn_negotiated
);
9010 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9011 EXPECT_EQ("hello!", response_data
);
9013 response
= trans3
.GetResponseInfo();
9014 ASSERT_TRUE(response
!= NULL
);
9015 ASSERT_TRUE(response
->headers
.get() != NULL
);
9016 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9017 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9018 EXPECT_TRUE(response
->was_npn_negotiated
);
9019 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9020 EXPECT_EQ("hello!", response_data
);
9023 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9024 session_deps_
.use_alternate_protocols
= true;
9025 session_deps_
.next_protos
= SpdyNextProtos();
9027 HttpRequestInfo request
;
9028 request
.method
= "GET";
9029 request
.url
= GURL("http://www.google.com/");
9030 request
.load_flags
= 0;
9032 std::string alternate_protocol_http_header
=
9033 GetAlternateProtocolHttpHeader();
9035 MockRead data_reads
[] = {
9036 MockRead("HTTP/1.1 200 OK\r\n"),
9037 MockRead(alternate_protocol_http_header
.c_str()),
9038 MockRead("hello world"),
9039 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9040 MockRead(ASYNC
, OK
),
9043 StaticSocketDataProvider
first_transaction(
9044 data_reads
, arraysize(data_reads
), NULL
, 0);
9045 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9047 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9048 ssl
.SetNextProto(GetParam());
9049 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9051 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9052 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9054 hanging_alternate_protocol_socket
.set_connect_data(
9055 never_finishing_connect
);
9056 session_deps_
.socket_factory
->AddSocketDataProvider(
9057 &hanging_alternate_protocol_socket
);
9059 // 2nd request is just a copy of the first one, over HTTP again.
9060 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9062 TestCompletionCallback callback
;
9064 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9065 scoped_ptr
<HttpTransaction
> trans(
9066 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9068 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9070 EXPECT_EQ(OK
, callback
.WaitForResult());
9072 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9073 ASSERT_TRUE(response
!= NULL
);
9074 ASSERT_TRUE(response
->headers
.get() != NULL
);
9075 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9077 std::string response_data
;
9078 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9079 EXPECT_EQ("hello world", response_data
);
9081 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9083 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9084 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9085 EXPECT_EQ(OK
, callback
.WaitForResult());
9087 response
= trans
->GetResponseInfo();
9088 ASSERT_TRUE(response
!= NULL
);
9089 ASSERT_TRUE(response
->headers
.get() != NULL
);
9090 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9091 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9092 EXPECT_FALSE(response
->was_npn_negotiated
);
9094 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9095 EXPECT_EQ("hello world", response_data
);
9098 class CapturingProxyResolver
: public ProxyResolver
{
9100 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9101 virtual ~CapturingProxyResolver() {}
9103 virtual int GetProxyForURL(const GURL
& url
,
9105 const CompletionCallback
& callback
,
9106 RequestHandle
* request
,
9107 const BoundNetLog
& net_log
) OVERRIDE
{
9108 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9109 HostPortPair("myproxy", 80));
9110 results
->UseProxyServer(proxy_server
);
9111 resolved_
.push_back(url
);
9115 virtual void CancelRequest(RequestHandle request
) OVERRIDE
{
9119 virtual LoadState
GetLoadState(RequestHandle request
) const OVERRIDE
{
9121 return LOAD_STATE_IDLE
;
9124 virtual void CancelSetPacScript() OVERRIDE
{
9128 virtual int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9129 const CompletionCallback
& /*callback*/) OVERRIDE
{
9133 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9136 std::vector
<GURL
> resolved_
;
9138 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9141 TEST_P(HttpNetworkTransactionTest
,
9142 UseAlternateProtocolForTunneledNpnSpdy
) {
9143 session_deps_
.use_alternate_protocols
= true;
9144 session_deps_
.next_protos
= SpdyNextProtos();
9146 ProxyConfig proxy_config
;
9147 proxy_config
.set_auto_detect(true);
9148 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9150 CapturingProxyResolver
* capturing_proxy_resolver
=
9151 new CapturingProxyResolver();
9152 session_deps_
.proxy_service
.reset(new ProxyService(
9153 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
9155 CapturingNetLog net_log
;
9156 session_deps_
.net_log
= &net_log
;
9158 HttpRequestInfo request
;
9159 request
.method
= "GET";
9160 request
.url
= GURL("http://www.google.com/");
9161 request
.load_flags
= 0;
9163 std::string alternate_protocol_http_header
=
9164 GetAlternateProtocolHttpHeader();
9166 MockRead data_reads
[] = {
9167 MockRead("HTTP/1.1 200 OK\r\n"),
9168 MockRead(alternate_protocol_http_header
.c_str()),
9169 MockRead("hello world"),
9170 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9171 MockRead(ASYNC
, OK
),
9174 StaticSocketDataProvider
first_transaction(
9175 data_reads
, arraysize(data_reads
), NULL
, 0);
9176 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9178 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9179 ssl
.SetNextProto(GetParam());
9180 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9182 scoped_ptr
<SpdyFrame
> req(
9183 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9184 MockWrite spdy_writes
[] = {
9185 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9186 "Host: www.google.com\r\n"
9187 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9188 CreateMockWrite(*req
), // 3
9191 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9193 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9194 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9195 MockRead spdy_reads
[] = {
9196 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9197 CreateMockRead(*resp
.get(), 4), // 2, 4
9198 CreateMockRead(*data
.get(), 4), // 5
9199 MockRead(ASYNC
, 0, 0, 4), // 6
9202 OrderedSocketData
spdy_data(
9203 spdy_reads
, arraysize(spdy_reads
),
9204 spdy_writes
, arraysize(spdy_writes
));
9205 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9207 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9208 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9210 hanging_non_alternate_protocol_socket
.set_connect_data(
9211 never_finishing_connect
);
9212 session_deps_
.socket_factory
->AddSocketDataProvider(
9213 &hanging_non_alternate_protocol_socket
);
9215 TestCompletionCallback callback
;
9217 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9218 scoped_ptr
<HttpTransaction
> trans(
9219 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9221 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9222 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9223 EXPECT_EQ(OK
, callback
.WaitForResult());
9225 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9226 ASSERT_TRUE(response
!= NULL
);
9227 ASSERT_TRUE(response
->headers
.get() != NULL
);
9228 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9229 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9230 EXPECT_FALSE(response
->was_npn_negotiated
);
9232 std::string response_data
;
9233 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9234 EXPECT_EQ("hello world", response_data
);
9236 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9238 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9239 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9240 EXPECT_EQ(OK
, callback
.WaitForResult());
9242 response
= trans
->GetResponseInfo();
9243 ASSERT_TRUE(response
!= NULL
);
9244 ASSERT_TRUE(response
->headers
.get() != NULL
);
9245 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9246 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9247 EXPECT_TRUE(response
->was_npn_negotiated
);
9249 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9250 EXPECT_EQ("hello!", response_data
);
9251 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
9252 EXPECT_EQ("http://www.google.com/",
9253 capturing_proxy_resolver
->resolved()[0].spec());
9254 EXPECT_EQ("https://www.google.com/",
9255 capturing_proxy_resolver
->resolved()[1].spec());
9257 LoadTimingInfo load_timing_info
;
9258 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9259 TestLoadTimingNotReusedWithPac(load_timing_info
,
9260 CONNECT_TIMING_HAS_SSL_TIMES
);
9263 TEST_P(HttpNetworkTransactionTest
,
9264 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9265 session_deps_
.use_alternate_protocols
= true;
9266 session_deps_
.next_protos
= SpdyNextProtos();
9268 HttpRequestInfo request
;
9269 request
.method
= "GET";
9270 request
.url
= GURL("http://www.google.com/");
9271 request
.load_flags
= 0;
9273 std::string alternate_protocol_http_header
=
9274 GetAlternateProtocolHttpHeader();
9276 MockRead data_reads
[] = {
9277 MockRead("HTTP/1.1 200 OK\r\n"),
9278 MockRead(alternate_protocol_http_header
.c_str()),
9279 MockRead("hello world"),
9280 MockRead(ASYNC
, OK
),
9283 StaticSocketDataProvider
first_transaction(
9284 data_reads
, arraysize(data_reads
), NULL
, 0);
9285 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9287 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9288 ssl
.SetNextProto(GetParam());
9289 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9291 scoped_ptr
<SpdyFrame
> req(
9292 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9293 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9295 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9296 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9297 MockRead spdy_reads
[] = {
9298 CreateMockRead(*resp
),
9299 CreateMockRead(*data
),
9300 MockRead(ASYNC
, 0, 0),
9303 DelayedSocketData
spdy_data(
9304 1, // wait for one write to finish before reading.
9305 spdy_reads
, arraysize(spdy_reads
),
9306 spdy_writes
, arraysize(spdy_writes
));
9307 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9309 TestCompletionCallback callback
;
9311 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9313 scoped_ptr
<HttpTransaction
> trans(
9314 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9316 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9317 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9318 EXPECT_EQ(OK
, callback
.WaitForResult());
9320 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9321 ASSERT_TRUE(response
!= NULL
);
9322 ASSERT_TRUE(response
->headers
.get() != NULL
);
9323 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9325 std::string response_data
;
9326 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9327 EXPECT_EQ("hello world", response_data
);
9329 // Set up an initial SpdySession in the pool to reuse.
9330 HostPortPair
host_port_pair("www.google.com", 443);
9331 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9332 PRIVACY_MODE_DISABLED
);
9333 base::WeakPtr
<SpdySession
> spdy_session
=
9334 CreateSecureSpdySession(session
, key
, BoundNetLog());
9336 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9338 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9340 EXPECT_EQ(OK
, callback
.WaitForResult());
9342 response
= trans
->GetResponseInfo();
9343 ASSERT_TRUE(response
!= NULL
);
9344 ASSERT_TRUE(response
->headers
.get() != NULL
);
9345 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9346 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9347 EXPECT_TRUE(response
->was_npn_negotiated
);
9349 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9350 EXPECT_EQ("hello!", response_data
);
9353 // GenerateAuthToken is a mighty big test.
9354 // It tests all permutation of GenerateAuthToken behavior:
9355 // - Synchronous and Asynchronous completion.
9356 // - OK or error on completion.
9357 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9358 // - HTTP or HTTPS backend (to include proxy tunneling).
9359 // - Non-authenticating and authenticating backend.
9361 // In all, there are 44 reasonable permuations (for example, if there are
9362 // problems generating an auth token for an authenticating proxy, we don't
9363 // need to test all permutations of the backend server).
9365 // The test proceeds by going over each of the configuration cases, and
9366 // potentially running up to three rounds in each of the tests. The TestConfig
9367 // specifies both the configuration for the test as well as the expectations
9369 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9370 static const char kServer
[] = "http://www.example.com";
9371 static const char kSecureServer
[] = "https://www.example.com";
9372 static const char kProxy
[] = "myproxy:70";
9373 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9381 const MockWrite
kGet(
9382 "GET / HTTP/1.1\r\n"
9383 "Host: www.example.com\r\n"
9384 "Connection: keep-alive\r\n\r\n");
9385 const MockWrite
kGetProxy(
9386 "GET http://www.example.com/ HTTP/1.1\r\n"
9387 "Host: www.example.com\r\n"
9388 "Proxy-Connection: keep-alive\r\n\r\n");
9389 const MockWrite
kGetAuth(
9390 "GET / HTTP/1.1\r\n"
9391 "Host: www.example.com\r\n"
9392 "Connection: keep-alive\r\n"
9393 "Authorization: auth_token\r\n\r\n");
9394 const MockWrite
kGetProxyAuth(
9395 "GET http://www.example.com/ HTTP/1.1\r\n"
9396 "Host: www.example.com\r\n"
9397 "Proxy-Connection: keep-alive\r\n"
9398 "Proxy-Authorization: auth_token\r\n\r\n");
9399 const MockWrite
kGetAuthThroughProxy(
9400 "GET http://www.example.com/ HTTP/1.1\r\n"
9401 "Host: www.example.com\r\n"
9402 "Proxy-Connection: keep-alive\r\n"
9403 "Authorization: auth_token\r\n\r\n");
9404 const MockWrite
kGetAuthWithProxyAuth(
9405 "GET http://www.example.com/ HTTP/1.1\r\n"
9406 "Host: www.example.com\r\n"
9407 "Proxy-Connection: keep-alive\r\n"
9408 "Proxy-Authorization: auth_token\r\n"
9409 "Authorization: auth_token\r\n\r\n");
9410 const MockWrite
kConnect(
9411 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9412 "Host: www.example.com\r\n"
9413 "Proxy-Connection: keep-alive\r\n\r\n");
9414 const MockWrite
kConnectProxyAuth(
9415 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9416 "Host: www.example.com\r\n"
9417 "Proxy-Connection: keep-alive\r\n"
9418 "Proxy-Authorization: auth_token\r\n\r\n");
9420 const MockRead
kSuccess(
9421 "HTTP/1.1 200 OK\r\n"
9422 "Content-Type: text/html; charset=iso-8859-1\r\n"
9423 "Content-Length: 3\r\n\r\n"
9425 const MockRead
kFailure(
9426 "Should not be called.");
9427 const MockRead
kServerChallenge(
9428 "HTTP/1.1 401 Unauthorized\r\n"
9429 "WWW-Authenticate: Mock realm=server\r\n"
9430 "Content-Type: text/html; charset=iso-8859-1\r\n"
9431 "Content-Length: 14\r\n\r\n"
9432 "Unauthorized\r\n");
9433 const MockRead
kProxyChallenge(
9434 "HTTP/1.1 407 Unauthorized\r\n"
9435 "Proxy-Authenticate: Mock realm=proxy\r\n"
9436 "Proxy-Connection: close\r\n"
9437 "Content-Type: text/html; charset=iso-8859-1\r\n"
9438 "Content-Length: 14\r\n\r\n"
9439 "Unauthorized\r\n");
9440 const MockRead
kProxyConnected(
9441 "HTTP/1.1 200 Connection Established\r\n\r\n");
9443 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9444 // no constructors, but the C++ compiler on Windows warns about
9445 // unspecified data in compound literals. So, moved to using constructors,
9446 // and TestRound's created with the default constructor should not be used.
9449 : expected_rv(ERR_UNEXPECTED
),
9453 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9454 int expected_rv_arg
)
9457 expected_rv(expected_rv_arg
),
9461 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9462 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9463 const MockRead
* extra_read_arg
)
9466 expected_rv(expected_rv_arg
),
9467 extra_write(extra_write_arg
),
9468 extra_read(extra_read_arg
) {
9473 const MockWrite
* extra_write
;
9474 const MockRead
* extra_read
;
9477 static const int kNoSSL
= 500;
9480 const char* proxy_url
;
9481 AuthTiming proxy_auth_timing
;
9483 const char* server_url
;
9484 AuthTiming server_auth_timing
;
9486 int num_auth_rounds
;
9487 int first_ssl_round
;
9488 TestRound rounds
[3];
9489 } test_configs
[] = {
9490 // Non-authenticating HTTP server with a direct connection.
9491 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9492 { TestRound(kGet
, kSuccess
, OK
)}},
9493 // Authenticating HTTP server with a direct connection.
9494 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9495 { TestRound(kGet
, kServerChallenge
, OK
),
9496 TestRound(kGetAuth
, kSuccess
, OK
)}},
9497 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9498 { TestRound(kGet
, kServerChallenge
, OK
),
9499 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9500 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9501 { TestRound(kGet
, kServerChallenge
, OK
),
9502 TestRound(kGetAuth
, kSuccess
, OK
)}},
9503 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9504 { TestRound(kGet
, kServerChallenge
, OK
),
9505 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9506 // Non-authenticating HTTP server through a non-authenticating proxy.
9507 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9508 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9509 // Authenticating HTTP server through a non-authenticating proxy.
9510 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9511 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9512 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9513 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9514 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9515 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9516 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9517 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9518 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9519 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9520 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9521 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9522 // Non-authenticating HTTP server through an authenticating proxy.
9523 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9524 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9525 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9526 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9527 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9528 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9529 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9530 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9531 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9532 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9533 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9534 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9535 // Authenticating HTTP server through an authenticating proxy.
9536 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9537 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9538 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9539 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9540 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9541 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9542 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9543 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9544 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9545 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9546 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9547 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9548 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9549 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9550 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9551 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9552 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9553 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9554 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9555 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9556 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9557 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9558 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9559 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9560 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9561 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9562 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9563 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9564 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9565 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9566 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9567 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9568 // Non-authenticating HTTPS server with a direct connection.
9569 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9570 { TestRound(kGet
, kSuccess
, OK
)}},
9571 // Authenticating HTTPS server with a direct connection.
9572 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9573 { TestRound(kGet
, kServerChallenge
, OK
),
9574 TestRound(kGetAuth
, kSuccess
, OK
)}},
9575 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9576 { TestRound(kGet
, kServerChallenge
, OK
),
9577 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9578 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9579 { TestRound(kGet
, kServerChallenge
, OK
),
9580 TestRound(kGetAuth
, kSuccess
, OK
)}},
9581 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9582 { TestRound(kGet
, kServerChallenge
, OK
),
9583 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9584 // Non-authenticating HTTPS server with a non-authenticating proxy.
9585 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9586 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9587 // Authenticating HTTPS server through a non-authenticating proxy.
9588 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9589 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9590 TestRound(kGetAuth
, kSuccess
, OK
)}},
9591 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9592 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9593 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9594 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9595 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9596 TestRound(kGetAuth
, kSuccess
, OK
)}},
9597 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9598 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9599 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9600 // Non-Authenticating HTTPS server through an authenticating proxy.
9601 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9602 { TestRound(kConnect
, kProxyChallenge
, OK
),
9603 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9604 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9605 { TestRound(kConnect
, kProxyChallenge
, OK
),
9606 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9607 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9608 { TestRound(kConnect
, kProxyChallenge
, OK
),
9609 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9610 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9611 { TestRound(kConnect
, kProxyChallenge
, OK
),
9612 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9613 // Authenticating HTTPS server through an authenticating proxy.
9614 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9615 { TestRound(kConnect
, kProxyChallenge
, OK
),
9616 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9617 &kGet
, &kServerChallenge
),
9618 TestRound(kGetAuth
, kSuccess
, OK
)}},
9619 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9620 { TestRound(kConnect
, kProxyChallenge
, OK
),
9621 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9622 &kGet
, &kServerChallenge
),
9623 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9624 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9625 { TestRound(kConnect
, kProxyChallenge
, OK
),
9626 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9627 &kGet
, &kServerChallenge
),
9628 TestRound(kGetAuth
, kSuccess
, OK
)}},
9629 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9630 { TestRound(kConnect
, kProxyChallenge
, OK
),
9631 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9632 &kGet
, &kServerChallenge
),
9633 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9634 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9635 { TestRound(kConnect
, kProxyChallenge
, OK
),
9636 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9637 &kGet
, &kServerChallenge
),
9638 TestRound(kGetAuth
, kSuccess
, OK
)}},
9639 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9640 { TestRound(kConnect
, kProxyChallenge
, OK
),
9641 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9642 &kGet
, &kServerChallenge
),
9643 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9644 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9645 { TestRound(kConnect
, kProxyChallenge
, OK
),
9646 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9647 &kGet
, &kServerChallenge
),
9648 TestRound(kGetAuth
, kSuccess
, OK
)}},
9649 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9650 { TestRound(kConnect
, kProxyChallenge
, OK
),
9651 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9652 &kGet
, &kServerChallenge
),
9653 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9656 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_configs
); ++i
) {
9657 HttpAuthHandlerMock::Factory
* auth_factory(
9658 new HttpAuthHandlerMock::Factory());
9659 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9660 const TestConfig
& test_config
= test_configs
[i
];
9662 // Set up authentication handlers as necessary.
9663 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9664 for (int n
= 0; n
< 2; n
++) {
9665 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9666 std::string auth_challenge
= "Mock realm=proxy";
9667 GURL
origin(test_config
.proxy_url
);
9668 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9669 auth_challenge
.end());
9670 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9671 origin
, BoundNetLog());
9672 auth_handler
->SetGenerateExpectation(
9673 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9674 test_config
.proxy_auth_rv
);
9675 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9678 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9679 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9680 std::string auth_challenge
= "Mock realm=server";
9681 GURL
origin(test_config
.server_url
);
9682 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9683 auth_challenge
.end());
9684 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9685 origin
, BoundNetLog());
9686 auth_handler
->SetGenerateExpectation(
9687 test_config
.server_auth_timing
== AUTH_ASYNC
,
9688 test_config
.server_auth_rv
);
9689 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9691 if (test_config
.proxy_url
) {
9692 session_deps_
.proxy_service
.reset(
9693 ProxyService::CreateFixed(test_config
.proxy_url
));
9695 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9698 HttpRequestInfo request
;
9699 request
.method
= "GET";
9700 request
.url
= GURL(test_config
.server_url
);
9701 request
.load_flags
= 0;
9703 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9704 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
9706 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9707 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9709 // Set up expected reads and writes.
9711 reads
[0] = read_write_round
.read
;
9712 size_t length_reads
= 1;
9713 if (read_write_round
.extra_read
) {
9714 reads
[1] = *read_write_round
.extra_read
;
9718 MockWrite writes
[2];
9719 writes
[0] = read_write_round
.write
;
9720 size_t length_writes
= 1;
9721 if (read_write_round
.extra_write
) {
9722 writes
[1] = *read_write_round
.extra_write
;
9725 StaticSocketDataProvider
data_provider(
9726 reads
, length_reads
, writes
, length_writes
);
9727 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9729 // Add an SSL sequence if necessary.
9730 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9731 if (round
>= test_config
.first_ssl_round
)
9732 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9733 &ssl_socket_data_provider
);
9735 // Start or restart the transaction.
9736 TestCompletionCallback callback
;
9739 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9741 rv
= trans
.RestartWithAuth(
9742 AuthCredentials(kFoo
, kBar
), callback
.callback());
9744 if (rv
== ERR_IO_PENDING
)
9745 rv
= callback
.WaitForResult();
9747 // Compare results with expected data.
9748 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9749 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9750 if (read_write_round
.expected_rv
== OK
) {
9751 ASSERT_TRUE(response
!= NULL
);
9753 EXPECT_TRUE(response
== NULL
);
9754 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9757 if (round
+ 1 < test_config
.num_auth_rounds
) {
9758 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9760 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9766 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9767 // Do multi-round authentication and make sure it works correctly.
9768 HttpAuthHandlerMock::Factory
* auth_factory(
9769 new HttpAuthHandlerMock::Factory());
9770 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9771 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9772 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9773 session_deps_
.host_resolver
->set_synchronous_mode(true);
9775 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9776 auth_handler
->set_connection_based(true);
9777 std::string auth_challenge
= "Mock realm=server";
9778 GURL
origin("http://www.example.com");
9779 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9780 auth_challenge
.end());
9781 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9782 origin
, BoundNetLog());
9783 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9786 const HttpResponseInfo
* response
= NULL
;
9787 HttpRequestInfo request
;
9788 request
.method
= "GET";
9789 request
.url
= origin
;
9790 request
.load_flags
= 0;
9792 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9794 // Use a TCP Socket Pool with only one connection per group. This is used
9795 // to validate that the TCP socket is not released to the pool between
9796 // each round of multi-round authentication.
9797 HttpNetworkSessionPeer
session_peer(session
);
9798 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9799 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9800 50, // Max sockets for pool
9801 1, // Max sockets per group
9802 &transport_pool_histograms
,
9803 session_deps_
.host_resolver
.get(),
9804 session_deps_
.socket_factory
.get(),
9805 session_deps_
.net_log
);
9806 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
9807 new MockClientSocketPoolManager
);
9808 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9809 session_peer
.SetClientSocketPoolManager(
9810 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
9812 scoped_ptr
<HttpTransaction
> trans(
9813 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9814 TestCompletionCallback callback
;
9816 const MockWrite
kGet(
9817 "GET / HTTP/1.1\r\n"
9818 "Host: www.example.com\r\n"
9819 "Connection: keep-alive\r\n\r\n");
9820 const MockWrite
kGetAuth(
9821 "GET / HTTP/1.1\r\n"
9822 "Host: www.example.com\r\n"
9823 "Connection: keep-alive\r\n"
9824 "Authorization: auth_token\r\n\r\n");
9826 const MockRead
kServerChallenge(
9827 "HTTP/1.1 401 Unauthorized\r\n"
9828 "WWW-Authenticate: Mock realm=server\r\n"
9829 "Content-Type: text/html; charset=iso-8859-1\r\n"
9830 "Content-Length: 14\r\n\r\n"
9831 "Unauthorized\r\n");
9832 const MockRead
kSuccess(
9833 "HTTP/1.1 200 OK\r\n"
9834 "Content-Type: text/html; charset=iso-8859-1\r\n"
9835 "Content-Length: 3\r\n\r\n"
9838 MockWrite writes
[] = {
9847 // Competing request
9850 MockRead reads
[] = {
9859 // Competing response
9862 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9863 writes
, arraysize(writes
));
9864 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9866 const char* const kSocketGroup
= "www.example.com:80";
9868 // First round of authentication.
9869 auth_handler
->SetGenerateExpectation(false, OK
);
9870 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9871 if (rv
== ERR_IO_PENDING
)
9872 rv
= callback
.WaitForResult();
9874 response
= trans
->GetResponseInfo();
9875 ASSERT_TRUE(response
!= NULL
);
9876 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9877 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9879 // In between rounds, another request comes in for the same domain.
9880 // It should not be able to grab the TCP socket that trans has already
9882 scoped_ptr
<HttpTransaction
> trans_compete(
9883 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9884 TestCompletionCallback callback_compete
;
9885 rv
= trans_compete
->Start(
9886 &request
, callback_compete
.callback(), BoundNetLog());
9887 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9888 // callback_compete.WaitForResult at this point would stall forever,
9889 // since the HttpNetworkTransaction does not release the request back to
9890 // the pool until after authentication completes.
9892 // Second round of authentication.
9893 auth_handler
->SetGenerateExpectation(false, OK
);
9894 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9895 if (rv
== ERR_IO_PENDING
)
9896 rv
= callback
.WaitForResult();
9898 response
= trans
->GetResponseInfo();
9899 ASSERT_TRUE(response
!= NULL
);
9900 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9901 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9903 // Third round of authentication.
9904 auth_handler
->SetGenerateExpectation(false, OK
);
9905 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9906 if (rv
== ERR_IO_PENDING
)
9907 rv
= callback
.WaitForResult();
9909 response
= trans
->GetResponseInfo();
9910 ASSERT_TRUE(response
!= NULL
);
9911 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9912 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9914 // Fourth round of authentication, which completes successfully.
9915 auth_handler
->SetGenerateExpectation(false, OK
);
9916 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9917 if (rv
== ERR_IO_PENDING
)
9918 rv
= callback
.WaitForResult();
9920 response
= trans
->GetResponseInfo();
9921 ASSERT_TRUE(response
!= NULL
);
9922 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9923 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9925 // Read the body since the fourth round was successful. This will also
9926 // release the socket back to the pool.
9927 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9928 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9929 if (rv
== ERR_IO_PENDING
)
9930 rv
= callback
.WaitForResult();
9932 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9934 // There are still 0 idle sockets, since the trans_compete transaction
9935 // will be handed it immediately after trans releases it to the group.
9936 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9938 // The competing request can now finish. Wait for the headers and then
9940 rv
= callback_compete
.WaitForResult();
9942 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9943 if (rv
== ERR_IO_PENDING
)
9944 rv
= callback
.WaitForResult();
9946 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9949 // Finally, the socket is released to the group.
9950 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9953 // This tests the case that a request is issued via http instead of spdy after
9954 // npn is negotiated.
9955 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9956 session_deps_
.use_alternate_protocols
= true;
9957 NextProtoVector next_protos
;
9958 next_protos
.push_back(kProtoHTTP11
);
9959 session_deps_
.next_protos
= next_protos
;
9961 HttpRequestInfo request
;
9962 request
.method
= "GET";
9963 request
.url
= GURL("https://www.google.com/");
9964 request
.load_flags
= 0;
9966 MockWrite data_writes
[] = {
9967 MockWrite("GET / HTTP/1.1\r\n"
9968 "Host: www.google.com\r\n"
9969 "Connection: keep-alive\r\n\r\n"),
9972 std::string alternate_protocol_http_header
=
9973 GetAlternateProtocolHttpHeader();
9975 MockRead data_reads
[] = {
9976 MockRead("HTTP/1.1 200 OK\r\n"),
9977 MockRead(alternate_protocol_http_header
.c_str()),
9978 MockRead("hello world"),
9979 MockRead(SYNCHRONOUS
, OK
),
9982 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9983 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9984 ssl
.next_proto
= "http/1.1";
9985 ssl
.protocol_negotiated
= kProtoHTTP11
;
9987 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9989 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9990 data_writes
, arraysize(data_writes
));
9991 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9993 TestCompletionCallback callback
;
9995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9996 scoped_ptr
<HttpTransaction
> trans(
9997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9999 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10001 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10002 EXPECT_EQ(OK
, callback
.WaitForResult());
10004 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10005 ASSERT_TRUE(response
!= NULL
);
10006 ASSERT_TRUE(response
->headers
.get() != NULL
);
10007 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10009 std::string response_data
;
10010 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10011 EXPECT_EQ("hello world", response_data
);
10013 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10014 EXPECT_TRUE(response
->was_npn_negotiated
);
10017 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10018 // Simulate the SSL handshake completing with an NPN negotiation
10019 // followed by an immediate server closing of the socket.
10020 // Fix crash: http://crbug.com/46369
10021 session_deps_
.use_alternate_protocols
= true;
10022 session_deps_
.next_protos
= SpdyNextProtos();
10024 HttpRequestInfo request
;
10025 request
.method
= "GET";
10026 request
.url
= GURL("https://www.google.com/");
10027 request
.load_flags
= 0;
10029 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10030 ssl
.SetNextProto(GetParam());
10031 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10033 scoped_ptr
<SpdyFrame
> req(
10034 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10035 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10037 MockRead spdy_reads
[] = {
10038 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10041 DelayedSocketData
spdy_data(
10042 0, // don't wait in this case, immediate hangup.
10043 spdy_reads
, arraysize(spdy_reads
),
10044 spdy_writes
, arraysize(spdy_writes
));
10045 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10047 TestCompletionCallback callback
;
10049 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10050 scoped_ptr
<HttpTransaction
> trans(
10051 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10053 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10054 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10055 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10058 // A subclass of HttpAuthHandlerMock that records the request URL when
10059 // it gets it. This is needed since the auth handler may get destroyed
10060 // before we get a chance to query it.
10061 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10063 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10065 virtual ~UrlRecordingHttpAuthHandlerMock() {}
10068 virtual int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10069 const HttpRequestInfo
* request
,
10070 const CompletionCallback
& callback
,
10071 std::string
* auth_token
) OVERRIDE
{
10072 *url_
= request
->url
;
10073 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10074 credentials
, request
, callback
, auth_token
);
10081 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10082 // This test ensures that the URL passed into the proxy is upgraded
10083 // to https when doing an Alternate Protocol upgrade.
10084 session_deps_
.use_alternate_protocols
= true;
10085 session_deps_
.next_protos
= SpdyNextProtos();
10087 session_deps_
.proxy_service
.reset(
10088 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10089 CapturingNetLog net_log
;
10090 session_deps_
.net_log
= &net_log
;
10093 HttpAuthHandlerMock::Factory
* auth_factory
=
10094 new HttpAuthHandlerMock::Factory();
10095 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10096 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10097 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10098 auth_factory
->set_do_init_from_challenge(true);
10099 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10102 HttpRequestInfo request
;
10103 request
.method
= "GET";
10104 request
.url
= GURL("http://www.google.com");
10105 request
.load_flags
= 0;
10107 // First round goes unauthenticated through the proxy.
10108 MockWrite data_writes_1
[] = {
10109 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10110 "Host: www.google.com\r\n"
10111 "Proxy-Connection: keep-alive\r\n"
10114 MockRead data_reads_1
[] = {
10115 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10116 MockRead("HTTP/1.1 200 OK\r\n"
10117 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10118 "Proxy-Connection: close\r\n"
10121 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10122 data_writes_1
, arraysize(data_writes_1
));
10124 // Second round tries to tunnel to www.google.com due to the
10125 // Alternate-Protocol announcement in the first round. It fails due
10126 // to a proxy authentication challenge.
10127 // After the failure, a tunnel is established to www.google.com using
10128 // Proxy-Authorization headers. There is then a SPDY request round.
10130 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10131 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10132 // does a Disconnect and Connect on the same socket, rather than trying
10133 // to obtain a new one.
10135 // NOTE: Originally, the proxy response to the second CONNECT request
10136 // simply returned another 407 so the unit test could skip the SSL connection
10137 // establishment and SPDY framing issues. Alas, the
10138 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10139 // complicated to set up expectations for than the SPDY session.
10141 scoped_ptr
<SpdyFrame
> req(
10142 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10143 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10144 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10146 MockWrite data_writes_2
[] = {
10147 // First connection attempt without Proxy-Authorization.
10148 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10149 "Host: www.google.com\r\n"
10150 "Proxy-Connection: keep-alive\r\n"
10153 // Second connection attempt with Proxy-Authorization.
10154 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10155 "Host: www.google.com\r\n"
10156 "Proxy-Connection: keep-alive\r\n"
10157 "Proxy-Authorization: auth_token\r\n"
10161 CreateMockWrite(*req
),
10163 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10164 "Proxy-Authenticate: Mock\r\n"
10165 "Proxy-Connection: close\r\n"
10167 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10168 MockRead data_reads_2
[] = {
10169 // First connection attempt fails
10170 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10171 MockRead(ASYNC
, kRejectConnectResponse
,
10172 arraysize(kRejectConnectResponse
) - 1, 1),
10174 // Second connection attempt passes
10175 MockRead(ASYNC
, kAcceptConnectResponse
,
10176 arraysize(kAcceptConnectResponse
) -1, 4),
10179 CreateMockRead(*resp
.get(), 6),
10180 CreateMockRead(*data
.get(), 6),
10181 MockRead(ASYNC
, 0, 0, 6),
10183 OrderedSocketData
data_2(
10184 data_reads_2
, arraysize(data_reads_2
),
10185 data_writes_2
, arraysize(data_writes_2
));
10187 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10188 ssl
.SetNextProto(GetParam());
10190 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10191 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10193 hanging_non_alternate_protocol_socket
.set_connect_data(
10194 never_finishing_connect
);
10196 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10197 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10198 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10199 session_deps_
.socket_factory
->AddSocketDataProvider(
10200 &hanging_non_alternate_protocol_socket
);
10201 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10203 // First round should work and provide the Alternate-Protocol state.
10204 TestCompletionCallback callback_1
;
10205 scoped_ptr
<HttpTransaction
> trans_1(
10206 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10207 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10208 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10209 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10211 // Second round should attempt a tunnel connect and get an auth challenge.
10212 TestCompletionCallback callback_2
;
10213 scoped_ptr
<HttpTransaction
> trans_2(
10214 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10215 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10216 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10217 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10218 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10219 ASSERT_TRUE(response
!= NULL
);
10220 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10222 // Restart with auth. Tunnel should work and response received.
10223 TestCompletionCallback callback_3
;
10224 rv
= trans_2
->RestartWithAuth(
10225 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10226 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10227 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10229 // After all that work, these two lines (or actually, just the scheme) are
10230 // what this test is all about. Make sure it happens correctly.
10231 EXPECT_EQ("https", request_url
.scheme());
10232 EXPECT_EQ("www.google.com", request_url
.host());
10234 LoadTimingInfo load_timing_info
;
10235 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10236 TestLoadTimingNotReusedWithPac(load_timing_info
,
10237 CONNECT_TIMING_HAS_SSL_TIMES
);
10240 // Test that if we cancel the transaction as the connection is completing, that
10241 // everything tears down correctly.
10242 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10243 // Setup everything about the connection to complete synchronously, so that
10244 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10245 // for is the callback from the HttpStreamRequest.
10246 // Then cancel the transaction.
10247 // Verify that we don't crash.
10248 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10249 MockRead data_reads
[] = {
10250 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10251 MockRead(SYNCHRONOUS
, "hello world"),
10252 MockRead(SYNCHRONOUS
, OK
),
10255 HttpRequestInfo request
;
10256 request
.method
= "GET";
10257 request
.url
= GURL("http://www.google.com/");
10258 request
.load_flags
= 0;
10260 session_deps_
.host_resolver
->set_synchronous_mode(true);
10261 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10262 scoped_ptr
<HttpTransaction
> trans(
10263 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10265 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10266 data
.set_connect_data(mock_connect
);
10267 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10269 TestCompletionCallback callback
;
10271 CapturingBoundNetLog log
;
10272 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10273 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10274 trans
.reset(); // Cancel the transaction here.
10276 base::MessageLoop::current()->RunUntilIdle();
10279 // Test that if a transaction is cancelled after receiving the headers, the
10280 // stream is drained properly and added back to the socket pool. The main
10281 // purpose of this test is to make sure that an HttpStreamParser can be read
10282 // from after the HttpNetworkTransaction and the objects it owns have been
10284 // See http://crbug.com/368418
10285 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10286 MockRead data_reads
[] = {
10287 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10288 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10289 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10290 MockRead(ASYNC
, "1"),
10291 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10292 // HttpNetworkTransaction has been deleted.
10293 MockRead(ASYNC
, "2"),
10294 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10296 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10297 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10299 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10302 HttpRequestInfo request
;
10303 request
.method
= "GET";
10304 request
.url
= GURL("http://www.google.com/");
10305 request
.load_flags
= 0;
10307 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10308 TestCompletionCallback callback
;
10310 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10311 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10312 callback
.WaitForResult();
10314 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10315 ASSERT_TRUE(response
!= NULL
);
10316 EXPECT_TRUE(response
->headers
.get() != NULL
);
10317 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10319 // The transaction and HttpRequestInfo are deleted.
10322 // Let the HttpResponseBodyDrainer drain the socket.
10323 base::MessageLoop::current()->RunUntilIdle();
10325 // Socket should now be idle, waiting to be reused.
10326 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10329 // Test a basic GET request through a proxy.
10330 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10331 session_deps_
.proxy_service
.reset(
10332 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10333 CapturingBoundNetLog log
;
10334 session_deps_
.net_log
= log
.bound().net_log();
10335 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10337 HttpRequestInfo request
;
10338 request
.method
= "GET";
10339 request
.url
= GURL("http://www.google.com/");
10341 MockWrite data_writes1
[] = {
10342 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10343 "Host: www.google.com\r\n"
10344 "Proxy-Connection: keep-alive\r\n\r\n"),
10347 MockRead data_reads1
[] = {
10348 MockRead("HTTP/1.1 200 OK\r\n"),
10349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10350 MockRead("Content-Length: 100\r\n\r\n"),
10351 MockRead(SYNCHRONOUS
, OK
),
10354 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10355 data_writes1
, arraysize(data_writes1
));
10356 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10358 TestCompletionCallback callback1
;
10360 scoped_ptr
<HttpTransaction
> trans(
10361 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10362 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10363 trans
->SetBeforeProxyHeadersSentCallback(
10364 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10365 base::Unretained(&proxy_headers_handler
)));
10367 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10370 rv
= callback1
.WaitForResult();
10373 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10374 ASSERT_TRUE(response
!= NULL
);
10376 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10377 EXPECT_EQ(200, response
->headers
->response_code());
10378 EXPECT_EQ(100, response
->headers
->GetContentLength());
10379 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10381 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10382 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10383 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10384 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10386 LoadTimingInfo load_timing_info
;
10387 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10388 TestLoadTimingNotReusedWithPac(load_timing_info
,
10389 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10392 // Test a basic HTTPS GET request through a proxy.
10393 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10394 session_deps_
.proxy_service
.reset(
10395 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10396 CapturingBoundNetLog log
;
10397 session_deps_
.net_log
= log
.bound().net_log();
10398 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10400 HttpRequestInfo request
;
10401 request
.method
= "GET";
10402 request
.url
= GURL("https://www.google.com/");
10404 // Since we have proxy, should try to establish tunnel.
10405 MockWrite data_writes1
[] = {
10406 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10407 "Host: www.google.com\r\n"
10408 "Proxy-Connection: keep-alive\r\n\r\n"),
10410 MockWrite("GET / HTTP/1.1\r\n"
10411 "Host: www.google.com\r\n"
10412 "Connection: keep-alive\r\n\r\n"),
10415 MockRead data_reads1
[] = {
10416 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10418 MockRead("HTTP/1.1 200 OK\r\n"),
10419 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10420 MockRead("Content-Length: 100\r\n\r\n"),
10421 MockRead(SYNCHRONOUS
, OK
),
10424 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10425 data_writes1
, arraysize(data_writes1
));
10426 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10427 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10428 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10430 TestCompletionCallback callback1
;
10432 scoped_ptr
<HttpTransaction
> trans(
10433 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10435 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10438 rv
= callback1
.WaitForResult();
10440 net::CapturingNetLog::CapturedEntryList entries
;
10441 log
.GetEntries(&entries
);
10442 size_t pos
= ExpectLogContainsSomewhere(
10443 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10444 NetLog::PHASE_NONE
);
10445 ExpectLogContainsSomewhere(
10447 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10448 NetLog::PHASE_NONE
);
10450 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10451 ASSERT_TRUE(response
!= NULL
);
10453 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10454 EXPECT_EQ(200, response
->headers
->response_code());
10455 EXPECT_EQ(100, response
->headers
->GetContentLength());
10456 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10457 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10459 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10461 LoadTimingInfo load_timing_info
;
10462 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10463 TestLoadTimingNotReusedWithPac(load_timing_info
,
10464 CONNECT_TIMING_HAS_SSL_TIMES
);
10467 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10468 // while establishing the tunnel.
10469 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10470 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10471 CapturingBoundNetLog log
;
10472 session_deps_
.net_log
= log
.bound().net_log();
10473 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10475 HttpRequestInfo request
;
10476 request
.method
= "GET";
10477 request
.url
= GURL("https://www.google.com/");
10479 // Since we have proxy, should try to establish tunnel.
10480 MockWrite data_writes1
[] = {
10481 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10482 "Host: www.google.com\r\n"
10483 "Proxy-Connection: keep-alive\r\n\r\n"),
10485 MockWrite("GET / HTTP/1.1\r\n"
10486 "Host: www.google.com\r\n"
10487 "Connection: keep-alive\r\n\r\n"),
10490 MockRead data_reads1
[] = {
10491 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10492 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10493 MockRead(ASYNC
, 0, 0), // EOF
10496 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10497 data_writes1
, arraysize(data_writes1
));
10498 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10499 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10500 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10502 TestCompletionCallback callback1
;
10504 scoped_ptr
<HttpTransaction
> trans(
10505 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10507 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10508 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10510 rv
= callback1
.WaitForResult();
10511 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10512 net::CapturingNetLog::CapturedEntryList entries
;
10513 log
.GetEntries(&entries
);
10514 size_t pos
= ExpectLogContainsSomewhere(
10515 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10516 NetLog::PHASE_NONE
);
10517 ExpectLogContainsSomewhere(
10519 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10520 NetLog::PHASE_NONE
);
10523 // Test for crbug.com/55424.
10524 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10525 scoped_ptr
<SpdyFrame
> req(
10526 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10527 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10529 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10530 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10531 MockRead spdy_reads
[] = {
10532 CreateMockRead(*resp
),
10533 CreateMockRead(*data
),
10534 MockRead(ASYNC
, 0, 0),
10537 DelayedSocketData
spdy_data(
10538 1, // wait for one write to finish before reading.
10539 spdy_reads
, arraysize(spdy_reads
),
10540 spdy_writes
, arraysize(spdy_writes
));
10541 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10543 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10544 ssl
.SetNextProto(GetParam());
10545 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10547 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10549 // Set up an initial SpdySession in the pool to reuse.
10550 HostPortPair
host_port_pair("www.google.com", 443);
10551 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10552 PRIVACY_MODE_DISABLED
);
10553 base::WeakPtr
<SpdySession
> spdy_session
=
10554 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10556 HttpRequestInfo request
;
10557 request
.method
= "GET";
10558 request
.url
= GURL("https://www.google.com/");
10559 request
.load_flags
= 0;
10561 // This is the important line that marks this as a preconnect.
10562 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10564 scoped_ptr
<HttpTransaction
> trans(
10565 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10567 TestCompletionCallback callback
;
10568 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10569 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10570 EXPECT_EQ(OK
, callback
.WaitForResult());
10573 // Given a net error, cause that error to be returned from the first Write()
10574 // call and verify that the HttpTransaction fails with that error.
10575 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10576 int error
, IoMode mode
) {
10577 net::HttpRequestInfo request_info
;
10578 request_info
.url
= GURL("https://www.example.com/");
10579 request_info
.method
= "GET";
10580 request_info
.load_flags
= net::LOAD_NORMAL
;
10582 SSLSocketDataProvider
ssl_data(mode
, OK
);
10583 net::MockWrite data_writes
[] = {
10584 net::MockWrite(mode
, error
),
10586 net::StaticSocketDataProvider
data(NULL
, 0,
10587 data_writes
, arraysize(data_writes
));
10588 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10589 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10591 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10592 scoped_ptr
<HttpTransaction
> trans(
10593 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10595 TestCompletionCallback callback
;
10596 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10597 if (rv
== net::ERR_IO_PENDING
)
10598 rv
= callback
.WaitForResult();
10599 ASSERT_EQ(error
, rv
);
10602 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10603 // Just check a grab bag of cert errors.
10604 static const int kErrors
[] = {
10605 ERR_CERT_COMMON_NAME_INVALID
,
10606 ERR_CERT_AUTHORITY_INVALID
,
10607 ERR_CERT_DATE_INVALID
,
10609 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10610 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10611 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10615 // Ensure that a client certificate is removed from the SSL client auth
10617 // 1) No proxy is involved.
10618 // 2) TLS False Start is disabled.
10619 // 3) The initial TLS handshake requests a client certificate.
10620 // 4) The client supplies an invalid/unacceptable certificate.
10621 TEST_P(HttpNetworkTransactionTest
,
10622 ClientAuthCertCache_Direct_NoFalseStart
) {
10623 net::HttpRequestInfo request_info
;
10624 request_info
.url
= GURL("https://www.example.com/");
10625 request_info
.method
= "GET";
10626 request_info
.load_flags
= net::LOAD_NORMAL
;
10628 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10629 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10631 // [ssl_]data1 contains the data for the first SSL handshake. When a
10632 // CertificateRequest is received for the first time, the handshake will
10633 // be aborted to allow the caller to provide a certificate.
10634 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10635 ssl_data1
.cert_request_info
= cert_request
.get();
10636 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10637 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10638 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10640 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10641 // False Start is not being used, the result of the SSL handshake will be
10642 // returned as part of the SSLClientSocket::Connect() call. This test
10643 // matches the result of a server sending a handshake_failure alert,
10644 // rather than a Finished message, because it requires a client
10645 // certificate and none was supplied.
10646 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10647 ssl_data2
.cert_request_info
= cert_request
.get();
10648 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10649 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10650 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10652 // [ssl_]data3 contains the data for the third SSL handshake. When a
10653 // connection to a server fails during an SSL handshake,
10654 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10655 // connection was attempted with TLSv1.1. This is transparent to the caller
10656 // of the HttpNetworkTransaction. Because this test failure is due to
10657 // requiring a client certificate, this fallback handshake should also
10659 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10660 ssl_data3
.cert_request_info
= cert_request
.get();
10661 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10662 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10663 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10665 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10666 // connection to a server fails during an SSL handshake,
10667 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10668 // connection was attempted with TLSv1. This is transparent to the caller
10669 // of the HttpNetworkTransaction. Because this test failure is due to
10670 // requiring a client certificate, this fallback handshake should also
10672 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10673 ssl_data4
.cert_request_info
= cert_request
.get();
10674 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10675 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10676 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10678 // Need one more if TLSv1.2 is enabled.
10679 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10680 ssl_data5
.cert_request_info
= cert_request
.get();
10681 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10682 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10683 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10685 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10686 scoped_ptr
<HttpTransaction
> trans(
10687 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10689 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10690 TestCompletionCallback callback
;
10691 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10692 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10694 // Complete the SSL handshake, which should abort due to requiring a
10695 // client certificate.
10696 rv
= callback
.WaitForResult();
10697 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10699 // Indicate that no certificate should be supplied. From the perspective
10700 // of SSLClientCertCache, NULL is just as meaningful as a real
10701 // certificate, so this is the same as supply a
10702 // legitimate-but-unacceptable certificate.
10703 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10704 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10706 // Ensure the certificate was added to the client auth cache before
10707 // allowing the connection to continue restarting.
10708 scoped_refptr
<X509Certificate
> client_cert
;
10709 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10710 HostPortPair("www.example.com", 443), &client_cert
));
10711 ASSERT_EQ(NULL
, client_cert
.get());
10713 // Restart the handshake. This will consume ssl_data2, which fails, and
10714 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10715 // The result code is checked against what ssl_data4 should return.
10716 rv
= callback
.WaitForResult();
10717 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10719 // Ensure that the client certificate is removed from the cache on a
10720 // handshake failure.
10721 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10722 HostPortPair("www.example.com", 443), &client_cert
));
10725 // Ensure that a client certificate is removed from the SSL client auth
10727 // 1) No proxy is involved.
10728 // 2) TLS False Start is enabled.
10729 // 3) The initial TLS handshake requests a client certificate.
10730 // 4) The client supplies an invalid/unacceptable certificate.
10731 TEST_P(HttpNetworkTransactionTest
,
10732 ClientAuthCertCache_Direct_FalseStart
) {
10733 net::HttpRequestInfo request_info
;
10734 request_info
.url
= GURL("https://www.example.com/");
10735 request_info
.method
= "GET";
10736 request_info
.load_flags
= net::LOAD_NORMAL
;
10738 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10739 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10741 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10742 // return successfully after reading up to the peer's Certificate message.
10743 // This is to allow the caller to call SSLClientSocket::Write(), which can
10744 // enqueue application data to be sent in the same packet as the
10745 // ChangeCipherSpec and Finished messages.
10746 // The actual handshake will be finished when SSLClientSocket::Read() is
10747 // called, which expects to process the peer's ChangeCipherSpec and
10748 // Finished messages. If there was an error negotiating with the peer,
10749 // such as due to the peer requiring a client certificate when none was
10750 // supplied, the alert sent by the peer won't be processed until Read() is
10753 // Like the non-False Start case, when a client certificate is requested by
10754 // the peer, the handshake is aborted during the Connect() call.
10755 // [ssl_]data1 represents the initial SSL handshake with the peer.
10756 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10757 ssl_data1
.cert_request_info
= cert_request
.get();
10758 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10759 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10760 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10762 // When a client certificate is supplied, Connect() will not be aborted
10763 // when the peer requests the certificate. Instead, the handshake will
10764 // artificially succeed, allowing the caller to write the HTTP request to
10765 // the socket. The handshake messages are not processed until Read() is
10766 // called, which then detects that the handshake was aborted, due to the
10767 // peer sending a handshake_failure because it requires a client
10769 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10770 ssl_data2
.cert_request_info
= cert_request
.get();
10771 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10772 net::MockRead data2_reads
[] = {
10773 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10775 net::StaticSocketDataProvider
data2(
10776 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10777 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10779 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10780 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10781 // TLSv1. It has the same behaviour as [ssl_]data2.
10782 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10783 ssl_data3
.cert_request_info
= cert_request
.get();
10784 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10785 net::StaticSocketDataProvider
data3(
10786 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10787 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10789 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10790 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10791 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10792 ssl_data4
.cert_request_info
= cert_request
.get();
10793 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10794 net::StaticSocketDataProvider
data4(
10795 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10796 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10798 // Need one more if TLSv1.2 is enabled.
10799 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10800 ssl_data5
.cert_request_info
= cert_request
.get();
10801 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10802 net::StaticSocketDataProvider
data5(
10803 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10804 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10806 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10807 scoped_ptr
<HttpTransaction
> trans(
10808 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10810 // Begin the initial SSL handshake.
10811 TestCompletionCallback callback
;
10812 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10813 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10815 // Complete the SSL handshake, which should abort due to requiring a
10816 // client certificate.
10817 rv
= callback
.WaitForResult();
10818 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10820 // Indicate that no certificate should be supplied. From the perspective
10821 // of SSLClientCertCache, NULL is just as meaningful as a real
10822 // certificate, so this is the same as supply a
10823 // legitimate-but-unacceptable certificate.
10824 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10825 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10827 // Ensure the certificate was added to the client auth cache before
10828 // allowing the connection to continue restarting.
10829 scoped_refptr
<X509Certificate
> client_cert
;
10830 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10831 HostPortPair("www.example.com", 443), &client_cert
));
10832 ASSERT_EQ(NULL
, client_cert
.get());
10834 // Restart the handshake. This will consume ssl_data2, which fails, and
10835 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10836 // The result code is checked against what ssl_data4 should return.
10837 rv
= callback
.WaitForResult();
10838 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10840 // Ensure that the client certificate is removed from the cache on a
10841 // handshake failure.
10842 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10843 HostPortPair("www.example.com", 443), &client_cert
));
10846 // Ensure that a client certificate is removed from the SSL client auth
10848 // 1) An HTTPS proxy is involved.
10849 // 3) The HTTPS proxy requests a client certificate.
10850 // 4) The client supplies an invalid/unacceptable certificate for the
10852 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10853 // then for connecting to an HTTP endpoint.
10854 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10855 session_deps_
.proxy_service
.reset(
10856 ProxyService::CreateFixed("https://proxy:70"));
10857 CapturingBoundNetLog log
;
10858 session_deps_
.net_log
= log
.bound().net_log();
10860 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10861 cert_request
->host_and_port
= HostPortPair("proxy", 70);
10863 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10864 // [ssl_]data[1-3]. Rather than represending the endpoint
10865 // (www.example.com:443), they represent failures with the HTTPS proxy
10867 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10868 ssl_data1
.cert_request_info
= cert_request
.get();
10869 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10870 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10871 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10873 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10874 ssl_data2
.cert_request_info
= cert_request
.get();
10875 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10876 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10877 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10879 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10881 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10882 ssl_data3
.cert_request_info
= cert_request
.get();
10883 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10884 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10885 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10888 net::HttpRequestInfo requests
[2];
10889 requests
[0].url
= GURL("https://www.example.com/");
10890 requests
[0].method
= "GET";
10891 requests
[0].load_flags
= net::LOAD_NORMAL
;
10893 requests
[1].url
= GURL("http://www.example.com/");
10894 requests
[1].method
= "GET";
10895 requests
[1].load_flags
= net::LOAD_NORMAL
;
10897 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10898 session_deps_
.socket_factory
->ResetNextMockIndexes();
10899 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10900 scoped_ptr
<HttpNetworkTransaction
> trans(
10901 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10903 // Begin the SSL handshake with the proxy.
10904 TestCompletionCallback callback
;
10905 int rv
= trans
->Start(
10906 &requests
[i
], callback
.callback(), net::BoundNetLog());
10907 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10909 // Complete the SSL handshake, which should abort due to requiring a
10910 // client certificate.
10911 rv
= callback
.WaitForResult();
10912 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10914 // Indicate that no certificate should be supplied. From the perspective
10915 // of SSLClientCertCache, NULL is just as meaningful as a real
10916 // certificate, so this is the same as supply a
10917 // legitimate-but-unacceptable certificate.
10918 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10919 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10921 // Ensure the certificate was added to the client auth cache before
10922 // allowing the connection to continue restarting.
10923 scoped_refptr
<X509Certificate
> client_cert
;
10924 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10925 HostPortPair("proxy", 70), &client_cert
));
10926 ASSERT_EQ(NULL
, client_cert
.get());
10927 // Ensure the certificate was NOT cached for the endpoint. This only
10928 // applies to HTTPS requests, but is fine to check for HTTP requests.
10929 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10930 HostPortPair("www.example.com", 443), &client_cert
));
10932 // Restart the handshake. This will consume ssl_data2, which fails, and
10933 // then consume ssl_data3, which should also fail. The result code is
10934 // checked against what ssl_data3 should return.
10935 rv
= callback
.WaitForResult();
10936 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10938 // Now that the new handshake has failed, ensure that the client
10939 // certificate was removed from the client auth cache.
10940 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10941 HostPortPair("proxy", 70), &client_cert
));
10942 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10943 HostPortPair("www.example.com", 443), &client_cert
));
10947 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10948 // TEST_P is a macro that expands directly to code that stringizes the
10949 // arguments. As a result, macros passed as parameters (such as prefix
10950 // or test_case_name) will not be expanded by the preprocessor. To
10951 // work around this, indirect the macro for TEST_P, so that the
10952 // pre-processor will expand macros such as MAYBE_test_name before
10953 // instantiating the test.
10954 #define WRAPPED_TEST_P(test_case_name, test_name) \
10955 TEST_P(test_case_name, test_name)
10957 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10958 #if defined(OS_WIN)
10959 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10961 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10963 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10964 session_deps_
.use_alternate_protocols
= true;
10965 session_deps_
.next_protos
= SpdyNextProtos();
10967 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10968 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10969 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10970 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10971 pool_peer
.DisableDomainAuthenticationVerification();
10973 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10974 ssl
.SetNextProto(GetParam());
10975 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10977 scoped_ptr
<SpdyFrame
> host1_req(
10978 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10979 scoped_ptr
<SpdyFrame
> host2_req(
10980 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10981 MockWrite spdy_writes
[] = {
10982 CreateMockWrite(*host1_req
, 1),
10983 CreateMockWrite(*host2_req
, 4),
10985 scoped_ptr
<SpdyFrame
> host1_resp(
10986 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10987 scoped_ptr
<SpdyFrame
> host1_resp_body(
10988 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10989 scoped_ptr
<SpdyFrame
> host2_resp(
10990 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10991 scoped_ptr
<SpdyFrame
> host2_resp_body(
10992 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10993 MockRead spdy_reads
[] = {
10994 CreateMockRead(*host1_resp
, 2),
10995 CreateMockRead(*host1_resp_body
, 3),
10996 CreateMockRead(*host2_resp
, 5),
10997 CreateMockRead(*host2_resp_body
, 6),
10998 MockRead(ASYNC
, 0, 7),
11001 IPAddressNumber ip
;
11002 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11003 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11004 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11005 OrderedSocketData
spdy_data(
11007 spdy_reads
, arraysize(spdy_reads
),
11008 spdy_writes
, arraysize(spdy_writes
));
11009 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11011 TestCompletionCallback callback
;
11012 HttpRequestInfo request1
;
11013 request1
.method
= "GET";
11014 request1
.url
= GURL("https://www.google.com/");
11015 request1
.load_flags
= 0;
11016 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11018 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11019 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11020 EXPECT_EQ(OK
, callback
.WaitForResult());
11022 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11023 ASSERT_TRUE(response
!= NULL
);
11024 ASSERT_TRUE(response
->headers
.get() != NULL
);
11025 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11027 std::string response_data
;
11028 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11029 EXPECT_EQ("hello!", response_data
);
11031 // Preload www.gmail.com into HostCache.
11032 HostPortPair
host_port("www.gmail.com", 443);
11033 HostResolver::RequestInfo
resolve_info(host_port
);
11034 AddressList ignored
;
11035 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11038 callback
.callback(),
11041 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11042 rv
= callback
.WaitForResult();
11045 HttpRequestInfo request2
;
11046 request2
.method
= "GET";
11047 request2
.url
= GURL("https://www.gmail.com/");
11048 request2
.load_flags
= 0;
11049 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11051 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11053 EXPECT_EQ(OK
, callback
.WaitForResult());
11055 response
= trans2
.GetResponseInfo();
11056 ASSERT_TRUE(response
!= NULL
);
11057 ASSERT_TRUE(response
->headers
.get() != NULL
);
11058 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11059 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11060 EXPECT_TRUE(response
->was_npn_negotiated
);
11061 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11062 EXPECT_EQ("hello!", response_data
);
11064 #undef MAYBE_UseIPConnectionPooling
11066 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11067 session_deps_
.use_alternate_protocols
= true;
11068 session_deps_
.next_protos
= SpdyNextProtos();
11070 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11071 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11072 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11073 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11074 pool_peer
.DisableDomainAuthenticationVerification();
11076 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11077 ssl
.SetNextProto(GetParam());
11078 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11080 scoped_ptr
<SpdyFrame
> host1_req(
11081 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11082 scoped_ptr
<SpdyFrame
> host2_req(
11083 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11084 MockWrite spdy_writes
[] = {
11085 CreateMockWrite(*host1_req
, 1),
11086 CreateMockWrite(*host2_req
, 4),
11088 scoped_ptr
<SpdyFrame
> host1_resp(
11089 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11090 scoped_ptr
<SpdyFrame
> host1_resp_body(
11091 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11092 scoped_ptr
<SpdyFrame
> host2_resp(
11093 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11094 scoped_ptr
<SpdyFrame
> host2_resp_body(
11095 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11096 MockRead spdy_reads
[] = {
11097 CreateMockRead(*host1_resp
, 2),
11098 CreateMockRead(*host1_resp_body
, 3),
11099 CreateMockRead(*host2_resp
, 5),
11100 CreateMockRead(*host2_resp_body
, 6),
11101 MockRead(ASYNC
, 0, 7),
11104 IPAddressNumber ip
;
11105 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11106 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11107 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11108 OrderedSocketData
spdy_data(
11110 spdy_reads
, arraysize(spdy_reads
),
11111 spdy_writes
, arraysize(spdy_writes
));
11112 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11114 TestCompletionCallback callback
;
11115 HttpRequestInfo request1
;
11116 request1
.method
= "GET";
11117 request1
.url
= GURL("https://www.google.com/");
11118 request1
.load_flags
= 0;
11119 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11121 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11122 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11123 EXPECT_EQ(OK
, callback
.WaitForResult());
11125 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11126 ASSERT_TRUE(response
!= NULL
);
11127 ASSERT_TRUE(response
->headers
.get() != NULL
);
11128 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11130 std::string response_data
;
11131 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11132 EXPECT_EQ("hello!", response_data
);
11134 HttpRequestInfo request2
;
11135 request2
.method
= "GET";
11136 request2
.url
= GURL("https://www.gmail.com/");
11137 request2
.load_flags
= 0;
11138 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11140 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11141 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11142 EXPECT_EQ(OK
, callback
.WaitForResult());
11144 response
= trans2
.GetResponseInfo();
11145 ASSERT_TRUE(response
!= NULL
);
11146 ASSERT_TRUE(response
->headers
.get() != NULL
);
11147 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11148 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11149 EXPECT_TRUE(response
->was_npn_negotiated
);
11150 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11151 EXPECT_EQ("hello!", response_data
);
11154 class OneTimeCachingHostResolver
: public net::HostResolver
{
11156 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11157 : host_port_(host_port
) {}
11158 virtual ~OneTimeCachingHostResolver() {}
11160 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11162 // HostResolver methods:
11163 virtual int Resolve(const RequestInfo
& info
,
11164 RequestPriority priority
,
11165 AddressList
* addresses
,
11166 const CompletionCallback
& callback
,
11167 RequestHandle
* out_req
,
11168 const BoundNetLog
& net_log
) OVERRIDE
{
11169 return host_resolver_
.Resolve(
11170 info
, priority
, addresses
, callback
, out_req
, net_log
);
11173 virtual int ResolveFromCache(const RequestInfo
& info
,
11174 AddressList
* addresses
,
11175 const BoundNetLog
& net_log
) OVERRIDE
{
11176 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11177 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11178 host_resolver_
.GetHostCache()->clear();
11182 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
11183 host_resolver_
.CancelRequest(req
);
11186 MockCachingHostResolver
* GetMockHostResolver() {
11187 return &host_resolver_
;
11191 MockCachingHostResolver host_resolver_
;
11192 const HostPortPair host_port_
;
11195 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11196 #if defined(OS_WIN)
11197 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11198 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11200 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11201 UseIPConnectionPoolingWithHostCacheExpiration
11203 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11204 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11205 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11206 // prefix doesn't work with parametrized tests).
11207 #if defined(OS_WIN)
11210 session_deps_
.use_alternate_protocols
= true;
11211 session_deps_
.next_protos
= SpdyNextProtos();
11213 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11214 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11215 HttpNetworkSession::Params params
=
11216 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11217 params
.host_resolver
= &host_resolver
;
11218 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11219 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11220 pool_peer
.DisableDomainAuthenticationVerification();
11222 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11223 ssl
.SetNextProto(GetParam());
11224 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11226 scoped_ptr
<SpdyFrame
> host1_req(
11227 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11228 scoped_ptr
<SpdyFrame
> host2_req(
11229 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11230 MockWrite spdy_writes
[] = {
11231 CreateMockWrite(*host1_req
, 1),
11232 CreateMockWrite(*host2_req
, 4),
11234 scoped_ptr
<SpdyFrame
> host1_resp(
11235 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11236 scoped_ptr
<SpdyFrame
> host1_resp_body(
11237 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11238 scoped_ptr
<SpdyFrame
> host2_resp(
11239 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11240 scoped_ptr
<SpdyFrame
> host2_resp_body(
11241 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11242 MockRead spdy_reads
[] = {
11243 CreateMockRead(*host1_resp
, 2),
11244 CreateMockRead(*host1_resp_body
, 3),
11245 CreateMockRead(*host2_resp
, 5),
11246 CreateMockRead(*host2_resp_body
, 6),
11247 MockRead(ASYNC
, 0, 7),
11250 IPAddressNumber ip
;
11251 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11252 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11253 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11254 OrderedSocketData
spdy_data(
11256 spdy_reads
, arraysize(spdy_reads
),
11257 spdy_writes
, arraysize(spdy_writes
));
11258 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11260 TestCompletionCallback callback
;
11261 HttpRequestInfo request1
;
11262 request1
.method
= "GET";
11263 request1
.url
= GURL("https://www.google.com/");
11264 request1
.load_flags
= 0;
11265 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11267 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11268 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11269 EXPECT_EQ(OK
, callback
.WaitForResult());
11271 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11272 ASSERT_TRUE(response
!= NULL
);
11273 ASSERT_TRUE(response
->headers
.get() != NULL
);
11274 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11276 std::string response_data
;
11277 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11278 EXPECT_EQ("hello!", response_data
);
11280 // Preload cache entries into HostCache.
11281 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11282 AddressList ignored
;
11283 rv
= host_resolver
.Resolve(resolve_info
,
11286 callback
.callback(),
11289 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11290 rv
= callback
.WaitForResult();
11293 HttpRequestInfo request2
;
11294 request2
.method
= "GET";
11295 request2
.url
= GURL("https://www.gmail.com/");
11296 request2
.load_flags
= 0;
11297 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11299 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11300 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11301 EXPECT_EQ(OK
, callback
.WaitForResult());
11303 response
= trans2
.GetResponseInfo();
11304 ASSERT_TRUE(response
!= NULL
);
11305 ASSERT_TRUE(response
->headers
.get() != NULL
);
11306 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11307 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11308 EXPECT_TRUE(response
->was_npn_negotiated
);
11309 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11310 EXPECT_EQ("hello!", response_data
);
11313 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11315 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11316 const std::string https_url
= "https://www.google.com/";
11317 const std::string http_url
= "http://www.google.com:443/";
11319 // SPDY GET for HTTPS URL
11320 scoped_ptr
<SpdyFrame
> req1(
11321 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11323 MockWrite writes1
[] = {
11324 CreateMockWrite(*req1
, 0),
11327 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11328 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11329 MockRead reads1
[] = {
11330 CreateMockRead(*resp1
, 1),
11331 CreateMockRead(*body1
, 2),
11332 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11335 DelayedSocketData
data1(
11336 1, reads1
, arraysize(reads1
),
11337 writes1
, arraysize(writes1
));
11338 MockConnect
connect_data1(ASYNC
, OK
);
11339 data1
.set_connect_data(connect_data1
);
11341 // HTTP GET for the HTTP URL
11342 MockWrite writes2
[] = {
11343 MockWrite(ASYNC
, 4,
11344 "GET / HTTP/1.1\r\n"
11345 "Host: www.google.com:443\r\n"
11346 "Connection: keep-alive\r\n\r\n"),
11349 MockRead reads2
[] = {
11350 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11351 MockRead(ASYNC
, 6, "hello"),
11352 MockRead(ASYNC
, 7, OK
),
11355 DelayedSocketData
data2(
11356 1, reads2
, arraysize(reads2
),
11357 writes2
, arraysize(writes2
));
11359 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11360 ssl
.SetNextProto(GetParam());
11361 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11362 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11363 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11365 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11367 // Start the first transaction to set up the SpdySession
11368 HttpRequestInfo request1
;
11369 request1
.method
= "GET";
11370 request1
.url
= GURL(https_url
);
11371 request1
.load_flags
= 0;
11372 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11373 TestCompletionCallback callback1
;
11374 EXPECT_EQ(ERR_IO_PENDING
,
11375 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11376 base::MessageLoop::current()->RunUntilIdle();
11378 EXPECT_EQ(OK
, callback1
.WaitForResult());
11379 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11381 // Now, start the HTTP request
11382 HttpRequestInfo request2
;
11383 request2
.method
= "GET";
11384 request2
.url
= GURL(http_url
);
11385 request2
.load_flags
= 0;
11386 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11387 TestCompletionCallback callback2
;
11388 EXPECT_EQ(ERR_IO_PENDING
,
11389 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11390 base::MessageLoop::current()->RunUntilIdle();
11392 EXPECT_EQ(OK
, callback2
.WaitForResult());
11393 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11396 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11397 const std::string https_url
= "https://www.google.com/";
11398 const std::string http_url
= "http://www.google.com:443/";
11400 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11401 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
11403 scoped_ptr
<SpdyFrame
> req1(
11404 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11405 scoped_ptr
<SpdyFrame
> wrapped_req1(
11406 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11408 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11409 SpdyHeaderBlock req2_block
;
11410 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11411 req2_block
[spdy_util_
.GetPathKey()] =
11412 spdy_util_
.is_spdy2() ? http_url
.c_str() : "/";
11413 req2_block
[spdy_util_
.GetHostKey()] = "www.google.com:443";
11414 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11415 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11416 scoped_ptr
<SpdyFrame
> req2(
11417 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11419 MockWrite writes1
[] = {
11420 CreateMockWrite(*connect
, 0),
11421 CreateMockWrite(*wrapped_req1
, 2),
11422 CreateMockWrite(*req2
, 5),
11425 scoped_ptr
<SpdyFrame
> conn_resp(
11426 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11427 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11428 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11429 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11430 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11431 scoped_ptr
<SpdyFrame
> wrapped_body1(
11432 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11433 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11434 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11435 MockRead reads1
[] = {
11436 CreateMockRead(*conn_resp
, 1),
11437 CreateMockRead(*wrapped_resp1
, 3),
11438 CreateMockRead(*wrapped_body1
, 4),
11439 CreateMockRead(*resp2
, 6),
11440 CreateMockRead(*body2
, 7),
11441 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11444 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11445 writes1
, arraysize(writes1
));
11446 MockConnect
connect_data1(ASYNC
, OK
);
11447 data1
.set_connect_data(connect_data1
);
11449 session_deps_
.proxy_service
.reset(
11450 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11451 CapturingNetLog log
;
11452 session_deps_
.net_log
= &log
;
11453 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11454 ssl1
.SetNextProto(GetParam());
11455 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11456 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11457 ssl2
.SetNextProto(GetParam());
11458 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11459 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11461 scoped_refptr
<HttpNetworkSession
> session(
11462 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11464 // Start the first transaction to set up the SpdySession
11465 HttpRequestInfo request1
;
11466 request1
.method
= "GET";
11467 request1
.url
= GURL(https_url
);
11468 request1
.load_flags
= 0;
11469 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11470 TestCompletionCallback callback1
;
11471 EXPECT_EQ(ERR_IO_PENDING
,
11472 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11473 base::MessageLoop::current()->RunUntilIdle();
11476 EXPECT_EQ(OK
, callback1
.WaitForResult());
11477 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11479 LoadTimingInfo load_timing_info1
;
11480 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11481 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11482 CONNECT_TIMING_HAS_SSL_TIMES
);
11484 // Now, start the HTTP request
11485 HttpRequestInfo request2
;
11486 request2
.method
= "GET";
11487 request2
.url
= GURL(http_url
);
11488 request2
.load_flags
= 0;
11489 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11490 TestCompletionCallback callback2
;
11491 EXPECT_EQ(ERR_IO_PENDING
,
11492 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11493 base::MessageLoop::current()->RunUntilIdle();
11496 EXPECT_EQ(OK
, callback2
.WaitForResult());
11497 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11499 LoadTimingInfo load_timing_info2
;
11500 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11501 // The established SPDY sessions is considered reused by the HTTP request.
11502 TestLoadTimingReusedWithPac(load_timing_info2
);
11503 // HTTP requests over a SPDY session should have a different connection
11504 // socket_log_id than requests over a tunnel.
11505 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11508 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11509 session_deps_
.force_spdy_always
= true;
11510 const std::string https_url
= "https://www.google.com/";
11511 const std::string http_url
= "http://www.google.com:443/";
11513 // SPDY GET for HTTPS URL
11514 scoped_ptr
<SpdyFrame
> req1(
11515 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11516 // SPDY GET for the HTTP URL
11517 scoped_ptr
<SpdyFrame
> req2(
11518 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11520 MockWrite writes
[] = {
11521 CreateMockWrite(*req1
, 1),
11522 CreateMockWrite(*req2
, 4),
11525 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11526 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11527 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11528 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11529 MockRead reads
[] = {
11530 CreateMockRead(*resp1
, 2),
11531 CreateMockRead(*body1
, 3),
11532 CreateMockRead(*resp2
, 5),
11533 CreateMockRead(*body2
, 6),
11534 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11537 OrderedSocketData
data(reads
, arraysize(reads
),
11538 writes
, arraysize(writes
));
11540 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11541 ssl
.SetNextProto(GetParam());
11542 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11543 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11545 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11547 // Start the first transaction to set up the SpdySession
11548 HttpRequestInfo request1
;
11549 request1
.method
= "GET";
11550 request1
.url
= GURL(https_url
);
11551 request1
.load_flags
= 0;
11552 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11553 TestCompletionCallback callback1
;
11554 EXPECT_EQ(ERR_IO_PENDING
,
11555 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11556 base::MessageLoop::current()->RunUntilIdle();
11558 EXPECT_EQ(OK
, callback1
.WaitForResult());
11559 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11561 // Now, start the HTTP request
11562 HttpRequestInfo request2
;
11563 request2
.method
= "GET";
11564 request2
.url
= GURL(http_url
);
11565 request2
.load_flags
= 0;
11566 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11567 TestCompletionCallback callback2
;
11568 EXPECT_EQ(ERR_IO_PENDING
,
11569 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11570 base::MessageLoop::current()->RunUntilIdle();
11572 EXPECT_EQ(OK
, callback2
.WaitForResult());
11573 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11576 // Test that in the case where we have a SPDY session to a SPDY proxy
11577 // that we do not pool other origins that resolve to the same IP when
11578 // the certificate does not match the new origin.
11579 // http://crbug.com/134690
11580 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11581 const std::string url1
= "http://www.google.com/";
11582 const std::string url2
= "https://mail.google.com/";
11583 const std::string ip_addr
= "1.2.3.4";
11585 // SPDY GET for HTTP URL (through SPDY proxy)
11586 scoped_ptr
<SpdyHeaderBlock
> headers(
11587 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11588 scoped_ptr
<SpdyFrame
> req1(
11589 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
11591 MockWrite writes1
[] = {
11592 CreateMockWrite(*req1
, 0),
11595 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11596 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11597 MockRead reads1
[] = {
11598 CreateMockRead(*resp1
, 1),
11599 CreateMockRead(*body1
, 2),
11600 MockRead(ASYNC
, OK
, 3) // EOF
11603 scoped_ptr
<DeterministicSocketData
> data1(
11604 new DeterministicSocketData(reads1
, arraysize(reads1
),
11605 writes1
, arraysize(writes1
)));
11606 IPAddressNumber ip
;
11607 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11608 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11609 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11610 data1
->set_connect_data(connect_data1
);
11612 // SPDY GET for HTTPS URL (direct)
11613 scoped_ptr
<SpdyFrame
> req2(
11614 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11616 MockWrite writes2
[] = {
11617 CreateMockWrite(*req2
, 0),
11620 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11621 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11622 MockRead reads2
[] = {
11623 CreateMockRead(*resp2
, 1),
11624 CreateMockRead(*body2
, 2),
11625 MockRead(ASYNC
, OK
, 3) // EOF
11628 scoped_ptr
<DeterministicSocketData
> data2(
11629 new DeterministicSocketData(reads2
, arraysize(reads2
),
11630 writes2
, arraysize(writes2
)));
11631 MockConnect
connect_data2(ASYNC
, OK
);
11632 data2
->set_connect_data(connect_data2
);
11634 // Set up a proxy config that sends HTTP requests to a proxy, and
11635 // all others direct.
11636 ProxyConfig proxy_config
;
11637 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11638 CapturingProxyResolver
* capturing_proxy_resolver
=
11639 new CapturingProxyResolver();
11640 session_deps_
.proxy_service
.reset(new ProxyService(
11641 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11644 // Load a valid cert. Note, that this does not need to
11645 // be valid for proxy because the MockSSLClientSocket does
11646 // not actually verify it. But SpdySession will use this
11647 // to see if it is valid for the new origin
11648 base::FilePath certs_dir
= GetTestCertsDirectory();
11649 scoped_refptr
<X509Certificate
> server_cert(
11650 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11651 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
.get());
11653 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11654 ssl1
.SetNextProto(GetParam());
11655 ssl1
.cert
= server_cert
;
11656 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11657 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11660 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11661 ssl2
.SetNextProto(GetParam());
11662 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11663 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11666 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11667 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11668 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11670 scoped_refptr
<HttpNetworkSession
> session(
11671 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11673 // Start the first transaction to set up the SpdySession
11674 HttpRequestInfo request1
;
11675 request1
.method
= "GET";
11676 request1
.url
= GURL(url1
);
11677 request1
.load_flags
= 0;
11678 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11679 TestCompletionCallback callback1
;
11680 ASSERT_EQ(ERR_IO_PENDING
,
11681 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11684 ASSERT_TRUE(callback1
.have_result());
11685 EXPECT_EQ(OK
, callback1
.WaitForResult());
11686 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11688 // Now, start the HTTP request
11689 HttpRequestInfo request2
;
11690 request2
.method
= "GET";
11691 request2
.url
= GURL(url2
);
11692 request2
.load_flags
= 0;
11693 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11694 TestCompletionCallback callback2
;
11695 EXPECT_EQ(ERR_IO_PENDING
,
11696 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11697 base::MessageLoop::current()->RunUntilIdle();
11700 ASSERT_TRUE(callback2
.have_result());
11701 EXPECT_EQ(OK
, callback2
.WaitForResult());
11702 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11705 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11706 // error) in SPDY session, removes the socket from pool and closes the SPDY
11707 // session. Verify that new url's from the same HttpNetworkSession (and a new
11708 // SpdySession) do work. http://crbug.com/224701
11709 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11710 const std::string https_url
= "https://www.google.com/";
11712 MockRead reads1
[] = {
11713 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11716 scoped_ptr
<DeterministicSocketData
> data1(
11717 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11720 scoped_ptr
<SpdyFrame
> req2(
11721 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11722 MockWrite writes2
[] = {
11723 CreateMockWrite(*req2
, 0),
11726 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11727 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11728 MockRead reads2
[] = {
11729 CreateMockRead(*resp2
, 1),
11730 CreateMockRead(*body2
, 2),
11731 MockRead(ASYNC
, OK
, 3) // EOF
11734 scoped_ptr
<DeterministicSocketData
> data2(
11735 new DeterministicSocketData(reads2
, arraysize(reads2
),
11736 writes2
, arraysize(writes2
)));
11738 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11739 ssl1
.SetNextProto(GetParam());
11740 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11741 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11744 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11745 ssl2
.SetNextProto(GetParam());
11746 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11747 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11750 scoped_refptr
<HttpNetworkSession
> session(
11751 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11753 // Start the first transaction to set up the SpdySession and verify that
11754 // connection was closed.
11755 HttpRequestInfo request1
;
11756 request1
.method
= "GET";
11757 request1
.url
= GURL(https_url
);
11758 request1
.load_flags
= 0;
11759 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11760 TestCompletionCallback callback1
;
11761 EXPECT_EQ(ERR_IO_PENDING
,
11762 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11763 base::MessageLoop::current()->RunUntilIdle();
11764 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11766 // Now, start the second request and make sure it succeeds.
11767 HttpRequestInfo request2
;
11768 request2
.method
= "GET";
11769 request2
.url
= GURL(https_url
);
11770 request2
.load_flags
= 0;
11771 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11772 TestCompletionCallback callback2
;
11773 EXPECT_EQ(ERR_IO_PENDING
,
11774 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11775 base::MessageLoop::current()->RunUntilIdle();
11778 ASSERT_TRUE(callback2
.have_result());
11779 EXPECT_EQ(OK
, callback2
.WaitForResult());
11780 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11783 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11784 session_deps_
.next_protos
= SpdyNextProtos();
11785 ClientSocketPoolManager::set_max_sockets_per_group(
11786 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11787 ClientSocketPoolManager::set_max_sockets_per_pool(
11788 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11790 // Use two different hosts with different IPs so they don't get pooled.
11791 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11792 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11793 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11795 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11796 ssl1
.SetNextProto(GetParam());
11797 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11798 ssl2
.SetNextProto(GetParam());
11799 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11800 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11802 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11803 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11804 MockWrite spdy1_writes
[] = {
11805 CreateMockWrite(*host1_req
, 1),
11807 scoped_ptr
<SpdyFrame
> host1_resp(
11808 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11809 scoped_ptr
<SpdyFrame
> host1_resp_body(
11810 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11811 MockRead spdy1_reads
[] = {
11812 CreateMockRead(*host1_resp
, 2),
11813 CreateMockRead(*host1_resp_body
, 3),
11814 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11817 scoped_ptr
<OrderedSocketData
> spdy1_data(
11818 new OrderedSocketData(
11819 spdy1_reads
, arraysize(spdy1_reads
),
11820 spdy1_writes
, arraysize(spdy1_writes
)));
11821 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11823 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11824 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11825 MockWrite spdy2_writes
[] = {
11826 CreateMockWrite(*host2_req
, 1),
11828 scoped_ptr
<SpdyFrame
> host2_resp(
11829 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11830 scoped_ptr
<SpdyFrame
> host2_resp_body(
11831 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11832 MockRead spdy2_reads
[] = {
11833 CreateMockRead(*host2_resp
, 2),
11834 CreateMockRead(*host2_resp_body
, 3),
11835 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11838 scoped_ptr
<OrderedSocketData
> spdy2_data(
11839 new OrderedSocketData(
11840 spdy2_reads
, arraysize(spdy2_reads
),
11841 spdy2_writes
, arraysize(spdy2_writes
)));
11842 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11844 MockWrite http_write
[] = {
11845 MockWrite("GET / HTTP/1.1\r\n"
11846 "Host: www.a.com\r\n"
11847 "Connection: keep-alive\r\n\r\n"),
11850 MockRead http_read
[] = {
11851 MockRead("HTTP/1.1 200 OK\r\n"),
11852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11853 MockRead("Content-Length: 6\r\n\r\n"),
11854 MockRead("hello!"),
11856 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11857 http_write
, arraysize(http_write
));
11858 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11860 HostPortPair
host_port_pair_a("www.a.com", 443);
11861 SpdySessionKey
spdy_session_key_a(
11862 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11864 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11866 TestCompletionCallback callback
;
11867 HttpRequestInfo request1
;
11868 request1
.method
= "GET";
11869 request1
.url
= GURL("https://www.a.com/");
11870 request1
.load_flags
= 0;
11871 scoped_ptr
<HttpNetworkTransaction
> trans(
11872 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11874 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11875 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11876 EXPECT_EQ(OK
, callback
.WaitForResult());
11878 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11879 ASSERT_TRUE(response
!= NULL
);
11880 ASSERT_TRUE(response
->headers
.get() != NULL
);
11881 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11882 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11883 EXPECT_TRUE(response
->was_npn_negotiated
);
11885 std::string response_data
;
11886 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11887 EXPECT_EQ("hello!", response_data
);
11890 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11892 HostPortPair
host_port_pair_b("www.b.com", 443);
11893 SpdySessionKey
spdy_session_key_b(
11894 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11896 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11897 HttpRequestInfo request2
;
11898 request2
.method
= "GET";
11899 request2
.url
= GURL("https://www.b.com/");
11900 request2
.load_flags
= 0;
11901 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11903 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11904 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11905 EXPECT_EQ(OK
, callback
.WaitForResult());
11907 response
= trans
->GetResponseInfo();
11908 ASSERT_TRUE(response
!= NULL
);
11909 ASSERT_TRUE(response
->headers
.get() != NULL
);
11910 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11911 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11912 EXPECT_TRUE(response
->was_npn_negotiated
);
11913 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11914 EXPECT_EQ("hello!", response_data
);
11916 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11918 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11920 HostPortPair
host_port_pair_a1("www.a.com", 80);
11921 SpdySessionKey
spdy_session_key_a1(
11922 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11924 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11925 HttpRequestInfo request3
;
11926 request3
.method
= "GET";
11927 request3
.url
= GURL("http://www.a.com/");
11928 request3
.load_flags
= 0;
11929 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11931 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11932 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11933 EXPECT_EQ(OK
, callback
.WaitForResult());
11935 response
= trans
->GetResponseInfo();
11936 ASSERT_TRUE(response
!= NULL
);
11937 ASSERT_TRUE(response
->headers
.get() != NULL
);
11938 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11939 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11940 EXPECT_FALSE(response
->was_npn_negotiated
);
11941 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11942 EXPECT_EQ("hello!", response_data
);
11944 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11946 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11949 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11950 HttpRequestInfo request
;
11951 request
.method
= "GET";
11952 request
.url
= GURL("http://www.google.com/");
11953 request
.load_flags
= 0;
11955 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11956 scoped_ptr
<HttpTransaction
> trans(
11957 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11959 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11960 StaticSocketDataProvider data
;
11961 data
.set_connect_data(mock_connect
);
11962 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11964 TestCompletionCallback callback
;
11966 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11967 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11969 rv
= callback
.WaitForResult();
11970 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11972 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11974 // We don't care whether this succeeds or fails, but it shouldn't crash.
11975 HttpRequestHeaders request_headers
;
11976 trans
->GetFullRequestHeaders(&request_headers
);
11979 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11980 HttpRequestInfo request
;
11981 request
.method
= "GET";
11982 request
.url
= GURL("http://www.google.com/");
11983 request
.load_flags
= 0;
11985 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11986 scoped_ptr
<HttpTransaction
> trans(
11987 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11989 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11990 StaticSocketDataProvider data
;
11991 data
.set_connect_data(mock_connect
);
11992 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11994 TestCompletionCallback callback
;
11996 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11997 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11999 rv
= callback
.WaitForResult();
12000 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12002 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12004 // We don't care whether this succeeds or fails, but it shouldn't crash.
12005 HttpRequestHeaders request_headers
;
12006 trans
->GetFullRequestHeaders(&request_headers
);
12009 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12010 HttpRequestInfo request
;
12011 request
.method
= "GET";
12012 request
.url
= GURL("http://www.google.com/");
12013 request
.load_flags
= 0;
12015 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12016 scoped_ptr
<HttpTransaction
> trans(
12017 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12019 MockWrite data_writes
[] = {
12020 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12022 MockRead data_reads
[] = {
12023 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12026 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12027 data_writes
, arraysize(data_writes
));
12028 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12030 TestCompletionCallback callback
;
12032 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12033 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12035 rv
= callback
.WaitForResult();
12036 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12038 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12040 HttpRequestHeaders request_headers
;
12041 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12042 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12045 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12046 HttpRequestInfo request
;
12047 request
.method
= "GET";
12048 request
.url
= GURL("http://www.google.com/");
12049 request
.load_flags
= 0;
12051 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12052 scoped_ptr
<HttpTransaction
> trans(
12053 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12055 MockWrite data_writes
[] = {
12056 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12058 MockRead data_reads
[] = {
12059 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12062 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12063 data_writes
, arraysize(data_writes
));
12064 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12066 TestCompletionCallback callback
;
12068 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12071 rv
= callback
.WaitForResult();
12072 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12074 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12076 HttpRequestHeaders request_headers
;
12077 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12078 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12081 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12082 HttpRequestInfo request
;
12083 request
.method
= "GET";
12084 request
.url
= GURL("http://www.google.com/");
12085 request
.load_flags
= 0;
12087 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12088 scoped_ptr
<HttpTransaction
> trans(
12089 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12091 MockWrite data_writes
[] = {
12092 MockWrite("GET / HTTP/1.1\r\n"
12093 "Host: www.google.com\r\n"
12094 "Connection: keep-alive\r\n\r\n"),
12096 MockRead data_reads
[] = {
12097 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12100 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12101 data_writes
, arraysize(data_writes
));
12102 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12104 TestCompletionCallback callback
;
12106 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12107 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12109 rv
= callback
.WaitForResult();
12110 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12112 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12114 HttpRequestHeaders request_headers
;
12115 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12116 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12119 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12120 HttpRequestInfo request
;
12121 request
.method
= "GET";
12122 request
.url
= GURL("http://www.google.com/");
12123 request
.load_flags
= 0;
12125 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12126 scoped_ptr
<HttpTransaction
> trans(
12127 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12129 MockWrite data_writes
[] = {
12130 MockWrite("GET / HTTP/1.1\r\n"
12131 "Host: www.google.com\r\n"
12132 "Connection: keep-alive\r\n\r\n"),
12134 MockRead data_reads
[] = {
12135 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12138 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12139 data_writes
, arraysize(data_writes
));
12140 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12142 TestCompletionCallback callback
;
12144 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12145 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12147 rv
= callback
.WaitForResult();
12148 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12150 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12152 HttpRequestHeaders request_headers
;
12153 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12154 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12157 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12158 HttpRequestInfo request
;
12159 request
.method
= "GET";
12160 request
.url
= GURL("http://www.google.com/");
12161 request
.load_flags
= 0;
12162 request
.extra_headers
.SetHeader("X-Foo", "bar");
12164 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12165 scoped_ptr
<HttpTransaction
> trans(
12166 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12168 MockWrite data_writes
[] = {
12169 MockWrite("GET / HTTP/1.1\r\n"
12170 "Host: www.google.com\r\n"
12171 "Connection: keep-alive\r\n"
12172 "X-Foo: bar\r\n\r\n"),
12174 MockRead data_reads
[] = {
12175 MockRead("HTTP/1.1 200 OK\r\n"
12176 "Content-Length: 5\r\n\r\n"
12178 MockRead(ASYNC
, ERR_UNEXPECTED
),
12181 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12182 data_writes
, arraysize(data_writes
));
12183 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12185 TestCompletionCallback callback
;
12187 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12188 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12190 rv
= callback
.WaitForResult();
12193 HttpRequestHeaders request_headers
;
12194 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12196 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12197 EXPECT_EQ("bar", foo
);
12202 // Fake HttpStreamBase that simply records calls to SetPriority().
12203 class FakeStream
: public HttpStreamBase
,
12204 public base::SupportsWeakPtr
<FakeStream
> {
12206 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12207 virtual ~FakeStream() {}
12209 RequestPriority
priority() const { return priority_
; }
12211 virtual int InitializeStream(const HttpRequestInfo
* request_info
,
12212 RequestPriority priority
,
12213 const BoundNetLog
& net_log
,
12214 const CompletionCallback
& callback
) OVERRIDE
{
12215 return ERR_IO_PENDING
;
12218 virtual int SendRequest(const HttpRequestHeaders
& request_headers
,
12219 HttpResponseInfo
* response
,
12220 const CompletionCallback
& callback
) OVERRIDE
{
12222 return ERR_UNEXPECTED
;
12225 virtual int ReadResponseHeaders(const CompletionCallback
& callback
) OVERRIDE
{
12227 return ERR_UNEXPECTED
;
12230 virtual int ReadResponseBody(IOBuffer
* buf
, int buf_len
,
12231 const CompletionCallback
& callback
) OVERRIDE
{
12233 return ERR_UNEXPECTED
;
12236 virtual void Close(bool not_reusable
) OVERRIDE
{}
12238 virtual bool IsResponseBodyComplete() const OVERRIDE
{
12243 virtual bool CanFindEndOfResponse() const OVERRIDE
{
12247 virtual bool IsConnectionReused() const OVERRIDE
{
12252 virtual void SetConnectionReused() OVERRIDE
{
12256 virtual bool IsConnectionReusable() const OVERRIDE
{
12261 virtual int64
GetTotalReceivedBytes() const OVERRIDE
{
12266 virtual bool GetLoadTimingInfo(
12267 LoadTimingInfo
* load_timing_info
) const OVERRIDE
{
12272 virtual void GetSSLInfo(SSLInfo
* ssl_info
) OVERRIDE
{
12276 virtual void GetSSLCertRequestInfo(
12277 SSLCertRequestInfo
* cert_request_info
) OVERRIDE
{
12281 virtual bool IsSpdyHttpStream() const OVERRIDE
{
12286 virtual void Drain(HttpNetworkSession
* session
) OVERRIDE
{
12290 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12291 priority_
= priority
;
12295 RequestPriority priority_
;
12297 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12300 // Fake HttpStreamRequest that simply records calls to SetPriority()
12301 // and vends FakeStreams with its current priority.
12302 class FakeStreamRequest
: public HttpStreamRequest
,
12303 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12305 FakeStreamRequest(RequestPriority priority
,
12306 HttpStreamRequest::Delegate
* delegate
)
12307 : priority_(priority
),
12308 delegate_(delegate
),
12309 websocket_stream_create_helper_(NULL
) {}
12311 FakeStreamRequest(RequestPriority priority
,
12312 HttpStreamRequest::Delegate
* delegate
,
12313 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12314 : priority_(priority
),
12315 delegate_(delegate
),
12316 websocket_stream_create_helper_(create_helper
) {}
12318 virtual ~FakeStreamRequest() {}
12320 RequestPriority
priority() const { return priority_
; }
12322 const WebSocketHandshakeStreamBase::CreateHelper
*
12323 websocket_stream_create_helper() const {
12324 return websocket_stream_create_helper_
;
12327 // Create a new FakeStream and pass it to the request's
12328 // delegate. Returns a weak pointer to the FakeStream.
12329 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12330 FakeStream
* fake_stream
= new FakeStream(priority_
);
12331 // Do this before calling OnStreamReady() as OnStreamReady() may
12332 // immediately delete |fake_stream|.
12333 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12334 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12335 return weak_stream
;
12338 virtual int RestartTunnelWithProxyAuth(
12339 const AuthCredentials
& credentials
) OVERRIDE
{
12341 return ERR_UNEXPECTED
;
12344 virtual LoadState
GetLoadState() const OVERRIDE
{
12346 return LoadState();
12349 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12350 priority_
= priority
;
12353 virtual bool was_npn_negotiated() const OVERRIDE
{
12357 virtual NextProto
protocol_negotiated() const OVERRIDE
{
12358 return kProtoUnknown
;
12361 virtual bool using_spdy() const OVERRIDE
{
12366 RequestPriority priority_
;
12367 HttpStreamRequest::Delegate
* const delegate_
;
12368 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12370 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12373 // Fake HttpStreamFactory that vends FakeStreamRequests.
12374 class FakeStreamFactory
: public HttpStreamFactory
{
12376 FakeStreamFactory() {}
12377 virtual ~FakeStreamFactory() {}
12379 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12380 // RequestStream() (which may be NULL if it was destroyed already).
12381 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12382 return last_stream_request_
;
12385 virtual HttpStreamRequest
* RequestStream(
12386 const HttpRequestInfo
& info
,
12387 RequestPriority priority
,
12388 const SSLConfig
& server_ssl_config
,
12389 const SSLConfig
& proxy_ssl_config
,
12390 HttpStreamRequest::Delegate
* delegate
,
12391 const BoundNetLog
& net_log
) OVERRIDE
{
12392 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12393 last_stream_request_
= fake_request
->AsWeakPtr();
12394 return fake_request
;
12397 virtual HttpStreamRequest
* RequestWebSocketHandshakeStream(
12398 const HttpRequestInfo
& info
,
12399 RequestPriority priority
,
12400 const SSLConfig
& server_ssl_config
,
12401 const SSLConfig
& proxy_ssl_config
,
12402 HttpStreamRequest::Delegate
* delegate
,
12403 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12404 const BoundNetLog
& net_log
) OVERRIDE
{
12405 FakeStreamRequest
* fake_request
=
12406 new FakeStreamRequest(priority
, delegate
, create_helper
);
12407 last_stream_request_
= fake_request
->AsWeakPtr();
12408 return fake_request
;
12411 virtual void PreconnectStreams(int num_streams
,
12412 const HttpRequestInfo
& info
,
12413 RequestPriority priority
,
12414 const SSLConfig
& server_ssl_config
,
12415 const SSLConfig
& proxy_ssl_config
) OVERRIDE
{
12419 virtual const HostMappingRules
* GetHostMappingRules() const OVERRIDE
{
12425 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12427 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12430 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12432 class FakeWebSocketStreamCreateHelper
:
12433 public WebSocketHandshakeStreamBase::CreateHelper
{
12435 virtual WebSocketHandshakeStreamBase
* CreateBasicStream(
12436 scoped_ptr
<ClientSocketHandle
> connection
,
12437 bool using_proxy
) OVERRIDE
{
12442 virtual WebSocketHandshakeStreamBase
* CreateSpdyStream(
12443 const base::WeakPtr
<SpdySession
>& session
,
12444 bool use_relative_url
) OVERRIDE
{
12449 virtual ~FakeWebSocketStreamCreateHelper() {}
12451 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12453 return scoped_ptr
<WebSocketStream
>();
12459 // Make sure that HttpNetworkTransaction passes on its priority to its
12460 // stream request on start.
12461 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12462 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12463 HttpNetworkSessionPeer
peer(session
);
12464 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12465 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12467 HttpNetworkTransaction
trans(LOW
, session
.get());
12469 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12471 HttpRequestInfo request
;
12472 TestCompletionCallback callback
;
12473 EXPECT_EQ(ERR_IO_PENDING
,
12474 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12476 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12477 fake_factory
->last_stream_request();
12478 ASSERT_TRUE(fake_request
!= NULL
);
12479 EXPECT_EQ(LOW
, fake_request
->priority());
12482 // Make sure that HttpNetworkTransaction passes on its priority
12483 // updates to its stream request.
12484 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12485 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12486 HttpNetworkSessionPeer
peer(session
);
12487 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12488 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12490 HttpNetworkTransaction
trans(LOW
, session
.get());
12492 HttpRequestInfo request
;
12493 TestCompletionCallback callback
;
12494 EXPECT_EQ(ERR_IO_PENDING
,
12495 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12497 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12498 fake_factory
->last_stream_request();
12499 ASSERT_TRUE(fake_request
!= NULL
);
12500 EXPECT_EQ(LOW
, fake_request
->priority());
12502 trans
.SetPriority(LOWEST
);
12503 ASSERT_TRUE(fake_request
!= NULL
);
12504 EXPECT_EQ(LOWEST
, fake_request
->priority());
12507 // Make sure that HttpNetworkTransaction passes on its priority
12508 // updates to its stream.
12509 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12510 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12511 HttpNetworkSessionPeer
peer(session
);
12512 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12513 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12515 HttpNetworkTransaction
trans(LOW
, session
.get());
12517 HttpRequestInfo request
;
12518 TestCompletionCallback callback
;
12519 EXPECT_EQ(ERR_IO_PENDING
,
12520 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12522 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12523 fake_factory
->last_stream_request();
12524 ASSERT_TRUE(fake_request
!= NULL
);
12525 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12526 ASSERT_TRUE(fake_stream
!= NULL
);
12527 EXPECT_EQ(LOW
, fake_stream
->priority());
12529 trans
.SetPriority(LOWEST
);
12530 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12533 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12534 // The same logic needs to be tested for both ws: and wss: schemes, but this
12535 // test is already parameterised on NextProto, so it uses a loop to verify
12536 // that the different schemes work.
12537 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
12538 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
12539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12540 HttpNetworkSessionPeer
peer(session
);
12541 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12542 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
12543 peer
.SetHttpStreamFactoryForWebSocket(
12544 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12546 HttpNetworkTransaction
trans(LOW
, session
.get());
12547 trans
.SetWebSocketHandshakeStreamCreateHelper(
12548 &websocket_stream_create_helper
);
12550 HttpRequestInfo request
;
12551 TestCompletionCallback callback
;
12552 request
.method
= "GET";
12553 request
.url
= GURL(test_cases
[i
]);
12555 EXPECT_EQ(ERR_IO_PENDING
,
12556 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12558 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12559 fake_factory
->last_stream_request();
12560 ASSERT_TRUE(fake_request
!= NULL
);
12561 EXPECT_EQ(&websocket_stream_create_helper
,
12562 fake_request
->websocket_stream_create_helper());
12566 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12567 // if the transport socket pool is stalled on the global socket limit.
12568 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
12569 ClientSocketPoolManager::set_max_sockets_per_group(
12570 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12571 ClientSocketPoolManager::set_max_sockets_per_pool(
12572 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12574 // Set up SSL request.
12576 HttpRequestInfo ssl_request
;
12577 ssl_request
.method
= "GET";
12578 ssl_request
.url
= GURL("https://www.google.com/");
12580 MockWrite ssl_writes
[] = {
12581 MockWrite("GET / HTTP/1.1\r\n"
12582 "Host: www.google.com\r\n"
12583 "Connection: keep-alive\r\n\r\n"),
12585 MockRead ssl_reads
[] = {
12586 MockRead("HTTP/1.1 200 OK\r\n"),
12587 MockRead("Content-Length: 11\r\n\r\n"),
12588 MockRead("hello world"),
12589 MockRead(SYNCHRONOUS
, OK
),
12591 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
12592 ssl_writes
, arraysize(ssl_writes
));
12593 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12595 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12596 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12598 // Set up HTTP request.
12600 HttpRequestInfo http_request
;
12601 http_request
.method
= "GET";
12602 http_request
.url
= GURL("http://www.google.com/");
12604 MockWrite http_writes
[] = {
12605 MockWrite("GET / HTTP/1.1\r\n"
12606 "Host: www.google.com\r\n"
12607 "Connection: keep-alive\r\n\r\n"),
12609 MockRead http_reads
[] = {
12610 MockRead("HTTP/1.1 200 OK\r\n"),
12611 MockRead("Content-Length: 7\r\n\r\n"),
12612 MockRead("falafel"),
12613 MockRead(SYNCHRONOUS
, OK
),
12615 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12616 http_writes
, arraysize(http_writes
));
12617 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12619 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12621 // Start the SSL request.
12622 TestCompletionCallback ssl_callback
;
12623 scoped_ptr
<HttpTransaction
> ssl_trans(
12624 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12625 ASSERT_EQ(ERR_IO_PENDING
,
12626 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
12629 // Start the HTTP request. Pool should stall.
12630 TestCompletionCallback http_callback
;
12631 scoped_ptr
<HttpTransaction
> http_trans(
12632 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12633 ASSERT_EQ(ERR_IO_PENDING
,
12634 http_trans
->Start(&http_request
, http_callback
.callback(),
12636 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
12638 // Wait for response from SSL request.
12639 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
12640 std::string response_data
;
12641 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
12642 EXPECT_EQ("hello world", response_data
);
12644 // The SSL socket should automatically be closed, so the HTTP request can
12646 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
12647 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
12649 // The HTTP request can now complete.
12650 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12651 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12652 EXPECT_EQ("falafel", response_data
);
12654 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
12657 // Tests that when a SSL connection is established but there's no corresponding
12658 // request that needs it, the new socket is closed if the transport socket pool
12659 // is stalled on the global socket limit.
12660 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
12661 ClientSocketPoolManager::set_max_sockets_per_group(
12662 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12663 ClientSocketPoolManager::set_max_sockets_per_pool(
12664 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12666 // Set up an ssl request.
12668 HttpRequestInfo ssl_request
;
12669 ssl_request
.method
= "GET";
12670 ssl_request
.url
= GURL("https://www.foopy.com/");
12672 // No data will be sent on the SSL socket.
12673 StaticSocketDataProvider ssl_data
;
12674 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12676 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12677 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12679 // Set up HTTP request.
12681 HttpRequestInfo http_request
;
12682 http_request
.method
= "GET";
12683 http_request
.url
= GURL("http://www.google.com/");
12685 MockWrite http_writes
[] = {
12686 MockWrite("GET / HTTP/1.1\r\n"
12687 "Host: www.google.com\r\n"
12688 "Connection: keep-alive\r\n\r\n"),
12690 MockRead http_reads
[] = {
12691 MockRead("HTTP/1.1 200 OK\r\n"),
12692 MockRead("Content-Length: 7\r\n\r\n"),
12693 MockRead("falafel"),
12694 MockRead(SYNCHRONOUS
, OK
),
12696 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12697 http_writes
, arraysize(http_writes
));
12698 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12700 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12702 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12703 // cancelled when a normal transaction is cancelled.
12704 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
12705 net::SSLConfig ssl_config
;
12706 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
12707 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
12708 ssl_config
, ssl_config
);
12709 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
12711 // Start the HTTP request. Pool should stall.
12712 TestCompletionCallback http_callback
;
12713 scoped_ptr
<HttpTransaction
> http_trans(
12714 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12715 ASSERT_EQ(ERR_IO_PENDING
,
12716 http_trans
->Start(&http_request
, http_callback
.callback(),
12718 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
12720 // The SSL connection will automatically be closed once the connection is
12721 // established, to let the HTTP request start.
12722 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12723 std::string response_data
;
12724 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12725 EXPECT_EQ("falafel", response_data
);
12727 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
12730 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
12731 ScopedVector
<UploadElementReader
> element_readers
;
12732 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12733 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12735 HttpRequestInfo request
;
12736 request
.method
= "POST";
12737 request
.url
= GURL("http://www.foo.com/");
12738 request
.upload_data_stream
= &upload_data_stream
;
12739 request
.load_flags
= 0;
12741 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12742 scoped_ptr
<HttpTransaction
> trans(
12743 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12744 // Send headers successfully, but get an error while sending the body.
12745 MockWrite data_writes
[] = {
12746 MockWrite("POST / HTTP/1.1\r\n"
12747 "Host: www.foo.com\r\n"
12748 "Connection: keep-alive\r\n"
12749 "Content-Length: 3\r\n\r\n"),
12750 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12753 MockRead data_reads
[] = {
12754 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12755 MockRead("hello world"),
12756 MockRead(SYNCHRONOUS
, OK
),
12758 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12759 arraysize(data_writes
));
12760 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12762 TestCompletionCallback callback
;
12764 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12765 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12767 rv
= callback
.WaitForResult();
12770 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12771 ASSERT_TRUE(response
!= NULL
);
12773 EXPECT_TRUE(response
->headers
.get() != NULL
);
12774 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12776 std::string response_data
;
12777 rv
= ReadTransaction(trans
.get(), &response_data
);
12779 EXPECT_EQ("hello world", response_data
);
12782 // This test makes sure the retry logic doesn't trigger when reading an error
12783 // response from a server that rejected a POST with a CONNECTION_RESET.
12784 TEST_P(HttpNetworkTransactionTest
,
12785 PostReadsErrorResponseAfterResetOnReusedSocket
) {
12786 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12787 MockWrite data_writes
[] = {
12788 MockWrite("GET / HTTP/1.1\r\n"
12789 "Host: www.foo.com\r\n"
12790 "Connection: keep-alive\r\n\r\n"),
12791 MockWrite("POST / HTTP/1.1\r\n"
12792 "Host: www.foo.com\r\n"
12793 "Connection: keep-alive\r\n"
12794 "Content-Length: 3\r\n\r\n"),
12795 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12798 MockRead data_reads
[] = {
12799 MockRead("HTTP/1.1 200 Peachy\r\n"
12800 "Content-Length: 14\r\n\r\n"),
12801 MockRead("first response"),
12802 MockRead("HTTP/1.1 400 Not OK\r\n"
12803 "Content-Length: 15\r\n\r\n"),
12804 MockRead("second response"),
12805 MockRead(SYNCHRONOUS
, OK
),
12807 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12808 arraysize(data_writes
));
12809 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12811 TestCompletionCallback callback
;
12812 HttpRequestInfo request1
;
12813 request1
.method
= "GET";
12814 request1
.url
= GURL("http://www.foo.com/");
12815 request1
.load_flags
= 0;
12817 scoped_ptr
<HttpTransaction
> trans1(
12818 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12819 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
12820 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12822 rv
= callback
.WaitForResult();
12825 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12826 ASSERT_TRUE(response1
!= NULL
);
12828 EXPECT_TRUE(response1
->headers
.get() != NULL
);
12829 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
12831 std::string response_data1
;
12832 rv
= ReadTransaction(trans1
.get(), &response_data1
);
12834 EXPECT_EQ("first response", response_data1
);
12835 // Delete the transaction to release the socket back into the socket pool.
12838 ScopedVector
<UploadElementReader
> element_readers
;
12839 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12840 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12842 HttpRequestInfo request2
;
12843 request2
.method
= "POST";
12844 request2
.url
= GURL("http://www.foo.com/");
12845 request2
.upload_data_stream
= &upload_data_stream
;
12846 request2
.load_flags
= 0;
12848 scoped_ptr
<HttpTransaction
> trans2(
12849 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12850 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
12851 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12853 rv
= callback
.WaitForResult();
12856 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
12857 ASSERT_TRUE(response2
!= NULL
);
12859 EXPECT_TRUE(response2
->headers
.get() != NULL
);
12860 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
12862 std::string response_data2
;
12863 rv
= ReadTransaction(trans2
.get(), &response_data2
);
12865 EXPECT_EQ("second response", response_data2
);
12868 TEST_P(HttpNetworkTransactionTest
,
12869 PostReadsErrorResponseAfterResetPartialBodySent
) {
12870 ScopedVector
<UploadElementReader
> element_readers
;
12871 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12872 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12874 HttpRequestInfo request
;
12875 request
.method
= "POST";
12876 request
.url
= GURL("http://www.foo.com/");
12877 request
.upload_data_stream
= &upload_data_stream
;
12878 request
.load_flags
= 0;
12880 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12881 scoped_ptr
<HttpTransaction
> trans(
12882 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12883 // Send headers successfully, but get an error while sending the body.
12884 MockWrite data_writes
[] = {
12885 MockWrite("POST / HTTP/1.1\r\n"
12886 "Host: www.foo.com\r\n"
12887 "Connection: keep-alive\r\n"
12888 "Content-Length: 3\r\n\r\n"
12890 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12893 MockRead data_reads
[] = {
12894 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12895 MockRead("hello world"),
12896 MockRead(SYNCHRONOUS
, OK
),
12898 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12899 arraysize(data_writes
));
12900 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12902 TestCompletionCallback callback
;
12904 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12905 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12907 rv
= callback
.WaitForResult();
12910 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12911 ASSERT_TRUE(response
!= NULL
);
12913 EXPECT_TRUE(response
->headers
.get() != NULL
);
12914 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12916 std::string response_data
;
12917 rv
= ReadTransaction(trans
.get(), &response_data
);
12919 EXPECT_EQ("hello world", response_data
);
12922 // This tests the more common case than the previous test, where headers and
12923 // body are not merged into a single request.
12924 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
12925 ScopedVector
<UploadElementReader
> element_readers
;
12926 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12927 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
12929 HttpRequestInfo request
;
12930 request
.method
= "POST";
12931 request
.url
= GURL("http://www.foo.com/");
12932 request
.upload_data_stream
= &upload_data_stream
;
12933 request
.load_flags
= 0;
12935 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12936 scoped_ptr
<HttpTransaction
> trans(
12937 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12938 // Send headers successfully, but get an error while sending the body.
12939 MockWrite data_writes
[] = {
12940 MockWrite("POST / HTTP/1.1\r\n"
12941 "Host: www.foo.com\r\n"
12942 "Connection: keep-alive\r\n"
12943 "Transfer-Encoding: chunked\r\n\r\n"),
12944 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12947 MockRead data_reads
[] = {
12948 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12949 MockRead("hello world"),
12950 MockRead(SYNCHRONOUS
, OK
),
12952 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12953 arraysize(data_writes
));
12954 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12956 TestCompletionCallback callback
;
12958 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12959 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12960 // Make sure the headers are sent before adding a chunk. This ensures that
12961 // they can't be merged with the body in a single send. Not currently
12962 // necessary since a chunked body is never merged with headers, but this makes
12963 // the test more future proof.
12964 base::RunLoop().RunUntilIdle();
12966 upload_data_stream
.AppendChunk("last chunk", 10, true);
12968 rv
= callback
.WaitForResult();
12971 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12972 ASSERT_TRUE(response
!= NULL
);
12974 EXPECT_TRUE(response
->headers
.get() != NULL
);
12975 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12977 std::string response_data
;
12978 rv
= ReadTransaction(trans
.get(), &response_data
);
12980 EXPECT_EQ("hello world", response_data
);
12983 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
12984 ScopedVector
<UploadElementReader
> element_readers
;
12985 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12986 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12988 HttpRequestInfo request
;
12989 request
.method
= "POST";
12990 request
.url
= GURL("http://www.foo.com/");
12991 request
.upload_data_stream
= &upload_data_stream
;
12992 request
.load_flags
= 0;
12994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12995 scoped_ptr
<HttpTransaction
> trans(
12996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12998 MockWrite data_writes
[] = {
12999 MockWrite("POST / HTTP/1.1\r\n"
13000 "Host: www.foo.com\r\n"
13001 "Connection: keep-alive\r\n"
13002 "Content-Length: 3\r\n\r\n"),
13003 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13006 MockRead data_reads
[] = {
13007 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13008 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13009 MockRead("hello world"),
13010 MockRead(SYNCHRONOUS
, OK
),
13012 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13013 arraysize(data_writes
));
13014 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13016 TestCompletionCallback callback
;
13018 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13019 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13021 rv
= callback
.WaitForResult();
13024 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13025 ASSERT_TRUE(response
!= NULL
);
13027 EXPECT_TRUE(response
->headers
.get() != NULL
);
13028 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13030 std::string response_data
;
13031 rv
= ReadTransaction(trans
.get(), &response_data
);
13033 EXPECT_EQ("hello world", response_data
);
13036 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13037 ScopedVector
<UploadElementReader
> element_readers
;
13038 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13039 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13041 HttpRequestInfo request
;
13042 request
.method
= "POST";
13043 request
.url
= GURL("http://www.foo.com/");
13044 request
.upload_data_stream
= &upload_data_stream
;
13045 request
.load_flags
= 0;
13047 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13048 scoped_ptr
<HttpTransaction
> trans(
13049 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13050 // Send headers successfully, but get an error while sending the body.
13051 MockWrite data_writes
[] = {
13052 MockWrite("POST / HTTP/1.1\r\n"
13053 "Host: www.foo.com\r\n"
13054 "Connection: keep-alive\r\n"
13055 "Content-Length: 3\r\n\r\n"),
13056 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13059 MockRead data_reads
[] = {
13060 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13061 MockRead("hello world"),
13062 MockRead(SYNCHRONOUS
, OK
),
13064 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13065 arraysize(data_writes
));
13066 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13068 TestCompletionCallback callback
;
13070 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13071 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13073 rv
= callback
.WaitForResult();
13074 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13076 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13077 EXPECT_TRUE(response
== NULL
);
13080 TEST_P(HttpNetworkTransactionTest
,
13081 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13082 ScopedVector
<UploadElementReader
> element_readers
;
13083 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13084 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13086 HttpRequestInfo request
;
13087 request
.method
= "POST";
13088 request
.url
= GURL("http://www.foo.com/");
13089 request
.upload_data_stream
= &upload_data_stream
;
13090 request
.load_flags
= 0;
13092 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13093 scoped_ptr
<HttpTransaction
> trans(
13094 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13095 // Send headers successfully, but get an error while sending the body.
13096 MockWrite data_writes
[] = {
13097 MockWrite("POST / HTTP/1.1\r\n"
13098 "Host: www.foo.com\r\n"
13099 "Connection: keep-alive\r\n"
13100 "Content-Length: 3\r\n\r\n"),
13101 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13104 MockRead data_reads
[] = {
13105 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13106 MockRead("HTTP/1.0 302 Redirect\r\n"),
13107 MockRead("Location: http://somewhere-else.com/\r\n"),
13108 MockRead("Content-Length: 0\r\n\r\n"),
13109 MockRead(SYNCHRONOUS
, OK
),
13111 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13112 arraysize(data_writes
));
13113 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13115 TestCompletionCallback callback
;
13117 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13118 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13120 rv
= callback
.WaitForResult();
13121 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13123 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13124 EXPECT_TRUE(response
== NULL
);
13127 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13128 ScopedVector
<UploadElementReader
> element_readers
;
13129 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13130 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13132 HttpRequestInfo request
;
13133 request
.method
= "POST";
13134 request
.url
= GURL("http://www.foo.com/");
13135 request
.upload_data_stream
= &upload_data_stream
;
13136 request
.load_flags
= 0;
13138 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13139 scoped_ptr
<HttpTransaction
> trans(
13140 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13141 // Send headers successfully, but get an error while sending the body.
13142 MockWrite data_writes
[] = {
13143 MockWrite("POST / HTTP/1.1\r\n"
13144 "Host: www.foo.com\r\n"
13145 "Connection: keep-alive\r\n"
13146 "Content-Length: 3\r\n\r\n"),
13147 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13150 MockRead data_reads
[] = {
13151 MockRead("HTTP 0.9 rocks!"),
13152 MockRead(SYNCHRONOUS
, OK
),
13154 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13155 arraysize(data_writes
));
13156 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13158 TestCompletionCallback callback
;
13160 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13161 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13163 rv
= callback
.WaitForResult();
13164 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13166 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13167 EXPECT_TRUE(response
== NULL
);
13170 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13171 ScopedVector
<UploadElementReader
> element_readers
;
13172 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13173 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13175 HttpRequestInfo request
;
13176 request
.method
= "POST";
13177 request
.url
= GURL("http://www.foo.com/");
13178 request
.upload_data_stream
= &upload_data_stream
;
13179 request
.load_flags
= 0;
13181 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13182 scoped_ptr
<HttpTransaction
> trans(
13183 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13184 // Send headers successfully, but get an error while sending the body.
13185 MockWrite data_writes
[] = {
13186 MockWrite("POST / HTTP/1.1\r\n"
13187 "Host: www.foo.com\r\n"
13188 "Connection: keep-alive\r\n"
13189 "Content-Length: 3\r\n\r\n"),
13190 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13193 MockRead data_reads
[] = {
13194 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13195 MockRead(SYNCHRONOUS
, OK
),
13197 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13198 arraysize(data_writes
));
13199 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13201 TestCompletionCallback callback
;
13203 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13204 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13206 rv
= callback
.WaitForResult();
13207 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13209 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13210 EXPECT_TRUE(response
== NULL
);