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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
1238 MockRead data_reads
[] = {
1241 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1242 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1244 TestCompletionCallback callback
;
1246 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1247 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1249 rv
= callback
.WaitForResult();
1250 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1253 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1254 const MockWrite
* write_failure
,
1255 const MockRead
* read_failure
) {
1256 HttpRequestInfo request
;
1257 request
.method
= "GET";
1258 request
.url
= GURL("http://www.foo.com/");
1259 request
.load_flags
= 0;
1261 CapturingNetLog net_log
;
1262 session_deps_
.net_log
= &net_log
;
1263 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1265 // Written data for successfully sending both requests.
1266 MockWrite data1_writes
[] = {
1267 MockWrite("GET / HTTP/1.1\r\n"
1268 "Host: www.foo.com\r\n"
1269 "Connection: keep-alive\r\n\r\n"),
1270 MockWrite("GET / HTTP/1.1\r\n"
1271 "Host: www.foo.com\r\n"
1272 "Connection: keep-alive\r\n\r\n")
1275 // Read results for the first request.
1276 MockRead data1_reads
[] = {
1277 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1279 MockRead(ASYNC
, OK
),
1282 if (write_failure
) {
1283 ASSERT_FALSE(read_failure
);
1284 data1_writes
[1] = *write_failure
;
1286 ASSERT_TRUE(read_failure
);
1287 data1_reads
[2] = *read_failure
;
1290 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1291 data1_writes
, arraysize(data1_writes
));
1292 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1294 MockRead data2_reads
[] = {
1295 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1297 MockRead(ASYNC
, OK
),
1299 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1300 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1302 const char* kExpectedResponseData
[] = {
1306 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1307 for (int i
= 0; i
< 2; ++i
) {
1308 TestCompletionCallback callback
;
1310 scoped_ptr
<HttpTransaction
> trans(
1311 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1313 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1314 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1316 rv
= callback
.WaitForResult();
1319 LoadTimingInfo load_timing_info
;
1320 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1321 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1323 first_socket_log_id
= load_timing_info
.socket_log_id
;
1325 // The second request should be using a new socket.
1326 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1329 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1330 ASSERT_TRUE(response
!= NULL
);
1332 EXPECT_TRUE(response
->headers
.get() != NULL
);
1333 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1335 std::string response_data
;
1336 rv
= ReadTransaction(trans
.get(), &response_data
);
1338 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1342 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1343 const MockWrite
* write_failure
,
1344 const MockRead
* read_failure
,
1346 HttpRequestInfo request
;
1347 request
.method
= "GET";
1348 request
.url
= GURL("https://www.foo.com/");
1349 request
.load_flags
= 0;
1351 CapturingNetLog net_log
;
1352 session_deps_
.net_log
= &net_log
;
1353 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1355 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1356 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1358 ssl1
.SetNextProto(GetParam());
1359 ssl2
.SetNextProto(GetParam());
1361 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1362 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1364 // SPDY versions of the request and response.
1365 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1366 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1367 scoped_ptr
<SpdyFrame
> spdy_response(
1368 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1369 scoped_ptr
<SpdyFrame
> spdy_data(
1370 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1372 // HTTP/1.1 versions of the request and response.
1373 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1374 "Host: www.foo.com\r\n"
1375 "Connection: keep-alive\r\n\r\n";
1376 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1377 const char kHttpData
[] = "hello";
1379 std::vector
<MockRead
> data1_reads
;
1380 std::vector
<MockWrite
> data1_writes
;
1381 if (write_failure
) {
1382 ASSERT_FALSE(read_failure
);
1383 data1_writes
.push_back(*write_failure
);
1384 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1386 ASSERT_TRUE(read_failure
);
1388 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1390 data1_writes
.push_back(MockWrite(kHttpRequest
));
1392 data1_reads
.push_back(*read_failure
);
1395 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1396 &data1_writes
[0], data1_writes
.size());
1397 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1399 std::vector
<MockRead
> data2_reads
;
1400 std::vector
<MockWrite
> data2_writes
;
1403 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1405 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1406 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1407 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1409 data2_writes
.push_back(
1410 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1412 data2_reads
.push_back(
1413 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1414 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1415 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1417 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1418 &data2_writes
[0], data2_writes
.size());
1419 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1421 // Preconnect a socket.
1422 net::SSLConfig ssl_config
;
1423 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1424 session
->GetNextProtos(&ssl_config
.next_protos
);
1425 session
->http_stream_factory()->PreconnectStreams(
1426 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1427 // Wait for the preconnect to complete.
1428 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1429 base::RunLoop().RunUntilIdle();
1430 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1432 // Make the request.
1433 TestCompletionCallback callback
;
1435 scoped_ptr
<HttpTransaction
> trans(
1436 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1438 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1439 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1441 rv
= callback
.WaitForResult();
1444 LoadTimingInfo load_timing_info
;
1445 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1446 TestLoadTimingNotReused(
1448 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1450 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1451 ASSERT_TRUE(response
!= NULL
);
1453 EXPECT_TRUE(response
->headers
.get() != NULL
);
1454 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1456 std::string response_data
;
1457 rv
= ReadTransaction(trans
.get(), &response_data
);
1459 EXPECT_EQ(kHttpData
, response_data
);
1462 TEST_P(HttpNetworkTransactionTest
,
1463 KeepAliveConnectionNotConnectedOnWrite
) {
1464 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1465 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1468 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1469 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1470 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1473 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1474 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1475 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1478 // Make sure that on a 408 response (Request Timeout), the request is retried,
1479 // if the socket was a reused keep alive socket.
1480 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1481 MockRead
read_failure(SYNCHRONOUS
,
1482 "HTTP/1.1 408 Request Timeout\r\n"
1483 "Connection: Keep-Alive\r\n"
1484 "Content-Length: 6\r\n\r\n"
1486 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1489 TEST_P(HttpNetworkTransactionTest
,
1490 PreconnectErrorNotConnectedOnWrite
) {
1491 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1492 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1495 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1496 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1497 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1500 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1501 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1502 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1505 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1506 MockRead
read_failure(ASYNC
, OK
); // EOF
1507 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1510 // Make sure that on a 408 response (Request Timeout), the request is retried,
1511 // if the socket was a preconnected (UNUSED_IDLE) socket.
1512 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1513 MockRead
read_failure(SYNCHRONOUS
,
1514 "HTTP/1.1 408 Request Timeout\r\n"
1515 "Connection: Keep-Alive\r\n"
1516 "Content-Length: 6\r\n\r\n"
1518 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1519 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1522 TEST_P(HttpNetworkTransactionTest
,
1523 SpdyPreconnectErrorNotConnectedOnWrite
) {
1524 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1525 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1528 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1529 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1530 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1533 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1534 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1535 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1538 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1539 MockRead
read_failure(ASYNC
, OK
); // EOF
1540 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1543 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1544 HttpRequestInfo request
;
1545 request
.method
= "GET";
1546 request
.url
= GURL("http://www.google.com/");
1547 request
.load_flags
= 0;
1549 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1550 scoped_ptr
<HttpTransaction
> trans(
1551 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1553 MockRead data_reads
[] = {
1554 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1555 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1556 MockRead("hello world"),
1557 MockRead(SYNCHRONOUS
, OK
),
1559 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1560 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1562 TestCompletionCallback callback
;
1564 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1565 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1567 rv
= callback
.WaitForResult();
1568 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1570 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1571 EXPECT_TRUE(response
== NULL
);
1574 // What do various browsers do when the server closes a non-keepalive
1575 // connection without sending any response header or body?
1578 // Safari 3.1.2 (Windows): error page
1579 // Firefox 3.0.1: blank page
1580 // Opera 9.52: after five attempts, blank page
1581 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1582 // Us: error page (EMPTY_RESPONSE)
1583 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1584 MockRead data_reads
[] = {
1585 MockRead(SYNCHRONOUS
, OK
), // EOF
1586 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1587 MockRead("hello world"),
1588 MockRead(SYNCHRONOUS
, OK
),
1590 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1591 arraysize(data_reads
));
1592 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1595 // Test that network access can be deferred and resumed.
1596 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1597 HttpRequestInfo request
;
1598 request
.method
= "GET";
1599 request
.url
= GURL("http://www.google.com/");
1600 request
.load_flags
= 0;
1602 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1603 scoped_ptr
<HttpTransaction
> trans(
1604 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1606 // Defer on OnBeforeNetworkStart.
1607 BeforeNetworkStartHandler
net_start_handler(true); // defer
1608 trans
->SetBeforeNetworkStartCallback(
1609 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1610 base::Unretained(&net_start_handler
)));
1612 MockRead data_reads
[] = {
1613 MockRead("HTTP/1.0 200 OK\r\n"),
1614 MockRead("Content-Length: 5\r\n\r\n"),
1616 MockRead(SYNCHRONOUS
, 0),
1618 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1619 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1621 TestCompletionCallback callback
;
1623 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1624 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1625 base::MessageLoop::current()->RunUntilIdle();
1627 // Should have deferred for network start.
1628 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1629 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1630 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1632 trans
->ResumeNetworkStart();
1633 rv
= callback
.WaitForResult();
1635 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1637 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1638 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1639 if (rv
== ERR_IO_PENDING
)
1640 rv
= callback
.WaitForResult();
1645 // Test that network use can be deferred and canceled.
1646 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1647 HttpRequestInfo request
;
1648 request
.method
= "GET";
1649 request
.url
= GURL("http://www.google.com/");
1650 request
.load_flags
= 0;
1652 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1653 scoped_ptr
<HttpTransaction
> trans(
1654 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1656 // Defer on OnBeforeNetworkStart.
1657 BeforeNetworkStartHandler
net_start_handler(true); // defer
1658 trans
->SetBeforeNetworkStartCallback(
1659 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1660 base::Unretained(&net_start_handler
)));
1662 TestCompletionCallback callback
;
1664 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1665 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1666 base::MessageLoop::current()->RunUntilIdle();
1668 // Should have deferred for network start.
1669 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1670 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1671 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1674 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1675 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1676 // destructor in such situations.
1677 // See http://crbug.com/154712 and http://crbug.com/156609.
1678 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1679 HttpRequestInfo request
;
1680 request
.method
= "GET";
1681 request
.url
= GURL("http://www.google.com/");
1682 request
.load_flags
= 0;
1684 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1685 scoped_ptr
<HttpTransaction
> trans(
1686 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1688 MockRead data_reads
[] = {
1689 MockRead("HTTP/1.0 200 OK\r\n"),
1690 MockRead("Connection: keep-alive\r\n"),
1691 MockRead("Content-Length: 100\r\n\r\n"),
1693 MockRead(SYNCHRONOUS
, 0),
1695 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1696 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1698 TestCompletionCallback callback
;
1700 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1701 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1703 rv
= callback
.WaitForResult();
1706 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1707 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1708 if (rv
== ERR_IO_PENDING
)
1709 rv
= callback
.WaitForResult();
1711 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1712 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1715 base::MessageLoop::current()->RunUntilIdle();
1716 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1719 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1720 HttpRequestInfo request
;
1721 request
.method
= "GET";
1722 request
.url
= GURL("http://www.google.com/");
1723 request
.load_flags
= 0;
1725 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1726 scoped_ptr
<HttpTransaction
> trans(
1727 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1729 MockRead data_reads
[] = {
1730 MockRead("HTTP/1.0 200 OK\r\n"),
1731 MockRead("Connection: keep-alive\r\n"),
1732 MockRead("Content-Length: 100\r\n\r\n"),
1733 MockRead(SYNCHRONOUS
, 0),
1735 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1736 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1738 TestCompletionCallback callback
;
1740 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1741 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1743 rv
= callback
.WaitForResult();
1746 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1747 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1748 if (rv
== ERR_IO_PENDING
)
1749 rv
= callback
.WaitForResult();
1750 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1753 base::MessageLoop::current()->RunUntilIdle();
1754 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1757 // Test that we correctly reuse a keep-alive connection after not explicitly
1758 // reading the body.
1759 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1760 HttpRequestInfo request
;
1761 request
.method
= "GET";
1762 request
.url
= GURL("http://www.foo.com/");
1763 request
.load_flags
= 0;
1765 CapturingNetLog net_log
;
1766 session_deps_
.net_log
= &net_log
;
1767 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1769 // Note that because all these reads happen in the same
1770 // StaticSocketDataProvider, it shows that the same socket is being reused for
1771 // all transactions.
1772 MockRead data1_reads
[] = {
1773 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1774 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1775 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1776 MockRead("HTTP/1.1 302 Found\r\n"
1777 "Content-Length: 0\r\n\r\n"),
1778 MockRead("HTTP/1.1 302 Found\r\n"
1779 "Content-Length: 5\r\n\r\n"
1781 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1782 "Content-Length: 0\r\n\r\n"),
1783 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1784 "Content-Length: 5\r\n\r\n"
1786 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1789 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1790 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1792 MockRead data2_reads
[] = {
1793 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1795 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1796 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1798 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1799 std::string response_lines
[kNumUnreadBodies
];
1801 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1802 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1803 TestCompletionCallback callback
;
1805 scoped_ptr
<HttpTransaction
> trans(
1806 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1808 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1809 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1811 rv
= callback
.WaitForResult();
1814 LoadTimingInfo load_timing_info
;
1815 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1817 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1818 first_socket_log_id
= load_timing_info
.socket_log_id
;
1820 TestLoadTimingReused(load_timing_info
);
1821 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1824 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1825 ASSERT_TRUE(response
!= NULL
);
1827 ASSERT_TRUE(response
->headers
.get() != NULL
);
1828 response_lines
[i
] = response
->headers
->GetStatusLine();
1830 // We intentionally don't read the response bodies.
1833 const char* const kStatusLines
[] = {
1834 "HTTP/1.1 204 No Content",
1835 "HTTP/1.1 205 Reset Content",
1836 "HTTP/1.1 304 Not Modified",
1837 "HTTP/1.1 302 Found",
1838 "HTTP/1.1 302 Found",
1839 "HTTP/1.1 301 Moved Permanently",
1840 "HTTP/1.1 301 Moved Permanently",
1843 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1844 forgot_to_update_kStatusLines
);
1846 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1847 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1849 TestCompletionCallback callback
;
1850 scoped_ptr
<HttpTransaction
> trans(
1851 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1852 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1853 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1854 rv
= callback
.WaitForResult();
1856 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1857 ASSERT_TRUE(response
!= NULL
);
1858 ASSERT_TRUE(response
->headers
.get() != NULL
);
1859 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1860 std::string response_data
;
1861 rv
= ReadTransaction(trans
.get(), &response_data
);
1863 EXPECT_EQ("hello", response_data
);
1866 // Test the request-challenge-retry sequence for basic auth.
1867 // (basic auth is the easiest to mock, because it has no randomness).
1868 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1869 HttpRequestInfo request
;
1870 request
.method
= "GET";
1871 request
.url
= GURL("http://www.google.com/");
1872 request
.load_flags
= 0;
1874 CapturingNetLog log
;
1875 session_deps_
.net_log
= &log
;
1876 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1877 scoped_ptr
<HttpTransaction
> trans(
1878 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1880 MockWrite data_writes1
[] = {
1881 MockWrite("GET / HTTP/1.1\r\n"
1882 "Host: www.google.com\r\n"
1883 "Connection: keep-alive\r\n\r\n"),
1886 MockRead data_reads1
[] = {
1887 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1888 // Give a couple authenticate options (only the middle one is actually
1890 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1891 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1892 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1893 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1894 // Large content-length -- won't matter, as connection will be reset.
1895 MockRead("Content-Length: 10000\r\n\r\n"),
1896 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1899 // After calling trans->RestartWithAuth(), this is the request we should
1900 // be issuing -- the final header line contains the credentials.
1901 MockWrite data_writes2
[] = {
1902 MockWrite("GET / HTTP/1.1\r\n"
1903 "Host: www.google.com\r\n"
1904 "Connection: keep-alive\r\n"
1905 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1908 // Lastly, the server responds with the actual content.
1909 MockRead data_reads2
[] = {
1910 MockRead("HTTP/1.0 200 OK\r\n"),
1911 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1912 MockRead("Content-Length: 100\r\n\r\n"),
1913 MockRead(SYNCHRONOUS
, OK
),
1916 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1917 data_writes1
, arraysize(data_writes1
));
1918 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1919 data_writes2
, arraysize(data_writes2
));
1920 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1921 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1923 TestCompletionCallback callback1
;
1925 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1928 rv
= callback1
.WaitForResult();
1931 LoadTimingInfo load_timing_info1
;
1932 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1933 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1935 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1936 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1938 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1939 ASSERT_TRUE(response
!= NULL
);
1940 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1942 TestCompletionCallback callback2
;
1944 rv
= trans
->RestartWithAuth(
1945 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1948 rv
= callback2
.WaitForResult();
1951 LoadTimingInfo load_timing_info2
;
1952 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1953 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1954 // The load timing after restart should have a new socket ID, and times after
1955 // those of the first load timing.
1956 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1957 load_timing_info2
.connect_timing
.connect_start
);
1958 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1960 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1961 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1963 response
= trans
->GetResponseInfo();
1964 ASSERT_TRUE(response
!= NULL
);
1965 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1966 EXPECT_EQ(100, response
->headers
->GetContentLength());
1969 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1970 HttpRequestInfo request
;
1971 request
.method
= "GET";
1972 request
.url
= GURL("http://www.google.com/");
1973 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1975 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1976 scoped_ptr
<HttpTransaction
> trans(
1977 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1979 MockWrite data_writes
[] = {
1980 MockWrite("GET / HTTP/1.1\r\n"
1981 "Host: www.google.com\r\n"
1982 "Connection: keep-alive\r\n\r\n"),
1985 MockRead data_reads
[] = {
1986 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1987 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1988 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1989 // Large content-length -- won't matter, as connection will be reset.
1990 MockRead("Content-Length: 10000\r\n\r\n"),
1991 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1994 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1995 data_writes
, arraysize(data_writes
));
1996 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1997 TestCompletionCallback callback
;
1999 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2002 rv
= callback
.WaitForResult();
2005 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2006 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2008 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2009 ASSERT_TRUE(response
!= NULL
);
2010 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2013 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2015 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2016 HttpRequestInfo request
;
2017 request
.method
= "GET";
2018 request
.url
= GURL("http://www.google.com/");
2019 request
.load_flags
= 0;
2021 CapturingNetLog log
;
2022 session_deps_
.net_log
= &log
;
2023 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2025 MockWrite data_writes1
[] = {
2026 MockWrite("GET / HTTP/1.1\r\n"
2027 "Host: www.google.com\r\n"
2028 "Connection: keep-alive\r\n\r\n"),
2030 // After calling trans->RestartWithAuth(), this is the request we should
2031 // be issuing -- the final header line contains the credentials.
2032 MockWrite("GET / HTTP/1.1\r\n"
2033 "Host: www.google.com\r\n"
2034 "Connection: keep-alive\r\n"
2035 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2038 MockRead data_reads1
[] = {
2039 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2040 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2041 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2042 MockRead("Content-Length: 14\r\n\r\n"),
2043 MockRead("Unauthorized\r\n"),
2045 // Lastly, the server responds with the actual content.
2046 MockRead("HTTP/1.1 200 OK\r\n"),
2047 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2048 MockRead("Content-Length: 5\r\n\r\n"),
2052 // If there is a regression where we disconnect a Keep-Alive
2053 // connection during an auth roundtrip, we'll end up reading this.
2054 MockRead data_reads2
[] = {
2055 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2058 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2059 data_writes1
, arraysize(data_writes1
));
2060 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2062 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2063 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2065 TestCompletionCallback callback1
;
2067 scoped_ptr
<HttpTransaction
> trans(
2068 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2069 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2070 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2072 rv
= callback1
.WaitForResult();
2075 LoadTimingInfo load_timing_info1
;
2076 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2077 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2079 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2080 ASSERT_TRUE(response
!= NULL
);
2081 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2083 TestCompletionCallback callback2
;
2085 rv
= trans
->RestartWithAuth(
2086 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2089 rv
= callback2
.WaitForResult();
2092 LoadTimingInfo load_timing_info2
;
2093 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2094 TestLoadTimingReused(load_timing_info2
);
2095 // The load timing after restart should have the same socket ID, and times
2096 // those of the first load timing.
2097 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2098 load_timing_info2
.send_start
);
2099 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2101 response
= trans
->GetResponseInfo();
2102 ASSERT_TRUE(response
!= NULL
);
2103 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2104 EXPECT_EQ(5, response
->headers
->GetContentLength());
2106 std::string response_data
;
2107 rv
= ReadTransaction(trans
.get(), &response_data
);
2109 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2110 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2113 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2114 // connection and with no response body to drain.
2115 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2116 HttpRequestInfo request
;
2117 request
.method
= "GET";
2118 request
.url
= GURL("http://www.google.com/");
2119 request
.load_flags
= 0;
2121 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2123 MockWrite data_writes1
[] = {
2124 MockWrite("GET / HTTP/1.1\r\n"
2125 "Host: www.google.com\r\n"
2126 "Connection: keep-alive\r\n\r\n"),
2128 // After calling trans->RestartWithAuth(), this is the request we should
2129 // be issuing -- the final header line contains the credentials.
2130 MockWrite("GET / HTTP/1.1\r\n"
2131 "Host: www.google.com\r\n"
2132 "Connection: keep-alive\r\n"
2133 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2136 MockRead data_reads1
[] = {
2137 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2138 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2139 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2141 // Lastly, the server responds with the actual content.
2142 MockRead("HTTP/1.1 200 OK\r\n"),
2143 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2144 MockRead("Content-Length: 5\r\n\r\n"),
2148 // An incorrect reconnect would cause this to be read.
2149 MockRead data_reads2
[] = {
2150 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2153 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2154 data_writes1
, arraysize(data_writes1
));
2155 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2157 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2158 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2160 TestCompletionCallback callback1
;
2162 scoped_ptr
<HttpTransaction
> trans(
2163 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2164 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2167 rv
= callback1
.WaitForResult();
2170 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2171 ASSERT_TRUE(response
!= NULL
);
2172 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2174 TestCompletionCallback callback2
;
2176 rv
= trans
->RestartWithAuth(
2177 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2178 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2180 rv
= callback2
.WaitForResult();
2183 response
= trans
->GetResponseInfo();
2184 ASSERT_TRUE(response
!= NULL
);
2185 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2186 EXPECT_EQ(5, response
->headers
->GetContentLength());
2189 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2190 // connection and with a large response body to drain.
2191 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2192 HttpRequestInfo request
;
2193 request
.method
= "GET";
2194 request
.url
= GURL("http://www.google.com/");
2195 request
.load_flags
= 0;
2197 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2199 MockWrite data_writes1
[] = {
2200 MockWrite("GET / HTTP/1.1\r\n"
2201 "Host: www.google.com\r\n"
2202 "Connection: keep-alive\r\n\r\n"),
2204 // After calling trans->RestartWithAuth(), this is the request we should
2205 // be issuing -- the final header line contains the credentials.
2206 MockWrite("GET / HTTP/1.1\r\n"
2207 "Host: www.google.com\r\n"
2208 "Connection: keep-alive\r\n"
2209 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2212 // Respond with 5 kb of response body.
2213 std::string
large_body_string("Unauthorized");
2214 large_body_string
.append(5 * 1024, ' ');
2215 large_body_string
.append("\r\n");
2217 MockRead data_reads1
[] = {
2218 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2219 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2220 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2221 // 5134 = 12 + 5 * 1024 + 2
2222 MockRead("Content-Length: 5134\r\n\r\n"),
2223 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2225 // Lastly, the server responds with the actual content.
2226 MockRead("HTTP/1.1 200 OK\r\n"),
2227 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2228 MockRead("Content-Length: 5\r\n\r\n"),
2232 // An incorrect reconnect would cause this to be read.
2233 MockRead data_reads2
[] = {
2234 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2237 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2238 data_writes1
, arraysize(data_writes1
));
2239 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2241 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2242 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2244 TestCompletionCallback callback1
;
2246 scoped_ptr
<HttpTransaction
> trans(
2247 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2248 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2249 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2251 rv
= callback1
.WaitForResult();
2254 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2255 ASSERT_TRUE(response
!= NULL
);
2256 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2258 TestCompletionCallback callback2
;
2260 rv
= trans
->RestartWithAuth(
2261 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2262 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2264 rv
= callback2
.WaitForResult();
2267 response
= trans
->GetResponseInfo();
2268 ASSERT_TRUE(response
!= NULL
);
2269 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2270 EXPECT_EQ(5, response
->headers
->GetContentLength());
2273 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2274 // connection, but the server gets impatient and closes the connection.
2275 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2276 HttpRequestInfo request
;
2277 request
.method
= "GET";
2278 request
.url
= GURL("http://www.google.com/");
2279 request
.load_flags
= 0;
2281 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2283 MockWrite data_writes1
[] = {
2284 MockWrite("GET / HTTP/1.1\r\n"
2285 "Host: www.google.com\r\n"
2286 "Connection: keep-alive\r\n\r\n"),
2287 // This simulates the seemingly successful write to a closed connection
2288 // if the bug is not fixed.
2289 MockWrite("GET / HTTP/1.1\r\n"
2290 "Host: www.google.com\r\n"
2291 "Connection: keep-alive\r\n"
2292 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2295 MockRead data_reads1
[] = {
2296 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2297 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2299 MockRead("Content-Length: 14\r\n\r\n"),
2300 // Tell MockTCPClientSocket to simulate the server closing the connection.
2301 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2302 MockRead("Unauthorized\r\n"),
2303 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2306 // After calling trans->RestartWithAuth(), this is the request we should
2307 // be issuing -- the final header line contains the credentials.
2308 MockWrite data_writes2
[] = {
2309 MockWrite("GET / HTTP/1.1\r\n"
2310 "Host: www.google.com\r\n"
2311 "Connection: keep-alive\r\n"
2312 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2315 // Lastly, the server responds with the actual content.
2316 MockRead data_reads2
[] = {
2317 MockRead("HTTP/1.1 200 OK\r\n"),
2318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2319 MockRead("Content-Length: 5\r\n\r\n"),
2323 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2324 data_writes1
, arraysize(data_writes1
));
2325 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2326 data_writes2
, arraysize(data_writes2
));
2327 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2328 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2330 TestCompletionCallback callback1
;
2332 scoped_ptr
<HttpTransaction
> trans(
2333 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2334 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2335 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2337 rv
= callback1
.WaitForResult();
2340 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2341 ASSERT_TRUE(response
!= NULL
);
2342 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2344 TestCompletionCallback callback2
;
2346 rv
= trans
->RestartWithAuth(
2347 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2350 rv
= callback2
.WaitForResult();
2353 response
= trans
->GetResponseInfo();
2354 ASSERT_TRUE(response
!= NULL
);
2355 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2356 EXPECT_EQ(5, response
->headers
->GetContentLength());
2359 // Test the request-challenge-retry sequence for basic auth, over a connection
2360 // that requires a restart when setting up an SSL tunnel.
2361 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
2362 HttpRequestInfo request
;
2363 request
.method
= "GET";
2364 request
.url
= GURL("https://www.google.com/");
2365 // when the no authentication data flag is set.
2366 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2368 // Configure against proxy server "myproxy:70".
2369 session_deps_
.proxy_service
.reset(
2370 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2371 CapturingBoundNetLog log
;
2372 session_deps_
.net_log
= log
.bound().net_log();
2373 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2375 // Since we have proxy, should try to establish tunnel.
2376 MockWrite data_writes1
[] = {
2377 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2378 "Host: www.google.com\r\n"
2379 "Proxy-Connection: keep-alive\r\n\r\n"),
2381 // After calling trans->RestartWithAuth(), this is the request we should
2382 // be issuing -- the final header line contains the credentials.
2383 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2384 "Host: www.google.com\r\n"
2385 "Proxy-Connection: keep-alive\r\n"
2386 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2388 MockWrite("GET / HTTP/1.1\r\n"
2389 "Host: www.google.com\r\n"
2390 "Connection: keep-alive\r\n\r\n"),
2393 // The proxy responds to the connect with a 407, using a persistent
2395 MockRead data_reads1
[] = {
2397 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2398 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2399 MockRead("Proxy-Connection: close\r\n\r\n"),
2401 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2403 MockRead("HTTP/1.1 200 OK\r\n"),
2404 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2405 MockRead("Content-Length: 5\r\n\r\n"),
2406 MockRead(SYNCHRONOUS
, "hello"),
2409 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2410 data_writes1
, arraysize(data_writes1
));
2411 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2412 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2413 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2415 TestCompletionCallback callback1
;
2417 scoped_ptr
<HttpTransaction
> trans(
2418 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2420 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2421 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2423 rv
= callback1
.WaitForResult();
2425 net::CapturingNetLog::CapturedEntryList entries
;
2426 log
.GetEntries(&entries
);
2427 size_t pos
= ExpectLogContainsSomewhere(
2428 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2429 NetLog::PHASE_NONE
);
2430 ExpectLogContainsSomewhere(
2432 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2433 NetLog::PHASE_NONE
);
2435 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2436 ASSERT_TRUE(response
!= NULL
);
2437 ASSERT_FALSE(response
->headers
.get() == NULL
);
2438 EXPECT_EQ(407, response
->headers
->response_code());
2439 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2440 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2442 LoadTimingInfo load_timing_info
;
2443 // CONNECT requests and responses are handled at the connect job level, so
2444 // the transaction does not yet have a connection.
2445 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2447 TestCompletionCallback callback2
;
2449 rv
= trans
->RestartWithAuth(
2450 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2451 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2453 rv
= callback2
.WaitForResult();
2456 response
= trans
->GetResponseInfo();
2457 ASSERT_TRUE(response
!= NULL
);
2459 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2460 EXPECT_EQ(200, response
->headers
->response_code());
2461 EXPECT_EQ(5, response
->headers
->GetContentLength());
2462 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2464 // The password prompt info should not be set.
2465 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2467 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2468 TestLoadTimingNotReusedWithPac(load_timing_info
,
2469 CONNECT_TIMING_HAS_SSL_TIMES
);
2472 session
->CloseAllConnections();
2475 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2476 // proxy connection, when setting up an SSL tunnel.
2477 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2478 HttpRequestInfo request
;
2479 request
.method
= "GET";
2480 request
.url
= GURL("https://www.google.com/");
2481 // Ensure that proxy authentication is attempted even
2482 // when the no authentication data flag is set.
2483 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2485 // Configure against proxy server "myproxy:70".
2486 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2487 CapturingBoundNetLog log
;
2488 session_deps_
.net_log
= log
.bound().net_log();
2489 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2491 scoped_ptr
<HttpTransaction
> trans(
2492 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2494 // Since we have proxy, should try to establish tunnel.
2495 MockWrite data_writes1
[] = {
2496 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2497 "Host: www.google.com\r\n"
2498 "Proxy-Connection: keep-alive\r\n\r\n"),
2500 // After calling trans->RestartWithAuth(), this is the request we should
2501 // be issuing -- the final header line contains the credentials.
2502 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2503 "Host: www.google.com\r\n"
2504 "Proxy-Connection: keep-alive\r\n"
2505 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2508 // The proxy responds to the connect with a 407, using a persistent
2510 MockRead data_reads1
[] = {
2512 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2513 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2514 MockRead("Content-Length: 10\r\n\r\n"),
2515 MockRead("0123456789"),
2517 // Wrong credentials (wrong password).
2518 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2519 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2520 MockRead("Content-Length: 10\r\n\r\n"),
2521 // No response body because the test stops reading here.
2522 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2525 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2526 data_writes1
, arraysize(data_writes1
));
2527 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2529 TestCompletionCallback callback1
;
2531 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2532 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2534 rv
= callback1
.WaitForResult();
2536 net::CapturingNetLog::CapturedEntryList entries
;
2537 log
.GetEntries(&entries
);
2538 size_t pos
= ExpectLogContainsSomewhere(
2539 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2540 NetLog::PHASE_NONE
);
2541 ExpectLogContainsSomewhere(
2543 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2544 NetLog::PHASE_NONE
);
2546 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2547 ASSERT_TRUE(response
!= NULL
);
2548 ASSERT_FALSE(response
->headers
.get() == NULL
);
2549 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2550 EXPECT_EQ(407, response
->headers
->response_code());
2551 EXPECT_EQ(10, response
->headers
->GetContentLength());
2552 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2553 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2555 TestCompletionCallback callback2
;
2557 // Wrong password (should be "bar").
2558 rv
= trans
->RestartWithAuth(
2559 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2560 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2562 rv
= callback2
.WaitForResult();
2565 response
= trans
->GetResponseInfo();
2566 ASSERT_TRUE(response
!= NULL
);
2567 ASSERT_FALSE(response
->headers
.get() == NULL
);
2568 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2569 EXPECT_EQ(407, response
->headers
->response_code());
2570 EXPECT_EQ(10, response
->headers
->GetContentLength());
2571 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2572 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2574 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2576 session
->CloseAllConnections();
2579 // Test that we don't read the response body when we fail to establish a tunnel,
2580 // even if the user cancels the proxy's auth attempt.
2581 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2582 HttpRequestInfo request
;
2583 request
.method
= "GET";
2584 request
.url
= GURL("https://www.google.com/");
2585 request
.load_flags
= 0;
2587 // Configure against proxy server "myproxy:70".
2588 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2590 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2592 scoped_ptr
<HttpTransaction
> trans(
2593 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2595 // Since we have proxy, should try to establish tunnel.
2596 MockWrite data_writes
[] = {
2597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2598 "Host: www.google.com\r\n"
2599 "Proxy-Connection: keep-alive\r\n\r\n"),
2602 // The proxy responds to the connect with a 407.
2603 MockRead data_reads
[] = {
2604 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2605 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2606 MockRead("Content-Length: 10\r\n\r\n"),
2607 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2610 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2611 data_writes
, arraysize(data_writes
));
2612 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2614 TestCompletionCallback callback
;
2616 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2617 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2619 rv
= callback
.WaitForResult();
2622 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2623 ASSERT_TRUE(response
!= NULL
);
2625 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2626 EXPECT_EQ(407, response
->headers
->response_code());
2627 EXPECT_EQ(10, response
->headers
->GetContentLength());
2628 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2630 std::string response_data
;
2631 rv
= ReadTransaction(trans
.get(), &response_data
);
2632 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2634 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2635 session
->CloseAllConnections();
2638 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2639 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2640 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2641 HttpRequestInfo request
;
2642 request
.method
= "GET";
2643 request
.url
= GURL("http://www.google.com/");
2644 request
.load_flags
= 0;
2646 // We are using a DIRECT connection (i.e. no proxy) for this session.
2647 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2648 scoped_ptr
<HttpTransaction
> trans(
2649 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
2651 MockWrite data_writes1
[] = {
2652 MockWrite("GET / HTTP/1.1\r\n"
2653 "Host: www.google.com\r\n"
2654 "Connection: keep-alive\r\n\r\n"),
2657 MockRead data_reads1
[] = {
2658 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2659 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2660 // Large content-length -- won't matter, as connection will be reset.
2661 MockRead("Content-Length: 10000\r\n\r\n"),
2662 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2665 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2666 data_writes1
, arraysize(data_writes1
));
2667 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2669 TestCompletionCallback callback
;
2671 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2672 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2674 rv
= callback
.WaitForResult();
2675 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2678 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2679 // through a non-authenticating proxy. The request should fail with
2680 // ERR_UNEXPECTED_PROXY_AUTH.
2681 // Note that it is impossible to detect if an HTTP server returns a 407 through
2682 // a non-authenticating proxy - there is nothing to indicate whether the
2683 // response came from the proxy or the server, so it is treated as if the proxy
2684 // issued the challenge.
2685 TEST_P(HttpNetworkTransactionTest
,
2686 HttpsServerRequestsProxyAuthThroughProxy
) {
2687 HttpRequestInfo request
;
2688 request
.method
= "GET";
2689 request
.url
= GURL("https://www.google.com/");
2691 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2692 CapturingBoundNetLog log
;
2693 session_deps_
.net_log
= log
.bound().net_log();
2694 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2696 // Since we have proxy, should try to establish tunnel.
2697 MockWrite data_writes1
[] = {
2698 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2699 "Host: www.google.com\r\n"
2700 "Proxy-Connection: keep-alive\r\n\r\n"),
2702 MockWrite("GET / HTTP/1.1\r\n"
2703 "Host: www.google.com\r\n"
2704 "Connection: keep-alive\r\n\r\n"),
2707 MockRead data_reads1
[] = {
2708 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2710 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2711 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2713 MockRead(SYNCHRONOUS
, OK
),
2716 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2717 data_writes1
, arraysize(data_writes1
));
2718 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2719 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2720 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2722 TestCompletionCallback callback1
;
2724 scoped_ptr
<HttpTransaction
> trans(
2725 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2727 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2728 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2730 rv
= callback1
.WaitForResult();
2731 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2732 net::CapturingNetLog::CapturedEntryList entries
;
2733 log
.GetEntries(&entries
);
2734 size_t pos
= ExpectLogContainsSomewhere(
2735 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2736 NetLog::PHASE_NONE
);
2737 ExpectLogContainsSomewhere(
2739 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2740 NetLog::PHASE_NONE
);
2743 // Test the load timing for HTTPS requests with an HTTP proxy.
2744 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2745 HttpRequestInfo request1
;
2746 request1
.method
= "GET";
2747 request1
.url
= GURL("https://www.google.com/1");
2749 HttpRequestInfo request2
;
2750 request2
.method
= "GET";
2751 request2
.url
= GURL("https://www.google.com/2");
2753 // Configure against proxy server "myproxy:70".
2754 session_deps_
.proxy_service
.reset(
2755 ProxyService::CreateFixed("PROXY myproxy:70"));
2756 CapturingBoundNetLog log
;
2757 session_deps_
.net_log
= log
.bound().net_log();
2758 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2760 // Since we have proxy, should try to establish tunnel.
2761 MockWrite data_writes1
[] = {
2762 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2763 "Host: www.google.com\r\n"
2764 "Proxy-Connection: keep-alive\r\n\r\n"),
2766 MockWrite("GET /1 HTTP/1.1\r\n"
2767 "Host: www.google.com\r\n"
2768 "Connection: keep-alive\r\n\r\n"),
2770 MockWrite("GET /2 HTTP/1.1\r\n"
2771 "Host: www.google.com\r\n"
2772 "Connection: keep-alive\r\n\r\n"),
2775 // The proxy responds to the connect with a 407, using a persistent
2777 MockRead data_reads1
[] = {
2778 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2780 MockRead("HTTP/1.1 200 OK\r\n"),
2781 MockRead("Content-Length: 1\r\n\r\n"),
2782 MockRead(SYNCHRONOUS
, "1"),
2784 MockRead("HTTP/1.1 200 OK\r\n"),
2785 MockRead("Content-Length: 2\r\n\r\n"),
2786 MockRead(SYNCHRONOUS
, "22"),
2789 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2790 data_writes1
, arraysize(data_writes1
));
2791 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2792 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2793 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2795 TestCompletionCallback callback1
;
2796 scoped_ptr
<HttpTransaction
> trans1(
2797 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2799 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2800 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2802 rv
= callback1
.WaitForResult();
2805 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2806 ASSERT_TRUE(response1
!= NULL
);
2807 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2808 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2810 LoadTimingInfo load_timing_info1
;
2811 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2812 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2816 TestCompletionCallback callback2
;
2817 scoped_ptr
<HttpTransaction
> trans2(
2818 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2820 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2823 rv
= callback2
.WaitForResult();
2826 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2827 ASSERT_TRUE(response2
!= NULL
);
2828 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2829 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2831 LoadTimingInfo load_timing_info2
;
2832 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2833 TestLoadTimingReused(load_timing_info2
);
2835 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2838 session
->CloseAllConnections();
2841 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2842 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2843 HttpRequestInfo request1
;
2844 request1
.method
= "GET";
2845 request1
.url
= GURL("https://www.google.com/1");
2847 HttpRequestInfo request2
;
2848 request2
.method
= "GET";
2849 request2
.url
= GURL("https://www.google.com/2");
2851 // Configure against proxy server "myproxy:70".
2852 session_deps_
.proxy_service
.reset(
2853 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2854 CapturingBoundNetLog log
;
2855 session_deps_
.net_log
= log
.bound().net_log();
2856 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2858 // Since we have proxy, should try to establish tunnel.
2859 MockWrite data_writes1
[] = {
2860 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2861 "Host: www.google.com\r\n"
2862 "Proxy-Connection: keep-alive\r\n\r\n"),
2864 MockWrite("GET /1 HTTP/1.1\r\n"
2865 "Host: www.google.com\r\n"
2866 "Connection: keep-alive\r\n\r\n"),
2868 MockWrite("GET /2 HTTP/1.1\r\n"
2869 "Host: www.google.com\r\n"
2870 "Connection: keep-alive\r\n\r\n"),
2873 // The proxy responds to the connect with a 407, using a persistent
2875 MockRead data_reads1
[] = {
2876 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2878 MockRead("HTTP/1.1 200 OK\r\n"),
2879 MockRead("Content-Length: 1\r\n\r\n"),
2880 MockRead(SYNCHRONOUS
, "1"),
2882 MockRead("HTTP/1.1 200 OK\r\n"),
2883 MockRead("Content-Length: 2\r\n\r\n"),
2884 MockRead(SYNCHRONOUS
, "22"),
2887 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2888 data_writes1
, arraysize(data_writes1
));
2889 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2890 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2893 TestCompletionCallback callback1
;
2894 scoped_ptr
<HttpTransaction
> trans1(
2895 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2897 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2898 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2900 rv
= callback1
.WaitForResult();
2903 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2904 ASSERT_TRUE(response1
!= NULL
);
2905 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2906 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2908 LoadTimingInfo load_timing_info1
;
2909 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2910 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2911 CONNECT_TIMING_HAS_SSL_TIMES
);
2915 TestCompletionCallback callback2
;
2916 scoped_ptr
<HttpTransaction
> trans2(
2917 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2919 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2920 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2922 rv
= callback2
.WaitForResult();
2925 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2926 ASSERT_TRUE(response2
!= NULL
);
2927 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2928 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2930 LoadTimingInfo load_timing_info2
;
2931 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2932 TestLoadTimingReusedWithPac(load_timing_info2
);
2934 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2937 session
->CloseAllConnections();
2940 // Test a simple get through an HTTPS Proxy.
2941 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2942 HttpRequestInfo request
;
2943 request
.method
= "GET";
2944 request
.url
= GURL("http://www.google.com/");
2946 // Configure against https proxy server "proxy:70".
2947 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2948 "https://proxy:70"));
2949 CapturingBoundNetLog log
;
2950 session_deps_
.net_log
= log
.bound().net_log();
2951 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2953 // Since we have proxy, should use full url
2954 MockWrite data_writes1
[] = {
2955 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2956 "Host: www.google.com\r\n"
2957 "Proxy-Connection: keep-alive\r\n\r\n"),
2960 MockRead data_reads1
[] = {
2961 MockRead("HTTP/1.1 200 OK\r\n"),
2962 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2963 MockRead("Content-Length: 100\r\n\r\n"),
2964 MockRead(SYNCHRONOUS
, OK
),
2967 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2968 data_writes1
, arraysize(data_writes1
));
2969 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2970 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2971 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2973 TestCompletionCallback callback1
;
2975 scoped_ptr
<HttpTransaction
> trans(
2976 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2978 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2981 rv
= callback1
.WaitForResult();
2984 LoadTimingInfo load_timing_info
;
2985 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2986 TestLoadTimingNotReused(load_timing_info
,
2987 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2989 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2990 ASSERT_TRUE(response
!= NULL
);
2992 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2993 EXPECT_EQ(200, response
->headers
->response_code());
2994 EXPECT_EQ(100, response
->headers
->GetContentLength());
2995 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2997 // The password prompt info should not be set.
2998 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3001 // Test a SPDY get through an HTTPS Proxy.
3002 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3003 HttpRequestInfo request
;
3004 request
.method
= "GET";
3005 request
.url
= GURL("http://www.google.com/");
3006 request
.load_flags
= 0;
3008 // Configure against https proxy server "proxy:70".
3009 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3010 "https://proxy:70"));
3011 CapturingBoundNetLog log
;
3012 session_deps_
.net_log
= log
.bound().net_log();
3013 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3015 // fetch http://www.google.com/ via SPDY
3016 scoped_ptr
<SpdyFrame
> req(
3017 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3018 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
3020 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3021 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3022 MockRead spdy_reads
[] = {
3023 CreateMockRead(*resp
),
3024 CreateMockRead(*data
),
3025 MockRead(ASYNC
, 0, 0),
3028 DelayedSocketData
spdy_data(
3029 1, // wait for one write to finish before reading.
3030 spdy_reads
, arraysize(spdy_reads
),
3031 spdy_writes
, arraysize(spdy_writes
));
3032 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3034 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3035 ssl
.SetNextProto(GetParam());
3036 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3038 TestCompletionCallback callback1
;
3040 scoped_ptr
<HttpTransaction
> trans(
3041 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3043 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3044 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3046 rv
= callback1
.WaitForResult();
3049 LoadTimingInfo load_timing_info
;
3050 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3051 TestLoadTimingNotReused(load_timing_info
,
3052 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3054 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3055 ASSERT_TRUE(response
!= NULL
);
3056 ASSERT_TRUE(response
->headers
.get() != NULL
);
3057 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3059 std::string response_data
;
3060 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3061 EXPECT_EQ(kUploadData
, response_data
);
3064 // Verifies that a session which races and wins against the owning transaction
3065 // (completing prior to host resolution), doesn't fail the transaction.
3066 // Regression test for crbug.com/334413.
3067 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3068 HttpRequestInfo request
;
3069 request
.method
= "GET";
3070 request
.url
= GURL("http://www.google.com/");
3071 request
.load_flags
= 0;
3073 // Configure SPDY proxy server "proxy:70".
3074 session_deps_
.proxy_service
.reset(
3075 ProxyService::CreateFixed("https://proxy:70"));
3076 CapturingBoundNetLog log
;
3077 session_deps_
.net_log
= log
.bound().net_log();
3078 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3080 // Fetch http://www.google.com/ through the SPDY proxy.
3081 scoped_ptr
<SpdyFrame
> req(
3082 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3083 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3085 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3086 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3087 MockRead spdy_reads
[] = {
3088 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3091 DelayedSocketData
spdy_data(
3092 1, // wait for one write to finish before reading.
3094 arraysize(spdy_reads
),
3096 arraysize(spdy_writes
));
3097 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3099 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3100 ssl
.SetNextProto(GetParam());
3101 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3103 TestCompletionCallback callback1
;
3105 scoped_ptr
<HttpTransaction
> trans(
3106 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3108 // Stall the hostname resolution begun by the transaction.
3109 session_deps_
.host_resolver
->set_synchronous_mode(false);
3110 session_deps_
.host_resolver
->set_ondemand_mode(true);
3112 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3113 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3115 // Race a session to the proxy, which completes first.
3116 session_deps_
.host_resolver
->set_ondemand_mode(false);
3118 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3119 base::WeakPtr
<SpdySession
> spdy_session
=
3120 CreateSecureSpdySession(session
, key
, log
.bound());
3122 // Unstall the resolution begun by the transaction.
3123 session_deps_
.host_resolver
->set_ondemand_mode(true);
3124 session_deps_
.host_resolver
->ResolveAllPending();
3126 EXPECT_FALSE(callback1
.have_result());
3127 rv
= callback1
.WaitForResult();
3130 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3131 ASSERT_TRUE(response
!= NULL
);
3132 ASSERT_TRUE(response
->headers
.get() != NULL
);
3133 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3135 std::string response_data
;
3136 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3137 EXPECT_EQ(kUploadData
, response_data
);
3140 // Test a SPDY get through an HTTPS Proxy.
3141 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3142 HttpRequestInfo request
;
3143 request
.method
= "GET";
3144 request
.url
= GURL("http://www.google.com/");
3145 request
.load_flags
= 0;
3147 // Configure against https proxy server "myproxy:70".
3148 session_deps_
.proxy_service
.reset(
3149 ProxyService::CreateFixed("https://myproxy:70"));
3150 CapturingBoundNetLog log
;
3151 session_deps_
.net_log
= log
.bound().net_log();
3152 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3154 // The first request will be a bare GET, the second request will be a
3155 // GET with a Proxy-Authorization header.
3156 scoped_ptr
<SpdyFrame
> req_get(
3157 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3158 const char* const kExtraAuthorizationHeaders
[] = {
3159 "proxy-authorization", "Basic Zm9vOmJhcg=="
3161 scoped_ptr
<SpdyFrame
> req_get_authorization(
3162 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3163 arraysize(kExtraAuthorizationHeaders
) / 2,
3168 MockWrite spdy_writes
[] = {
3169 CreateMockWrite(*req_get
, 1),
3170 CreateMockWrite(*req_get_authorization
, 4),
3173 // The first response is a 407 proxy authentication challenge, and the second
3174 // response will be a 200 response since the second request includes a valid
3175 // Authorization header.
3176 const char* const kExtraAuthenticationHeaders
[] = {
3177 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3179 scoped_ptr
<SpdyFrame
> resp_authentication(
3180 spdy_util_
.ConstructSpdySynReplyError(
3181 "407 Proxy Authentication Required",
3182 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3184 scoped_ptr
<SpdyFrame
> body_authentication(
3185 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3186 scoped_ptr
<SpdyFrame
> resp_data(
3187 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3188 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3189 MockRead spdy_reads
[] = {
3190 CreateMockRead(*resp_authentication
, 2),
3191 CreateMockRead(*body_authentication
, 3),
3192 CreateMockRead(*resp_data
, 5),
3193 CreateMockRead(*body_data
, 6),
3194 MockRead(ASYNC
, 0, 7),
3197 OrderedSocketData
data(
3198 spdy_reads
, arraysize(spdy_reads
),
3199 spdy_writes
, arraysize(spdy_writes
));
3200 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3202 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3203 ssl
.SetNextProto(GetParam());
3204 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3206 TestCompletionCallback callback1
;
3208 scoped_ptr
<HttpTransaction
> trans(
3209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3211 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3212 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3214 rv
= callback1
.WaitForResult();
3217 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3219 ASSERT_TRUE(response
!= NULL
);
3220 ASSERT_TRUE(response
->headers
.get() != NULL
);
3221 EXPECT_EQ(407, response
->headers
->response_code());
3222 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3223 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3225 TestCompletionCallback callback2
;
3227 rv
= trans
->RestartWithAuth(
3228 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3229 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3231 rv
= callback2
.WaitForResult();
3234 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3236 ASSERT_TRUE(response_restart
!= NULL
);
3237 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3238 EXPECT_EQ(200, response_restart
->headers
->response_code());
3239 // The password prompt info should not be set.
3240 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3243 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3244 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3245 HttpRequestInfo request
;
3246 request
.method
= "GET";
3247 request
.url
= GURL("https://www.google.com/");
3248 request
.load_flags
= 0;
3250 // Configure against https proxy server "proxy:70".
3251 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3252 "https://proxy:70"));
3253 CapturingBoundNetLog log
;
3254 session_deps_
.net_log
= log
.bound().net_log();
3255 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3257 scoped_ptr
<HttpTransaction
> trans(
3258 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3260 // CONNECT to www.google.com:443 via SPDY
3261 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3263 // fetch https://www.google.com/ via HTTP
3265 const char get
[] = "GET / HTTP/1.1\r\n"
3266 "Host: www.google.com\r\n"
3267 "Connection: keep-alive\r\n\r\n";
3268 scoped_ptr
<SpdyFrame
> wrapped_get(
3269 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3270 scoped_ptr
<SpdyFrame
> conn_resp(
3271 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3272 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3273 "Content-Length: 10\r\n\r\n";
3274 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3275 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3276 scoped_ptr
<SpdyFrame
> wrapped_body(
3277 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3278 scoped_ptr
<SpdyFrame
> window_update(
3279 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3281 MockWrite spdy_writes
[] = {
3282 CreateMockWrite(*connect
, 1),
3283 CreateMockWrite(*wrapped_get
, 3),
3284 CreateMockWrite(*window_update
, 5),
3287 MockRead spdy_reads
[] = {
3288 CreateMockRead(*conn_resp
, 2, ASYNC
),
3289 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3290 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3291 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3292 MockRead(ASYNC
, 0, 8),
3295 OrderedSocketData
spdy_data(
3296 spdy_reads
, arraysize(spdy_reads
),
3297 spdy_writes
, arraysize(spdy_writes
));
3298 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3300 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3301 ssl
.SetNextProto(GetParam());
3302 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3303 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3304 ssl2
.was_npn_negotiated
= false;
3305 ssl2
.protocol_negotiated
= kProtoUnknown
;
3306 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3308 TestCompletionCallback callback1
;
3310 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3311 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3313 rv
= callback1
.WaitForResult();
3316 LoadTimingInfo load_timing_info
;
3317 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3318 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3320 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3321 ASSERT_TRUE(response
!= NULL
);
3322 ASSERT_TRUE(response
->headers
.get() != NULL
);
3323 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3325 std::string response_data
;
3326 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3327 EXPECT_EQ("1234567890", response_data
);
3330 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3331 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3332 HttpRequestInfo request
;
3333 request
.method
= "GET";
3334 request
.url
= GURL("https://www.google.com/");
3335 request
.load_flags
= 0;
3337 // Configure against https proxy server "proxy:70".
3338 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3339 "https://proxy:70"));
3340 CapturingBoundNetLog log
;
3341 session_deps_
.net_log
= log
.bound().net_log();
3342 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3344 scoped_ptr
<HttpTransaction
> trans(
3345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3347 // CONNECT to www.google.com:443 via SPDY
3348 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3350 // fetch https://www.google.com/ via SPDY
3351 const char* const kMyUrl
= "https://www.google.com/";
3352 scoped_ptr
<SpdyFrame
> get(
3353 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3354 scoped_ptr
<SpdyFrame
> wrapped_get(
3355 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3356 scoped_ptr
<SpdyFrame
> conn_resp(
3357 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3358 scoped_ptr
<SpdyFrame
> get_resp(
3359 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3360 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3361 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3362 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3363 scoped_ptr
<SpdyFrame
> wrapped_body(
3364 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3365 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3366 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3367 scoped_ptr
<SpdyFrame
> window_update_body(
3368 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3370 MockWrite spdy_writes
[] = {
3371 CreateMockWrite(*connect
, 1),
3372 CreateMockWrite(*wrapped_get
, 3),
3373 CreateMockWrite(*window_update_get_resp
, 5),
3374 CreateMockWrite(*window_update_body
, 7),
3377 MockRead spdy_reads
[] = {
3378 CreateMockRead(*conn_resp
, 2, ASYNC
),
3379 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3380 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3381 MockRead(ASYNC
, 0, 8),
3384 OrderedSocketData
spdy_data(
3385 spdy_reads
, arraysize(spdy_reads
),
3386 spdy_writes
, arraysize(spdy_writes
));
3387 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3389 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3390 ssl
.SetNextProto(GetParam());
3391 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3392 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3393 ssl2
.SetNextProto(GetParam());
3394 ssl2
.protocol_negotiated
= GetParam();
3395 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3397 TestCompletionCallback callback1
;
3399 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3402 rv
= callback1
.WaitForResult();
3405 LoadTimingInfo load_timing_info
;
3406 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3407 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3409 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3410 ASSERT_TRUE(response
!= NULL
);
3411 ASSERT_TRUE(response
->headers
.get() != NULL
);
3412 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3414 std::string response_data
;
3415 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3416 EXPECT_EQ(kUploadData
, response_data
);
3419 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3420 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3421 HttpRequestInfo request
;
3422 request
.method
= "GET";
3423 request
.url
= GURL("https://www.google.com/");
3424 request
.load_flags
= 0;
3426 // Configure against https proxy server "proxy:70".
3427 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3428 "https://proxy:70"));
3429 CapturingBoundNetLog log
;
3430 session_deps_
.net_log
= log
.bound().net_log();
3431 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3433 scoped_ptr
<HttpTransaction
> trans(
3434 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3436 // CONNECT to www.google.com:443 via SPDY
3437 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3439 scoped_ptr
<SpdyFrame
> get(
3440 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3442 MockWrite spdy_writes
[] = {
3443 CreateMockWrite(*connect
, 1),
3444 CreateMockWrite(*get
, 3),
3447 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3448 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3449 MockRead spdy_reads
[] = {
3450 CreateMockRead(*resp
, 2, ASYNC
),
3451 MockRead(ASYNC
, 0, 4),
3454 OrderedSocketData
spdy_data(
3455 spdy_reads
, arraysize(spdy_reads
),
3456 spdy_writes
, arraysize(spdy_writes
));
3457 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3459 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3460 ssl
.SetNextProto(GetParam());
3461 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3462 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3463 ssl2
.SetNextProto(GetParam());
3464 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3466 TestCompletionCallback callback1
;
3468 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3469 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3471 rv
= callback1
.WaitForResult();
3472 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3474 // TODO(ttuttle): Anything else to check here?
3477 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3478 // HTTPS Proxy to different servers.
3479 TEST_P(HttpNetworkTransactionTest
,
3480 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3481 // Configure against https proxy server "proxy:70".
3482 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3483 "https://proxy:70"));
3484 CapturingBoundNetLog log
;
3485 session_deps_
.net_log
= log
.bound().net_log();
3486 scoped_refptr
<HttpNetworkSession
> session(
3487 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3489 HttpRequestInfo request1
;
3490 request1
.method
= "GET";
3491 request1
.url
= GURL("https://www.google.com/");
3492 request1
.load_flags
= 0;
3494 HttpRequestInfo request2
;
3495 request2
.method
= "GET";
3496 request2
.url
= GURL("https://news.google.com/");
3497 request2
.load_flags
= 0;
3499 // CONNECT to www.google.com:443 via SPDY.
3500 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3502 scoped_ptr
<SpdyFrame
> conn_resp1(
3503 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3505 // Fetch https://www.google.com/ via HTTP.
3506 const char get1
[] = "GET / HTTP/1.1\r\n"
3507 "Host: www.google.com\r\n"
3508 "Connection: keep-alive\r\n\r\n";
3509 scoped_ptr
<SpdyFrame
> wrapped_get1(
3510 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3511 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3512 "Content-Length: 1\r\n\r\n";
3513 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3514 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3515 scoped_ptr
<SpdyFrame
> wrapped_body1(
3516 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3517 scoped_ptr
<SpdyFrame
> window_update(
3518 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3520 // CONNECT to news.google.com:443 via SPDY.
3521 SpdyHeaderBlock connect2_block
;
3522 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3523 connect2_block
[spdy_util_
.GetPathKey()] = "news.google.com:443";
3524 connect2_block
[spdy_util_
.GetHostKey()] = "news.google.com";
3525 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3526 scoped_ptr
<SpdyFrame
> connect2(
3527 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3529 scoped_ptr
<SpdyFrame
> conn_resp2(
3530 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3532 // Fetch https://news.google.com/ via HTTP.
3533 const char get2
[] = "GET / HTTP/1.1\r\n"
3534 "Host: news.google.com\r\n"
3535 "Connection: keep-alive\r\n\r\n";
3536 scoped_ptr
<SpdyFrame
> wrapped_get2(
3537 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3538 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3539 "Content-Length: 2\r\n\r\n";
3540 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3541 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3542 scoped_ptr
<SpdyFrame
> wrapped_body2(
3543 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3545 MockWrite spdy_writes
[] = {
3546 CreateMockWrite(*connect1
, 0),
3547 CreateMockWrite(*wrapped_get1
, 2),
3548 CreateMockWrite(*connect2
, 5),
3549 CreateMockWrite(*wrapped_get2
, 7),
3552 MockRead spdy_reads
[] = {
3553 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3554 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3555 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3556 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3557 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3558 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3559 MockRead(ASYNC
, 0, 10),
3562 DeterministicSocketData
spdy_data(
3563 spdy_reads
, arraysize(spdy_reads
),
3564 spdy_writes
, arraysize(spdy_writes
));
3565 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3567 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3568 ssl
.SetNextProto(GetParam());
3569 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3570 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3571 ssl2
.was_npn_negotiated
= false;
3572 ssl2
.protocol_negotiated
= kProtoUnknown
;
3573 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3574 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3575 ssl3
.was_npn_negotiated
= false;
3576 ssl3
.protocol_negotiated
= kProtoUnknown
;
3577 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3579 TestCompletionCallback callback
;
3581 scoped_ptr
<HttpTransaction
> trans(
3582 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3583 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3584 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3585 // The first connect and request, each of their responses, and the body.
3586 spdy_data
.RunFor(5);
3588 rv
= callback
.WaitForResult();
3591 LoadTimingInfo load_timing_info
;
3592 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3593 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3595 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3596 ASSERT_TRUE(response
!= NULL
);
3597 ASSERT_TRUE(response
->headers
.get() != NULL
);
3598 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3600 std::string response_data
;
3601 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3602 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3604 scoped_ptr
<HttpTransaction
> trans2(
3605 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3606 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3607 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3609 // The second connect and request, each of their responses, and the body.
3610 spdy_data
.RunFor(5);
3611 rv
= callback
.WaitForResult();
3614 LoadTimingInfo load_timing_info2
;
3615 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3616 // Even though the SPDY connection is reused, a new tunnelled connection has
3617 // to be created, so the socket's load timing looks like a fresh connection.
3618 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3620 // The requests should have different IDs, since they each are using their own
3622 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3624 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3627 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3628 // HTTPS Proxy to the same server.
3629 TEST_P(HttpNetworkTransactionTest
,
3630 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3631 // Configure against https proxy server "proxy:70".
3632 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3633 "https://proxy:70"));
3634 CapturingBoundNetLog log
;
3635 session_deps_
.net_log
= log
.bound().net_log();
3636 scoped_refptr
<HttpNetworkSession
> session(
3637 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3639 HttpRequestInfo request1
;
3640 request1
.method
= "GET";
3641 request1
.url
= GURL("https://www.google.com/");
3642 request1
.load_flags
= 0;
3644 HttpRequestInfo request2
;
3645 request2
.method
= "GET";
3646 request2
.url
= GURL("https://www.google.com/2");
3647 request2
.load_flags
= 0;
3649 // CONNECT to www.google.com:443 via SPDY.
3650 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3652 scoped_ptr
<SpdyFrame
> conn_resp1(
3653 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3655 // Fetch https://www.google.com/ via HTTP.
3656 const char get1
[] = "GET / HTTP/1.1\r\n"
3657 "Host: www.google.com\r\n"
3658 "Connection: keep-alive\r\n\r\n";
3659 scoped_ptr
<SpdyFrame
> wrapped_get1(
3660 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3661 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3662 "Content-Length: 1\r\n\r\n";
3663 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3664 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3665 scoped_ptr
<SpdyFrame
> wrapped_body1(
3666 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3667 scoped_ptr
<SpdyFrame
> window_update(
3668 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3670 // Fetch https://www.google.com/2 via HTTP.
3671 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3672 "Host: www.google.com\r\n"
3673 "Connection: keep-alive\r\n\r\n";
3674 scoped_ptr
<SpdyFrame
> wrapped_get2(
3675 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3676 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3677 "Content-Length: 2\r\n\r\n";
3678 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3679 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3680 scoped_ptr
<SpdyFrame
> wrapped_body2(
3681 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3683 MockWrite spdy_writes
[] = {
3684 CreateMockWrite(*connect1
, 0),
3685 CreateMockWrite(*wrapped_get1
, 2),
3686 CreateMockWrite(*wrapped_get2
, 5),
3689 MockRead spdy_reads
[] = {
3690 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3691 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3692 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3693 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3694 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3695 MockRead(ASYNC
, 0, 8),
3698 DeterministicSocketData
spdy_data(
3699 spdy_reads
, arraysize(spdy_reads
),
3700 spdy_writes
, arraysize(spdy_writes
));
3701 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3703 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3704 ssl
.SetNextProto(GetParam());
3705 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3706 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3707 ssl2
.was_npn_negotiated
= false;
3708 ssl2
.protocol_negotiated
= kProtoUnknown
;
3709 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3711 TestCompletionCallback callback
;
3713 scoped_ptr
<HttpTransaction
> trans(
3714 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3715 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3716 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3717 // The first connect and request, each of their responses, and the body.
3718 spdy_data
.RunFor(5);
3720 rv
= callback
.WaitForResult();
3723 LoadTimingInfo load_timing_info
;
3724 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3725 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3727 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3728 ASSERT_TRUE(response
!= NULL
);
3729 ASSERT_TRUE(response
->headers
.get() != NULL
);
3730 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3732 std::string response_data
;
3733 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3734 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3737 scoped_ptr
<HttpTransaction
> trans2(
3738 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3739 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3740 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3742 // The second request, response, and body. There should not be a second
3744 spdy_data
.RunFor(3);
3745 rv
= callback
.WaitForResult();
3748 LoadTimingInfo load_timing_info2
;
3749 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3750 TestLoadTimingReused(load_timing_info2
);
3752 // The requests should have the same ID.
3753 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3755 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3758 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3759 // Proxy to different servers.
3760 TEST_P(HttpNetworkTransactionTest
,
3761 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3762 // Configure against https proxy server "proxy:70".
3763 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3764 "https://proxy:70"));
3765 CapturingBoundNetLog log
;
3766 session_deps_
.net_log
= log
.bound().net_log();
3767 scoped_refptr
<HttpNetworkSession
> session(
3768 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3770 HttpRequestInfo request1
;
3771 request1
.method
= "GET";
3772 request1
.url
= GURL("http://www.google.com/");
3773 request1
.load_flags
= 0;
3775 HttpRequestInfo request2
;
3776 request2
.method
= "GET";
3777 request2
.url
= GURL("http://news.google.com/");
3778 request2
.load_flags
= 0;
3780 // http://www.google.com/
3781 scoped_ptr
<SpdyHeaderBlock
> headers(
3782 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3783 scoped_ptr
<SpdyFrame
> get1(
3784 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
3785 scoped_ptr
<SpdyFrame
> get_resp1(
3786 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3787 scoped_ptr
<SpdyFrame
> body1(
3788 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3790 // http://news.google.com/
3791 scoped_ptr
<SpdyHeaderBlock
> headers2(
3792 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3793 scoped_ptr
<SpdyFrame
> get2(
3794 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
3795 scoped_ptr
<SpdyFrame
> get_resp2(
3796 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3797 scoped_ptr
<SpdyFrame
> body2(
3798 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3800 MockWrite spdy_writes
[] = {
3801 CreateMockWrite(*get1
, 0),
3802 CreateMockWrite(*get2
, 3),
3805 MockRead spdy_reads
[] = {
3806 CreateMockRead(*get_resp1
, 1, ASYNC
),
3807 CreateMockRead(*body1
, 2, ASYNC
),
3808 CreateMockRead(*get_resp2
, 4, ASYNC
),
3809 CreateMockRead(*body2
, 5, ASYNC
),
3810 MockRead(ASYNC
, 0, 6),
3813 DeterministicSocketData
spdy_data(
3814 spdy_reads
, arraysize(spdy_reads
),
3815 spdy_writes
, arraysize(spdy_writes
));
3816 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3818 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3819 ssl
.SetNextProto(GetParam());
3820 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3822 TestCompletionCallback callback
;
3824 scoped_ptr
<HttpTransaction
> trans(
3825 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3826 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3827 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3828 spdy_data
.RunFor(2);
3830 rv
= callback
.WaitForResult();
3833 LoadTimingInfo load_timing_info
;
3834 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3835 TestLoadTimingNotReused(load_timing_info
,
3836 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3838 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3839 ASSERT_TRUE(response
!= NULL
);
3840 ASSERT_TRUE(response
->headers
.get() != NULL
);
3841 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3843 std::string response_data
;
3844 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3845 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3846 spdy_data
.RunFor(1);
3847 EXPECT_EQ(1, callback
.WaitForResult());
3848 // Delete the first request, so the second one can reuse the socket.
3851 scoped_ptr
<HttpTransaction
> trans2(
3852 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3853 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3856 spdy_data
.RunFor(2);
3857 rv
= callback
.WaitForResult();
3860 LoadTimingInfo load_timing_info2
;
3861 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3862 TestLoadTimingReused(load_timing_info2
);
3864 // The requests should have the same ID.
3865 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3867 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3868 spdy_data
.RunFor(1);
3869 EXPECT_EQ(2, callback
.WaitForResult());
3872 // Test the challenge-response-retry sequence through an HTTPS Proxy
3873 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3874 HttpRequestInfo request
;
3875 request
.method
= "GET";
3876 request
.url
= GURL("http://www.google.com/");
3877 // when the no authentication data flag is set.
3878 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3880 // Configure against https proxy server "myproxy:70".
3881 session_deps_
.proxy_service
.reset(
3882 ProxyService::CreateFixed("https://myproxy:70"));
3883 CapturingBoundNetLog log
;
3884 session_deps_
.net_log
= log
.bound().net_log();
3885 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3887 // Since we have proxy, should use full url
3888 MockWrite data_writes1
[] = {
3889 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3890 "Host: www.google.com\r\n"
3891 "Proxy-Connection: keep-alive\r\n\r\n"),
3893 // After calling trans->RestartWithAuth(), this is the request we should
3894 // be issuing -- the final header line contains the credentials.
3895 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3896 "Host: www.google.com\r\n"
3897 "Proxy-Connection: keep-alive\r\n"
3898 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3901 // The proxy responds to the GET with a 407, using a persistent
3903 MockRead data_reads1
[] = {
3905 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3906 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3907 MockRead("Proxy-Connection: keep-alive\r\n"),
3908 MockRead("Content-Length: 0\r\n\r\n"),
3910 MockRead("HTTP/1.1 200 OK\r\n"),
3911 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3912 MockRead("Content-Length: 100\r\n\r\n"),
3913 MockRead(SYNCHRONOUS
, OK
),
3916 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3917 data_writes1
, arraysize(data_writes1
));
3918 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3919 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3920 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3922 TestCompletionCallback callback1
;
3924 scoped_ptr
<HttpTransaction
> trans(
3925 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3927 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3928 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3930 rv
= callback1
.WaitForResult();
3933 LoadTimingInfo load_timing_info
;
3934 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3935 TestLoadTimingNotReused(load_timing_info
,
3936 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3938 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3939 ASSERT_TRUE(response
!= NULL
);
3940 ASSERT_FALSE(response
->headers
.get() == NULL
);
3941 EXPECT_EQ(407, response
->headers
->response_code());
3942 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3943 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3945 TestCompletionCallback callback2
;
3947 rv
= trans
->RestartWithAuth(
3948 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3949 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3951 rv
= callback2
.WaitForResult();
3954 load_timing_info
= LoadTimingInfo();
3955 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3956 // Retrying with HTTP AUTH is considered to be reusing a socket.
3957 TestLoadTimingReused(load_timing_info
);
3959 response
= trans
->GetResponseInfo();
3960 ASSERT_TRUE(response
!= NULL
);
3962 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3963 EXPECT_EQ(200, response
->headers
->response_code());
3964 EXPECT_EQ(100, response
->headers
->GetContentLength());
3965 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3967 // The password prompt info should not be set.
3968 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3971 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3972 const MockRead
& status
, int expected_status
) {
3973 HttpRequestInfo request
;
3974 request
.method
= "GET";
3975 request
.url
= GURL("https://www.google.com/");
3976 request
.load_flags
= 0;
3978 // Configure against proxy server "myproxy:70".
3979 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3980 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3982 // Since we have proxy, should try to establish tunnel.
3983 MockWrite data_writes
[] = {
3984 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3985 "Host: www.google.com\r\n"
3986 "Proxy-Connection: keep-alive\r\n\r\n"),
3989 MockRead data_reads
[] = {
3991 MockRead("Content-Length: 10\r\n\r\n"),
3992 // No response body because the test stops reading here.
3993 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3996 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3997 data_writes
, arraysize(data_writes
));
3998 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4000 TestCompletionCallback callback
;
4002 scoped_ptr
<HttpTransaction
> trans(
4003 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4005 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4006 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4008 rv
= callback
.WaitForResult();
4009 EXPECT_EQ(expected_status
, rv
);
4012 void HttpNetworkTransactionTest::ConnectStatusHelper(
4013 const MockRead
& status
) {
4014 ConnectStatusHelperWithExpectedStatus(
4015 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4018 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4019 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4022 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4023 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4026 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4027 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4030 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4031 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4034 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4035 ConnectStatusHelper(
4036 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4039 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4040 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4043 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4044 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4047 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4048 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4051 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4052 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4055 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4056 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4059 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4060 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4063 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4064 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4067 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4068 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4071 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4072 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4075 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4076 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4079 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4080 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4083 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4084 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4087 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4088 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4091 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4092 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4095 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4096 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4099 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4100 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4103 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4104 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4107 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4108 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4111 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4112 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4115 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4116 ConnectStatusHelperWithExpectedStatus(
4117 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4118 ERR_PROXY_AUTH_UNSUPPORTED
);
4121 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4122 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4125 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4126 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4129 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4130 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4133 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4134 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4137 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4138 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4141 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4142 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4145 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4146 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4149 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4150 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4153 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4154 ConnectStatusHelper(
4155 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4158 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4159 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4162 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4163 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4166 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4167 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4170 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4171 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4174 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4175 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4178 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4179 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4182 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4183 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4186 // Test the flow when both the proxy server AND origin server require
4187 // authentication. Again, this uses basic auth for both since that is
4188 // the simplest to mock.
4189 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4190 HttpRequestInfo request
;
4191 request
.method
= "GET";
4192 request
.url
= GURL("http://www.google.com/");
4193 request
.load_flags
= 0;
4195 // Configure against proxy server "myproxy:70".
4196 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4197 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4199 scoped_ptr
<HttpTransaction
> trans(
4200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4202 MockWrite data_writes1
[] = {
4203 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4204 "Host: www.google.com\r\n"
4205 "Proxy-Connection: keep-alive\r\n\r\n"),
4208 MockRead data_reads1
[] = {
4209 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4210 // Give a couple authenticate options (only the middle one is actually
4212 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4213 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4214 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4216 // Large content-length -- won't matter, as connection will be reset.
4217 MockRead("Content-Length: 10000\r\n\r\n"),
4218 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4221 // After calling trans->RestartWithAuth() the first time, this is the
4222 // request we should be issuing -- the final header line contains the
4223 // proxy's credentials.
4224 MockWrite data_writes2
[] = {
4225 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4226 "Host: www.google.com\r\n"
4227 "Proxy-Connection: keep-alive\r\n"
4228 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4231 // Now the proxy server lets the request pass through to origin server.
4232 // The origin server responds with a 401.
4233 MockRead data_reads2
[] = {
4234 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4235 // Note: We are using the same realm-name as the proxy server. This is
4236 // completely valid, as realms are unique across hosts.
4237 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4238 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4239 MockRead("Content-Length: 2000\r\n\r\n"),
4240 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4243 // After calling trans->RestartWithAuth() the second time, we should send
4244 // the credentials for both the proxy and origin server.
4245 MockWrite data_writes3
[] = {
4246 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4247 "Host: www.google.com\r\n"
4248 "Proxy-Connection: keep-alive\r\n"
4249 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4250 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4253 // Lastly we get the desired content.
4254 MockRead data_reads3
[] = {
4255 MockRead("HTTP/1.0 200 OK\r\n"),
4256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4257 MockRead("Content-Length: 100\r\n\r\n"),
4258 MockRead(SYNCHRONOUS
, OK
),
4261 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4262 data_writes1
, arraysize(data_writes1
));
4263 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4264 data_writes2
, arraysize(data_writes2
));
4265 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4266 data_writes3
, arraysize(data_writes3
));
4267 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4268 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4269 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4271 TestCompletionCallback callback1
;
4273 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4276 rv
= callback1
.WaitForResult();
4279 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4280 ASSERT_TRUE(response
!= NULL
);
4281 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4283 TestCompletionCallback callback2
;
4285 rv
= trans
->RestartWithAuth(
4286 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4287 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4289 rv
= callback2
.WaitForResult();
4292 response
= trans
->GetResponseInfo();
4293 ASSERT_TRUE(response
!= NULL
);
4294 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4296 TestCompletionCallback callback3
;
4298 rv
= trans
->RestartWithAuth(
4299 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4300 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4302 rv
= callback3
.WaitForResult();
4305 response
= trans
->GetResponseInfo();
4306 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4307 EXPECT_EQ(100, response
->headers
->GetContentLength());
4310 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4311 // can't hook into its internals to cause it to generate predictable NTLM
4312 // authorization headers.
4313 #if defined(NTLM_PORTABLE)
4314 // The NTLM authentication unit tests were generated by capturing the HTTP
4315 // requests and responses using Fiddler 2 and inspecting the generated random
4316 // bytes in the debugger.
4318 // Enter the correct password and authenticate successfully.
4319 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4320 HttpRequestInfo request
;
4321 request
.method
= "GET";
4322 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4324 // Ensure load is not disrupted by flags which suppress behaviour specific
4325 // to other auth schemes.
4326 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4328 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4330 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4332 MockWrite data_writes1
[] = {
4333 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4334 "Host: 172.22.68.17\r\n"
4335 "Connection: keep-alive\r\n\r\n"),
4338 MockRead data_reads1
[] = {
4339 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4340 // Negotiate and NTLM are often requested together. However, we only want
4341 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4342 // the header that requests Negotiate for this test.
4343 MockRead("WWW-Authenticate: NTLM\r\n"),
4344 MockRead("Connection: close\r\n"),
4345 MockRead("Content-Length: 42\r\n"),
4346 MockRead("Content-Type: text/html\r\n\r\n"),
4347 // Missing content -- won't matter, as connection will be reset.
4348 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4351 MockWrite data_writes2
[] = {
4352 // After restarting with a null identity, this is the
4353 // request we should be issuing -- the final header line contains a Type
4355 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4356 "Host: 172.22.68.17\r\n"
4357 "Connection: keep-alive\r\n"
4358 "Authorization: NTLM "
4359 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4361 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4362 // (the credentials for the origin server). The second request continues
4363 // on the same connection.
4364 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4365 "Host: 172.22.68.17\r\n"
4366 "Connection: keep-alive\r\n"
4367 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4368 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4369 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4370 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4371 "ahlhx5I=\r\n\r\n"),
4374 MockRead data_reads2
[] = {
4375 // The origin server responds with a Type 2 message.
4376 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4377 MockRead("WWW-Authenticate: NTLM "
4378 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4379 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4380 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4381 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4382 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4383 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4385 MockRead("Content-Length: 42\r\n"),
4386 MockRead("Content-Type: text/html\r\n\r\n"),
4387 MockRead("You are not authorized to view this page\r\n"),
4389 // Lastly we get the desired content.
4390 MockRead("HTTP/1.1 200 OK\r\n"),
4391 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4392 MockRead("Content-Length: 13\r\n\r\n"),
4393 MockRead("Please Login\r\n"),
4394 MockRead(SYNCHRONOUS
, OK
),
4397 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4398 data_writes1
, arraysize(data_writes1
));
4399 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4400 data_writes2
, arraysize(data_writes2
));
4401 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4402 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4404 TestCompletionCallback callback1
;
4406 scoped_ptr
<HttpTransaction
> trans(
4407 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4409 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4410 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4412 rv
= callback1
.WaitForResult();
4415 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4417 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4418 ASSERT_FALSE(response
== NULL
);
4419 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4421 TestCompletionCallback callback2
;
4423 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4424 callback2
.callback());
4425 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4427 rv
= callback2
.WaitForResult();
4430 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4432 response
= trans
->GetResponseInfo();
4433 ASSERT_TRUE(response
!= NULL
);
4434 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4436 TestCompletionCallback callback3
;
4438 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4439 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4441 rv
= callback3
.WaitForResult();
4444 response
= trans
->GetResponseInfo();
4445 ASSERT_TRUE(response
!= NULL
);
4446 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4447 EXPECT_EQ(13, response
->headers
->GetContentLength());
4450 // Enter a wrong password, and then the correct one.
4451 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4452 HttpRequestInfo request
;
4453 request
.method
= "GET";
4454 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4455 request
.load_flags
= 0;
4457 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4459 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4461 MockWrite data_writes1
[] = {
4462 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4463 "Host: 172.22.68.17\r\n"
4464 "Connection: keep-alive\r\n\r\n"),
4467 MockRead data_reads1
[] = {
4468 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4469 // Negotiate and NTLM are often requested together. However, we only want
4470 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4471 // the header that requests Negotiate for this test.
4472 MockRead("WWW-Authenticate: NTLM\r\n"),
4473 MockRead("Connection: close\r\n"),
4474 MockRead("Content-Length: 42\r\n"),
4475 MockRead("Content-Type: text/html\r\n\r\n"),
4476 // Missing content -- won't matter, as connection will be reset.
4477 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4480 MockWrite data_writes2
[] = {
4481 // After restarting with a null identity, this is the
4482 // request we should be issuing -- the final header line contains a Type
4484 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4485 "Host: 172.22.68.17\r\n"
4486 "Connection: keep-alive\r\n"
4487 "Authorization: NTLM "
4488 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4490 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4491 // (the credentials for the origin server). The second request continues
4492 // on the same connection.
4493 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4494 "Host: 172.22.68.17\r\n"
4495 "Connection: keep-alive\r\n"
4496 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4497 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4498 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4499 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4500 "4Ww7b7E=\r\n\r\n"),
4503 MockRead data_reads2
[] = {
4504 // The origin server responds with a Type 2 message.
4505 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4506 MockRead("WWW-Authenticate: NTLM "
4507 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4508 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4509 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4510 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4511 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4512 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4514 MockRead("Content-Length: 42\r\n"),
4515 MockRead("Content-Type: text/html\r\n\r\n"),
4516 MockRead("You are not authorized to view this page\r\n"),
4519 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4520 MockRead("WWW-Authenticate: NTLM\r\n"),
4521 MockRead("Connection: close\r\n"),
4522 MockRead("Content-Length: 42\r\n"),
4523 MockRead("Content-Type: text/html\r\n\r\n"),
4524 // Missing content -- won't matter, as connection will be reset.
4525 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4528 MockWrite data_writes3
[] = {
4529 // After restarting with a null identity, this is the
4530 // request we should be issuing -- the final header line contains a Type
4532 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4533 "Host: 172.22.68.17\r\n"
4534 "Connection: keep-alive\r\n"
4535 "Authorization: NTLM "
4536 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4538 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4539 // (the credentials for the origin server). The second request continues
4540 // on the same connection.
4541 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4542 "Host: 172.22.68.17\r\n"
4543 "Connection: keep-alive\r\n"
4544 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4545 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4546 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4547 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4548 "+4MUm7c=\r\n\r\n"),
4551 MockRead data_reads3
[] = {
4552 // The origin server responds with a Type 2 message.
4553 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4554 MockRead("WWW-Authenticate: NTLM "
4555 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4556 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4557 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4558 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4559 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4560 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4562 MockRead("Content-Length: 42\r\n"),
4563 MockRead("Content-Type: text/html\r\n\r\n"),
4564 MockRead("You are not authorized to view this page\r\n"),
4566 // Lastly we get the desired content.
4567 MockRead("HTTP/1.1 200 OK\r\n"),
4568 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4569 MockRead("Content-Length: 13\r\n\r\n"),
4570 MockRead("Please Login\r\n"),
4571 MockRead(SYNCHRONOUS
, OK
),
4574 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4575 data_writes1
, arraysize(data_writes1
));
4576 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4577 data_writes2
, arraysize(data_writes2
));
4578 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4579 data_writes3
, arraysize(data_writes3
));
4580 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4581 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4582 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4584 TestCompletionCallback callback1
;
4586 scoped_ptr
<HttpTransaction
> trans(
4587 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4589 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4590 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4592 rv
= callback1
.WaitForResult();
4595 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4597 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4598 ASSERT_TRUE(response
!= NULL
);
4599 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4601 TestCompletionCallback callback2
;
4603 // Enter the wrong password.
4604 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4605 callback2
.callback());
4606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4608 rv
= callback2
.WaitForResult();
4611 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4612 TestCompletionCallback callback3
;
4613 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4614 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4615 rv
= callback3
.WaitForResult();
4617 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4619 response
= trans
->GetResponseInfo();
4620 ASSERT_FALSE(response
== NULL
);
4621 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4623 TestCompletionCallback callback4
;
4625 // Now enter the right password.
4626 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4627 callback4
.callback());
4628 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4630 rv
= callback4
.WaitForResult();
4633 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4635 TestCompletionCallback callback5
;
4637 // One more roundtrip
4638 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4641 rv
= callback5
.WaitForResult();
4644 response
= trans
->GetResponseInfo();
4645 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4646 EXPECT_EQ(13, response
->headers
->GetContentLength());
4648 #endif // NTLM_PORTABLE
4650 // Test reading a server response which has only headers, and no body.
4651 // After some maximum number of bytes is consumed, the transaction should
4652 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4653 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4654 HttpRequestInfo request
;
4655 request
.method
= "GET";
4656 request
.url
= GURL("http://www.google.com/");
4657 request
.load_flags
= 0;
4659 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4660 scoped_ptr
<HttpTransaction
> trans(
4661 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4663 // Respond with 300 kb of headers (we should fail after 256 kb).
4664 std::string large_headers_string
;
4665 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4667 MockRead data_reads
[] = {
4668 MockRead("HTTP/1.0 200 OK\r\n"),
4669 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4670 MockRead("\r\nBODY"),
4671 MockRead(SYNCHRONOUS
, OK
),
4673 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4674 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4676 TestCompletionCallback callback
;
4678 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4679 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4681 rv
= callback
.WaitForResult();
4682 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4684 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4685 EXPECT_TRUE(response
== NULL
);
4688 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4689 // establish tunnel.
4690 // http://code.google.com/p/chromium/issues/detail?id=3772
4691 TEST_P(HttpNetworkTransactionTest
,
4692 DontRecycleTransportSocketForSSLTunnel
) {
4693 HttpRequestInfo request
;
4694 request
.method
= "GET";
4695 request
.url
= GURL("https://www.google.com/");
4696 request
.load_flags
= 0;
4698 // Configure against proxy server "myproxy:70".
4699 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4701 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4703 scoped_ptr
<HttpTransaction
> trans(
4704 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4706 // Since we have proxy, should try to establish tunnel.
4707 MockWrite data_writes1
[] = {
4708 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4709 "Host: www.google.com\r\n"
4710 "Proxy-Connection: keep-alive\r\n\r\n"),
4713 // The proxy responds to the connect with a 404, using a persistent
4714 // connection. Usually a proxy would return 501 (not implemented),
4715 // or 200 (tunnel established).
4716 MockRead data_reads1
[] = {
4717 MockRead("HTTP/1.1 404 Not Found\r\n"),
4718 MockRead("Content-Length: 10\r\n\r\n"),
4719 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4722 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4723 data_writes1
, arraysize(data_writes1
));
4724 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4726 TestCompletionCallback callback1
;
4728 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4731 rv
= callback1
.WaitForResult();
4732 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4734 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4735 EXPECT_TRUE(response
== NULL
);
4737 // Empty the current queue. This is necessary because idle sockets are
4738 // added to the connection pool asynchronously with a PostTask.
4739 base::MessageLoop::current()->RunUntilIdle();
4741 // We now check to make sure the TCPClientSocket was not added back to
4743 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4745 base::MessageLoop::current()->RunUntilIdle();
4746 // Make sure that the socket didn't get recycled after calling the destructor.
4747 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4750 // Make sure that we recycle a socket after reading all of the response body.
4751 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4752 HttpRequestInfo request
;
4753 request
.method
= "GET";
4754 request
.url
= GURL("http://www.google.com/");
4755 request
.load_flags
= 0;
4757 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4759 scoped_ptr
<HttpTransaction
> trans(
4760 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4762 MockRead data_reads
[] = {
4763 // A part of the response body is received with the response headers.
4764 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4765 // The rest of the response body is received in two parts.
4768 MockRead("junk"), // Should not be read!!
4769 MockRead(SYNCHRONOUS
, OK
),
4772 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4773 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4775 TestCompletionCallback callback
;
4777 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4778 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4780 rv
= callback
.WaitForResult();
4783 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4784 ASSERT_TRUE(response
!= NULL
);
4786 EXPECT_TRUE(response
->headers
.get() != NULL
);
4787 std::string status_line
= response
->headers
->GetStatusLine();
4788 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4790 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4792 std::string response_data
;
4793 rv
= ReadTransaction(trans
.get(), &response_data
);
4795 EXPECT_EQ("hello world", response_data
);
4797 // Empty the current queue. This is necessary because idle sockets are
4798 // added to the connection pool asynchronously with a PostTask.
4799 base::MessageLoop::current()->RunUntilIdle();
4801 // We now check to make sure the socket was added back to the pool.
4802 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4805 // Make sure that we recycle a SSL socket after reading all of the response
4807 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4808 HttpRequestInfo request
;
4809 request
.method
= "GET";
4810 request
.url
= GURL("https://www.google.com/");
4811 request
.load_flags
= 0;
4813 MockWrite data_writes
[] = {
4814 MockWrite("GET / HTTP/1.1\r\n"
4815 "Host: www.google.com\r\n"
4816 "Connection: keep-alive\r\n\r\n"),
4819 MockRead data_reads
[] = {
4820 MockRead("HTTP/1.1 200 OK\r\n"),
4821 MockRead("Content-Length: 11\r\n\r\n"),
4822 MockRead("hello world"),
4823 MockRead(SYNCHRONOUS
, OK
),
4826 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4827 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4829 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4830 data_writes
, arraysize(data_writes
));
4831 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4833 TestCompletionCallback callback
;
4835 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4836 scoped_ptr
<HttpTransaction
> trans(
4837 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4839 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4841 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4842 EXPECT_EQ(OK
, callback
.WaitForResult());
4844 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4845 ASSERT_TRUE(response
!= NULL
);
4846 ASSERT_TRUE(response
->headers
.get() != NULL
);
4847 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4849 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4851 std::string response_data
;
4852 rv
= ReadTransaction(trans
.get(), &response_data
);
4854 EXPECT_EQ("hello world", response_data
);
4856 // Empty the current queue. This is necessary because idle sockets are
4857 // added to the connection pool asynchronously with a PostTask.
4858 base::MessageLoop::current()->RunUntilIdle();
4860 // We now check to make sure the socket was added back to the pool.
4861 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4864 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4865 // from the pool and make sure that we recover okay.
4866 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4867 HttpRequestInfo request
;
4868 request
.method
= "GET";
4869 request
.url
= GURL("https://www.google.com/");
4870 request
.load_flags
= 0;
4872 MockWrite data_writes
[] = {
4873 MockWrite("GET / HTTP/1.1\r\n"
4874 "Host: www.google.com\r\n"
4875 "Connection: keep-alive\r\n\r\n"),
4876 MockWrite("GET / HTTP/1.1\r\n"
4877 "Host: www.google.com\r\n"
4878 "Connection: keep-alive\r\n\r\n"),
4881 MockRead data_reads
[] = {
4882 MockRead("HTTP/1.1 200 OK\r\n"),
4883 MockRead("Content-Length: 11\r\n\r\n"),
4884 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4885 MockRead("hello world"),
4886 MockRead(ASYNC
, 0, 0) // EOF
4889 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4890 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4892 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4894 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4895 data_writes
, arraysize(data_writes
));
4896 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4897 data_writes
, arraysize(data_writes
));
4898 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4899 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4901 TestCompletionCallback callback
;
4903 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4904 scoped_ptr
<HttpTransaction
> trans(
4905 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4907 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4909 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4910 EXPECT_EQ(OK
, callback
.WaitForResult());
4912 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4913 ASSERT_TRUE(response
!= NULL
);
4914 ASSERT_TRUE(response
->headers
.get() != NULL
);
4915 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4917 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4919 std::string response_data
;
4920 rv
= ReadTransaction(trans
.get(), &response_data
);
4922 EXPECT_EQ("hello world", response_data
);
4924 // Empty the current queue. This is necessary because idle sockets are
4925 // added to the connection pool asynchronously with a PostTask.
4926 base::MessageLoop::current()->RunUntilIdle();
4928 // We now check to make sure the socket was added back to the pool.
4929 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4931 // Now start the second transaction, which should reuse the previous socket.
4933 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4935 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4937 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4938 EXPECT_EQ(OK
, callback
.WaitForResult());
4940 response
= trans
->GetResponseInfo();
4941 ASSERT_TRUE(response
!= NULL
);
4942 ASSERT_TRUE(response
->headers
.get() != NULL
);
4943 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4945 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4947 rv
= ReadTransaction(trans
.get(), &response_data
);
4949 EXPECT_EQ("hello world", response_data
);
4951 // Empty the current queue. This is necessary because idle sockets are
4952 // added to the connection pool asynchronously with a PostTask.
4953 base::MessageLoop::current()->RunUntilIdle();
4955 // We now check to make sure the socket was added back to the pool.
4956 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4959 // Make sure that we recycle a socket after a zero-length response.
4960 // http://crbug.com/9880
4961 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4962 HttpRequestInfo request
;
4963 request
.method
= "GET";
4964 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4965 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4966 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4967 "rt=prt.2642,ol.2649,xjs.2951");
4968 request
.load_flags
= 0;
4970 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4972 scoped_ptr
<HttpTransaction
> trans(
4973 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4975 MockRead data_reads
[] = {
4976 MockRead("HTTP/1.1 204 No Content\r\n"
4977 "Content-Length: 0\r\n"
4978 "Content-Type: text/html\r\n\r\n"),
4979 MockRead("junk"), // Should not be read!!
4980 MockRead(SYNCHRONOUS
, OK
),
4983 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4984 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4986 TestCompletionCallback callback
;
4988 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4989 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4991 rv
= callback
.WaitForResult();
4994 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4995 ASSERT_TRUE(response
!= NULL
);
4997 EXPECT_TRUE(response
->headers
.get() != NULL
);
4998 std::string status_line
= response
->headers
->GetStatusLine();
4999 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5001 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5003 std::string response_data
;
5004 rv
= ReadTransaction(trans
.get(), &response_data
);
5006 EXPECT_EQ("", response_data
);
5008 // Empty the current queue. This is necessary because idle sockets are
5009 // added to the connection pool asynchronously with a PostTask.
5010 base::MessageLoop::current()->RunUntilIdle();
5012 // We now check to make sure the socket was added back to the pool.
5013 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5016 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5017 ScopedVector
<UploadElementReader
> element_readers
;
5018 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5019 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5021 HttpRequestInfo request
[2];
5022 // Transaction 1: a GET request that succeeds. The socket is recycled
5024 request
[0].method
= "GET";
5025 request
[0].url
= GURL("http://www.google.com/");
5026 request
[0].load_flags
= 0;
5027 // Transaction 2: a POST request. Reuses the socket kept alive from
5028 // transaction 1. The first attempts fails when writing the POST data.
5029 // This causes the transaction to retry with a new socket. The second
5030 // attempt succeeds.
5031 request
[1].method
= "POST";
5032 request
[1].url
= GURL("http://www.google.com/login.cgi");
5033 request
[1].upload_data_stream
= &upload_data_stream
;
5034 request
[1].load_flags
= 0;
5036 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5038 // The first socket is used for transaction 1 and the first attempt of
5041 // The response of transaction 1.
5042 MockRead data_reads1
[] = {
5043 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5044 MockRead("hello world"),
5045 MockRead(SYNCHRONOUS
, OK
),
5047 // The mock write results of transaction 1 and the first attempt of
5049 MockWrite data_writes1
[] = {
5050 MockWrite(SYNCHRONOUS
, 64), // GET
5051 MockWrite(SYNCHRONOUS
, 93), // POST
5052 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5054 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5055 data_writes1
, arraysize(data_writes1
));
5057 // The second socket is used for the second attempt of transaction 2.
5059 // The response of transaction 2.
5060 MockRead data_reads2
[] = {
5061 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5062 MockRead("welcome"),
5063 MockRead(SYNCHRONOUS
, OK
),
5065 // The mock write results of the second attempt of transaction 2.
5066 MockWrite data_writes2
[] = {
5067 MockWrite(SYNCHRONOUS
, 93), // POST
5068 MockWrite(SYNCHRONOUS
, 3), // POST data
5070 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5071 data_writes2
, arraysize(data_writes2
));
5073 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5074 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5076 const char* kExpectedResponseData
[] = {
5077 "hello world", "welcome"
5080 for (int i
= 0; i
< 2; ++i
) {
5081 scoped_ptr
<HttpTransaction
> trans(
5082 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5084 TestCompletionCallback callback
;
5086 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5089 rv
= callback
.WaitForResult();
5092 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5093 ASSERT_TRUE(response
!= NULL
);
5095 EXPECT_TRUE(response
->headers
.get() != NULL
);
5096 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5098 std::string response_data
;
5099 rv
= ReadTransaction(trans
.get(), &response_data
);
5101 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5105 // Test the request-challenge-retry sequence for basic auth when there is
5106 // an identity in the URL. The request should be sent as normal, but when
5107 // it fails the identity from the URL is used to answer the challenge.
5108 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5109 HttpRequestInfo request
;
5110 request
.method
= "GET";
5111 request
.url
= GURL("http://foo:b@r@www.google.com/");
5112 request
.load_flags
= LOAD_NORMAL
;
5114 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5115 scoped_ptr
<HttpTransaction
> trans(
5116 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5118 // The password contains an escaped character -- for this test to pass it
5119 // will need to be unescaped by HttpNetworkTransaction.
5120 EXPECT_EQ("b%40r", request
.url
.password());
5122 MockWrite data_writes1
[] = {
5123 MockWrite("GET / HTTP/1.1\r\n"
5124 "Host: www.google.com\r\n"
5125 "Connection: keep-alive\r\n\r\n"),
5128 MockRead data_reads1
[] = {
5129 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5130 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5131 MockRead("Content-Length: 10\r\n\r\n"),
5132 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5135 // After the challenge above, the transaction will be restarted using the
5136 // identity from the url (foo, b@r) to answer the challenge.
5137 MockWrite data_writes2
[] = {
5138 MockWrite("GET / HTTP/1.1\r\n"
5139 "Host: www.google.com\r\n"
5140 "Connection: keep-alive\r\n"
5141 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5144 MockRead data_reads2
[] = {
5145 MockRead("HTTP/1.0 200 OK\r\n"),
5146 MockRead("Content-Length: 100\r\n\r\n"),
5147 MockRead(SYNCHRONOUS
, OK
),
5150 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5151 data_writes1
, arraysize(data_writes1
));
5152 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5153 data_writes2
, arraysize(data_writes2
));
5154 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5155 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5157 TestCompletionCallback callback1
;
5158 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5159 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5160 rv
= callback1
.WaitForResult();
5162 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5164 TestCompletionCallback callback2
;
5165 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5167 rv
= callback2
.WaitForResult();
5169 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5171 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5172 ASSERT_TRUE(response
!= NULL
);
5174 // There is no challenge info, since the identity in URL worked.
5175 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5177 EXPECT_EQ(100, response
->headers
->GetContentLength());
5179 // Empty the current queue.
5180 base::MessageLoop::current()->RunUntilIdle();
5183 // Test the request-challenge-retry sequence for basic auth when there is an
5184 // incorrect identity in the URL. The identity from the URL should be used only
5186 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5187 HttpRequestInfo request
;
5188 request
.method
= "GET";
5189 // Note: the URL has a username:password in it. The password "baz" is
5190 // wrong (should be "bar").
5191 request
.url
= GURL("http://foo:baz@www.google.com/");
5193 request
.load_flags
= LOAD_NORMAL
;
5195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5196 scoped_ptr
<HttpTransaction
> trans(
5197 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5199 MockWrite data_writes1
[] = {
5200 MockWrite("GET / HTTP/1.1\r\n"
5201 "Host: www.google.com\r\n"
5202 "Connection: keep-alive\r\n\r\n"),
5205 MockRead data_reads1
[] = {
5206 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5207 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5208 MockRead("Content-Length: 10\r\n\r\n"),
5209 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5212 // After the challenge above, the transaction will be restarted using the
5213 // identity from the url (foo, baz) to answer the challenge.
5214 MockWrite data_writes2
[] = {
5215 MockWrite("GET / HTTP/1.1\r\n"
5216 "Host: www.google.com\r\n"
5217 "Connection: keep-alive\r\n"
5218 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5221 MockRead data_reads2
[] = {
5222 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5223 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5224 MockRead("Content-Length: 10\r\n\r\n"),
5225 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5228 // After the challenge above, the transaction will be restarted using the
5229 // identity supplied by the user (foo, bar) to answer the challenge.
5230 MockWrite data_writes3
[] = {
5231 MockWrite("GET / HTTP/1.1\r\n"
5232 "Host: www.google.com\r\n"
5233 "Connection: keep-alive\r\n"
5234 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5237 MockRead data_reads3
[] = {
5238 MockRead("HTTP/1.0 200 OK\r\n"),
5239 MockRead("Content-Length: 100\r\n\r\n"),
5240 MockRead(SYNCHRONOUS
, OK
),
5243 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5244 data_writes1
, arraysize(data_writes1
));
5245 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5246 data_writes2
, arraysize(data_writes2
));
5247 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5248 data_writes3
, arraysize(data_writes3
));
5249 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5250 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5251 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5253 TestCompletionCallback callback1
;
5255 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5258 rv
= callback1
.WaitForResult();
5261 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5262 TestCompletionCallback callback2
;
5263 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5264 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5265 rv
= callback2
.WaitForResult();
5267 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5269 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5270 ASSERT_TRUE(response
!= NULL
);
5271 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5273 TestCompletionCallback callback3
;
5274 rv
= trans
->RestartWithAuth(
5275 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5276 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5277 rv
= callback3
.WaitForResult();
5279 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5281 response
= trans
->GetResponseInfo();
5282 ASSERT_TRUE(response
!= NULL
);
5284 // There is no challenge info, since the identity worked.
5285 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5287 EXPECT_EQ(100, response
->headers
->GetContentLength());
5289 // Empty the current queue.
5290 base::MessageLoop::current()->RunUntilIdle();
5294 // Test the request-challenge-retry sequence for basic auth when there is a
5295 // correct identity in the URL, but its use is being suppressed. The identity
5296 // from the URL should never be used.
5297 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5298 HttpRequestInfo request
;
5299 request
.method
= "GET";
5300 request
.url
= GURL("http://foo:bar@www.google.com/");
5301 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5303 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5304 scoped_ptr
<HttpTransaction
> trans(
5305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5307 MockWrite data_writes1
[] = {
5308 MockWrite("GET / HTTP/1.1\r\n"
5309 "Host: www.google.com\r\n"
5310 "Connection: keep-alive\r\n\r\n"),
5313 MockRead data_reads1
[] = {
5314 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5315 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5316 MockRead("Content-Length: 10\r\n\r\n"),
5317 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5320 // After the challenge above, the transaction will be restarted using the
5321 // identity supplied by the user, not the one in the URL, to answer the
5323 MockWrite data_writes3
[] = {
5324 MockWrite("GET / HTTP/1.1\r\n"
5325 "Host: www.google.com\r\n"
5326 "Connection: keep-alive\r\n"
5327 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5330 MockRead data_reads3
[] = {
5331 MockRead("HTTP/1.0 200 OK\r\n"),
5332 MockRead("Content-Length: 100\r\n\r\n"),
5333 MockRead(SYNCHRONOUS
, OK
),
5336 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5337 data_writes1
, arraysize(data_writes1
));
5338 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5339 data_writes3
, arraysize(data_writes3
));
5340 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5341 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5343 TestCompletionCallback callback1
;
5344 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5345 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5346 rv
= callback1
.WaitForResult();
5348 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5350 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5351 ASSERT_TRUE(response
!= NULL
);
5352 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5354 TestCompletionCallback callback3
;
5355 rv
= trans
->RestartWithAuth(
5356 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5357 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5358 rv
= callback3
.WaitForResult();
5360 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5362 response
= trans
->GetResponseInfo();
5363 ASSERT_TRUE(response
!= NULL
);
5365 // There is no challenge info, since the identity worked.
5366 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5367 EXPECT_EQ(100, response
->headers
->GetContentLength());
5369 // Empty the current queue.
5370 base::MessageLoop::current()->RunUntilIdle();
5373 // Test that previously tried username/passwords for a realm get re-used.
5374 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5375 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5377 // Transaction 1: authenticate (foo, bar) on MyRealm1
5379 HttpRequestInfo request
;
5380 request
.method
= "GET";
5381 request
.url
= GURL("http://www.google.com/x/y/z");
5382 request
.load_flags
= 0;
5384 scoped_ptr
<HttpTransaction
> trans(
5385 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5387 MockWrite data_writes1
[] = {
5388 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5389 "Host: www.google.com\r\n"
5390 "Connection: keep-alive\r\n\r\n"),
5393 MockRead data_reads1
[] = {
5394 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5395 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5396 MockRead("Content-Length: 10000\r\n\r\n"),
5397 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5400 // Resend with authorization (username=foo, password=bar)
5401 MockWrite data_writes2
[] = {
5402 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5403 "Host: www.google.com\r\n"
5404 "Connection: keep-alive\r\n"
5405 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5408 // Sever accepts the authorization.
5409 MockRead data_reads2
[] = {
5410 MockRead("HTTP/1.0 200 OK\r\n"),
5411 MockRead("Content-Length: 100\r\n\r\n"),
5412 MockRead(SYNCHRONOUS
, OK
),
5415 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5416 data_writes1
, arraysize(data_writes1
));
5417 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5418 data_writes2
, arraysize(data_writes2
));
5419 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5420 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5422 TestCompletionCallback callback1
;
5424 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5425 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5427 rv
= callback1
.WaitForResult();
5430 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5431 ASSERT_TRUE(response
!= NULL
);
5432 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5434 TestCompletionCallback callback2
;
5436 rv
= trans
->RestartWithAuth(
5437 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5440 rv
= callback2
.WaitForResult();
5443 response
= trans
->GetResponseInfo();
5444 ASSERT_TRUE(response
!= NULL
);
5445 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5446 EXPECT_EQ(100, response
->headers
->GetContentLength());
5449 // ------------------------------------------------------------------------
5451 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5453 HttpRequestInfo request
;
5454 request
.method
= "GET";
5455 // Note that Transaction 1 was at /x/y/z, so this is in the same
5456 // protection space as MyRealm1.
5457 request
.url
= GURL("http://www.google.com/x/y/a/b");
5458 request
.load_flags
= 0;
5460 scoped_ptr
<HttpTransaction
> trans(
5461 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5463 MockWrite data_writes1
[] = {
5464 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5465 "Host: www.google.com\r\n"
5466 "Connection: keep-alive\r\n"
5467 // Send preemptive authorization for MyRealm1
5468 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5471 // The server didn't like the preemptive authorization, and
5472 // challenges us for a different realm (MyRealm2).
5473 MockRead data_reads1
[] = {
5474 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5475 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5476 MockRead("Content-Length: 10000\r\n\r\n"),
5477 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5480 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5481 MockWrite data_writes2
[] = {
5482 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5483 "Host: www.google.com\r\n"
5484 "Connection: keep-alive\r\n"
5485 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5488 // Sever accepts the authorization.
5489 MockRead data_reads2
[] = {
5490 MockRead("HTTP/1.0 200 OK\r\n"),
5491 MockRead("Content-Length: 100\r\n\r\n"),
5492 MockRead(SYNCHRONOUS
, OK
),
5495 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5496 data_writes1
, arraysize(data_writes1
));
5497 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5498 data_writes2
, arraysize(data_writes2
));
5499 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5500 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5502 TestCompletionCallback callback1
;
5504 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5507 rv
= callback1
.WaitForResult();
5510 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5511 ASSERT_TRUE(response
!= NULL
);
5512 ASSERT_TRUE(response
->auth_challenge
.get());
5513 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5514 EXPECT_EQ("www.google.com:80",
5515 response
->auth_challenge
->challenger
.ToString());
5516 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5517 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5519 TestCompletionCallback callback2
;
5521 rv
= trans
->RestartWithAuth(
5522 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5523 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5525 rv
= callback2
.WaitForResult();
5528 response
= trans
->GetResponseInfo();
5529 ASSERT_TRUE(response
!= NULL
);
5530 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5531 EXPECT_EQ(100, response
->headers
->GetContentLength());
5534 // ------------------------------------------------------------------------
5536 // Transaction 3: Resend a request in MyRealm's protection space --
5537 // succeed with preemptive authorization.
5539 HttpRequestInfo request
;
5540 request
.method
= "GET";
5541 request
.url
= GURL("http://www.google.com/x/y/z2");
5542 request
.load_flags
= 0;
5544 scoped_ptr
<HttpTransaction
> trans(
5545 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5547 MockWrite data_writes1
[] = {
5548 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5549 "Host: www.google.com\r\n"
5550 "Connection: keep-alive\r\n"
5551 // The authorization for MyRealm1 gets sent preemptively
5552 // (since the url is in the same protection space)
5553 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5556 // Sever accepts the preemptive authorization
5557 MockRead data_reads1
[] = {
5558 MockRead("HTTP/1.0 200 OK\r\n"),
5559 MockRead("Content-Length: 100\r\n\r\n"),
5560 MockRead(SYNCHRONOUS
, OK
),
5563 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5564 data_writes1
, arraysize(data_writes1
));
5565 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5567 TestCompletionCallback callback1
;
5569 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5570 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5572 rv
= callback1
.WaitForResult();
5575 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5576 ASSERT_TRUE(response
!= NULL
);
5578 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5579 EXPECT_EQ(100, response
->headers
->GetContentLength());
5582 // ------------------------------------------------------------------------
5584 // Transaction 4: request another URL in MyRealm (however the
5585 // url is not known to belong to the protection space, so no pre-auth).
5587 HttpRequestInfo request
;
5588 request
.method
= "GET";
5589 request
.url
= GURL("http://www.google.com/x/1");
5590 request
.load_flags
= 0;
5592 scoped_ptr
<HttpTransaction
> trans(
5593 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5595 MockWrite data_writes1
[] = {
5596 MockWrite("GET /x/1 HTTP/1.1\r\n"
5597 "Host: www.google.com\r\n"
5598 "Connection: keep-alive\r\n\r\n"),
5601 MockRead data_reads1
[] = {
5602 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5603 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5604 MockRead("Content-Length: 10000\r\n\r\n"),
5605 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5608 // Resend with authorization from MyRealm's cache.
5609 MockWrite data_writes2
[] = {
5610 MockWrite("GET /x/1 HTTP/1.1\r\n"
5611 "Host: www.google.com\r\n"
5612 "Connection: keep-alive\r\n"
5613 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5616 // Sever accepts the authorization.
5617 MockRead data_reads2
[] = {
5618 MockRead("HTTP/1.0 200 OK\r\n"),
5619 MockRead("Content-Length: 100\r\n\r\n"),
5620 MockRead(SYNCHRONOUS
, OK
),
5623 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5624 data_writes1
, arraysize(data_writes1
));
5625 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5626 data_writes2
, arraysize(data_writes2
));
5627 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5628 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5630 TestCompletionCallback callback1
;
5632 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5633 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5635 rv
= callback1
.WaitForResult();
5638 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5639 TestCompletionCallback callback2
;
5640 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5642 rv
= callback2
.WaitForResult();
5644 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5646 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5647 ASSERT_TRUE(response
!= NULL
);
5648 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5649 EXPECT_EQ(100, response
->headers
->GetContentLength());
5652 // ------------------------------------------------------------------------
5654 // Transaction 5: request a URL in MyRealm, but the server rejects the
5655 // cached identity. Should invalidate and re-prompt.
5657 HttpRequestInfo request
;
5658 request
.method
= "GET";
5659 request
.url
= GURL("http://www.google.com/p/q/t");
5660 request
.load_flags
= 0;
5662 scoped_ptr
<HttpTransaction
> trans(
5663 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5665 MockWrite data_writes1
[] = {
5666 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5667 "Host: www.google.com\r\n"
5668 "Connection: keep-alive\r\n\r\n"),
5671 MockRead data_reads1
[] = {
5672 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5673 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5674 MockRead("Content-Length: 10000\r\n\r\n"),
5675 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5678 // Resend with authorization from cache for MyRealm.
5679 MockWrite data_writes2
[] = {
5680 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5681 "Host: www.google.com\r\n"
5682 "Connection: keep-alive\r\n"
5683 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5686 // Sever rejects the authorization.
5687 MockRead data_reads2
[] = {
5688 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5689 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5690 MockRead("Content-Length: 10000\r\n\r\n"),
5691 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5694 // At this point we should prompt for new credentials for MyRealm.
5695 // Restart with username=foo3, password=foo4.
5696 MockWrite data_writes3
[] = {
5697 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5698 "Host: www.google.com\r\n"
5699 "Connection: keep-alive\r\n"
5700 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5703 // Sever accepts the authorization.
5704 MockRead data_reads3
[] = {
5705 MockRead("HTTP/1.0 200 OK\r\n"),
5706 MockRead("Content-Length: 100\r\n\r\n"),
5707 MockRead(SYNCHRONOUS
, OK
),
5710 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5711 data_writes1
, arraysize(data_writes1
));
5712 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5713 data_writes2
, arraysize(data_writes2
));
5714 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5715 data_writes3
, arraysize(data_writes3
));
5716 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5717 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5718 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5720 TestCompletionCallback callback1
;
5722 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5723 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5725 rv
= callback1
.WaitForResult();
5728 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5729 TestCompletionCallback callback2
;
5730 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5731 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5732 rv
= callback2
.WaitForResult();
5734 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5736 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5737 ASSERT_TRUE(response
!= NULL
);
5738 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5740 TestCompletionCallback callback3
;
5742 rv
= trans
->RestartWithAuth(
5743 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5744 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5746 rv
= callback3
.WaitForResult();
5749 response
= trans
->GetResponseInfo();
5750 ASSERT_TRUE(response
!= NULL
);
5751 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5752 EXPECT_EQ(100, response
->headers
->GetContentLength());
5756 // Tests that nonce count increments when multiple auth attempts
5757 // are started with the same nonce.
5758 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5759 HttpAuthHandlerDigest::Factory
* digest_factory
=
5760 new HttpAuthHandlerDigest::Factory();
5761 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5762 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5763 digest_factory
->set_nonce_generator(nonce_generator
);
5764 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5765 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5767 // Transaction 1: authenticate (foo, bar) on MyRealm1
5769 HttpRequestInfo request
;
5770 request
.method
= "GET";
5771 request
.url
= GURL("http://www.google.com/x/y/z");
5772 request
.load_flags
= 0;
5774 scoped_ptr
<HttpTransaction
> trans(
5775 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5777 MockWrite data_writes1
[] = {
5778 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5779 "Host: www.google.com\r\n"
5780 "Connection: keep-alive\r\n\r\n"),
5783 MockRead data_reads1
[] = {
5784 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5785 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5786 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5787 MockRead(SYNCHRONOUS
, OK
),
5790 // Resend with authorization (username=foo, password=bar)
5791 MockWrite data_writes2
[] = {
5792 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5793 "Host: www.google.com\r\n"
5794 "Connection: keep-alive\r\n"
5795 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5796 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5797 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5798 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5801 // Sever accepts the authorization.
5802 MockRead data_reads2
[] = {
5803 MockRead("HTTP/1.0 200 OK\r\n"),
5804 MockRead(SYNCHRONOUS
, OK
),
5807 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5808 data_writes1
, arraysize(data_writes1
));
5809 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5810 data_writes2
, arraysize(data_writes2
));
5811 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5812 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5814 TestCompletionCallback callback1
;
5816 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5817 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5819 rv
= callback1
.WaitForResult();
5822 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5823 ASSERT_TRUE(response
!= NULL
);
5824 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5826 TestCompletionCallback callback2
;
5828 rv
= trans
->RestartWithAuth(
5829 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5830 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5832 rv
= callback2
.WaitForResult();
5835 response
= trans
->GetResponseInfo();
5836 ASSERT_TRUE(response
!= NULL
);
5837 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5840 // ------------------------------------------------------------------------
5842 // Transaction 2: Request another resource in digestive's protection space.
5843 // This will preemptively add an Authorization header which should have an
5844 // "nc" value of 2 (as compared to 1 in the first use.
5846 HttpRequestInfo request
;
5847 request
.method
= "GET";
5848 // Note that Transaction 1 was at /x/y/z, so this is in the same
5849 // protection space as digest.
5850 request
.url
= GURL("http://www.google.com/x/y/a/b");
5851 request
.load_flags
= 0;
5853 scoped_ptr
<HttpTransaction
> trans(
5854 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5856 MockWrite data_writes1
[] = {
5857 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5858 "Host: www.google.com\r\n"
5859 "Connection: keep-alive\r\n"
5860 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5861 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5862 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5863 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5866 // Sever accepts the authorization.
5867 MockRead data_reads1
[] = {
5868 MockRead("HTTP/1.0 200 OK\r\n"),
5869 MockRead("Content-Length: 100\r\n\r\n"),
5870 MockRead(SYNCHRONOUS
, OK
),
5873 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5874 data_writes1
, arraysize(data_writes1
));
5875 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5877 TestCompletionCallback callback1
;
5879 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5880 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5882 rv
= callback1
.WaitForResult();
5885 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5886 ASSERT_TRUE(response
!= NULL
);
5887 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5891 // Test the ResetStateForRestart() private method.
5892 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5893 // Create a transaction (the dependencies aren't important).
5894 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5895 scoped_ptr
<HttpNetworkTransaction
> trans(
5896 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5898 // Setup some state (which we expect ResetStateForRestart() will clear).
5899 trans
->read_buf_
= new IOBuffer(15);
5900 trans
->read_buf_len_
= 15;
5901 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5903 // Setup state in response_
5904 HttpResponseInfo
* response
= &trans
->response_
;
5905 response
->auth_challenge
= new AuthChallengeInfo();
5906 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5907 response
->response_time
= base::Time::Now();
5908 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5910 { // Setup state for response_.vary_data
5911 HttpRequestInfo request
;
5912 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5913 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5914 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5915 request
.extra_headers
.SetHeader("Foo", "1");
5916 request
.extra_headers
.SetHeader("bar", "23");
5917 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5920 // Cause the above state to be reset.
5921 trans
->ResetStateForRestart();
5923 // Verify that the state that needed to be reset, has been reset.
5924 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5925 EXPECT_EQ(0, trans
->read_buf_len_
);
5926 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5927 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5928 EXPECT_TRUE(response
->headers
.get() == NULL
);
5929 EXPECT_FALSE(response
->was_cached
);
5930 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5931 EXPECT_FALSE(response
->vary_data
.is_valid());
5934 // Test HTTPS connections to a site with a bad certificate
5935 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5936 HttpRequestInfo request
;
5937 request
.method
= "GET";
5938 request
.url
= GURL("https://www.google.com/");
5939 request
.load_flags
= 0;
5941 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5942 scoped_ptr
<HttpTransaction
> trans(
5943 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5945 MockWrite data_writes
[] = {
5946 MockWrite("GET / HTTP/1.1\r\n"
5947 "Host: www.google.com\r\n"
5948 "Connection: keep-alive\r\n\r\n"),
5951 MockRead data_reads
[] = {
5952 MockRead("HTTP/1.0 200 OK\r\n"),
5953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5954 MockRead("Content-Length: 100\r\n\r\n"),
5955 MockRead(SYNCHRONOUS
, OK
),
5958 StaticSocketDataProvider ssl_bad_certificate
;
5959 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5960 data_writes
, arraysize(data_writes
));
5961 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5962 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5964 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5965 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5966 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5967 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5969 TestCompletionCallback callback
;
5971 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5972 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5974 rv
= callback
.WaitForResult();
5975 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5977 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5980 rv
= callback
.WaitForResult();
5983 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5985 ASSERT_TRUE(response
!= NULL
);
5986 EXPECT_EQ(100, response
->headers
->GetContentLength());
5989 // Test HTTPS connections to a site with a bad certificate, going through a
5991 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5992 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5994 HttpRequestInfo request
;
5995 request
.method
= "GET";
5996 request
.url
= GURL("https://www.google.com/");
5997 request
.load_flags
= 0;
5999 MockWrite proxy_writes
[] = {
6000 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6001 "Host: www.google.com\r\n"
6002 "Proxy-Connection: keep-alive\r\n\r\n"),
6005 MockRead proxy_reads
[] = {
6006 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6007 MockRead(SYNCHRONOUS
, OK
)
6010 MockWrite data_writes
[] = {
6011 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6012 "Host: www.google.com\r\n"
6013 "Proxy-Connection: keep-alive\r\n\r\n"),
6014 MockWrite("GET / HTTP/1.1\r\n"
6015 "Host: www.google.com\r\n"
6016 "Connection: keep-alive\r\n\r\n"),
6019 MockRead data_reads
[] = {
6020 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6021 MockRead("HTTP/1.0 200 OK\r\n"),
6022 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6023 MockRead("Content-Length: 100\r\n\r\n"),
6024 MockRead(SYNCHRONOUS
, OK
),
6027 StaticSocketDataProvider
ssl_bad_certificate(
6028 proxy_reads
, arraysize(proxy_reads
),
6029 proxy_writes
, arraysize(proxy_writes
));
6030 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6031 data_writes
, arraysize(data_writes
));
6032 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6033 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6035 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6036 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6037 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6038 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6040 TestCompletionCallback callback
;
6042 for (int i
= 0; i
< 2; i
++) {
6043 session_deps_
.socket_factory
->ResetNextMockIndexes();
6045 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6046 scoped_ptr
<HttpTransaction
> trans(
6047 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6049 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6050 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6052 rv
= callback
.WaitForResult();
6053 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6055 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6056 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6058 rv
= callback
.WaitForResult();
6061 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6063 ASSERT_TRUE(response
!= NULL
);
6064 EXPECT_EQ(100, response
->headers
->GetContentLength());
6069 // Test HTTPS connections to a site, going through an HTTPS proxy
6070 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6071 session_deps_
.proxy_service
.reset(
6072 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6073 CapturingNetLog net_log
;
6074 session_deps_
.net_log
= &net_log
;
6076 HttpRequestInfo request
;
6077 request
.method
= "GET";
6078 request
.url
= GURL("https://www.google.com/");
6079 request
.load_flags
= 0;
6081 MockWrite data_writes
[] = {
6082 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6083 "Host: www.google.com\r\n"
6084 "Proxy-Connection: keep-alive\r\n\r\n"),
6085 MockWrite("GET / HTTP/1.1\r\n"
6086 "Host: www.google.com\r\n"
6087 "Connection: keep-alive\r\n\r\n"),
6090 MockRead data_reads
[] = {
6091 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6092 MockRead("HTTP/1.1 200 OK\r\n"),
6093 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6094 MockRead("Content-Length: 100\r\n\r\n"),
6095 MockRead(SYNCHRONOUS
, OK
),
6098 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6099 data_writes
, arraysize(data_writes
));
6100 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6101 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6103 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6104 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6105 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6107 TestCompletionCallback callback
;
6109 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6110 scoped_ptr
<HttpTransaction
> trans(
6111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6113 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6116 rv
= callback
.WaitForResult();
6118 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6120 ASSERT_TRUE(response
!= NULL
);
6122 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6123 EXPECT_EQ(200, response
->headers
->response_code());
6124 EXPECT_EQ(100, response
->headers
->GetContentLength());
6125 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6127 LoadTimingInfo load_timing_info
;
6128 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6129 TestLoadTimingNotReusedWithPac(load_timing_info
,
6130 CONNECT_TIMING_HAS_SSL_TIMES
);
6133 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6134 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6135 session_deps_
.proxy_service
.reset(
6136 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6137 CapturingNetLog net_log
;
6138 session_deps_
.net_log
= &net_log
;
6140 HttpRequestInfo request
;
6141 request
.method
= "GET";
6142 request
.url
= GURL("https://www.google.com/");
6143 request
.load_flags
= 0;
6145 MockWrite data_writes
[] = {
6146 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6147 "Host: www.google.com\r\n"
6148 "Proxy-Connection: keep-alive\r\n\r\n"),
6151 MockRead data_reads
[] = {
6152 MockRead("HTTP/1.1 302 Redirect\r\n"),
6153 MockRead("Location: http://login.example.com/\r\n"),
6154 MockRead("Content-Length: 0\r\n\r\n"),
6155 MockRead(SYNCHRONOUS
, OK
),
6158 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6159 data_writes
, arraysize(data_writes
));
6160 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6162 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6163 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6165 TestCompletionCallback callback
;
6167 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6168 scoped_ptr
<HttpTransaction
> trans(
6169 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6171 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6172 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6174 rv
= callback
.WaitForResult();
6176 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6178 ASSERT_TRUE(response
!= NULL
);
6180 EXPECT_EQ(302, response
->headers
->response_code());
6182 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6183 EXPECT_EQ("http://login.example.com/", url
);
6185 // In the case of redirects from proxies, HttpNetworkTransaction returns
6186 // timing for the proxy connection instead of the connection to the host,
6187 // and no send / receive times.
6188 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6189 LoadTimingInfo load_timing_info
;
6190 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6192 EXPECT_FALSE(load_timing_info
.socket_reused
);
6193 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6195 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6196 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6197 load_timing_info
.proxy_resolve_end
);
6198 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6199 load_timing_info
.connect_timing
.connect_start
);
6200 ExpectConnectTimingHasTimes(
6201 load_timing_info
.connect_timing
,
6202 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6204 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6205 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6206 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6209 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6210 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6211 session_deps_
.proxy_service
.reset(
6212 ProxyService::CreateFixed("https://proxy:70"));
6214 HttpRequestInfo request
;
6215 request
.method
= "GET";
6216 request
.url
= GURL("https://www.google.com/");
6217 request
.load_flags
= 0;
6219 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6221 scoped_ptr
<SpdyFrame
> goaway(
6222 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6223 MockWrite data_writes
[] = {
6224 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6225 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6228 static const char* const kExtraHeaders
[] = {
6230 "http://login.example.com/",
6232 scoped_ptr
<SpdyFrame
> resp(
6233 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6234 arraysize(kExtraHeaders
)/2, 1));
6235 MockRead data_reads
[] = {
6236 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6237 MockRead(ASYNC
, 0, 2), // EOF
6240 DelayedSocketData
data(
6241 1, // wait for one write to finish before reading.
6242 data_reads
, arraysize(data_reads
),
6243 data_writes
, arraysize(data_writes
));
6244 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6245 proxy_ssl
.SetNextProto(GetParam());
6247 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6248 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6250 TestCompletionCallback callback
;
6252 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6253 scoped_ptr
<HttpTransaction
> trans(
6254 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6256 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6257 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6259 rv
= callback
.WaitForResult();
6261 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6263 ASSERT_TRUE(response
!= NULL
);
6265 EXPECT_EQ(302, response
->headers
->response_code());
6267 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6268 EXPECT_EQ("http://login.example.com/", url
);
6271 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6272 TEST_P(HttpNetworkTransactionTest
,
6273 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6274 session_deps_
.proxy_service
.reset(
6275 ProxyService::CreateFixed("https://proxy:70"));
6277 HttpRequestInfo request
;
6278 request
.method
= "GET";
6279 request
.url
= GURL("https://www.google.com/");
6280 request
.load_flags
= 0;
6282 MockWrite data_writes
[] = {
6283 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6284 "Host: www.google.com\r\n"
6285 "Proxy-Connection: keep-alive\r\n\r\n"),
6288 MockRead data_reads
[] = {
6289 MockRead("HTTP/1.1 404 Not Found\r\n"),
6290 MockRead("Content-Length: 23\r\n\r\n"),
6291 MockRead("The host does not exist"),
6292 MockRead(SYNCHRONOUS
, OK
),
6295 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6296 data_writes
, arraysize(data_writes
));
6297 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6299 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6300 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6302 TestCompletionCallback callback
;
6304 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6305 scoped_ptr
<HttpTransaction
> trans(
6306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6308 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6311 rv
= callback
.WaitForResult();
6312 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6314 // TODO(ttuttle): Anything else to check here?
6317 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6318 TEST_P(HttpNetworkTransactionTest
,
6319 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6320 session_deps_
.proxy_service
.reset(
6321 ProxyService::CreateFixed("https://proxy:70"));
6323 HttpRequestInfo request
;
6324 request
.method
= "GET";
6325 request
.url
= GURL("https://www.google.com/");
6326 request
.load_flags
= 0;
6328 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6330 scoped_ptr
<SpdyFrame
> rst(
6331 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6332 MockWrite data_writes
[] = {
6333 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6334 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6337 static const char* const kExtraHeaders
[] = {
6339 "http://login.example.com/",
6341 scoped_ptr
<SpdyFrame
> resp(
6342 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6343 arraysize(kExtraHeaders
)/2, 1));
6344 scoped_ptr
<SpdyFrame
> body(
6345 spdy_util_
.ConstructSpdyBodyFrame(
6346 1, "The host does not exist", 23, true));
6347 MockRead data_reads
[] = {
6348 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6349 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6350 MockRead(ASYNC
, 0, 4), // EOF
6353 DelayedSocketData
data(
6354 1, // wait for one write to finish before reading.
6355 data_reads
, arraysize(data_reads
),
6356 data_writes
, arraysize(data_writes
));
6357 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6358 proxy_ssl
.SetNextProto(GetParam());
6360 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6361 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6363 TestCompletionCallback callback
;
6365 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6366 scoped_ptr
<HttpTransaction
> trans(
6367 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6369 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6370 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6372 rv
= callback
.WaitForResult();
6373 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6375 // TODO(ttuttle): Anything else to check here?
6378 // Test the request-challenge-retry sequence for basic auth, through
6379 // a SPDY proxy over a single SPDY session.
6380 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6381 HttpRequestInfo request
;
6382 request
.method
= "GET";
6383 request
.url
= GURL("https://www.google.com/");
6384 // when the no authentication data flag is set.
6385 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6387 // Configure against https proxy server "myproxy:70".
6388 session_deps_
.proxy_service
.reset(
6389 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6390 CapturingBoundNetLog log
;
6391 session_deps_
.net_log
= log
.bound().net_log();
6392 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6394 // Since we have proxy, should try to establish tunnel.
6395 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6397 scoped_ptr
<SpdyFrame
> rst(
6398 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6400 // After calling trans->RestartWithAuth(), this is the request we should
6401 // be issuing -- the final header line contains the credentials.
6402 const char* const kAuthCredentials
[] = {
6403 "proxy-authorization", "Basic Zm9vOmJhcg==",
6405 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6406 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
));
6407 // fetch https://www.google.com/ via HTTP
6408 const char get
[] = "GET / HTTP/1.1\r\n"
6409 "Host: www.google.com\r\n"
6410 "Connection: keep-alive\r\n\r\n";
6411 scoped_ptr
<SpdyFrame
> wrapped_get(
6412 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6414 MockWrite spdy_writes
[] = {
6415 CreateMockWrite(*req
, 1, ASYNC
),
6416 CreateMockWrite(*rst
, 4, ASYNC
),
6417 CreateMockWrite(*connect2
, 5),
6418 CreateMockWrite(*wrapped_get
, 8),
6421 // The proxy responds to the connect with a 407, using a persistent
6423 const char* const kAuthStatus
= "407";
6424 const char* const kAuthChallenge
[] = {
6425 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6427 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6428 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6430 scoped_ptr
<SpdyFrame
> conn_resp(
6431 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6432 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6433 "Content-Length: 5\r\n\r\n";
6435 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6436 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6437 scoped_ptr
<SpdyFrame
> wrapped_body(
6438 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6439 MockRead spdy_reads
[] = {
6440 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6441 CreateMockRead(*conn_resp
, 6, ASYNC
),
6442 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6443 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6444 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6447 OrderedSocketData
spdy_data(
6448 spdy_reads
, arraysize(spdy_reads
),
6449 spdy_writes
, arraysize(spdy_writes
));
6450 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6451 // Negotiate SPDY to the proxy
6452 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6453 proxy
.SetNextProto(GetParam());
6454 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6455 // Vanilla SSL to the server
6456 SSLSocketDataProvider
server(ASYNC
, OK
);
6457 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6459 TestCompletionCallback callback1
;
6461 scoped_ptr
<HttpTransaction
> trans(
6462 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6464 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6465 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6467 rv
= callback1
.WaitForResult();
6469 net::CapturingNetLog::CapturedEntryList entries
;
6470 log
.GetEntries(&entries
);
6471 size_t pos
= ExpectLogContainsSomewhere(
6472 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6473 NetLog::PHASE_NONE
);
6474 ExpectLogContainsSomewhere(
6476 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6477 NetLog::PHASE_NONE
);
6479 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6480 ASSERT_TRUE(response
!= NULL
);
6481 ASSERT_FALSE(response
->headers
.get() == NULL
);
6482 EXPECT_EQ(407, response
->headers
->response_code());
6483 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6484 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6485 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6487 TestCompletionCallback callback2
;
6489 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6490 callback2
.callback());
6491 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6493 rv
= callback2
.WaitForResult();
6496 response
= trans
->GetResponseInfo();
6497 ASSERT_TRUE(response
!= NULL
);
6499 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6500 EXPECT_EQ(200, response
->headers
->response_code());
6501 EXPECT_EQ(5, response
->headers
->GetContentLength());
6502 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6504 // The password prompt info should not be set.
6505 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6507 LoadTimingInfo load_timing_info
;
6508 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6509 TestLoadTimingNotReusedWithPac(load_timing_info
,
6510 CONNECT_TIMING_HAS_SSL_TIMES
);
6513 session
->CloseAllConnections();
6516 // Test that an explicitly trusted SPDY proxy can push a resource from an
6517 // origin that is different from that of its associated resource.
6518 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6519 HttpRequestInfo request
;
6520 HttpRequestInfo push_request
;
6522 request
.method
= "GET";
6523 request
.url
= GURL("http://www.google.com/");
6524 push_request
.method
= "GET";
6525 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6527 // Configure against https proxy server "myproxy:70".
6528 session_deps_
.proxy_service
.reset(
6529 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6530 CapturingBoundNetLog log
;
6531 session_deps_
.net_log
= log
.bound().net_log();
6533 // Enable cross-origin push.
6534 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6536 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6538 scoped_ptr
<SpdyFrame
> stream1_syn(
6539 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6541 MockWrite spdy_writes
[] = {
6542 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6545 scoped_ptr
<SpdyFrame
>
6546 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6548 scoped_ptr
<SpdyFrame
>
6549 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6551 scoped_ptr
<SpdyFrame
>
6552 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6556 "http://www.another-origin.com/foo.dat"));
6557 const char kPushedData
[] = "pushed";
6558 scoped_ptr
<SpdyFrame
> stream2_body(
6559 spdy_util_
.ConstructSpdyBodyFrame(
6560 2, kPushedData
, strlen(kPushedData
), true));
6562 MockRead spdy_reads
[] = {
6563 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6564 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6565 CreateMockRead(*stream1_body
, 4, ASYNC
),
6566 CreateMockRead(*stream2_body
, 5, ASYNC
),
6567 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6570 OrderedSocketData
spdy_data(
6571 spdy_reads
, arraysize(spdy_reads
),
6572 spdy_writes
, arraysize(spdy_writes
));
6573 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6574 // Negotiate SPDY to the proxy
6575 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6576 proxy
.SetNextProto(GetParam());
6577 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6579 scoped_ptr
<HttpTransaction
> trans(
6580 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6581 TestCompletionCallback callback
;
6582 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6583 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6585 rv
= callback
.WaitForResult();
6587 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6589 scoped_ptr
<HttpTransaction
> push_trans(
6590 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6591 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6592 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6594 rv
= callback
.WaitForResult();
6596 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6598 ASSERT_TRUE(response
!= NULL
);
6599 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6601 EXPECT_EQ(200, response
->headers
->response_code());
6602 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6604 std::string response_data
;
6605 rv
= ReadTransaction(trans
.get(), &response_data
);
6607 EXPECT_EQ("hello!", response_data
);
6609 LoadTimingInfo load_timing_info
;
6610 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6611 TestLoadTimingNotReusedWithPac(load_timing_info
,
6612 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6614 // Verify the pushed stream.
6615 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6616 EXPECT_EQ(200, push_response
->headers
->response_code());
6618 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6620 EXPECT_EQ("pushed", response_data
);
6622 LoadTimingInfo push_load_timing_info
;
6623 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6624 TestLoadTimingReusedWithPac(push_load_timing_info
);
6625 // The transactions should share a socket ID, despite being for different
6627 EXPECT_EQ(load_timing_info
.socket_log_id
,
6628 push_load_timing_info
.socket_log_id
);
6632 session
->CloseAllConnections();
6635 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6636 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6637 HttpRequestInfo request
;
6639 request
.method
= "GET";
6640 request
.url
= GURL("http://www.google.com/");
6642 // Configure against https proxy server "myproxy:70".
6643 session_deps_
.proxy_service
.reset(
6644 ProxyService::CreateFixed("https://myproxy:70"));
6645 CapturingBoundNetLog log
;
6646 session_deps_
.net_log
= log
.bound().net_log();
6648 // Enable cross-origin push.
6649 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6651 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6653 scoped_ptr
<SpdyFrame
> stream1_syn(
6654 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6656 scoped_ptr
<SpdyFrame
> push_rst(
6657 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6659 MockWrite spdy_writes
[] = {
6660 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6661 CreateMockWrite(*push_rst
, 4),
6664 scoped_ptr
<SpdyFrame
>
6665 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6667 scoped_ptr
<SpdyFrame
>
6668 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6670 scoped_ptr
<SpdyFrame
>
6671 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6675 "https://www.another-origin.com/foo.dat"));
6677 MockRead spdy_reads
[] = {
6678 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6679 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6680 CreateMockRead(*stream1_body
, 5, ASYNC
),
6681 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6684 OrderedSocketData
spdy_data(
6685 spdy_reads
, arraysize(spdy_reads
),
6686 spdy_writes
, arraysize(spdy_writes
));
6687 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6688 // Negotiate SPDY to the proxy
6689 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6690 proxy
.SetNextProto(GetParam());
6691 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6693 scoped_ptr
<HttpTransaction
> trans(
6694 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6695 TestCompletionCallback callback
;
6696 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6699 rv
= callback
.WaitForResult();
6701 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6703 ASSERT_TRUE(response
!= NULL
);
6704 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6706 EXPECT_EQ(200, response
->headers
->response_code());
6707 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6709 std::string response_data
;
6710 rv
= ReadTransaction(trans
.get(), &response_data
);
6712 EXPECT_EQ("hello!", response_data
);
6715 session
->CloseAllConnections();
6718 // Test HTTPS connections to a site with a bad certificate, going through an
6720 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6721 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6722 "https://proxy:70"));
6724 HttpRequestInfo request
;
6725 request
.method
= "GET";
6726 request
.url
= GURL("https://www.google.com/");
6727 request
.load_flags
= 0;
6729 // Attempt to fetch the URL from a server with a bad cert
6730 MockWrite bad_cert_writes
[] = {
6731 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6732 "Host: www.google.com\r\n"
6733 "Proxy-Connection: keep-alive\r\n\r\n"),
6736 MockRead bad_cert_reads
[] = {
6737 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6738 MockRead(SYNCHRONOUS
, OK
)
6741 // Attempt to fetch the URL with a good cert
6742 MockWrite good_data_writes
[] = {
6743 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6744 "Host: www.google.com\r\n"
6745 "Proxy-Connection: keep-alive\r\n\r\n"),
6746 MockWrite("GET / HTTP/1.1\r\n"
6747 "Host: www.google.com\r\n"
6748 "Connection: keep-alive\r\n\r\n"),
6751 MockRead good_cert_reads
[] = {
6752 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6753 MockRead("HTTP/1.0 200 OK\r\n"),
6754 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6755 MockRead("Content-Length: 100\r\n\r\n"),
6756 MockRead(SYNCHRONOUS
, OK
),
6759 StaticSocketDataProvider
ssl_bad_certificate(
6760 bad_cert_reads
, arraysize(bad_cert_reads
),
6761 bad_cert_writes
, arraysize(bad_cert_writes
));
6762 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6763 good_data_writes
, arraysize(good_data_writes
));
6764 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6765 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6767 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6768 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6769 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6770 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6772 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6773 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6774 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6775 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6777 TestCompletionCallback callback
;
6779 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6780 scoped_ptr
<HttpTransaction
> trans(
6781 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6783 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6784 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6786 rv
= callback
.WaitForResult();
6787 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6789 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6790 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6792 rv
= callback
.WaitForResult();
6795 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6797 ASSERT_TRUE(response
!= NULL
);
6798 EXPECT_EQ(100, response
->headers
->GetContentLength());
6801 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6802 HttpRequestInfo request
;
6803 request
.method
= "GET";
6804 request
.url
= GURL("http://www.google.com/");
6805 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6806 "Chromium Ultra Awesome X Edition");
6808 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6809 scoped_ptr
<HttpTransaction
> trans(
6810 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6812 MockWrite data_writes
[] = {
6813 MockWrite("GET / HTTP/1.1\r\n"
6814 "Host: www.google.com\r\n"
6815 "Connection: keep-alive\r\n"
6816 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6819 // Lastly, the server responds with the actual content.
6820 MockRead data_reads
[] = {
6821 MockRead("HTTP/1.0 200 OK\r\n"),
6822 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6823 MockRead("Content-Length: 100\r\n\r\n"),
6824 MockRead(SYNCHRONOUS
, OK
),
6827 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6828 data_writes
, arraysize(data_writes
));
6829 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6831 TestCompletionCallback callback
;
6833 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6834 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6836 rv
= callback
.WaitForResult();
6840 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6841 HttpRequestInfo request
;
6842 request
.method
= "GET";
6843 request
.url
= GURL("https://www.google.com/");
6844 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6845 "Chromium Ultra Awesome X Edition");
6847 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6848 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6849 scoped_ptr
<HttpTransaction
> trans(
6850 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6852 MockWrite data_writes
[] = {
6853 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6854 "Host: www.google.com\r\n"
6855 "Proxy-Connection: keep-alive\r\n"
6856 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6858 MockRead data_reads
[] = {
6859 // Return an error, so the transaction stops here (this test isn't
6860 // interested in the rest).
6861 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6862 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6863 MockRead("Proxy-Connection: close\r\n\r\n"),
6866 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6867 data_writes
, arraysize(data_writes
));
6868 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6870 TestCompletionCallback callback
;
6872 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6873 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6875 rv
= callback
.WaitForResult();
6879 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6880 HttpRequestInfo request
;
6881 request
.method
= "GET";
6882 request
.url
= GURL("http://www.google.com/");
6883 request
.load_flags
= 0;
6884 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6885 "http://the.previous.site.com/");
6887 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6888 scoped_ptr
<HttpTransaction
> trans(
6889 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6891 MockWrite data_writes
[] = {
6892 MockWrite("GET / HTTP/1.1\r\n"
6893 "Host: www.google.com\r\n"
6894 "Connection: keep-alive\r\n"
6895 "Referer: http://the.previous.site.com/\r\n\r\n"),
6898 // Lastly, the server responds with the actual content.
6899 MockRead data_reads
[] = {
6900 MockRead("HTTP/1.0 200 OK\r\n"),
6901 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6902 MockRead("Content-Length: 100\r\n\r\n"),
6903 MockRead(SYNCHRONOUS
, OK
),
6906 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6907 data_writes
, arraysize(data_writes
));
6908 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6910 TestCompletionCallback callback
;
6912 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6913 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6915 rv
= callback
.WaitForResult();
6919 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6920 HttpRequestInfo request
;
6921 request
.method
= "POST";
6922 request
.url
= GURL("http://www.google.com/");
6924 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6925 scoped_ptr
<HttpTransaction
> trans(
6926 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6928 MockWrite data_writes
[] = {
6929 MockWrite("POST / HTTP/1.1\r\n"
6930 "Host: www.google.com\r\n"
6931 "Connection: keep-alive\r\n"
6932 "Content-Length: 0\r\n\r\n"),
6935 // Lastly, the server responds with the actual content.
6936 MockRead data_reads
[] = {
6937 MockRead("HTTP/1.0 200 OK\r\n"),
6938 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6939 MockRead("Content-Length: 100\r\n\r\n"),
6940 MockRead(SYNCHRONOUS
, OK
),
6943 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6944 data_writes
, arraysize(data_writes
));
6945 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6947 TestCompletionCallback callback
;
6949 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6952 rv
= callback
.WaitForResult();
6956 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6957 HttpRequestInfo request
;
6958 request
.method
= "PUT";
6959 request
.url
= GURL("http://www.google.com/");
6961 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6962 scoped_ptr
<HttpTransaction
> trans(
6963 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6965 MockWrite data_writes
[] = {
6966 MockWrite("PUT / HTTP/1.1\r\n"
6967 "Host: www.google.com\r\n"
6968 "Connection: keep-alive\r\n"
6969 "Content-Length: 0\r\n\r\n"),
6972 // Lastly, the server responds with the actual content.
6973 MockRead data_reads
[] = {
6974 MockRead("HTTP/1.0 200 OK\r\n"),
6975 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6976 MockRead("Content-Length: 100\r\n\r\n"),
6977 MockRead(SYNCHRONOUS
, OK
),
6980 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6981 data_writes
, arraysize(data_writes
));
6982 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6984 TestCompletionCallback callback
;
6986 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6987 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6989 rv
= callback
.WaitForResult();
6993 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6994 HttpRequestInfo request
;
6995 request
.method
= "HEAD";
6996 request
.url
= GURL("http://www.google.com/");
6998 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6999 scoped_ptr
<HttpTransaction
> trans(
7000 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7002 MockWrite data_writes
[] = {
7003 MockWrite("HEAD / HTTP/1.1\r\n"
7004 "Host: www.google.com\r\n"
7005 "Connection: keep-alive\r\n"
7006 "Content-Length: 0\r\n\r\n"),
7009 // Lastly, the server responds with the actual content.
7010 MockRead data_reads
[] = {
7011 MockRead("HTTP/1.0 200 OK\r\n"),
7012 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7013 MockRead("Content-Length: 100\r\n\r\n"),
7014 MockRead(SYNCHRONOUS
, OK
),
7017 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7018 data_writes
, arraysize(data_writes
));
7019 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7021 TestCompletionCallback callback
;
7023 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7024 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7026 rv
= callback
.WaitForResult();
7030 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7031 HttpRequestInfo request
;
7032 request
.method
= "GET";
7033 request
.url
= GURL("http://www.google.com/");
7034 request
.load_flags
= LOAD_BYPASS_CACHE
;
7036 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7037 scoped_ptr
<HttpTransaction
> trans(
7038 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7040 MockWrite data_writes
[] = {
7041 MockWrite("GET / HTTP/1.1\r\n"
7042 "Host: www.google.com\r\n"
7043 "Connection: keep-alive\r\n"
7044 "Pragma: no-cache\r\n"
7045 "Cache-Control: no-cache\r\n\r\n"),
7048 // Lastly, the server responds with the actual content.
7049 MockRead data_reads
[] = {
7050 MockRead("HTTP/1.0 200 OK\r\n"),
7051 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7052 MockRead("Content-Length: 100\r\n\r\n"),
7053 MockRead(SYNCHRONOUS
, OK
),
7056 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7057 data_writes
, arraysize(data_writes
));
7058 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7060 TestCompletionCallback callback
;
7062 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7063 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7065 rv
= callback
.WaitForResult();
7069 TEST_P(HttpNetworkTransactionTest
,
7070 BuildRequest_CacheControlValidateCache
) {
7071 HttpRequestInfo request
;
7072 request
.method
= "GET";
7073 request
.url
= GURL("http://www.google.com/");
7074 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7077 scoped_ptr
<HttpTransaction
> trans(
7078 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7080 MockWrite data_writes
[] = {
7081 MockWrite("GET / HTTP/1.1\r\n"
7082 "Host: www.google.com\r\n"
7083 "Connection: keep-alive\r\n"
7084 "Cache-Control: max-age=0\r\n\r\n"),
7087 // Lastly, the server responds with the actual content.
7088 MockRead data_reads
[] = {
7089 MockRead("HTTP/1.0 200 OK\r\n"),
7090 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7091 MockRead("Content-Length: 100\r\n\r\n"),
7092 MockRead(SYNCHRONOUS
, OK
),
7095 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7096 data_writes
, arraysize(data_writes
));
7097 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7099 TestCompletionCallback callback
;
7101 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7102 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7104 rv
= callback
.WaitForResult();
7108 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7109 HttpRequestInfo request
;
7110 request
.method
= "GET";
7111 request
.url
= GURL("http://www.google.com/");
7112 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7114 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7115 scoped_ptr
<HttpTransaction
> trans(
7116 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7118 MockWrite data_writes
[] = {
7119 MockWrite("GET / HTTP/1.1\r\n"
7120 "Host: www.google.com\r\n"
7121 "Connection: keep-alive\r\n"
7122 "FooHeader: Bar\r\n\r\n"),
7125 // Lastly, the server responds with the actual content.
7126 MockRead data_reads
[] = {
7127 MockRead("HTTP/1.0 200 OK\r\n"),
7128 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7129 MockRead("Content-Length: 100\r\n\r\n"),
7130 MockRead(SYNCHRONOUS
, OK
),
7133 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7134 data_writes
, arraysize(data_writes
));
7135 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7137 TestCompletionCallback callback
;
7139 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7140 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7142 rv
= callback
.WaitForResult();
7146 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7147 HttpRequestInfo request
;
7148 request
.method
= "GET";
7149 request
.url
= GURL("http://www.google.com/");
7150 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7151 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7152 request
.extra_headers
.SetHeader("FoO", "bar");
7154 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7155 scoped_ptr
<HttpTransaction
> trans(
7156 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7158 MockWrite data_writes
[] = {
7159 MockWrite("GET / HTTP/1.1\r\n"
7160 "Host: www.google.com\r\n"
7161 "Connection: keep-alive\r\n"
7162 "referer: www.foo.com\r\n"
7164 "FoO: bar\r\n\r\n"),
7167 // Lastly, the server responds with the actual content.
7168 MockRead data_reads
[] = {
7169 MockRead("HTTP/1.0 200 OK\r\n"),
7170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7171 MockRead("Content-Length: 100\r\n\r\n"),
7172 MockRead(SYNCHRONOUS
, OK
),
7175 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7176 data_writes
, arraysize(data_writes
));
7177 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7179 TestCompletionCallback callback
;
7181 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7182 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7184 rv
= callback
.WaitForResult();
7188 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7189 HttpRequestInfo request
;
7190 request
.method
= "GET";
7191 request
.url
= GURL("http://www.google.com/");
7192 request
.load_flags
= 0;
7194 session_deps_
.proxy_service
.reset(
7195 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7196 CapturingNetLog net_log
;
7197 session_deps_
.net_log
= &net_log
;
7199 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7200 scoped_ptr
<HttpTransaction
> trans(
7201 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7203 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7204 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7206 MockWrite data_writes
[] = {
7207 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7208 MockWrite("GET / HTTP/1.1\r\n"
7209 "Host: www.google.com\r\n"
7210 "Connection: keep-alive\r\n\r\n")
7213 MockRead data_reads
[] = {
7214 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7215 MockRead("HTTP/1.0 200 OK\r\n"),
7216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7217 MockRead("Payload"),
7218 MockRead(SYNCHRONOUS
, OK
)
7221 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7222 data_writes
, arraysize(data_writes
));
7223 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7225 TestCompletionCallback callback
;
7227 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7228 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7230 rv
= callback
.WaitForResult();
7233 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7234 ASSERT_TRUE(response
!= NULL
);
7236 LoadTimingInfo load_timing_info
;
7237 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7238 TestLoadTimingNotReusedWithPac(load_timing_info
,
7239 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7241 std::string response_text
;
7242 rv
= ReadTransaction(trans
.get(), &response_text
);
7244 EXPECT_EQ("Payload", response_text
);
7247 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7248 HttpRequestInfo request
;
7249 request
.method
= "GET";
7250 request
.url
= GURL("https://www.google.com/");
7251 request
.load_flags
= 0;
7253 session_deps_
.proxy_service
.reset(
7254 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7255 CapturingNetLog net_log
;
7256 session_deps_
.net_log
= &net_log
;
7258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7259 scoped_ptr
<HttpTransaction
> trans(
7260 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7262 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7263 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7265 MockWrite data_writes
[] = {
7266 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7267 arraysize(write_buffer
)),
7268 MockWrite("GET / HTTP/1.1\r\n"
7269 "Host: www.google.com\r\n"
7270 "Connection: keep-alive\r\n\r\n")
7273 MockRead data_reads
[] = {
7274 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7275 arraysize(read_buffer
)),
7276 MockRead("HTTP/1.0 200 OK\r\n"),
7277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7278 MockRead("Payload"),
7279 MockRead(SYNCHRONOUS
, OK
)
7282 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7283 data_writes
, arraysize(data_writes
));
7284 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7286 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7287 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7289 TestCompletionCallback callback
;
7291 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7292 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7294 rv
= callback
.WaitForResult();
7297 LoadTimingInfo load_timing_info
;
7298 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7299 TestLoadTimingNotReusedWithPac(load_timing_info
,
7300 CONNECT_TIMING_HAS_SSL_TIMES
);
7302 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7303 ASSERT_TRUE(response
!= NULL
);
7305 std::string response_text
;
7306 rv
= ReadTransaction(trans
.get(), &response_text
);
7308 EXPECT_EQ("Payload", response_text
);
7311 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7312 HttpRequestInfo request
;
7313 request
.method
= "GET";
7314 request
.url
= GURL("http://www.google.com/");
7315 request
.load_flags
= 0;
7317 session_deps_
.proxy_service
.reset(
7318 ProxyService::CreateFixed("socks4://myproxy:1080"));
7319 CapturingNetLog net_log
;
7320 session_deps_
.net_log
= &net_log
;
7322 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7323 scoped_ptr
<HttpTransaction
> trans(
7324 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7326 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7327 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7329 MockWrite data_writes
[] = {
7330 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7331 MockWrite("GET / HTTP/1.1\r\n"
7332 "Host: www.google.com\r\n"
7333 "Connection: keep-alive\r\n\r\n")
7336 MockRead data_reads
[] = {
7337 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7338 MockRead("HTTP/1.0 200 OK\r\n"),
7339 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7340 MockRead("Payload"),
7341 MockRead(SYNCHRONOUS
, OK
)
7344 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7345 data_writes
, arraysize(data_writes
));
7346 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7348 TestCompletionCallback callback
;
7350 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7351 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7353 rv
= callback
.WaitForResult();
7356 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7357 ASSERT_TRUE(response
!= NULL
);
7359 LoadTimingInfo load_timing_info
;
7360 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7361 TestLoadTimingNotReused(load_timing_info
,
7362 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7364 std::string response_text
;
7365 rv
= ReadTransaction(trans
.get(), &response_text
);
7367 EXPECT_EQ("Payload", response_text
);
7370 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7371 HttpRequestInfo request
;
7372 request
.method
= "GET";
7373 request
.url
= GURL("http://www.google.com/");
7374 request
.load_flags
= 0;
7376 session_deps_
.proxy_service
.reset(
7377 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7378 CapturingNetLog net_log
;
7379 session_deps_
.net_log
= &net_log
;
7381 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7382 scoped_ptr
<HttpTransaction
> trans(
7383 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7385 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7386 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7387 const char kSOCKS5OkRequest
[] = {
7389 0x01, // Command (CONNECT)
7391 0x03, // Address type (DOMAINNAME).
7392 0x0E, // Length of domain (14)
7394 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7395 0x00, 0x50, // 16-bit port (80)
7397 const char kSOCKS5OkResponse
[] =
7398 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7400 MockWrite data_writes
[] = {
7401 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7402 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7403 MockWrite("GET / HTTP/1.1\r\n"
7404 "Host: www.google.com\r\n"
7405 "Connection: keep-alive\r\n\r\n")
7408 MockRead data_reads
[] = {
7409 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7410 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7411 MockRead("HTTP/1.0 200 OK\r\n"),
7412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7413 MockRead("Payload"),
7414 MockRead(SYNCHRONOUS
, OK
)
7417 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7418 data_writes
, arraysize(data_writes
));
7419 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7421 TestCompletionCallback callback
;
7423 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7426 rv
= callback
.WaitForResult();
7429 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7430 ASSERT_TRUE(response
!= NULL
);
7432 LoadTimingInfo load_timing_info
;
7433 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7434 TestLoadTimingNotReusedWithPac(load_timing_info
,
7435 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7437 std::string response_text
;
7438 rv
= ReadTransaction(trans
.get(), &response_text
);
7440 EXPECT_EQ("Payload", response_text
);
7443 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7444 HttpRequestInfo request
;
7445 request
.method
= "GET";
7446 request
.url
= GURL("https://www.google.com/");
7447 request
.load_flags
= 0;
7449 session_deps_
.proxy_service
.reset(
7450 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7451 CapturingNetLog net_log
;
7452 session_deps_
.net_log
= &net_log
;
7454 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7455 scoped_ptr
<HttpTransaction
> trans(
7456 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7458 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7459 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7460 const unsigned char kSOCKS5OkRequest
[] = {
7462 0x01, // Command (CONNECT)
7464 0x03, // Address type (DOMAINNAME).
7465 0x0E, // Length of domain (14)
7467 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7468 0x01, 0xBB, // 16-bit port (443)
7471 const char kSOCKS5OkResponse
[] =
7472 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7474 MockWrite data_writes
[] = {
7475 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7476 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7477 arraysize(kSOCKS5OkRequest
)),
7478 MockWrite("GET / HTTP/1.1\r\n"
7479 "Host: www.google.com\r\n"
7480 "Connection: keep-alive\r\n\r\n")
7483 MockRead data_reads
[] = {
7484 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7485 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7486 MockRead("HTTP/1.0 200 OK\r\n"),
7487 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7488 MockRead("Payload"),
7489 MockRead(SYNCHRONOUS
, OK
)
7492 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7493 data_writes
, arraysize(data_writes
));
7494 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7496 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7497 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7499 TestCompletionCallback callback
;
7501 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7502 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7504 rv
= callback
.WaitForResult();
7507 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7508 ASSERT_TRUE(response
!= NULL
);
7510 LoadTimingInfo load_timing_info
;
7511 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7512 TestLoadTimingNotReusedWithPac(load_timing_info
,
7513 CONNECT_TIMING_HAS_SSL_TIMES
);
7515 std::string response_text
;
7516 rv
= ReadTransaction(trans
.get(), &response_text
);
7518 EXPECT_EQ("Payload", response_text
);
7523 // Tests that for connection endpoints the group names are correctly set.
7525 struct GroupNameTest
{
7526 std::string proxy_server
;
7528 std::string expected_group_name
;
7532 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7533 NextProto next_proto
,
7534 SpdySessionDependencies
* session_deps_
) {
7535 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7537 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7538 session
->http_server_properties();
7539 http_server_properties
->SetAlternateProtocol(
7540 HostPortPair("host.with.alternate", 80), 443,
7541 AlternateProtocolFromNextProto(next_proto
), 1);
7546 int GroupNameTransactionHelper(
7547 const std::string
& url
,
7548 const scoped_refptr
<HttpNetworkSession
>& session
) {
7549 HttpRequestInfo request
;
7550 request
.method
= "GET";
7551 request
.url
= GURL(url
);
7552 request
.load_flags
= 0;
7554 scoped_ptr
<HttpTransaction
> trans(
7555 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7557 TestCompletionCallback callback
;
7559 // We do not complete this request, the dtor will clean the transaction up.
7560 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7565 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7566 const GroupNameTest tests
[] = {
7569 "http://www.google.com/direct",
7570 "www.google.com:80",
7575 "http://[2001:1418:13:1::25]/direct",
7576 "[2001:1418:13:1::25]:80",
7583 "https://www.google.com/direct_ssl",
7584 "ssl/www.google.com:443",
7589 "https://[2001:1418:13:1::25]/direct",
7590 "ssl/[2001:1418:13:1::25]:443",
7595 "http://host.with.alternate/direct",
7596 "ssl/host.with.alternate:443",
7601 session_deps_
.use_alternate_protocols
= true;
7603 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7604 session_deps_
.proxy_service
.reset(
7605 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7606 scoped_refptr
<HttpNetworkSession
> session(
7607 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7609 HttpNetworkSessionPeer
peer(session
);
7610 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7611 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7612 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7613 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7614 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7615 new MockClientSocketPoolManager
);
7616 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7617 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7618 peer
.SetClientSocketPoolManager(
7619 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7621 EXPECT_EQ(ERR_IO_PENDING
,
7622 GroupNameTransactionHelper(tests
[i
].url
, session
));
7624 EXPECT_EQ(tests
[i
].expected_group_name
,
7625 ssl_conn_pool
->last_group_name_received());
7627 EXPECT_EQ(tests
[i
].expected_group_name
,
7628 transport_conn_pool
->last_group_name_received());
7633 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7634 const GroupNameTest tests
[] = {
7637 "http://www.google.com/http_proxy_normal",
7638 "www.google.com:80",
7645 "https://www.google.com/http_connect_ssl",
7646 "ssl/www.google.com:443",
7652 "http://host.with.alternate/direct",
7653 "ssl/host.with.alternate:443",
7659 "ftp://ftp.google.com/http_proxy_normal",
7660 "ftp/ftp.google.com:21",
7665 session_deps_
.use_alternate_protocols
= true;
7667 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7668 session_deps_
.proxy_service
.reset(
7669 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7670 scoped_refptr
<HttpNetworkSession
> session(
7671 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7673 HttpNetworkSessionPeer
peer(session
);
7675 HostPortPair
proxy_host("http_proxy", 80);
7676 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7677 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7678 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7679 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7681 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7682 new MockClientSocketPoolManager
);
7683 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7684 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7685 peer
.SetClientSocketPoolManager(
7686 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7688 EXPECT_EQ(ERR_IO_PENDING
,
7689 GroupNameTransactionHelper(tests
[i
].url
, session
));
7691 EXPECT_EQ(tests
[i
].expected_group_name
,
7692 ssl_conn_pool
->last_group_name_received());
7694 EXPECT_EQ(tests
[i
].expected_group_name
,
7695 http_proxy_pool
->last_group_name_received());
7699 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7700 const GroupNameTest tests
[] = {
7702 "socks4://socks_proxy:1080",
7703 "http://www.google.com/socks4_direct",
7704 "socks4/www.google.com:80",
7708 "socks5://socks_proxy:1080",
7709 "http://www.google.com/socks5_direct",
7710 "socks5/www.google.com:80",
7716 "socks4://socks_proxy:1080",
7717 "https://www.google.com/socks4_ssl",
7718 "socks4/ssl/www.google.com:443",
7722 "socks5://socks_proxy:1080",
7723 "https://www.google.com/socks5_ssl",
7724 "socks5/ssl/www.google.com:443",
7729 "socks4://socks_proxy:1080",
7730 "http://host.with.alternate/direct",
7731 "socks4/ssl/host.with.alternate:443",
7736 session_deps_
.use_alternate_protocols
= true;
7738 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7739 session_deps_
.proxy_service
.reset(
7740 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7741 scoped_refptr
<HttpNetworkSession
> session(
7742 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7744 HttpNetworkSessionPeer
peer(session
);
7746 HostPortPair
proxy_host("socks_proxy", 1080);
7747 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7748 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7749 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7750 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7752 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7753 new MockClientSocketPoolManager
);
7754 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7755 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7756 peer
.SetClientSocketPoolManager(
7757 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7759 scoped_ptr
<HttpTransaction
> trans(
7760 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7762 EXPECT_EQ(ERR_IO_PENDING
,
7763 GroupNameTransactionHelper(tests
[i
].url
, session
));
7765 EXPECT_EQ(tests
[i
].expected_group_name
,
7766 ssl_conn_pool
->last_group_name_received());
7768 EXPECT_EQ(tests
[i
].expected_group_name
,
7769 socks_conn_pool
->last_group_name_received());
7773 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
7774 HttpRequestInfo request
;
7775 request
.method
= "GET";
7776 request
.url
= GURL("http://www.google.com/");
7778 session_deps_
.proxy_service
.reset(
7779 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7781 // This simulates failure resolving all hostnames; that means we will fail
7782 // connecting to both proxies (myproxy:70 and foobar:80).
7783 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
7785 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7786 scoped_ptr
<HttpTransaction
> trans(
7787 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7789 TestCompletionCallback callback
;
7791 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7792 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7794 rv
= callback
.WaitForResult();
7795 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
7798 // Base test to make sure that when the load flags for a request specify to
7799 // bypass the cache, the DNS cache is not used.
7800 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7802 // Issue a request, asking to bypass the cache(s).
7803 HttpRequestInfo request
;
7804 request
.method
= "GET";
7805 request
.load_flags
= load_flags
;
7806 request
.url
= GURL("http://www.google.com/");
7808 // Select a host resolver that does caching.
7809 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
7811 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7812 scoped_ptr
<HttpTransaction
> trans(
7813 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7815 // Warm up the host cache so it has an entry for "www.google.com".
7816 AddressList addrlist
;
7817 TestCompletionCallback callback
;
7818 int rv
= session_deps_
.host_resolver
->Resolve(
7819 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7822 callback
.callback(),
7825 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7826 rv
= callback
.WaitForResult();
7829 // Verify that it was added to host cache, by doing a subsequent async lookup
7830 // and confirming it completes synchronously.
7831 rv
= session_deps_
.host_resolver
->Resolve(
7832 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7835 callback
.callback(),
7840 // Inject a failure the next time that "www.google.com" is resolved. This way
7841 // we can tell if the next lookup hit the cache, or the "network".
7842 // (cache --> success, "network" --> failure).
7843 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
7845 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7846 // first read -- this won't be reached as the host resolution will fail first.
7847 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
7848 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7849 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7852 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7853 ASSERT_EQ(ERR_IO_PENDING
, rv
);
7854 rv
= callback
.WaitForResult();
7856 // If we bypassed the cache, we would have gotten a failure while resolving
7857 // "www.google.com".
7858 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
7861 // There are multiple load flags that should trigger the host cache bypass.
7862 // Test each in isolation:
7863 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
7864 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
7867 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
7868 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
7871 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
7872 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
7875 // Make sure we can handle an error when writing the request.
7876 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
7877 HttpRequestInfo request
;
7878 request
.method
= "GET";
7879 request
.url
= GURL("http://www.foo.com/");
7880 request
.load_flags
= 0;
7882 MockWrite write_failure
[] = {
7883 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
7885 StaticSocketDataProvider
data(NULL
, 0,
7886 write_failure
, arraysize(write_failure
));
7887 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7888 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7890 TestCompletionCallback callback
;
7892 scoped_ptr
<HttpTransaction
> trans(
7893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7895 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7896 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7898 rv
= callback
.WaitForResult();
7899 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
7902 // Check that a connection closed after the start of the headers finishes ok.
7903 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
7904 HttpRequestInfo request
;
7905 request
.method
= "GET";
7906 request
.url
= GURL("http://www.foo.com/");
7907 request
.load_flags
= 0;
7909 MockRead data_reads
[] = {
7910 MockRead("HTTP/1."),
7911 MockRead(SYNCHRONOUS
, OK
),
7914 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7915 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7916 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7918 TestCompletionCallback callback
;
7920 scoped_ptr
<HttpTransaction
> trans(
7921 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7923 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7926 rv
= callback
.WaitForResult();
7929 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7930 ASSERT_TRUE(response
!= NULL
);
7932 EXPECT_TRUE(response
->headers
.get() != NULL
);
7933 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7935 std::string response_data
;
7936 rv
= ReadTransaction(trans
.get(), &response_data
);
7938 EXPECT_EQ("", response_data
);
7941 // Make sure that a dropped connection while draining the body for auth
7942 // restart does the right thing.
7943 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
7944 HttpRequestInfo request
;
7945 request
.method
= "GET";
7946 request
.url
= GURL("http://www.google.com/");
7947 request
.load_flags
= 0;
7949 MockWrite data_writes1
[] = {
7950 MockWrite("GET / HTTP/1.1\r\n"
7951 "Host: www.google.com\r\n"
7952 "Connection: keep-alive\r\n\r\n"),
7955 MockRead data_reads1
[] = {
7956 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7957 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7959 MockRead("Content-Length: 14\r\n\r\n"),
7961 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
7964 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7965 data_writes1
, arraysize(data_writes1
));
7966 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7968 // After calling trans->RestartWithAuth(), this is the request we should
7969 // be issuing -- the final header line contains the credentials.
7970 MockWrite data_writes2
[] = {
7971 MockWrite("GET / HTTP/1.1\r\n"
7972 "Host: www.google.com\r\n"
7973 "Connection: keep-alive\r\n"
7974 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7977 // Lastly, the server responds with the actual content.
7978 MockRead data_reads2
[] = {
7979 MockRead("HTTP/1.1 200 OK\r\n"),
7980 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7981 MockRead("Content-Length: 100\r\n\r\n"),
7982 MockRead(SYNCHRONOUS
, OK
),
7985 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7986 data_writes2
, arraysize(data_writes2
));
7987 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7988 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7990 TestCompletionCallback callback1
;
7992 scoped_ptr
<HttpTransaction
> trans(
7993 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7995 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7996 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7998 rv
= callback1
.WaitForResult();
8001 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8002 ASSERT_TRUE(response
!= NULL
);
8003 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8005 TestCompletionCallback callback2
;
8007 rv
= trans
->RestartWithAuth(
8008 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8009 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8011 rv
= callback2
.WaitForResult();
8014 response
= trans
->GetResponseInfo();
8015 ASSERT_TRUE(response
!= NULL
);
8016 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8017 EXPECT_EQ(100, response
->headers
->GetContentLength());
8020 // Test HTTPS connections going through a proxy that sends extra data.
8021 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8022 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8024 HttpRequestInfo request
;
8025 request
.method
= "GET";
8026 request
.url
= GURL("https://www.google.com/");
8027 request
.load_flags
= 0;
8029 MockRead proxy_reads
[] = {
8030 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8031 MockRead(SYNCHRONOUS
, OK
)
8034 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8035 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8037 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8038 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8040 TestCompletionCallback callback
;
8042 session_deps_
.socket_factory
->ResetNextMockIndexes();
8044 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8045 scoped_ptr
<HttpTransaction
> trans(
8046 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8048 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8051 rv
= callback
.WaitForResult();
8052 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8055 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8056 HttpRequestInfo request
;
8057 request
.method
= "GET";
8058 request
.url
= GURL("http://www.google.com/");
8059 request
.load_flags
= 0;
8061 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8062 scoped_ptr
<HttpTransaction
> trans(
8063 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8065 MockRead data_reads
[] = {
8066 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8067 MockRead(SYNCHRONOUS
, OK
),
8070 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8071 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8073 TestCompletionCallback callback
;
8075 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8076 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8078 EXPECT_EQ(OK
, callback
.WaitForResult());
8080 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8081 ASSERT_TRUE(response
!= NULL
);
8083 EXPECT_TRUE(response
->headers
.get() != NULL
);
8084 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8086 std::string response_data
;
8087 rv
= ReadTransaction(trans
.get(), &response_data
);
8088 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8091 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8092 base::FilePath temp_file_path
;
8093 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8094 const uint64 kFakeSize
= 100000; // file is actually blank
8095 UploadFileElementReader::ScopedOverridingContentLengthForTests
8096 overriding_content_length(kFakeSize
);
8098 ScopedVector
<UploadElementReader
> element_readers
;
8099 element_readers
.push_back(
8100 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8105 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8107 HttpRequestInfo request
;
8108 request
.method
= "POST";
8109 request
.url
= GURL("http://www.google.com/upload");
8110 request
.upload_data_stream
= &upload_data_stream
;
8111 request
.load_flags
= 0;
8113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8114 scoped_ptr
<HttpTransaction
> trans(
8115 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8117 MockRead data_reads
[] = {
8118 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8119 MockRead("hello world"),
8120 MockRead(SYNCHRONOUS
, OK
),
8122 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8123 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8125 TestCompletionCallback callback
;
8127 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8128 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8130 rv
= callback
.WaitForResult();
8133 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8134 ASSERT_TRUE(response
!= NULL
);
8136 EXPECT_TRUE(response
->headers
.get() != NULL
);
8137 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8139 std::string response_data
;
8140 rv
= ReadTransaction(trans
.get(), &response_data
);
8142 EXPECT_EQ("hello world", response_data
);
8144 base::DeleteFile(temp_file_path
, false);
8147 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8148 base::FilePath temp_file
;
8149 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8150 std::string
temp_file_content("Unreadable file.");
8151 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8152 temp_file_content
.length()));
8153 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8155 ScopedVector
<UploadElementReader
> element_readers
;
8156 element_readers
.push_back(
8157 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8162 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8164 HttpRequestInfo request
;
8165 request
.method
= "POST";
8166 request
.url
= GURL("http://www.google.com/upload");
8167 request
.upload_data_stream
= &upload_data_stream
;
8168 request
.load_flags
= 0;
8170 // If we try to upload an unreadable file, the transaction should fail.
8171 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8172 scoped_ptr
<HttpTransaction
> trans(
8173 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8175 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8178 TestCompletionCallback callback
;
8180 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8183 rv
= callback
.WaitForResult();
8184 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8187 EXPECT_FALSE(response
);
8189 base::DeleteFile(temp_file
, false);
8192 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8193 class FakeUploadElementReader
: public UploadElementReader
{
8195 FakeUploadElementReader() {}
8196 virtual ~FakeUploadElementReader() {}
8198 const CompletionCallback
& callback() const { return callback_
; }
8200 // UploadElementReader overrides:
8201 virtual int Init(const CompletionCallback
& callback
) OVERRIDE
{
8202 callback_
= callback
;
8203 return ERR_IO_PENDING
;
8205 virtual uint64
GetContentLength() const OVERRIDE
{ return 0; }
8206 virtual uint64
BytesRemaining() const OVERRIDE
{ return 0; }
8207 virtual int Read(IOBuffer
* buf
,
8209 const CompletionCallback
& callback
) OVERRIDE
{
8214 CompletionCallback callback_
;
8217 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8218 ScopedVector
<UploadElementReader
> element_readers
;
8219 element_readers
.push_back(fake_reader
);
8220 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8222 HttpRequestInfo request
;
8223 request
.method
= "POST";
8224 request
.url
= GURL("http://www.google.com/upload");
8225 request
.upload_data_stream
= &upload_data_stream
;
8226 request
.load_flags
= 0;
8228 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8229 scoped_ptr
<HttpTransaction
> trans(
8230 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8232 StaticSocketDataProvider data
;
8233 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8235 TestCompletionCallback callback
;
8236 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8237 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8238 base::MessageLoop::current()->RunUntilIdle();
8240 // Transaction is pending on request body initialization.
8241 ASSERT_FALSE(fake_reader
->callback().is_null());
8243 // Return Init()'s result after the transaction gets destroyed.
8245 fake_reader
->callback().Run(OK
); // Should not crash.
8248 // Tests that changes to Auth realms are treated like auth rejections.
8249 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8251 HttpRequestInfo request
;
8252 request
.method
= "GET";
8253 request
.url
= GURL("http://www.google.com/");
8254 request
.load_flags
= 0;
8256 // First transaction will request a resource and receive a Basic challenge
8257 // with realm="first_realm".
8258 MockWrite data_writes1
[] = {
8259 MockWrite("GET / HTTP/1.1\r\n"
8260 "Host: www.google.com\r\n"
8261 "Connection: keep-alive\r\n"
8264 MockRead data_reads1
[] = {
8265 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8266 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8270 // After calling trans->RestartWithAuth(), provide an Authentication header
8271 // for first_realm. The server will reject and provide a challenge with
8273 MockWrite data_writes2
[] = {
8274 MockWrite("GET / HTTP/1.1\r\n"
8275 "Host: www.google.com\r\n"
8276 "Connection: keep-alive\r\n"
8277 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8280 MockRead data_reads2
[] = {
8281 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8282 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8286 // This again fails, and goes back to first_realm. Make sure that the
8287 // entry is removed from cache.
8288 MockWrite data_writes3
[] = {
8289 MockWrite("GET / HTTP/1.1\r\n"
8290 "Host: www.google.com\r\n"
8291 "Connection: keep-alive\r\n"
8292 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8295 MockRead data_reads3
[] = {
8296 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8297 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8301 // Try one last time (with the correct password) and get the resource.
8302 MockWrite data_writes4
[] = {
8303 MockWrite("GET / HTTP/1.1\r\n"
8304 "Host: www.google.com\r\n"
8305 "Connection: keep-alive\r\n"
8306 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8309 MockRead data_reads4
[] = {
8310 MockRead("HTTP/1.1 200 OK\r\n"
8311 "Content-Type: text/html; charset=iso-8859-1\r\n"
8312 "Content-Length: 5\r\n"
8317 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8318 data_writes1
, arraysize(data_writes1
));
8319 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8320 data_writes2
, arraysize(data_writes2
));
8321 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8322 data_writes3
, arraysize(data_writes3
));
8323 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8324 data_writes4
, arraysize(data_writes4
));
8325 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8326 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8327 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8328 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8330 TestCompletionCallback callback1
;
8332 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8333 scoped_ptr
<HttpTransaction
> trans(
8334 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8336 // Issue the first request with Authorize headers. There should be a
8337 // password prompt for first_realm waiting to be filled in after the
8338 // transaction completes.
8339 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8340 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8341 rv
= callback1
.WaitForResult();
8343 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8344 ASSERT_TRUE(response
!= NULL
);
8345 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8346 ASSERT_FALSE(challenge
== NULL
);
8347 EXPECT_FALSE(challenge
->is_proxy
);
8348 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8349 EXPECT_EQ("first_realm", challenge
->realm
);
8350 EXPECT_EQ("basic", challenge
->scheme
);
8352 // Issue the second request with an incorrect password. There should be a
8353 // password prompt for second_realm waiting to be filled in after the
8354 // transaction completes.
8355 TestCompletionCallback callback2
;
8356 rv
= trans
->RestartWithAuth(
8357 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8358 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8359 rv
= callback2
.WaitForResult();
8361 response
= trans
->GetResponseInfo();
8362 ASSERT_TRUE(response
!= NULL
);
8363 challenge
= response
->auth_challenge
.get();
8364 ASSERT_FALSE(challenge
== NULL
);
8365 EXPECT_FALSE(challenge
->is_proxy
);
8366 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8367 EXPECT_EQ("second_realm", challenge
->realm
);
8368 EXPECT_EQ("basic", challenge
->scheme
);
8370 // Issue the third request with another incorrect password. There should be
8371 // a password prompt for first_realm waiting to be filled in. If the password
8372 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8373 // first_realm was not correctly removed.
8374 TestCompletionCallback callback3
;
8375 rv
= trans
->RestartWithAuth(
8376 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8377 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8378 rv
= callback3
.WaitForResult();
8380 response
= trans
->GetResponseInfo();
8381 ASSERT_TRUE(response
!= NULL
);
8382 challenge
= response
->auth_challenge
.get();
8383 ASSERT_FALSE(challenge
== NULL
);
8384 EXPECT_FALSE(challenge
->is_proxy
);
8385 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8386 EXPECT_EQ("first_realm", challenge
->realm
);
8387 EXPECT_EQ("basic", challenge
->scheme
);
8389 // Issue the fourth request with the correct password and username.
8390 TestCompletionCallback callback4
;
8391 rv
= trans
->RestartWithAuth(
8392 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8393 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8394 rv
= callback4
.WaitForResult();
8396 response
= trans
->GetResponseInfo();
8397 ASSERT_TRUE(response
!= NULL
);
8398 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8401 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8402 session_deps_
.next_protos
= SpdyNextProtos();
8403 session_deps_
.use_alternate_protocols
= true;
8405 std::string alternate_protocol_http_header
=
8406 GetAlternateProtocolHttpHeader();
8408 MockRead data_reads
[] = {
8409 MockRead("HTTP/1.1 200 OK\r\n"),
8410 MockRead(alternate_protocol_http_header
.c_str()),
8411 MockRead("hello world"),
8412 MockRead(SYNCHRONOUS
, OK
),
8415 HttpRequestInfo request
;
8416 request
.method
= "GET";
8417 request
.url
= GURL("http://www.google.com/");
8418 request
.load_flags
= 0;
8420 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8422 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8424 TestCompletionCallback callback
;
8426 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8427 scoped_ptr
<HttpTransaction
> trans(
8428 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8430 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8431 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8433 HostPortPair
http_host_port_pair("www.google.com", 80);
8434 HttpServerProperties
& http_server_properties
=
8435 *session
->http_server_properties();
8437 http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8439 EXPECT_EQ(OK
, callback
.WaitForResult());
8441 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8442 ASSERT_TRUE(response
!= NULL
);
8443 ASSERT_TRUE(response
->headers
.get() != NULL
);
8444 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8445 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8446 EXPECT_FALSE(response
->was_npn_negotiated
);
8448 std::string response_data
;
8449 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8450 EXPECT_EQ("hello world", response_data
);
8452 ASSERT_TRUE(http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8453 const AlternateProtocolInfo alternate
=
8454 http_server_properties
.GetAlternateProtocol(http_host_port_pair
);
8455 AlternateProtocolInfo
expected_alternate(
8456 443, AlternateProtocolFromNextProto(GetParam()), 1);
8457 EXPECT_TRUE(expected_alternate
.Equals(alternate
));
8460 TEST_P(HttpNetworkTransactionTest
,
8461 MarkBrokenAlternateProtocolAndFallback
) {
8462 session_deps_
.use_alternate_protocols
= true;
8464 HttpRequestInfo request
;
8465 request
.method
= "GET";
8466 request
.url
= GURL("http://www.google.com/");
8467 request
.load_flags
= 0;
8469 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8470 StaticSocketDataProvider first_data
;
8471 first_data
.set_connect_data(mock_connect
);
8472 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8474 MockRead data_reads
[] = {
8475 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8476 MockRead("hello world"),
8477 MockRead(ASYNC
, OK
),
8479 StaticSocketDataProvider
second_data(
8480 data_reads
, arraysize(data_reads
), NULL
, 0);
8481 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8483 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8485 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8486 session
->http_server_properties();
8487 // Port must be < 1024, or the header will be ignored (since initial port was
8488 // port 80 (another restricted port).
8489 http_server_properties
->SetAlternateProtocol(
8490 HostPortPair::FromURL(request
.url
),
8491 666 /* port is ignored by MockConnect anyway */,
8492 AlternateProtocolFromNextProto(GetParam()), 1);
8494 scoped_ptr
<HttpTransaction
> trans(
8495 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8496 TestCompletionCallback callback
;
8498 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8499 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8500 EXPECT_EQ(OK
, callback
.WaitForResult());
8502 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8503 ASSERT_TRUE(response
!= NULL
);
8504 ASSERT_TRUE(response
->headers
.get() != NULL
);
8505 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8507 std::string response_data
;
8508 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8509 EXPECT_EQ("hello world", response_data
);
8511 ASSERT_TRUE(http_server_properties
->HasAlternateProtocol(
8512 HostPortPair::FromURL(request
.url
)));
8513 const AlternateProtocolInfo alternate
=
8514 http_server_properties
->GetAlternateProtocol(
8515 HostPortPair::FromURL(request
.url
));
8516 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN
, alternate
.protocol
);
8519 TEST_P(HttpNetworkTransactionTest
,
8520 AlternateProtocolPortRestrictedBlocked
) {
8521 // Ensure that we're not allowed to redirect traffic via an alternate
8522 // protocol to an unrestricted (port >= 1024) when the original traffic was
8523 // on a restricted port (port < 1024). Ensure that we can redirect in all
8525 session_deps_
.use_alternate_protocols
= true;
8527 HttpRequestInfo restricted_port_request
;
8528 restricted_port_request
.method
= "GET";
8529 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8530 restricted_port_request
.load_flags
= 0;
8532 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8533 StaticSocketDataProvider first_data
;
8534 first_data
.set_connect_data(mock_connect
);
8535 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8537 MockRead data_reads
[] = {
8538 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8539 MockRead("hello world"),
8540 MockRead(ASYNC
, OK
),
8542 StaticSocketDataProvider
second_data(
8543 data_reads
, arraysize(data_reads
), NULL
, 0);
8544 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8546 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8548 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8549 session
->http_server_properties();
8550 const int kUnrestrictedAlternatePort
= 1024;
8551 http_server_properties
->SetAlternateProtocol(
8552 HostPortPair::FromURL(restricted_port_request
.url
),
8553 kUnrestrictedAlternatePort
,
8554 AlternateProtocolFromNextProto(GetParam()), 1);
8556 scoped_ptr
<HttpTransaction
> trans(
8557 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8558 TestCompletionCallback callback
;
8560 int rv
= trans
->Start(
8561 &restricted_port_request
,
8562 callback
.callback(), BoundNetLog());
8563 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8564 // Invalid change to unrestricted port should fail.
8565 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8568 TEST_P(HttpNetworkTransactionTest
,
8569 AlternateProtocolPortRestrictedPermitted
) {
8570 // Ensure that we're allowed to redirect traffic via an alternate
8571 // protocol to an unrestricted (port >= 1024) when the original traffic was
8572 // on a restricted port (port < 1024) if we set
8573 // enable_user_alternate_protocol_ports.
8575 session_deps_
.use_alternate_protocols
= true;
8576 session_deps_
.enable_user_alternate_protocol_ports
= true;
8578 HttpRequestInfo restricted_port_request
;
8579 restricted_port_request
.method
= "GET";
8580 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8581 restricted_port_request
.load_flags
= 0;
8583 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8584 StaticSocketDataProvider first_data
;
8585 first_data
.set_connect_data(mock_connect
);
8586 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8588 MockRead data_reads
[] = {
8589 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8590 MockRead("hello world"),
8591 MockRead(ASYNC
, OK
),
8593 StaticSocketDataProvider
second_data(
8594 data_reads
, arraysize(data_reads
), NULL
, 0);
8595 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8597 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8599 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8600 session
->http_server_properties();
8601 const int kUnrestrictedAlternatePort
= 1024;
8602 http_server_properties
->SetAlternateProtocol(
8603 HostPortPair::FromURL(restricted_port_request
.url
),
8604 kUnrestrictedAlternatePort
,
8605 AlternateProtocolFromNextProto(GetParam()), 1);
8607 scoped_ptr
<HttpTransaction
> trans(
8608 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8609 TestCompletionCallback callback
;
8611 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8612 &restricted_port_request
,
8613 callback
.callback(), BoundNetLog()));
8614 // Change to unrestricted port should succeed.
8615 EXPECT_EQ(OK
, callback
.WaitForResult());
8618 TEST_P(HttpNetworkTransactionTest
,
8619 AlternateProtocolPortRestrictedAllowed
) {
8620 // Ensure that we're not allowed to redirect traffic via an alternate
8621 // protocol to an unrestricted (port >= 1024) when the original traffic was
8622 // on a restricted port (port < 1024). Ensure that we can redirect in all
8624 session_deps_
.use_alternate_protocols
= true;
8626 HttpRequestInfo restricted_port_request
;
8627 restricted_port_request
.method
= "GET";
8628 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8629 restricted_port_request
.load_flags
= 0;
8631 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8632 StaticSocketDataProvider first_data
;
8633 first_data
.set_connect_data(mock_connect
);
8634 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8636 MockRead data_reads
[] = {
8637 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8638 MockRead("hello world"),
8639 MockRead(ASYNC
, OK
),
8641 StaticSocketDataProvider
second_data(
8642 data_reads
, arraysize(data_reads
), NULL
, 0);
8643 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8645 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8647 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8648 session
->http_server_properties();
8649 const int kRestrictedAlternatePort
= 80;
8650 http_server_properties
->SetAlternateProtocol(
8651 HostPortPair::FromURL(restricted_port_request
.url
),
8652 kRestrictedAlternatePort
,
8653 AlternateProtocolFromNextProto(GetParam()), 1);
8655 scoped_ptr
<HttpTransaction
> trans(
8656 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8657 TestCompletionCallback callback
;
8659 int rv
= trans
->Start(
8660 &restricted_port_request
,
8661 callback
.callback(), BoundNetLog());
8662 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8663 // Valid change to restricted port should pass.
8664 EXPECT_EQ(OK
, callback
.WaitForResult());
8667 TEST_P(HttpNetworkTransactionTest
,
8668 AlternateProtocolPortUnrestrictedAllowed1
) {
8669 // Ensure that we're not allowed to redirect traffic via an alternate
8670 // protocol to an unrestricted (port >= 1024) when the original traffic was
8671 // on a restricted port (port < 1024). Ensure that we can redirect in all
8673 session_deps_
.use_alternate_protocols
= true;
8675 HttpRequestInfo unrestricted_port_request
;
8676 unrestricted_port_request
.method
= "GET";
8677 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8678 unrestricted_port_request
.load_flags
= 0;
8680 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8681 StaticSocketDataProvider first_data
;
8682 first_data
.set_connect_data(mock_connect
);
8683 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8685 MockRead data_reads
[] = {
8686 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8687 MockRead("hello world"),
8688 MockRead(ASYNC
, OK
),
8690 StaticSocketDataProvider
second_data(
8691 data_reads
, arraysize(data_reads
), NULL
, 0);
8692 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8694 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8696 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8697 session
->http_server_properties();
8698 const int kRestrictedAlternatePort
= 80;
8699 http_server_properties
->SetAlternateProtocol(
8700 HostPortPair::FromURL(unrestricted_port_request
.url
),
8701 kRestrictedAlternatePort
,
8702 AlternateProtocolFromNextProto(GetParam()), 1);
8704 scoped_ptr
<HttpTransaction
> trans(
8705 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8706 TestCompletionCallback callback
;
8708 int rv
= trans
->Start(
8709 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8710 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8711 // Valid change to restricted port should pass.
8712 EXPECT_EQ(OK
, callback
.WaitForResult());
8715 TEST_P(HttpNetworkTransactionTest
,
8716 AlternateProtocolPortUnrestrictedAllowed2
) {
8717 // Ensure that we're not allowed to redirect traffic via an alternate
8718 // protocol to an unrestricted (port >= 1024) when the original traffic was
8719 // on a restricted port (port < 1024). Ensure that we can redirect in all
8721 session_deps_
.use_alternate_protocols
= true;
8723 HttpRequestInfo unrestricted_port_request
;
8724 unrestricted_port_request
.method
= "GET";
8725 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8726 unrestricted_port_request
.load_flags
= 0;
8728 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8729 StaticSocketDataProvider first_data
;
8730 first_data
.set_connect_data(mock_connect
);
8731 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8733 MockRead data_reads
[] = {
8734 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8735 MockRead("hello world"),
8736 MockRead(ASYNC
, OK
),
8738 StaticSocketDataProvider
second_data(
8739 data_reads
, arraysize(data_reads
), NULL
, 0);
8740 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8742 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8744 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8745 session
->http_server_properties();
8746 const int kUnrestrictedAlternatePort
= 1024;
8747 http_server_properties
->SetAlternateProtocol(
8748 HostPortPair::FromURL(unrestricted_port_request
.url
),
8749 kUnrestrictedAlternatePort
,
8750 AlternateProtocolFromNextProto(GetParam()), 1);
8752 scoped_ptr
<HttpTransaction
> trans(
8753 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8754 TestCompletionCallback callback
;
8756 int rv
= trans
->Start(
8757 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8758 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8759 // Valid change to an unrestricted port should pass.
8760 EXPECT_EQ(OK
, callback
.WaitForResult());
8763 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
8764 // Ensure that we're not allowed to redirect traffic via an alternate
8765 // protocol to an unsafe port, and that we resume the second
8766 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8767 session_deps_
.use_alternate_protocols
= true;
8769 HttpRequestInfo request
;
8770 request
.method
= "GET";
8771 request
.url
= GURL("http://www.google.com/");
8772 request
.load_flags
= 0;
8774 // The alternate protocol request will error out before we attempt to connect,
8775 // so only the standard HTTP request will try to connect.
8776 MockRead data_reads
[] = {
8777 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8778 MockRead("hello world"),
8779 MockRead(ASYNC
, OK
),
8781 StaticSocketDataProvider
data(
8782 data_reads
, arraysize(data_reads
), NULL
, 0);
8783 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8785 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8787 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8788 session
->http_server_properties();
8789 const int kUnsafePort
= 7;
8790 http_server_properties
->SetAlternateProtocol(
8791 HostPortPair::FromURL(request
.url
),
8793 AlternateProtocolFromNextProto(GetParam()), 1);
8795 scoped_ptr
<HttpTransaction
> trans(
8796 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8797 TestCompletionCallback callback
;
8799 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8800 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8801 // The HTTP request should succeed.
8802 EXPECT_EQ(OK
, callback
.WaitForResult());
8804 // Disable alternate protocol before the asserts.
8805 // HttpStreamFactory::set_use_alternate_protocols(false);
8807 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8808 ASSERT_TRUE(response
!= NULL
);
8809 ASSERT_TRUE(response
->headers
.get() != NULL
);
8810 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8812 std::string response_data
;
8813 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8814 EXPECT_EQ("hello world", response_data
);
8817 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
8818 session_deps_
.use_alternate_protocols
= true;
8819 session_deps_
.next_protos
= SpdyNextProtos();
8821 HttpRequestInfo request
;
8822 request
.method
= "GET";
8823 request
.url
= GURL("http://www.google.com/");
8824 request
.load_flags
= 0;
8826 std::string alternate_protocol_http_header
=
8827 GetAlternateProtocolHttpHeader();
8829 MockRead data_reads
[] = {
8830 MockRead("HTTP/1.1 200 OK\r\n"),
8831 MockRead(alternate_protocol_http_header
.c_str()),
8832 MockRead("hello world"),
8833 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8837 StaticSocketDataProvider
first_transaction(
8838 data_reads
, arraysize(data_reads
), NULL
, 0);
8839 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8841 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8842 ssl
.SetNextProto(GetParam());
8843 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8845 scoped_ptr
<SpdyFrame
> req(
8846 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8847 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8849 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8850 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8851 MockRead spdy_reads
[] = {
8852 CreateMockRead(*resp
),
8853 CreateMockRead(*data
),
8854 MockRead(ASYNC
, 0, 0),
8857 DelayedSocketData
spdy_data(
8858 1, // wait for one write to finish before reading.
8859 spdy_reads
, arraysize(spdy_reads
),
8860 spdy_writes
, arraysize(spdy_writes
));
8861 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8863 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8864 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8866 hanging_non_alternate_protocol_socket
.set_connect_data(
8867 never_finishing_connect
);
8868 session_deps_
.socket_factory
->AddSocketDataProvider(
8869 &hanging_non_alternate_protocol_socket
);
8871 TestCompletionCallback callback
;
8873 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8874 scoped_ptr
<HttpTransaction
> trans(
8875 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8877 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8879 EXPECT_EQ(OK
, callback
.WaitForResult());
8881 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8882 ASSERT_TRUE(response
!= NULL
);
8883 ASSERT_TRUE(response
->headers
.get() != NULL
);
8884 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8886 std::string response_data
;
8887 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8888 EXPECT_EQ("hello world", response_data
);
8890 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8892 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8893 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8894 EXPECT_EQ(OK
, callback
.WaitForResult());
8896 response
= trans
->GetResponseInfo();
8897 ASSERT_TRUE(response
!= NULL
);
8898 ASSERT_TRUE(response
->headers
.get() != NULL
);
8899 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8900 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8901 EXPECT_TRUE(response
->was_npn_negotiated
);
8903 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8904 EXPECT_EQ("hello!", response_data
);
8907 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
8908 session_deps_
.use_alternate_protocols
= true;
8909 session_deps_
.next_protos
= SpdyNextProtos();
8911 HttpRequestInfo request
;
8912 request
.method
= "GET";
8913 request
.url
= GURL("http://www.google.com/");
8914 request
.load_flags
= 0;
8916 std::string alternate_protocol_http_header
=
8917 GetAlternateProtocolHttpHeader();
8919 MockRead data_reads
[] = {
8920 MockRead("HTTP/1.1 200 OK\r\n"),
8921 MockRead(alternate_protocol_http_header
.c_str()),
8922 MockRead("hello world"),
8923 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8924 MockRead(ASYNC
, OK
),
8927 StaticSocketDataProvider
first_transaction(
8928 data_reads
, arraysize(data_reads
), NULL
, 0);
8929 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8930 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8932 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8933 StaticSocketDataProvider
hanging_socket(
8935 hanging_socket
.set_connect_data(never_finishing_connect
);
8936 // Socket 2 and 3 are the hanging Alternate-Protocol and
8937 // non-Alternate-Protocol jobs from the 2nd transaction.
8938 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8939 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8941 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8942 ssl
.SetNextProto(GetParam());
8943 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8945 scoped_ptr
<SpdyFrame
> req1(
8946 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8947 scoped_ptr
<SpdyFrame
> req2(
8948 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
8949 MockWrite spdy_writes
[] = {
8950 CreateMockWrite(*req1
),
8951 CreateMockWrite(*req2
),
8953 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8954 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8955 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
8956 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
8957 MockRead spdy_reads
[] = {
8958 CreateMockRead(*resp1
),
8959 CreateMockRead(*data1
),
8960 CreateMockRead(*resp2
),
8961 CreateMockRead(*data2
),
8962 MockRead(ASYNC
, 0, 0),
8965 DelayedSocketData
spdy_data(
8966 2, // wait for writes to finish before reading.
8967 spdy_reads
, arraysize(spdy_reads
),
8968 spdy_writes
, arraysize(spdy_writes
));
8969 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8970 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8972 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8973 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8975 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8976 TestCompletionCallback callback1
;
8977 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
8979 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
8980 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8981 EXPECT_EQ(OK
, callback1
.WaitForResult());
8983 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
8984 ASSERT_TRUE(response
!= NULL
);
8985 ASSERT_TRUE(response
->headers
.get() != NULL
);
8986 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8988 std::string response_data
;
8989 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
8990 EXPECT_EQ("hello world", response_data
);
8992 TestCompletionCallback callback2
;
8993 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
8994 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
8995 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8997 TestCompletionCallback callback3
;
8998 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
8999 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9002 EXPECT_EQ(OK
, callback2
.WaitForResult());
9003 EXPECT_EQ(OK
, callback3
.WaitForResult());
9005 response
= trans2
.GetResponseInfo();
9006 ASSERT_TRUE(response
!= NULL
);
9007 ASSERT_TRUE(response
->headers
.get() != NULL
);
9008 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9009 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9010 EXPECT_TRUE(response
->was_npn_negotiated
);
9011 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9012 EXPECT_EQ("hello!", response_data
);
9014 response
= trans3
.GetResponseInfo();
9015 ASSERT_TRUE(response
!= NULL
);
9016 ASSERT_TRUE(response
->headers
.get() != NULL
);
9017 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9018 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9019 EXPECT_TRUE(response
->was_npn_negotiated
);
9020 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9021 EXPECT_EQ("hello!", response_data
);
9024 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9025 session_deps_
.use_alternate_protocols
= true;
9026 session_deps_
.next_protos
= SpdyNextProtos();
9028 HttpRequestInfo request
;
9029 request
.method
= "GET";
9030 request
.url
= GURL("http://www.google.com/");
9031 request
.load_flags
= 0;
9033 std::string alternate_protocol_http_header
=
9034 GetAlternateProtocolHttpHeader();
9036 MockRead data_reads
[] = {
9037 MockRead("HTTP/1.1 200 OK\r\n"),
9038 MockRead(alternate_protocol_http_header
.c_str()),
9039 MockRead("hello world"),
9040 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9041 MockRead(ASYNC
, OK
),
9044 StaticSocketDataProvider
first_transaction(
9045 data_reads
, arraysize(data_reads
), NULL
, 0);
9046 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9048 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9049 ssl
.SetNextProto(GetParam());
9050 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9052 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9053 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9055 hanging_alternate_protocol_socket
.set_connect_data(
9056 never_finishing_connect
);
9057 session_deps_
.socket_factory
->AddSocketDataProvider(
9058 &hanging_alternate_protocol_socket
);
9060 // 2nd request is just a copy of the first one, over HTTP again.
9061 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9063 TestCompletionCallback callback
;
9065 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9066 scoped_ptr
<HttpTransaction
> trans(
9067 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9069 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9070 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9071 EXPECT_EQ(OK
, callback
.WaitForResult());
9073 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9074 ASSERT_TRUE(response
!= NULL
);
9075 ASSERT_TRUE(response
->headers
.get() != NULL
);
9076 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9078 std::string response_data
;
9079 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9080 EXPECT_EQ("hello world", response_data
);
9082 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9084 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9086 EXPECT_EQ(OK
, callback
.WaitForResult());
9088 response
= trans
->GetResponseInfo();
9089 ASSERT_TRUE(response
!= NULL
);
9090 ASSERT_TRUE(response
->headers
.get() != NULL
);
9091 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9092 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9093 EXPECT_FALSE(response
->was_npn_negotiated
);
9095 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9096 EXPECT_EQ("hello world", response_data
);
9099 class CapturingProxyResolver
: public ProxyResolver
{
9101 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9102 virtual ~CapturingProxyResolver() {}
9104 virtual int GetProxyForURL(const GURL
& url
,
9106 const CompletionCallback
& callback
,
9107 RequestHandle
* request
,
9108 const BoundNetLog
& net_log
) OVERRIDE
{
9109 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9110 HostPortPair("myproxy", 80));
9111 results
->UseProxyServer(proxy_server
);
9112 resolved_
.push_back(url
);
9116 virtual void CancelRequest(RequestHandle request
) OVERRIDE
{
9120 virtual LoadState
GetLoadState(RequestHandle request
) const OVERRIDE
{
9122 return LOAD_STATE_IDLE
;
9125 virtual void CancelSetPacScript() OVERRIDE
{
9129 virtual int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9130 const CompletionCallback
& /*callback*/) OVERRIDE
{
9134 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9137 std::vector
<GURL
> resolved_
;
9139 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9142 TEST_P(HttpNetworkTransactionTest
,
9143 UseAlternateProtocolForTunneledNpnSpdy
) {
9144 session_deps_
.use_alternate_protocols
= true;
9145 session_deps_
.next_protos
= SpdyNextProtos();
9147 ProxyConfig proxy_config
;
9148 proxy_config
.set_auto_detect(true);
9149 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9151 CapturingProxyResolver
* capturing_proxy_resolver
=
9152 new CapturingProxyResolver();
9153 session_deps_
.proxy_service
.reset(new ProxyService(
9154 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
9156 CapturingNetLog net_log
;
9157 session_deps_
.net_log
= &net_log
;
9159 HttpRequestInfo request
;
9160 request
.method
= "GET";
9161 request
.url
= GURL("http://www.google.com/");
9162 request
.load_flags
= 0;
9164 std::string alternate_protocol_http_header
=
9165 GetAlternateProtocolHttpHeader();
9167 MockRead data_reads
[] = {
9168 MockRead("HTTP/1.1 200 OK\r\n"),
9169 MockRead(alternate_protocol_http_header
.c_str()),
9170 MockRead("hello world"),
9171 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9172 MockRead(ASYNC
, OK
),
9175 StaticSocketDataProvider
first_transaction(
9176 data_reads
, arraysize(data_reads
), NULL
, 0);
9177 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9179 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9180 ssl
.SetNextProto(GetParam());
9181 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9183 scoped_ptr
<SpdyFrame
> req(
9184 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9185 MockWrite spdy_writes
[] = {
9186 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9187 "Host: www.google.com\r\n"
9188 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9189 CreateMockWrite(*req
), // 3
9192 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9194 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9195 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9196 MockRead spdy_reads
[] = {
9197 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9198 CreateMockRead(*resp
.get(), 4), // 2, 4
9199 CreateMockRead(*data
.get(), 4), // 5
9200 MockRead(ASYNC
, 0, 0, 4), // 6
9203 OrderedSocketData
spdy_data(
9204 spdy_reads
, arraysize(spdy_reads
),
9205 spdy_writes
, arraysize(spdy_writes
));
9206 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9208 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9209 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9211 hanging_non_alternate_protocol_socket
.set_connect_data(
9212 never_finishing_connect
);
9213 session_deps_
.socket_factory
->AddSocketDataProvider(
9214 &hanging_non_alternate_protocol_socket
);
9216 TestCompletionCallback callback
;
9218 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9219 scoped_ptr
<HttpTransaction
> trans(
9220 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9222 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9223 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9224 EXPECT_EQ(OK
, callback
.WaitForResult());
9226 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9227 ASSERT_TRUE(response
!= NULL
);
9228 ASSERT_TRUE(response
->headers
.get() != NULL
);
9229 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9230 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9231 EXPECT_FALSE(response
->was_npn_negotiated
);
9233 std::string response_data
;
9234 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9235 EXPECT_EQ("hello world", response_data
);
9237 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9239 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9240 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9241 EXPECT_EQ(OK
, callback
.WaitForResult());
9243 response
= trans
->GetResponseInfo();
9244 ASSERT_TRUE(response
!= NULL
);
9245 ASSERT_TRUE(response
->headers
.get() != NULL
);
9246 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9247 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9248 EXPECT_TRUE(response
->was_npn_negotiated
);
9250 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9251 EXPECT_EQ("hello!", response_data
);
9252 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
9253 EXPECT_EQ("http://www.google.com/",
9254 capturing_proxy_resolver
->resolved()[0].spec());
9255 EXPECT_EQ("https://www.google.com/",
9256 capturing_proxy_resolver
->resolved()[1].spec());
9258 LoadTimingInfo load_timing_info
;
9259 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9260 TestLoadTimingNotReusedWithPac(load_timing_info
,
9261 CONNECT_TIMING_HAS_SSL_TIMES
);
9264 TEST_P(HttpNetworkTransactionTest
,
9265 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9266 session_deps_
.use_alternate_protocols
= true;
9267 session_deps_
.next_protos
= SpdyNextProtos();
9269 HttpRequestInfo request
;
9270 request
.method
= "GET";
9271 request
.url
= GURL("http://www.google.com/");
9272 request
.load_flags
= 0;
9274 std::string alternate_protocol_http_header
=
9275 GetAlternateProtocolHttpHeader();
9277 MockRead data_reads
[] = {
9278 MockRead("HTTP/1.1 200 OK\r\n"),
9279 MockRead(alternate_protocol_http_header
.c_str()),
9280 MockRead("hello world"),
9281 MockRead(ASYNC
, OK
),
9284 StaticSocketDataProvider
first_transaction(
9285 data_reads
, arraysize(data_reads
), NULL
, 0);
9286 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9288 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9289 ssl
.SetNextProto(GetParam());
9290 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9292 scoped_ptr
<SpdyFrame
> req(
9293 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9294 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9296 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9297 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9298 MockRead spdy_reads
[] = {
9299 CreateMockRead(*resp
),
9300 CreateMockRead(*data
),
9301 MockRead(ASYNC
, 0, 0),
9304 DelayedSocketData
spdy_data(
9305 1, // wait for one write to finish before reading.
9306 spdy_reads
, arraysize(spdy_reads
),
9307 spdy_writes
, arraysize(spdy_writes
));
9308 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9310 TestCompletionCallback callback
;
9312 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9314 scoped_ptr
<HttpTransaction
> trans(
9315 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9317 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9318 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9319 EXPECT_EQ(OK
, callback
.WaitForResult());
9321 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9322 ASSERT_TRUE(response
!= NULL
);
9323 ASSERT_TRUE(response
->headers
.get() != NULL
);
9324 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9326 std::string response_data
;
9327 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9328 EXPECT_EQ("hello world", response_data
);
9330 // Set up an initial SpdySession in the pool to reuse.
9331 HostPortPair
host_port_pair("www.google.com", 443);
9332 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9333 PRIVACY_MODE_DISABLED
);
9334 base::WeakPtr
<SpdySession
> spdy_session
=
9335 CreateSecureSpdySession(session
, key
, BoundNetLog());
9337 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9339 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9340 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9341 EXPECT_EQ(OK
, callback
.WaitForResult());
9343 response
= trans
->GetResponseInfo();
9344 ASSERT_TRUE(response
!= NULL
);
9345 ASSERT_TRUE(response
->headers
.get() != NULL
);
9346 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9347 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9348 EXPECT_TRUE(response
->was_npn_negotiated
);
9350 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9351 EXPECT_EQ("hello!", response_data
);
9354 // GenerateAuthToken is a mighty big test.
9355 // It tests all permutation of GenerateAuthToken behavior:
9356 // - Synchronous and Asynchronous completion.
9357 // - OK or error on completion.
9358 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9359 // - HTTP or HTTPS backend (to include proxy tunneling).
9360 // - Non-authenticating and authenticating backend.
9362 // In all, there are 44 reasonable permuations (for example, if there are
9363 // problems generating an auth token for an authenticating proxy, we don't
9364 // need to test all permutations of the backend server).
9366 // The test proceeds by going over each of the configuration cases, and
9367 // potentially running up to three rounds in each of the tests. The TestConfig
9368 // specifies both the configuration for the test as well as the expectations
9370 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9371 static const char kServer
[] = "http://www.example.com";
9372 static const char kSecureServer
[] = "https://www.example.com";
9373 static const char kProxy
[] = "myproxy:70";
9374 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9382 const MockWrite
kGet(
9383 "GET / HTTP/1.1\r\n"
9384 "Host: www.example.com\r\n"
9385 "Connection: keep-alive\r\n\r\n");
9386 const MockWrite
kGetProxy(
9387 "GET http://www.example.com/ HTTP/1.1\r\n"
9388 "Host: www.example.com\r\n"
9389 "Proxy-Connection: keep-alive\r\n\r\n");
9390 const MockWrite
kGetAuth(
9391 "GET / HTTP/1.1\r\n"
9392 "Host: www.example.com\r\n"
9393 "Connection: keep-alive\r\n"
9394 "Authorization: auth_token\r\n\r\n");
9395 const MockWrite
kGetProxyAuth(
9396 "GET http://www.example.com/ HTTP/1.1\r\n"
9397 "Host: www.example.com\r\n"
9398 "Proxy-Connection: keep-alive\r\n"
9399 "Proxy-Authorization: auth_token\r\n\r\n");
9400 const MockWrite
kGetAuthThroughProxy(
9401 "GET http://www.example.com/ HTTP/1.1\r\n"
9402 "Host: www.example.com\r\n"
9403 "Proxy-Connection: keep-alive\r\n"
9404 "Authorization: auth_token\r\n\r\n");
9405 const MockWrite
kGetAuthWithProxyAuth(
9406 "GET http://www.example.com/ HTTP/1.1\r\n"
9407 "Host: www.example.com\r\n"
9408 "Proxy-Connection: keep-alive\r\n"
9409 "Proxy-Authorization: auth_token\r\n"
9410 "Authorization: auth_token\r\n\r\n");
9411 const MockWrite
kConnect(
9412 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9413 "Host: www.example.com\r\n"
9414 "Proxy-Connection: keep-alive\r\n\r\n");
9415 const MockWrite
kConnectProxyAuth(
9416 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9417 "Host: www.example.com\r\n"
9418 "Proxy-Connection: keep-alive\r\n"
9419 "Proxy-Authorization: auth_token\r\n\r\n");
9421 const MockRead
kSuccess(
9422 "HTTP/1.1 200 OK\r\n"
9423 "Content-Type: text/html; charset=iso-8859-1\r\n"
9424 "Content-Length: 3\r\n\r\n"
9426 const MockRead
kFailure(
9427 "Should not be called.");
9428 const MockRead
kServerChallenge(
9429 "HTTP/1.1 401 Unauthorized\r\n"
9430 "WWW-Authenticate: Mock realm=server\r\n"
9431 "Content-Type: text/html; charset=iso-8859-1\r\n"
9432 "Content-Length: 14\r\n\r\n"
9433 "Unauthorized\r\n");
9434 const MockRead
kProxyChallenge(
9435 "HTTP/1.1 407 Unauthorized\r\n"
9436 "Proxy-Authenticate: Mock realm=proxy\r\n"
9437 "Proxy-Connection: close\r\n"
9438 "Content-Type: text/html; charset=iso-8859-1\r\n"
9439 "Content-Length: 14\r\n\r\n"
9440 "Unauthorized\r\n");
9441 const MockRead
kProxyConnected(
9442 "HTTP/1.1 200 Connection Established\r\n\r\n");
9444 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9445 // no constructors, but the C++ compiler on Windows warns about
9446 // unspecified data in compound literals. So, moved to using constructors,
9447 // and TestRound's created with the default constructor should not be used.
9450 : expected_rv(ERR_UNEXPECTED
),
9454 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9455 int expected_rv_arg
)
9458 expected_rv(expected_rv_arg
),
9462 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9463 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9464 const MockRead
* extra_read_arg
)
9467 expected_rv(expected_rv_arg
),
9468 extra_write(extra_write_arg
),
9469 extra_read(extra_read_arg
) {
9474 const MockWrite
* extra_write
;
9475 const MockRead
* extra_read
;
9478 static const int kNoSSL
= 500;
9481 const char* proxy_url
;
9482 AuthTiming proxy_auth_timing
;
9484 const char* server_url
;
9485 AuthTiming server_auth_timing
;
9487 int num_auth_rounds
;
9488 int first_ssl_round
;
9489 TestRound rounds
[3];
9490 } test_configs
[] = {
9491 // Non-authenticating HTTP server with a direct connection.
9492 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9493 { TestRound(kGet
, kSuccess
, OK
)}},
9494 // Authenticating HTTP server with a direct connection.
9495 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9496 { TestRound(kGet
, kServerChallenge
, OK
),
9497 TestRound(kGetAuth
, kSuccess
, OK
)}},
9498 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9499 { TestRound(kGet
, kServerChallenge
, OK
),
9500 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9501 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9502 { TestRound(kGet
, kServerChallenge
, OK
),
9503 TestRound(kGetAuth
, kSuccess
, OK
)}},
9504 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9505 { TestRound(kGet
, kServerChallenge
, OK
),
9506 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9507 // Non-authenticating HTTP server through a non-authenticating proxy.
9508 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9509 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9510 // Authenticating HTTP server through a non-authenticating proxy.
9511 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9512 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9513 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9514 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9515 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9516 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9517 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9518 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9519 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9520 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9521 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9522 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9523 // Non-authenticating HTTP server through an authenticating proxy.
9524 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9525 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9526 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9527 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9528 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9529 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9530 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9531 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9532 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9533 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9534 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9535 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9536 // Authenticating HTTP server through an authenticating proxy.
9537 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9538 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9539 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9540 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9541 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9542 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9543 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9544 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9545 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9546 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9547 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9548 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9549 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9550 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9551 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9552 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9553 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9554 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9555 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9556 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9557 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9558 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9559 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9560 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9561 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9562 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9563 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9564 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9565 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9566 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9567 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9568 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9569 // Non-authenticating HTTPS server with a direct connection.
9570 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9571 { TestRound(kGet
, kSuccess
, OK
)}},
9572 // Authenticating HTTPS server with a direct connection.
9573 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9574 { TestRound(kGet
, kServerChallenge
, OK
),
9575 TestRound(kGetAuth
, kSuccess
, OK
)}},
9576 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9577 { TestRound(kGet
, kServerChallenge
, OK
),
9578 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9579 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9580 { TestRound(kGet
, kServerChallenge
, OK
),
9581 TestRound(kGetAuth
, kSuccess
, OK
)}},
9582 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9583 { TestRound(kGet
, kServerChallenge
, OK
),
9584 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9585 // Non-authenticating HTTPS server with a non-authenticating proxy.
9586 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9587 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9588 // Authenticating HTTPS server through a non-authenticating proxy.
9589 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9590 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9591 TestRound(kGetAuth
, kSuccess
, OK
)}},
9592 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9593 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9594 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9595 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9596 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9597 TestRound(kGetAuth
, kSuccess
, OK
)}},
9598 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9599 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9600 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9601 // Non-Authenticating HTTPS server through an authenticating proxy.
9602 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9603 { TestRound(kConnect
, kProxyChallenge
, OK
),
9604 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9605 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9606 { TestRound(kConnect
, kProxyChallenge
, OK
),
9607 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9608 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9609 { TestRound(kConnect
, kProxyChallenge
, OK
),
9610 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9611 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9612 { TestRound(kConnect
, kProxyChallenge
, OK
),
9613 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9614 // Authenticating HTTPS server through an authenticating proxy.
9615 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9616 { TestRound(kConnect
, kProxyChallenge
, OK
),
9617 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9618 &kGet
, &kServerChallenge
),
9619 TestRound(kGetAuth
, kSuccess
, OK
)}},
9620 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9621 { TestRound(kConnect
, kProxyChallenge
, OK
),
9622 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9623 &kGet
, &kServerChallenge
),
9624 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9625 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9626 { TestRound(kConnect
, kProxyChallenge
, OK
),
9627 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9628 &kGet
, &kServerChallenge
),
9629 TestRound(kGetAuth
, kSuccess
, OK
)}},
9630 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9631 { TestRound(kConnect
, kProxyChallenge
, OK
),
9632 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9633 &kGet
, &kServerChallenge
),
9634 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9635 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9636 { TestRound(kConnect
, kProxyChallenge
, OK
),
9637 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9638 &kGet
, &kServerChallenge
),
9639 TestRound(kGetAuth
, kSuccess
, OK
)}},
9640 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9641 { TestRound(kConnect
, kProxyChallenge
, OK
),
9642 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9643 &kGet
, &kServerChallenge
),
9644 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9645 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9646 { TestRound(kConnect
, kProxyChallenge
, OK
),
9647 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9648 &kGet
, &kServerChallenge
),
9649 TestRound(kGetAuth
, kSuccess
, OK
)}},
9650 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9651 { TestRound(kConnect
, kProxyChallenge
, OK
),
9652 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9653 &kGet
, &kServerChallenge
),
9654 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9657 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_configs
); ++i
) {
9658 HttpAuthHandlerMock::Factory
* auth_factory(
9659 new HttpAuthHandlerMock::Factory());
9660 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9661 const TestConfig
& test_config
= test_configs
[i
];
9663 // Set up authentication handlers as necessary.
9664 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9665 for (int n
= 0; n
< 2; n
++) {
9666 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9667 std::string auth_challenge
= "Mock realm=proxy";
9668 GURL
origin(test_config
.proxy_url
);
9669 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9670 auth_challenge
.end());
9671 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9672 origin
, BoundNetLog());
9673 auth_handler
->SetGenerateExpectation(
9674 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9675 test_config
.proxy_auth_rv
);
9676 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9679 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9680 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9681 std::string auth_challenge
= "Mock realm=server";
9682 GURL
origin(test_config
.server_url
);
9683 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9684 auth_challenge
.end());
9685 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9686 origin
, BoundNetLog());
9687 auth_handler
->SetGenerateExpectation(
9688 test_config
.server_auth_timing
== AUTH_ASYNC
,
9689 test_config
.server_auth_rv
);
9690 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9692 if (test_config
.proxy_url
) {
9693 session_deps_
.proxy_service
.reset(
9694 ProxyService::CreateFixed(test_config
.proxy_url
));
9696 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9699 HttpRequestInfo request
;
9700 request
.method
= "GET";
9701 request
.url
= GURL(test_config
.server_url
);
9702 request
.load_flags
= 0;
9704 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9705 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
9707 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9708 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9710 // Set up expected reads and writes.
9712 reads
[0] = read_write_round
.read
;
9713 size_t length_reads
= 1;
9714 if (read_write_round
.extra_read
) {
9715 reads
[1] = *read_write_round
.extra_read
;
9719 MockWrite writes
[2];
9720 writes
[0] = read_write_round
.write
;
9721 size_t length_writes
= 1;
9722 if (read_write_round
.extra_write
) {
9723 writes
[1] = *read_write_round
.extra_write
;
9726 StaticSocketDataProvider
data_provider(
9727 reads
, length_reads
, writes
, length_writes
);
9728 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9730 // Add an SSL sequence if necessary.
9731 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9732 if (round
>= test_config
.first_ssl_round
)
9733 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9734 &ssl_socket_data_provider
);
9736 // Start or restart the transaction.
9737 TestCompletionCallback callback
;
9740 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9742 rv
= trans
.RestartWithAuth(
9743 AuthCredentials(kFoo
, kBar
), callback
.callback());
9745 if (rv
== ERR_IO_PENDING
)
9746 rv
= callback
.WaitForResult();
9748 // Compare results with expected data.
9749 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9750 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9751 if (read_write_round
.expected_rv
== OK
) {
9752 ASSERT_TRUE(response
!= NULL
);
9754 EXPECT_TRUE(response
== NULL
);
9755 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9758 if (round
+ 1 < test_config
.num_auth_rounds
) {
9759 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9761 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9767 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9768 // Do multi-round authentication and make sure it works correctly.
9769 HttpAuthHandlerMock::Factory
* auth_factory(
9770 new HttpAuthHandlerMock::Factory());
9771 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9772 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9773 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9774 session_deps_
.host_resolver
->set_synchronous_mode(true);
9776 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9777 auth_handler
->set_connection_based(true);
9778 std::string auth_challenge
= "Mock realm=server";
9779 GURL
origin("http://www.example.com");
9780 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9781 auth_challenge
.end());
9782 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9783 origin
, BoundNetLog());
9784 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9787 const HttpResponseInfo
* response
= NULL
;
9788 HttpRequestInfo request
;
9789 request
.method
= "GET";
9790 request
.url
= origin
;
9791 request
.load_flags
= 0;
9793 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9795 // Use a TCP Socket Pool with only one connection per group. This is used
9796 // to validate that the TCP socket is not released to the pool between
9797 // each round of multi-round authentication.
9798 HttpNetworkSessionPeer
session_peer(session
);
9799 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9800 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9801 50, // Max sockets for pool
9802 1, // Max sockets per group
9803 &transport_pool_histograms
,
9804 session_deps_
.host_resolver
.get(),
9805 session_deps_
.socket_factory
.get(),
9806 session_deps_
.net_log
);
9807 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
9808 new MockClientSocketPoolManager
);
9809 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9810 session_peer
.SetClientSocketPoolManager(
9811 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
9813 scoped_ptr
<HttpTransaction
> trans(
9814 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9815 TestCompletionCallback callback
;
9817 const MockWrite
kGet(
9818 "GET / HTTP/1.1\r\n"
9819 "Host: www.example.com\r\n"
9820 "Connection: keep-alive\r\n\r\n");
9821 const MockWrite
kGetAuth(
9822 "GET / HTTP/1.1\r\n"
9823 "Host: www.example.com\r\n"
9824 "Connection: keep-alive\r\n"
9825 "Authorization: auth_token\r\n\r\n");
9827 const MockRead
kServerChallenge(
9828 "HTTP/1.1 401 Unauthorized\r\n"
9829 "WWW-Authenticate: Mock realm=server\r\n"
9830 "Content-Type: text/html; charset=iso-8859-1\r\n"
9831 "Content-Length: 14\r\n\r\n"
9832 "Unauthorized\r\n");
9833 const MockRead
kSuccess(
9834 "HTTP/1.1 200 OK\r\n"
9835 "Content-Type: text/html; charset=iso-8859-1\r\n"
9836 "Content-Length: 3\r\n\r\n"
9839 MockWrite writes
[] = {
9848 // Competing request
9851 MockRead reads
[] = {
9860 // Competing response
9863 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9864 writes
, arraysize(writes
));
9865 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9867 const char* const kSocketGroup
= "www.example.com:80";
9869 // First round of authentication.
9870 auth_handler
->SetGenerateExpectation(false, OK
);
9871 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9872 if (rv
== ERR_IO_PENDING
)
9873 rv
= callback
.WaitForResult();
9875 response
= trans
->GetResponseInfo();
9876 ASSERT_TRUE(response
!= NULL
);
9877 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9878 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9880 // In between rounds, another request comes in for the same domain.
9881 // It should not be able to grab the TCP socket that trans has already
9883 scoped_ptr
<HttpTransaction
> trans_compete(
9884 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9885 TestCompletionCallback callback_compete
;
9886 rv
= trans_compete
->Start(
9887 &request
, callback_compete
.callback(), BoundNetLog());
9888 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9889 // callback_compete.WaitForResult at this point would stall forever,
9890 // since the HttpNetworkTransaction does not release the request back to
9891 // the pool until after authentication completes.
9893 // Second round of authentication.
9894 auth_handler
->SetGenerateExpectation(false, OK
);
9895 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9896 if (rv
== ERR_IO_PENDING
)
9897 rv
= callback
.WaitForResult();
9899 response
= trans
->GetResponseInfo();
9900 ASSERT_TRUE(response
!= NULL
);
9901 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9902 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9904 // Third round of authentication.
9905 auth_handler
->SetGenerateExpectation(false, OK
);
9906 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9907 if (rv
== ERR_IO_PENDING
)
9908 rv
= callback
.WaitForResult();
9910 response
= trans
->GetResponseInfo();
9911 ASSERT_TRUE(response
!= NULL
);
9912 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9913 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9915 // Fourth round of authentication, which completes successfully.
9916 auth_handler
->SetGenerateExpectation(false, OK
);
9917 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9918 if (rv
== ERR_IO_PENDING
)
9919 rv
= callback
.WaitForResult();
9921 response
= trans
->GetResponseInfo();
9922 ASSERT_TRUE(response
!= NULL
);
9923 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9924 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9926 // Read the body since the fourth round was successful. This will also
9927 // release the socket back to the pool.
9928 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9929 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9930 if (rv
== ERR_IO_PENDING
)
9931 rv
= callback
.WaitForResult();
9933 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9935 // There are still 0 idle sockets, since the trans_compete transaction
9936 // will be handed it immediately after trans releases it to the group.
9937 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9939 // The competing request can now finish. Wait for the headers and then
9941 rv
= callback_compete
.WaitForResult();
9943 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9944 if (rv
== ERR_IO_PENDING
)
9945 rv
= callback
.WaitForResult();
9947 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9950 // Finally, the socket is released to the group.
9951 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9954 // This tests the case that a request is issued via http instead of spdy after
9955 // npn is negotiated.
9956 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9957 session_deps_
.use_alternate_protocols
= true;
9958 NextProtoVector next_protos
;
9959 next_protos
.push_back(kProtoHTTP11
);
9960 session_deps_
.next_protos
= next_protos
;
9962 HttpRequestInfo request
;
9963 request
.method
= "GET";
9964 request
.url
= GURL("https://www.google.com/");
9965 request
.load_flags
= 0;
9967 MockWrite data_writes
[] = {
9968 MockWrite("GET / HTTP/1.1\r\n"
9969 "Host: www.google.com\r\n"
9970 "Connection: keep-alive\r\n\r\n"),
9973 std::string alternate_protocol_http_header
=
9974 GetAlternateProtocolHttpHeader();
9976 MockRead data_reads
[] = {
9977 MockRead("HTTP/1.1 200 OK\r\n"),
9978 MockRead(alternate_protocol_http_header
.c_str()),
9979 MockRead("hello world"),
9980 MockRead(SYNCHRONOUS
, OK
),
9983 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9984 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9985 ssl
.next_proto
= "http/1.1";
9986 ssl
.protocol_negotiated
= kProtoHTTP11
;
9988 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9990 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9991 data_writes
, arraysize(data_writes
));
9992 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9994 TestCompletionCallback callback
;
9996 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9997 scoped_ptr
<HttpTransaction
> trans(
9998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10000 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10003 EXPECT_EQ(OK
, callback
.WaitForResult());
10005 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10006 ASSERT_TRUE(response
!= NULL
);
10007 ASSERT_TRUE(response
->headers
.get() != NULL
);
10008 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10010 std::string response_data
;
10011 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10012 EXPECT_EQ("hello world", response_data
);
10014 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10015 EXPECT_TRUE(response
->was_npn_negotiated
);
10018 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10019 // Simulate the SSL handshake completing with an NPN negotiation
10020 // followed by an immediate server closing of the socket.
10021 // Fix crash: http://crbug.com/46369
10022 session_deps_
.use_alternate_protocols
= true;
10023 session_deps_
.next_protos
= SpdyNextProtos();
10025 HttpRequestInfo request
;
10026 request
.method
= "GET";
10027 request
.url
= GURL("https://www.google.com/");
10028 request
.load_flags
= 0;
10030 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10031 ssl
.SetNextProto(GetParam());
10032 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10034 scoped_ptr
<SpdyFrame
> req(
10035 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10036 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10038 MockRead spdy_reads
[] = {
10039 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10042 DelayedSocketData
spdy_data(
10043 0, // don't wait in this case, immediate hangup.
10044 spdy_reads
, arraysize(spdy_reads
),
10045 spdy_writes
, arraysize(spdy_writes
));
10046 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10048 TestCompletionCallback callback
;
10050 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10051 scoped_ptr
<HttpTransaction
> trans(
10052 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10054 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10055 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10056 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10059 // A subclass of HttpAuthHandlerMock that records the request URL when
10060 // it gets it. This is needed since the auth handler may get destroyed
10061 // before we get a chance to query it.
10062 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10064 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10066 virtual ~UrlRecordingHttpAuthHandlerMock() {}
10069 virtual int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10070 const HttpRequestInfo
* request
,
10071 const CompletionCallback
& callback
,
10072 std::string
* auth_token
) OVERRIDE
{
10073 *url_
= request
->url
;
10074 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10075 credentials
, request
, callback
, auth_token
);
10082 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10083 // This test ensures that the URL passed into the proxy is upgraded
10084 // to https when doing an Alternate Protocol upgrade.
10085 session_deps_
.use_alternate_protocols
= true;
10086 session_deps_
.next_protos
= SpdyNextProtos();
10088 session_deps_
.proxy_service
.reset(
10089 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10090 CapturingNetLog net_log
;
10091 session_deps_
.net_log
= &net_log
;
10094 HttpAuthHandlerMock::Factory
* auth_factory
=
10095 new HttpAuthHandlerMock::Factory();
10096 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10097 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10098 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10099 auth_factory
->set_do_init_from_challenge(true);
10100 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10103 HttpRequestInfo request
;
10104 request
.method
= "GET";
10105 request
.url
= GURL("http://www.google.com");
10106 request
.load_flags
= 0;
10108 // First round goes unauthenticated through the proxy.
10109 MockWrite data_writes_1
[] = {
10110 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10111 "Host: www.google.com\r\n"
10112 "Proxy-Connection: keep-alive\r\n"
10115 MockRead data_reads_1
[] = {
10116 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10117 MockRead("HTTP/1.1 200 OK\r\n"
10118 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10119 "Proxy-Connection: close\r\n"
10122 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10123 data_writes_1
, arraysize(data_writes_1
));
10125 // Second round tries to tunnel to www.google.com due to the
10126 // Alternate-Protocol announcement in the first round. It fails due
10127 // to a proxy authentication challenge.
10128 // After the failure, a tunnel is established to www.google.com using
10129 // Proxy-Authorization headers. There is then a SPDY request round.
10131 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10132 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10133 // does a Disconnect and Connect on the same socket, rather than trying
10134 // to obtain a new one.
10136 // NOTE: Originally, the proxy response to the second CONNECT request
10137 // simply returned another 407 so the unit test could skip the SSL connection
10138 // establishment and SPDY framing issues. Alas, the
10139 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10140 // complicated to set up expectations for than the SPDY session.
10142 scoped_ptr
<SpdyFrame
> req(
10143 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10144 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10145 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10147 MockWrite data_writes_2
[] = {
10148 // First connection attempt without Proxy-Authorization.
10149 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10150 "Host: www.google.com\r\n"
10151 "Proxy-Connection: keep-alive\r\n"
10154 // Second connection attempt with Proxy-Authorization.
10155 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10156 "Host: www.google.com\r\n"
10157 "Proxy-Connection: keep-alive\r\n"
10158 "Proxy-Authorization: auth_token\r\n"
10162 CreateMockWrite(*req
),
10164 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10165 "Proxy-Authenticate: Mock\r\n"
10166 "Proxy-Connection: close\r\n"
10168 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10169 MockRead data_reads_2
[] = {
10170 // First connection attempt fails
10171 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10172 MockRead(ASYNC
, kRejectConnectResponse
,
10173 arraysize(kRejectConnectResponse
) - 1, 1),
10175 // Second connection attempt passes
10176 MockRead(ASYNC
, kAcceptConnectResponse
,
10177 arraysize(kAcceptConnectResponse
) -1, 4),
10180 CreateMockRead(*resp
.get(), 6),
10181 CreateMockRead(*data
.get(), 6),
10182 MockRead(ASYNC
, 0, 0, 6),
10184 OrderedSocketData
data_2(
10185 data_reads_2
, arraysize(data_reads_2
),
10186 data_writes_2
, arraysize(data_writes_2
));
10188 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10189 ssl
.SetNextProto(GetParam());
10191 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10192 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10194 hanging_non_alternate_protocol_socket
.set_connect_data(
10195 never_finishing_connect
);
10197 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10198 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10199 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10200 session_deps_
.socket_factory
->AddSocketDataProvider(
10201 &hanging_non_alternate_protocol_socket
);
10202 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10204 // First round should work and provide the Alternate-Protocol state.
10205 TestCompletionCallback callback_1
;
10206 scoped_ptr
<HttpTransaction
> trans_1(
10207 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10208 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10209 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10210 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10212 // Second round should attempt a tunnel connect and get an auth challenge.
10213 TestCompletionCallback callback_2
;
10214 scoped_ptr
<HttpTransaction
> trans_2(
10215 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10216 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10217 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10218 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10219 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10220 ASSERT_TRUE(response
!= NULL
);
10221 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10223 // Restart with auth. Tunnel should work and response received.
10224 TestCompletionCallback callback_3
;
10225 rv
= trans_2
->RestartWithAuth(
10226 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10228 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10230 // After all that work, these two lines (or actually, just the scheme) are
10231 // what this test is all about. Make sure it happens correctly.
10232 EXPECT_EQ("https", request_url
.scheme());
10233 EXPECT_EQ("www.google.com", request_url
.host());
10235 LoadTimingInfo load_timing_info
;
10236 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10237 TestLoadTimingNotReusedWithPac(load_timing_info
,
10238 CONNECT_TIMING_HAS_SSL_TIMES
);
10241 // Test that if we cancel the transaction as the connection is completing, that
10242 // everything tears down correctly.
10243 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10244 // Setup everything about the connection to complete synchronously, so that
10245 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10246 // for is the callback from the HttpStreamRequest.
10247 // Then cancel the transaction.
10248 // Verify that we don't crash.
10249 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10250 MockRead data_reads
[] = {
10251 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10252 MockRead(SYNCHRONOUS
, "hello world"),
10253 MockRead(SYNCHRONOUS
, OK
),
10256 HttpRequestInfo request
;
10257 request
.method
= "GET";
10258 request
.url
= GURL("http://www.google.com/");
10259 request
.load_flags
= 0;
10261 session_deps_
.host_resolver
->set_synchronous_mode(true);
10262 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10263 scoped_ptr
<HttpTransaction
> trans(
10264 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
10266 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10267 data
.set_connect_data(mock_connect
);
10268 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10270 TestCompletionCallback callback
;
10272 CapturingBoundNetLog log
;
10273 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10275 trans
.reset(); // Cancel the transaction here.
10277 base::MessageLoop::current()->RunUntilIdle();
10280 // Test that if a transaction is cancelled after receiving the headers, the
10281 // stream is drained properly and added back to the socket pool. The main
10282 // purpose of this test is to make sure that an HttpStreamParser can be read
10283 // from after the HttpNetworkTransaction and the objects it owns have been
10285 // See http://crbug.com/368418
10286 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10287 MockRead data_reads
[] = {
10288 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10289 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10290 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10291 MockRead(ASYNC
, "1"),
10292 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10293 // HttpNetworkTransaction has been deleted.
10294 MockRead(ASYNC
, "2"),
10295 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10297 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10298 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10300 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10303 HttpRequestInfo request
;
10304 request
.method
= "GET";
10305 request
.url
= GURL("http://www.google.com/");
10306 request
.load_flags
= 0;
10308 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
10309 TestCompletionCallback callback
;
10311 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10312 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10313 callback
.WaitForResult();
10315 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10316 ASSERT_TRUE(response
!= NULL
);
10317 EXPECT_TRUE(response
->headers
.get() != NULL
);
10318 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10320 // The transaction and HttpRequestInfo are deleted.
10323 // Let the HttpResponseBodyDrainer drain the socket.
10324 base::MessageLoop::current()->RunUntilIdle();
10326 // Socket should now be idle, waiting to be reused.
10327 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
10330 // Test a basic GET request through a proxy.
10331 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10332 session_deps_
.proxy_service
.reset(
10333 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10334 CapturingBoundNetLog log
;
10335 session_deps_
.net_log
= log
.bound().net_log();
10336 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10338 HttpRequestInfo request
;
10339 request
.method
= "GET";
10340 request
.url
= GURL("http://www.google.com/");
10342 MockWrite data_writes1
[] = {
10343 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10344 "Host: www.google.com\r\n"
10345 "Proxy-Connection: keep-alive\r\n\r\n"),
10348 MockRead data_reads1
[] = {
10349 MockRead("HTTP/1.1 200 OK\r\n"),
10350 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10351 MockRead("Content-Length: 100\r\n\r\n"),
10352 MockRead(SYNCHRONOUS
, OK
),
10355 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10356 data_writes1
, arraysize(data_writes1
));
10357 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10359 TestCompletionCallback callback1
;
10361 scoped_ptr
<HttpTransaction
> trans(
10362 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10363 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10364 trans
->SetBeforeProxyHeadersSentCallback(
10365 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10366 base::Unretained(&proxy_headers_handler
)));
10368 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10371 rv
= callback1
.WaitForResult();
10374 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10375 ASSERT_TRUE(response
!= NULL
);
10377 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10378 EXPECT_EQ(200, response
->headers
->response_code());
10379 EXPECT_EQ(100, response
->headers
->GetContentLength());
10380 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10382 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10383 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10384 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10385 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10387 LoadTimingInfo load_timing_info
;
10388 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10389 TestLoadTimingNotReusedWithPac(load_timing_info
,
10390 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10393 // Test a basic HTTPS GET request through a proxy.
10394 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10395 session_deps_
.proxy_service
.reset(
10396 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10397 CapturingBoundNetLog log
;
10398 session_deps_
.net_log
= log
.bound().net_log();
10399 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10401 HttpRequestInfo request
;
10402 request
.method
= "GET";
10403 request
.url
= GURL("https://www.google.com/");
10405 // Since we have proxy, should try to establish tunnel.
10406 MockWrite data_writes1
[] = {
10407 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10408 "Host: www.google.com\r\n"
10409 "Proxy-Connection: keep-alive\r\n\r\n"),
10411 MockWrite("GET / HTTP/1.1\r\n"
10412 "Host: www.google.com\r\n"
10413 "Connection: keep-alive\r\n\r\n"),
10416 MockRead data_reads1
[] = {
10417 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10419 MockRead("HTTP/1.1 200 OK\r\n"),
10420 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10421 MockRead("Content-Length: 100\r\n\r\n"),
10422 MockRead(SYNCHRONOUS
, OK
),
10425 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10426 data_writes1
, arraysize(data_writes1
));
10427 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10428 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10429 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10431 TestCompletionCallback callback1
;
10433 scoped_ptr
<HttpTransaction
> trans(
10434 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10436 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10439 rv
= callback1
.WaitForResult();
10441 net::CapturingNetLog::CapturedEntryList entries
;
10442 log
.GetEntries(&entries
);
10443 size_t pos
= ExpectLogContainsSomewhere(
10444 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10445 NetLog::PHASE_NONE
);
10446 ExpectLogContainsSomewhere(
10448 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10449 NetLog::PHASE_NONE
);
10451 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10452 ASSERT_TRUE(response
!= NULL
);
10454 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10455 EXPECT_EQ(200, response
->headers
->response_code());
10456 EXPECT_EQ(100, response
->headers
->GetContentLength());
10457 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10458 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10460 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10462 LoadTimingInfo load_timing_info
;
10463 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10464 TestLoadTimingNotReusedWithPac(load_timing_info
,
10465 CONNECT_TIMING_HAS_SSL_TIMES
);
10468 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10469 // while establishing the tunnel.
10470 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10471 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10472 CapturingBoundNetLog log
;
10473 session_deps_
.net_log
= log
.bound().net_log();
10474 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10476 HttpRequestInfo request
;
10477 request
.method
= "GET";
10478 request
.url
= GURL("https://www.google.com/");
10480 // Since we have proxy, should try to establish tunnel.
10481 MockWrite data_writes1
[] = {
10482 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10483 "Host: www.google.com\r\n"
10484 "Proxy-Connection: keep-alive\r\n\r\n"),
10486 MockWrite("GET / HTTP/1.1\r\n"
10487 "Host: www.google.com\r\n"
10488 "Connection: keep-alive\r\n\r\n"),
10491 MockRead data_reads1
[] = {
10492 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10493 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10494 MockRead(ASYNC
, 0, 0), // EOF
10497 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10498 data_writes1
, arraysize(data_writes1
));
10499 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10500 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10501 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10503 TestCompletionCallback callback1
;
10505 scoped_ptr
<HttpTransaction
> trans(
10506 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10508 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10509 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10511 rv
= callback1
.WaitForResult();
10512 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10513 net::CapturingNetLog::CapturedEntryList entries
;
10514 log
.GetEntries(&entries
);
10515 size_t pos
= ExpectLogContainsSomewhere(
10516 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10517 NetLog::PHASE_NONE
);
10518 ExpectLogContainsSomewhere(
10520 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10521 NetLog::PHASE_NONE
);
10524 // Test for crbug.com/55424.
10525 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10526 scoped_ptr
<SpdyFrame
> req(
10527 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10528 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10530 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10531 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10532 MockRead spdy_reads
[] = {
10533 CreateMockRead(*resp
),
10534 CreateMockRead(*data
),
10535 MockRead(ASYNC
, 0, 0),
10538 DelayedSocketData
spdy_data(
10539 1, // wait for one write to finish before reading.
10540 spdy_reads
, arraysize(spdy_reads
),
10541 spdy_writes
, arraysize(spdy_writes
));
10542 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10544 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10545 ssl
.SetNextProto(GetParam());
10546 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10548 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10550 // Set up an initial SpdySession in the pool to reuse.
10551 HostPortPair
host_port_pair("www.google.com", 443);
10552 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10553 PRIVACY_MODE_DISABLED
);
10554 base::WeakPtr
<SpdySession
> spdy_session
=
10555 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10557 HttpRequestInfo request
;
10558 request
.method
= "GET";
10559 request
.url
= GURL("https://www.google.com/");
10560 request
.load_flags
= 0;
10562 // This is the important line that marks this as a preconnect.
10563 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10565 scoped_ptr
<HttpTransaction
> trans(
10566 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10568 TestCompletionCallback callback
;
10569 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10570 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10571 EXPECT_EQ(OK
, callback
.WaitForResult());
10574 // Given a net error, cause that error to be returned from the first Write()
10575 // call and verify that the HttpTransaction fails with that error.
10576 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10577 int error
, IoMode mode
) {
10578 net::HttpRequestInfo request_info
;
10579 request_info
.url
= GURL("https://www.example.com/");
10580 request_info
.method
= "GET";
10581 request_info
.load_flags
= net::LOAD_NORMAL
;
10583 SSLSocketDataProvider
ssl_data(mode
, OK
);
10584 net::MockWrite data_writes
[] = {
10585 net::MockWrite(mode
, error
),
10587 net::StaticSocketDataProvider
data(NULL
, 0,
10588 data_writes
, arraysize(data_writes
));
10589 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10590 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10592 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10593 scoped_ptr
<HttpTransaction
> trans(
10594 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10596 TestCompletionCallback callback
;
10597 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10598 if (rv
== net::ERR_IO_PENDING
)
10599 rv
= callback
.WaitForResult();
10600 ASSERT_EQ(error
, rv
);
10603 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10604 // Just check a grab bag of cert errors.
10605 static const int kErrors
[] = {
10606 ERR_CERT_COMMON_NAME_INVALID
,
10607 ERR_CERT_AUTHORITY_INVALID
,
10608 ERR_CERT_DATE_INVALID
,
10610 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10611 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10612 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10616 // Ensure that a client certificate is removed from the SSL client auth
10618 // 1) No proxy is involved.
10619 // 2) TLS False Start is disabled.
10620 // 3) The initial TLS handshake requests a client certificate.
10621 // 4) The client supplies an invalid/unacceptable certificate.
10622 TEST_P(HttpNetworkTransactionTest
,
10623 ClientAuthCertCache_Direct_NoFalseStart
) {
10624 net::HttpRequestInfo request_info
;
10625 request_info
.url
= GURL("https://www.example.com/");
10626 request_info
.method
= "GET";
10627 request_info
.load_flags
= net::LOAD_NORMAL
;
10629 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10630 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10632 // [ssl_]data1 contains the data for the first SSL handshake. When a
10633 // CertificateRequest is received for the first time, the handshake will
10634 // be aborted to allow the caller to provide a certificate.
10635 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10636 ssl_data1
.cert_request_info
= cert_request
.get();
10637 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10638 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10639 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10641 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10642 // False Start is not being used, the result of the SSL handshake will be
10643 // returned as part of the SSLClientSocket::Connect() call. This test
10644 // matches the result of a server sending a handshake_failure alert,
10645 // rather than a Finished message, because it requires a client
10646 // certificate and none was supplied.
10647 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10648 ssl_data2
.cert_request_info
= cert_request
.get();
10649 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10650 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10651 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10653 // [ssl_]data3 contains the data for the third SSL handshake. When a
10654 // connection to a server fails during an SSL handshake,
10655 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10656 // connection was attempted with TLSv1.1. This is transparent to the caller
10657 // of the HttpNetworkTransaction. Because this test failure is due to
10658 // requiring a client certificate, this fallback handshake should also
10660 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10661 ssl_data3
.cert_request_info
= cert_request
.get();
10662 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10663 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10664 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10666 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10667 // connection to a server fails during an SSL handshake,
10668 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10669 // connection was attempted with TLSv1. This is transparent to the caller
10670 // of the HttpNetworkTransaction. Because this test failure is due to
10671 // requiring a client certificate, this fallback handshake should also
10673 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10674 ssl_data4
.cert_request_info
= cert_request
.get();
10675 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10676 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10677 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10679 // Need one more if TLSv1.2 is enabled.
10680 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10681 ssl_data5
.cert_request_info
= cert_request
.get();
10682 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10683 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10684 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10686 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10687 scoped_ptr
<HttpTransaction
> trans(
10688 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10690 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10691 TestCompletionCallback callback
;
10692 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10693 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10695 // Complete the SSL handshake, which should abort due to requiring a
10696 // client certificate.
10697 rv
= callback
.WaitForResult();
10698 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10700 // Indicate that no certificate should be supplied. From the perspective
10701 // of SSLClientCertCache, NULL is just as meaningful as a real
10702 // certificate, so this is the same as supply a
10703 // legitimate-but-unacceptable certificate.
10704 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10705 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10707 // Ensure the certificate was added to the client auth cache before
10708 // allowing the connection to continue restarting.
10709 scoped_refptr
<X509Certificate
> client_cert
;
10710 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10711 HostPortPair("www.example.com", 443), &client_cert
));
10712 ASSERT_EQ(NULL
, client_cert
.get());
10714 // Restart the handshake. This will consume ssl_data2, which fails, and
10715 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10716 // The result code is checked against what ssl_data4 should return.
10717 rv
= callback
.WaitForResult();
10718 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10720 // Ensure that the client certificate is removed from the cache on a
10721 // handshake failure.
10722 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10723 HostPortPair("www.example.com", 443), &client_cert
));
10726 // Ensure that a client certificate is removed from the SSL client auth
10728 // 1) No proxy is involved.
10729 // 2) TLS False Start is enabled.
10730 // 3) The initial TLS handshake requests a client certificate.
10731 // 4) The client supplies an invalid/unacceptable certificate.
10732 TEST_P(HttpNetworkTransactionTest
,
10733 ClientAuthCertCache_Direct_FalseStart
) {
10734 net::HttpRequestInfo request_info
;
10735 request_info
.url
= GURL("https://www.example.com/");
10736 request_info
.method
= "GET";
10737 request_info
.load_flags
= net::LOAD_NORMAL
;
10739 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10740 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10742 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10743 // return successfully after reading up to the peer's Certificate message.
10744 // This is to allow the caller to call SSLClientSocket::Write(), which can
10745 // enqueue application data to be sent in the same packet as the
10746 // ChangeCipherSpec and Finished messages.
10747 // The actual handshake will be finished when SSLClientSocket::Read() is
10748 // called, which expects to process the peer's ChangeCipherSpec and
10749 // Finished messages. If there was an error negotiating with the peer,
10750 // such as due to the peer requiring a client certificate when none was
10751 // supplied, the alert sent by the peer won't be processed until Read() is
10754 // Like the non-False Start case, when a client certificate is requested by
10755 // the peer, the handshake is aborted during the Connect() call.
10756 // [ssl_]data1 represents the initial SSL handshake with the peer.
10757 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10758 ssl_data1
.cert_request_info
= cert_request
.get();
10759 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10760 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10761 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10763 // When a client certificate is supplied, Connect() will not be aborted
10764 // when the peer requests the certificate. Instead, the handshake will
10765 // artificially succeed, allowing the caller to write the HTTP request to
10766 // the socket. The handshake messages are not processed until Read() is
10767 // called, which then detects that the handshake was aborted, due to the
10768 // peer sending a handshake_failure because it requires a client
10770 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10771 ssl_data2
.cert_request_info
= cert_request
.get();
10772 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10773 net::MockRead data2_reads
[] = {
10774 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10776 net::StaticSocketDataProvider
data2(
10777 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10778 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10780 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10781 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10782 // TLSv1. It has the same behaviour as [ssl_]data2.
10783 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10784 ssl_data3
.cert_request_info
= cert_request
.get();
10785 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10786 net::StaticSocketDataProvider
data3(
10787 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10788 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10790 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10791 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10792 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10793 ssl_data4
.cert_request_info
= cert_request
.get();
10794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10795 net::StaticSocketDataProvider
data4(
10796 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10797 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10799 // Need one more if TLSv1.2 is enabled.
10800 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10801 ssl_data5
.cert_request_info
= cert_request
.get();
10802 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10803 net::StaticSocketDataProvider
data5(
10804 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10805 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10808 scoped_ptr
<HttpTransaction
> trans(
10809 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10811 // Begin the initial SSL handshake.
10812 TestCompletionCallback callback
;
10813 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10814 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10816 // Complete the SSL handshake, which should abort due to requiring a
10817 // client certificate.
10818 rv
= callback
.WaitForResult();
10819 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10821 // Indicate that no certificate should be supplied. From the perspective
10822 // of SSLClientCertCache, NULL is just as meaningful as a real
10823 // certificate, so this is the same as supply a
10824 // legitimate-but-unacceptable certificate.
10825 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10826 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10828 // Ensure the certificate was added to the client auth cache before
10829 // allowing the connection to continue restarting.
10830 scoped_refptr
<X509Certificate
> client_cert
;
10831 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10832 HostPortPair("www.example.com", 443), &client_cert
));
10833 ASSERT_EQ(NULL
, client_cert
.get());
10835 // Restart the handshake. This will consume ssl_data2, which fails, and
10836 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10837 // The result code is checked against what ssl_data4 should return.
10838 rv
= callback
.WaitForResult();
10839 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10841 // Ensure that the client certificate is removed from the cache on a
10842 // handshake failure.
10843 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10844 HostPortPair("www.example.com", 443), &client_cert
));
10847 // Ensure that a client certificate is removed from the SSL client auth
10849 // 1) An HTTPS proxy is involved.
10850 // 3) The HTTPS proxy requests a client certificate.
10851 // 4) The client supplies an invalid/unacceptable certificate for the
10853 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10854 // then for connecting to an HTTP endpoint.
10855 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10856 session_deps_
.proxy_service
.reset(
10857 ProxyService::CreateFixed("https://proxy:70"));
10858 CapturingBoundNetLog log
;
10859 session_deps_
.net_log
= log
.bound().net_log();
10861 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10862 cert_request
->host_and_port
= HostPortPair("proxy", 70);
10864 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10865 // [ssl_]data[1-3]. Rather than represending the endpoint
10866 // (www.example.com:443), they represent failures with the HTTPS proxy
10868 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10869 ssl_data1
.cert_request_info
= cert_request
.get();
10870 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10871 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10872 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10874 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10875 ssl_data2
.cert_request_info
= cert_request
.get();
10876 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10877 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10878 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10880 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10882 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10883 ssl_data3
.cert_request_info
= cert_request
.get();
10884 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10885 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10886 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10889 net::HttpRequestInfo requests
[2];
10890 requests
[0].url
= GURL("https://www.example.com/");
10891 requests
[0].method
= "GET";
10892 requests
[0].load_flags
= net::LOAD_NORMAL
;
10894 requests
[1].url
= GURL("http://www.example.com/");
10895 requests
[1].method
= "GET";
10896 requests
[1].load_flags
= net::LOAD_NORMAL
;
10898 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10899 session_deps_
.socket_factory
->ResetNextMockIndexes();
10900 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10901 scoped_ptr
<HttpNetworkTransaction
> trans(
10902 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10904 // Begin the SSL handshake with the proxy.
10905 TestCompletionCallback callback
;
10906 int rv
= trans
->Start(
10907 &requests
[i
], callback
.callback(), net::BoundNetLog());
10908 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10910 // Complete the SSL handshake, which should abort due to requiring a
10911 // client certificate.
10912 rv
= callback
.WaitForResult();
10913 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10915 // Indicate that no certificate should be supplied. From the perspective
10916 // of SSLClientCertCache, NULL is just as meaningful as a real
10917 // certificate, so this is the same as supply a
10918 // legitimate-but-unacceptable certificate.
10919 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10920 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10922 // Ensure the certificate was added to the client auth cache before
10923 // allowing the connection to continue restarting.
10924 scoped_refptr
<X509Certificate
> client_cert
;
10925 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10926 HostPortPair("proxy", 70), &client_cert
));
10927 ASSERT_EQ(NULL
, client_cert
.get());
10928 // Ensure the certificate was NOT cached for the endpoint. This only
10929 // applies to HTTPS requests, but is fine to check for HTTP requests.
10930 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10931 HostPortPair("www.example.com", 443), &client_cert
));
10933 // Restart the handshake. This will consume ssl_data2, which fails, and
10934 // then consume ssl_data3, which should also fail. The result code is
10935 // checked against what ssl_data3 should return.
10936 rv
= callback
.WaitForResult();
10937 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10939 // Now that the new handshake has failed, ensure that the client
10940 // certificate was removed from the client auth cache.
10941 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10942 HostPortPair("proxy", 70), &client_cert
));
10943 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10944 HostPortPair("www.example.com", 443), &client_cert
));
10948 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10949 // TEST_P is a macro that expands directly to code that stringizes the
10950 // arguments. As a result, macros passed as parameters (such as prefix
10951 // or test_case_name) will not be expanded by the preprocessor. To
10952 // work around this, indirect the macro for TEST_P, so that the
10953 // pre-processor will expand macros such as MAYBE_test_name before
10954 // instantiating the test.
10955 #define WRAPPED_TEST_P(test_case_name, test_name) \
10956 TEST_P(test_case_name, test_name)
10958 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10959 #if defined(OS_WIN)
10960 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10962 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10964 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10965 session_deps_
.use_alternate_protocols
= true;
10966 session_deps_
.next_protos
= SpdyNextProtos();
10968 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10969 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10970 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10971 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10972 pool_peer
.DisableDomainAuthenticationVerification();
10974 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10975 ssl
.SetNextProto(GetParam());
10976 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10978 scoped_ptr
<SpdyFrame
> host1_req(
10979 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10980 scoped_ptr
<SpdyFrame
> host2_req(
10981 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10982 MockWrite spdy_writes
[] = {
10983 CreateMockWrite(*host1_req
, 1),
10984 CreateMockWrite(*host2_req
, 4),
10986 scoped_ptr
<SpdyFrame
> host1_resp(
10987 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10988 scoped_ptr
<SpdyFrame
> host1_resp_body(
10989 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10990 scoped_ptr
<SpdyFrame
> host2_resp(
10991 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10992 scoped_ptr
<SpdyFrame
> host2_resp_body(
10993 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10994 MockRead spdy_reads
[] = {
10995 CreateMockRead(*host1_resp
, 2),
10996 CreateMockRead(*host1_resp_body
, 3),
10997 CreateMockRead(*host2_resp
, 5),
10998 CreateMockRead(*host2_resp_body
, 6),
10999 MockRead(ASYNC
, 0, 7),
11002 IPAddressNumber ip
;
11003 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11004 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11005 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11006 OrderedSocketData
spdy_data(
11008 spdy_reads
, arraysize(spdy_reads
),
11009 spdy_writes
, arraysize(spdy_writes
));
11010 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11012 TestCompletionCallback callback
;
11013 HttpRequestInfo request1
;
11014 request1
.method
= "GET";
11015 request1
.url
= GURL("https://www.google.com/");
11016 request1
.load_flags
= 0;
11017 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11019 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11020 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11021 EXPECT_EQ(OK
, callback
.WaitForResult());
11023 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11024 ASSERT_TRUE(response
!= NULL
);
11025 ASSERT_TRUE(response
->headers
.get() != NULL
);
11026 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11028 std::string response_data
;
11029 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11030 EXPECT_EQ("hello!", response_data
);
11032 // Preload www.gmail.com into HostCache.
11033 HostPortPair
host_port("www.gmail.com", 443);
11034 HostResolver::RequestInfo
resolve_info(host_port
);
11035 AddressList ignored
;
11036 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11039 callback
.callback(),
11042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11043 rv
= callback
.WaitForResult();
11046 HttpRequestInfo request2
;
11047 request2
.method
= "GET";
11048 request2
.url
= GURL("https://www.gmail.com/");
11049 request2
.load_flags
= 0;
11050 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11052 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11054 EXPECT_EQ(OK
, callback
.WaitForResult());
11056 response
= trans2
.GetResponseInfo();
11057 ASSERT_TRUE(response
!= NULL
);
11058 ASSERT_TRUE(response
->headers
.get() != NULL
);
11059 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11060 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11061 EXPECT_TRUE(response
->was_npn_negotiated
);
11062 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11063 EXPECT_EQ("hello!", response_data
);
11065 #undef MAYBE_UseIPConnectionPooling
11067 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11068 session_deps_
.use_alternate_protocols
= true;
11069 session_deps_
.next_protos
= SpdyNextProtos();
11071 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11072 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11073 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11074 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11075 pool_peer
.DisableDomainAuthenticationVerification();
11077 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11078 ssl
.SetNextProto(GetParam());
11079 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11081 scoped_ptr
<SpdyFrame
> host1_req(
11082 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11083 scoped_ptr
<SpdyFrame
> host2_req(
11084 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11085 MockWrite spdy_writes
[] = {
11086 CreateMockWrite(*host1_req
, 1),
11087 CreateMockWrite(*host2_req
, 4),
11089 scoped_ptr
<SpdyFrame
> host1_resp(
11090 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11091 scoped_ptr
<SpdyFrame
> host1_resp_body(
11092 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11093 scoped_ptr
<SpdyFrame
> host2_resp(
11094 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11095 scoped_ptr
<SpdyFrame
> host2_resp_body(
11096 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11097 MockRead spdy_reads
[] = {
11098 CreateMockRead(*host1_resp
, 2),
11099 CreateMockRead(*host1_resp_body
, 3),
11100 CreateMockRead(*host2_resp
, 5),
11101 CreateMockRead(*host2_resp_body
, 6),
11102 MockRead(ASYNC
, 0, 7),
11105 IPAddressNumber ip
;
11106 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11107 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11108 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11109 OrderedSocketData
spdy_data(
11111 spdy_reads
, arraysize(spdy_reads
),
11112 spdy_writes
, arraysize(spdy_writes
));
11113 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11115 TestCompletionCallback callback
;
11116 HttpRequestInfo request1
;
11117 request1
.method
= "GET";
11118 request1
.url
= GURL("https://www.google.com/");
11119 request1
.load_flags
= 0;
11120 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11122 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11124 EXPECT_EQ(OK
, callback
.WaitForResult());
11126 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11127 ASSERT_TRUE(response
!= NULL
);
11128 ASSERT_TRUE(response
->headers
.get() != NULL
);
11129 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11131 std::string response_data
;
11132 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11133 EXPECT_EQ("hello!", response_data
);
11135 HttpRequestInfo request2
;
11136 request2
.method
= "GET";
11137 request2
.url
= GURL("https://www.gmail.com/");
11138 request2
.load_flags
= 0;
11139 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11141 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11142 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11143 EXPECT_EQ(OK
, callback
.WaitForResult());
11145 response
= trans2
.GetResponseInfo();
11146 ASSERT_TRUE(response
!= NULL
);
11147 ASSERT_TRUE(response
->headers
.get() != NULL
);
11148 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11149 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11150 EXPECT_TRUE(response
->was_npn_negotiated
);
11151 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11152 EXPECT_EQ("hello!", response_data
);
11155 class OneTimeCachingHostResolver
: public net::HostResolver
{
11157 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11158 : host_port_(host_port
) {}
11159 virtual ~OneTimeCachingHostResolver() {}
11161 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11163 // HostResolver methods:
11164 virtual int Resolve(const RequestInfo
& info
,
11165 RequestPriority priority
,
11166 AddressList
* addresses
,
11167 const CompletionCallback
& callback
,
11168 RequestHandle
* out_req
,
11169 const BoundNetLog
& net_log
) OVERRIDE
{
11170 return host_resolver_
.Resolve(
11171 info
, priority
, addresses
, callback
, out_req
, net_log
);
11174 virtual int ResolveFromCache(const RequestInfo
& info
,
11175 AddressList
* addresses
,
11176 const BoundNetLog
& net_log
) OVERRIDE
{
11177 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11178 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11179 host_resolver_
.GetHostCache()->clear();
11183 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
11184 host_resolver_
.CancelRequest(req
);
11187 MockCachingHostResolver
* GetMockHostResolver() {
11188 return &host_resolver_
;
11192 MockCachingHostResolver host_resolver_
;
11193 const HostPortPair host_port_
;
11196 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11197 #if defined(OS_WIN)
11198 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11199 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11201 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11202 UseIPConnectionPoolingWithHostCacheExpiration
11204 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11205 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11206 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11207 // prefix doesn't work with parametrized tests).
11208 #if defined(OS_WIN)
11211 session_deps_
.use_alternate_protocols
= true;
11212 session_deps_
.next_protos
= SpdyNextProtos();
11214 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11215 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11216 HttpNetworkSession::Params params
=
11217 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11218 params
.host_resolver
= &host_resolver
;
11219 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11220 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11221 pool_peer
.DisableDomainAuthenticationVerification();
11223 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11224 ssl
.SetNextProto(GetParam());
11225 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11227 scoped_ptr
<SpdyFrame
> host1_req(
11228 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11229 scoped_ptr
<SpdyFrame
> host2_req(
11230 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11231 MockWrite spdy_writes
[] = {
11232 CreateMockWrite(*host1_req
, 1),
11233 CreateMockWrite(*host2_req
, 4),
11235 scoped_ptr
<SpdyFrame
> host1_resp(
11236 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11237 scoped_ptr
<SpdyFrame
> host1_resp_body(
11238 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11239 scoped_ptr
<SpdyFrame
> host2_resp(
11240 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11241 scoped_ptr
<SpdyFrame
> host2_resp_body(
11242 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11243 MockRead spdy_reads
[] = {
11244 CreateMockRead(*host1_resp
, 2),
11245 CreateMockRead(*host1_resp_body
, 3),
11246 CreateMockRead(*host2_resp
, 5),
11247 CreateMockRead(*host2_resp_body
, 6),
11248 MockRead(ASYNC
, 0, 7),
11251 IPAddressNumber ip
;
11252 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11253 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11254 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11255 OrderedSocketData
spdy_data(
11257 spdy_reads
, arraysize(spdy_reads
),
11258 spdy_writes
, arraysize(spdy_writes
));
11259 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11261 TestCompletionCallback callback
;
11262 HttpRequestInfo request1
;
11263 request1
.method
= "GET";
11264 request1
.url
= GURL("https://www.google.com/");
11265 request1
.load_flags
= 0;
11266 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11268 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11270 EXPECT_EQ(OK
, callback
.WaitForResult());
11272 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11273 ASSERT_TRUE(response
!= NULL
);
11274 ASSERT_TRUE(response
->headers
.get() != NULL
);
11275 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11277 std::string response_data
;
11278 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11279 EXPECT_EQ("hello!", response_data
);
11281 // Preload cache entries into HostCache.
11282 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11283 AddressList ignored
;
11284 rv
= host_resolver
.Resolve(resolve_info
,
11287 callback
.callback(),
11290 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11291 rv
= callback
.WaitForResult();
11294 HttpRequestInfo request2
;
11295 request2
.method
= "GET";
11296 request2
.url
= GURL("https://www.gmail.com/");
11297 request2
.load_flags
= 0;
11298 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11300 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11301 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11302 EXPECT_EQ(OK
, callback
.WaitForResult());
11304 response
= trans2
.GetResponseInfo();
11305 ASSERT_TRUE(response
!= NULL
);
11306 ASSERT_TRUE(response
->headers
.get() != NULL
);
11307 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11308 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11309 EXPECT_TRUE(response
->was_npn_negotiated
);
11310 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11311 EXPECT_EQ("hello!", response_data
);
11314 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11316 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11317 const std::string https_url
= "https://www.google.com/";
11318 const std::string http_url
= "http://www.google.com:443/";
11320 // SPDY GET for HTTPS URL
11321 scoped_ptr
<SpdyFrame
> req1(
11322 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11324 MockWrite writes1
[] = {
11325 CreateMockWrite(*req1
, 0),
11328 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11329 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11330 MockRead reads1
[] = {
11331 CreateMockRead(*resp1
, 1),
11332 CreateMockRead(*body1
, 2),
11333 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11336 DelayedSocketData
data1(
11337 1, reads1
, arraysize(reads1
),
11338 writes1
, arraysize(writes1
));
11339 MockConnect
connect_data1(ASYNC
, OK
);
11340 data1
.set_connect_data(connect_data1
);
11342 // HTTP GET for the HTTP URL
11343 MockWrite writes2
[] = {
11344 MockWrite(ASYNC
, 4,
11345 "GET / HTTP/1.1\r\n"
11346 "Host: www.google.com:443\r\n"
11347 "Connection: keep-alive\r\n\r\n"),
11350 MockRead reads2
[] = {
11351 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11352 MockRead(ASYNC
, 6, "hello"),
11353 MockRead(ASYNC
, 7, OK
),
11356 DelayedSocketData
data2(
11357 1, reads2
, arraysize(reads2
),
11358 writes2
, arraysize(writes2
));
11360 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11361 ssl
.SetNextProto(GetParam());
11362 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11363 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11364 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11366 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11368 // Start the first transaction to set up the SpdySession
11369 HttpRequestInfo request1
;
11370 request1
.method
= "GET";
11371 request1
.url
= GURL(https_url
);
11372 request1
.load_flags
= 0;
11373 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11374 TestCompletionCallback callback1
;
11375 EXPECT_EQ(ERR_IO_PENDING
,
11376 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11377 base::MessageLoop::current()->RunUntilIdle();
11379 EXPECT_EQ(OK
, callback1
.WaitForResult());
11380 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11382 // Now, start the HTTP request
11383 HttpRequestInfo request2
;
11384 request2
.method
= "GET";
11385 request2
.url
= GURL(http_url
);
11386 request2
.load_flags
= 0;
11387 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11388 TestCompletionCallback callback2
;
11389 EXPECT_EQ(ERR_IO_PENDING
,
11390 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11391 base::MessageLoop::current()->RunUntilIdle();
11393 EXPECT_EQ(OK
, callback2
.WaitForResult());
11394 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11397 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11398 const std::string https_url
= "https://www.google.com/";
11399 const std::string http_url
= "http://www.google.com:443/";
11401 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11402 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
11404 scoped_ptr
<SpdyFrame
> req1(
11405 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11406 scoped_ptr
<SpdyFrame
> wrapped_req1(
11407 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11409 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11410 SpdyHeaderBlock req2_block
;
11411 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11412 req2_block
[spdy_util_
.GetPathKey()] =
11413 spdy_util_
.is_spdy2() ? http_url
.c_str() : "/";
11414 req2_block
[spdy_util_
.GetHostKey()] = "www.google.com:443";
11415 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11416 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11417 scoped_ptr
<SpdyFrame
> req2(
11418 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11420 MockWrite writes1
[] = {
11421 CreateMockWrite(*connect
, 0),
11422 CreateMockWrite(*wrapped_req1
, 2),
11423 CreateMockWrite(*req2
, 5),
11426 scoped_ptr
<SpdyFrame
> conn_resp(
11427 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11428 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11429 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11430 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11431 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11432 scoped_ptr
<SpdyFrame
> wrapped_body1(
11433 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11434 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11435 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11436 MockRead reads1
[] = {
11437 CreateMockRead(*conn_resp
, 1),
11438 CreateMockRead(*wrapped_resp1
, 3),
11439 CreateMockRead(*wrapped_body1
, 4),
11440 CreateMockRead(*resp2
, 6),
11441 CreateMockRead(*body2
, 7),
11442 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11445 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11446 writes1
, arraysize(writes1
));
11447 MockConnect
connect_data1(ASYNC
, OK
);
11448 data1
.set_connect_data(connect_data1
);
11450 session_deps_
.proxy_service
.reset(
11451 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11452 CapturingNetLog log
;
11453 session_deps_
.net_log
= &log
;
11454 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11455 ssl1
.SetNextProto(GetParam());
11456 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11457 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11458 ssl2
.SetNextProto(GetParam());
11459 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11460 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11462 scoped_refptr
<HttpNetworkSession
> session(
11463 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11465 // Start the first transaction to set up the SpdySession
11466 HttpRequestInfo request1
;
11467 request1
.method
= "GET";
11468 request1
.url
= GURL(https_url
);
11469 request1
.load_flags
= 0;
11470 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11471 TestCompletionCallback callback1
;
11472 EXPECT_EQ(ERR_IO_PENDING
,
11473 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11474 base::MessageLoop::current()->RunUntilIdle();
11477 EXPECT_EQ(OK
, callback1
.WaitForResult());
11478 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11480 LoadTimingInfo load_timing_info1
;
11481 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11482 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11483 CONNECT_TIMING_HAS_SSL_TIMES
);
11485 // Now, start the HTTP request
11486 HttpRequestInfo request2
;
11487 request2
.method
= "GET";
11488 request2
.url
= GURL(http_url
);
11489 request2
.load_flags
= 0;
11490 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11491 TestCompletionCallback callback2
;
11492 EXPECT_EQ(ERR_IO_PENDING
,
11493 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11494 base::MessageLoop::current()->RunUntilIdle();
11497 EXPECT_EQ(OK
, callback2
.WaitForResult());
11498 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11500 LoadTimingInfo load_timing_info2
;
11501 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11502 // The established SPDY sessions is considered reused by the HTTP request.
11503 TestLoadTimingReusedWithPac(load_timing_info2
);
11504 // HTTP requests over a SPDY session should have a different connection
11505 // socket_log_id than requests over a tunnel.
11506 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11509 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11510 session_deps_
.force_spdy_always
= true;
11511 const std::string https_url
= "https://www.google.com/";
11512 const std::string http_url
= "http://www.google.com:443/";
11514 // SPDY GET for HTTPS URL
11515 scoped_ptr
<SpdyFrame
> req1(
11516 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11517 // SPDY GET for the HTTP URL
11518 scoped_ptr
<SpdyFrame
> req2(
11519 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11521 MockWrite writes
[] = {
11522 CreateMockWrite(*req1
, 1),
11523 CreateMockWrite(*req2
, 4),
11526 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11527 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11528 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11529 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11530 MockRead reads
[] = {
11531 CreateMockRead(*resp1
, 2),
11532 CreateMockRead(*body1
, 3),
11533 CreateMockRead(*resp2
, 5),
11534 CreateMockRead(*body2
, 6),
11535 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11538 OrderedSocketData
data(reads
, arraysize(reads
),
11539 writes
, arraysize(writes
));
11541 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11542 ssl
.SetNextProto(GetParam());
11543 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11544 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11546 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11548 // Start the first transaction to set up the SpdySession
11549 HttpRequestInfo request1
;
11550 request1
.method
= "GET";
11551 request1
.url
= GURL(https_url
);
11552 request1
.load_flags
= 0;
11553 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11554 TestCompletionCallback callback1
;
11555 EXPECT_EQ(ERR_IO_PENDING
,
11556 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11557 base::MessageLoop::current()->RunUntilIdle();
11559 EXPECT_EQ(OK
, callback1
.WaitForResult());
11560 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11562 // Now, start the HTTP request
11563 HttpRequestInfo request2
;
11564 request2
.method
= "GET";
11565 request2
.url
= GURL(http_url
);
11566 request2
.load_flags
= 0;
11567 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11568 TestCompletionCallback callback2
;
11569 EXPECT_EQ(ERR_IO_PENDING
,
11570 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11571 base::MessageLoop::current()->RunUntilIdle();
11573 EXPECT_EQ(OK
, callback2
.WaitForResult());
11574 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11577 // Test that in the case where we have a SPDY session to a SPDY proxy
11578 // that we do not pool other origins that resolve to the same IP when
11579 // the certificate does not match the new origin.
11580 // http://crbug.com/134690
11581 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11582 const std::string url1
= "http://www.google.com/";
11583 const std::string url2
= "https://mail.google.com/";
11584 const std::string ip_addr
= "1.2.3.4";
11586 // SPDY GET for HTTP URL (through SPDY proxy)
11587 scoped_ptr
<SpdyHeaderBlock
> headers(
11588 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11589 scoped_ptr
<SpdyFrame
> req1(
11590 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
11592 MockWrite writes1
[] = {
11593 CreateMockWrite(*req1
, 0),
11596 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11597 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11598 MockRead reads1
[] = {
11599 CreateMockRead(*resp1
, 1),
11600 CreateMockRead(*body1
, 2),
11601 MockRead(ASYNC
, OK
, 3) // EOF
11604 scoped_ptr
<DeterministicSocketData
> data1(
11605 new DeterministicSocketData(reads1
, arraysize(reads1
),
11606 writes1
, arraysize(writes1
)));
11607 IPAddressNumber ip
;
11608 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11609 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11610 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11611 data1
->set_connect_data(connect_data1
);
11613 // SPDY GET for HTTPS URL (direct)
11614 scoped_ptr
<SpdyFrame
> req2(
11615 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11617 MockWrite writes2
[] = {
11618 CreateMockWrite(*req2
, 0),
11621 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11622 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11623 MockRead reads2
[] = {
11624 CreateMockRead(*resp2
, 1),
11625 CreateMockRead(*body2
, 2),
11626 MockRead(ASYNC
, OK
, 3) // EOF
11629 scoped_ptr
<DeterministicSocketData
> data2(
11630 new DeterministicSocketData(reads2
, arraysize(reads2
),
11631 writes2
, arraysize(writes2
)));
11632 MockConnect
connect_data2(ASYNC
, OK
);
11633 data2
->set_connect_data(connect_data2
);
11635 // Set up a proxy config that sends HTTP requests to a proxy, and
11636 // all others direct.
11637 ProxyConfig proxy_config
;
11638 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11639 CapturingProxyResolver
* capturing_proxy_resolver
=
11640 new CapturingProxyResolver();
11641 session_deps_
.proxy_service
.reset(new ProxyService(
11642 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11645 // Load a valid cert. Note, that this does not need to
11646 // be valid for proxy because the MockSSLClientSocket does
11647 // not actually verify it. But SpdySession will use this
11648 // to see if it is valid for the new origin
11649 base::FilePath certs_dir
= GetTestCertsDirectory();
11650 scoped_refptr
<X509Certificate
> server_cert(
11651 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11652 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
);
11654 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11655 ssl1
.SetNextProto(GetParam());
11656 ssl1
.cert
= server_cert
;
11657 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11658 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11661 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11662 ssl2
.SetNextProto(GetParam());
11663 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11664 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11667 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11668 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11669 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11671 scoped_refptr
<HttpNetworkSession
> session(
11672 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11674 // Start the first transaction to set up the SpdySession
11675 HttpRequestInfo request1
;
11676 request1
.method
= "GET";
11677 request1
.url
= GURL(url1
);
11678 request1
.load_flags
= 0;
11679 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11680 TestCompletionCallback callback1
;
11681 ASSERT_EQ(ERR_IO_PENDING
,
11682 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11685 ASSERT_TRUE(callback1
.have_result());
11686 EXPECT_EQ(OK
, callback1
.WaitForResult());
11687 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11689 // Now, start the HTTP request
11690 HttpRequestInfo request2
;
11691 request2
.method
= "GET";
11692 request2
.url
= GURL(url2
);
11693 request2
.load_flags
= 0;
11694 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11695 TestCompletionCallback callback2
;
11696 EXPECT_EQ(ERR_IO_PENDING
,
11697 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11698 base::MessageLoop::current()->RunUntilIdle();
11701 ASSERT_TRUE(callback2
.have_result());
11702 EXPECT_EQ(OK
, callback2
.WaitForResult());
11703 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11706 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11707 // error) in SPDY session, removes the socket from pool and closes the SPDY
11708 // session. Verify that new url's from the same HttpNetworkSession (and a new
11709 // SpdySession) do work. http://crbug.com/224701
11710 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11711 const std::string https_url
= "https://www.google.com/";
11713 MockRead reads1
[] = {
11714 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11717 scoped_ptr
<DeterministicSocketData
> data1(
11718 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11721 scoped_ptr
<SpdyFrame
> req2(
11722 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11723 MockWrite writes2
[] = {
11724 CreateMockWrite(*req2
, 0),
11727 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11728 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11729 MockRead reads2
[] = {
11730 CreateMockRead(*resp2
, 1),
11731 CreateMockRead(*body2
, 2),
11732 MockRead(ASYNC
, OK
, 3) // EOF
11735 scoped_ptr
<DeterministicSocketData
> data2(
11736 new DeterministicSocketData(reads2
, arraysize(reads2
),
11737 writes2
, arraysize(writes2
)));
11739 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11740 ssl1
.SetNextProto(GetParam());
11741 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11742 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11745 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11746 ssl2
.SetNextProto(GetParam());
11747 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11748 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11751 scoped_refptr
<HttpNetworkSession
> session(
11752 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11754 // Start the first transaction to set up the SpdySession and verify that
11755 // connection was closed.
11756 HttpRequestInfo request1
;
11757 request1
.method
= "GET";
11758 request1
.url
= GURL(https_url
);
11759 request1
.load_flags
= 0;
11760 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11761 TestCompletionCallback callback1
;
11762 EXPECT_EQ(ERR_IO_PENDING
,
11763 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11764 base::MessageLoop::current()->RunUntilIdle();
11765 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11767 // Now, start the second request and make sure it succeeds.
11768 HttpRequestInfo request2
;
11769 request2
.method
= "GET";
11770 request2
.url
= GURL(https_url
);
11771 request2
.load_flags
= 0;
11772 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11773 TestCompletionCallback callback2
;
11774 EXPECT_EQ(ERR_IO_PENDING
,
11775 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11776 base::MessageLoop::current()->RunUntilIdle();
11779 ASSERT_TRUE(callback2
.have_result());
11780 EXPECT_EQ(OK
, callback2
.WaitForResult());
11781 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11784 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11785 session_deps_
.next_protos
= SpdyNextProtos();
11786 ClientSocketPoolManager::set_max_sockets_per_group(
11787 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11788 ClientSocketPoolManager::set_max_sockets_per_pool(
11789 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11791 // Use two different hosts with different IPs so they don't get pooled.
11792 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11793 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11794 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11796 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11797 ssl1
.SetNextProto(GetParam());
11798 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11799 ssl2
.SetNextProto(GetParam());
11800 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11801 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11803 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11804 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11805 MockWrite spdy1_writes
[] = {
11806 CreateMockWrite(*host1_req
, 1),
11808 scoped_ptr
<SpdyFrame
> host1_resp(
11809 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11810 scoped_ptr
<SpdyFrame
> host1_resp_body(
11811 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11812 MockRead spdy1_reads
[] = {
11813 CreateMockRead(*host1_resp
, 2),
11814 CreateMockRead(*host1_resp_body
, 3),
11815 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11818 scoped_ptr
<OrderedSocketData
> spdy1_data(
11819 new OrderedSocketData(
11820 spdy1_reads
, arraysize(spdy1_reads
),
11821 spdy1_writes
, arraysize(spdy1_writes
)));
11822 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11824 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11825 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11826 MockWrite spdy2_writes
[] = {
11827 CreateMockWrite(*host2_req
, 1),
11829 scoped_ptr
<SpdyFrame
> host2_resp(
11830 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11831 scoped_ptr
<SpdyFrame
> host2_resp_body(
11832 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11833 MockRead spdy2_reads
[] = {
11834 CreateMockRead(*host2_resp
, 2),
11835 CreateMockRead(*host2_resp_body
, 3),
11836 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11839 scoped_ptr
<OrderedSocketData
> spdy2_data(
11840 new OrderedSocketData(
11841 spdy2_reads
, arraysize(spdy2_reads
),
11842 spdy2_writes
, arraysize(spdy2_writes
)));
11843 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11845 MockWrite http_write
[] = {
11846 MockWrite("GET / HTTP/1.1\r\n"
11847 "Host: www.a.com\r\n"
11848 "Connection: keep-alive\r\n\r\n"),
11851 MockRead http_read
[] = {
11852 MockRead("HTTP/1.1 200 OK\r\n"),
11853 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11854 MockRead("Content-Length: 6\r\n\r\n"),
11855 MockRead("hello!"),
11857 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11858 http_write
, arraysize(http_write
));
11859 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11861 HostPortPair
host_port_pair_a("www.a.com", 443);
11862 SpdySessionKey
spdy_session_key_a(
11863 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11865 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11867 TestCompletionCallback callback
;
11868 HttpRequestInfo request1
;
11869 request1
.method
= "GET";
11870 request1
.url
= GURL("https://www.a.com/");
11871 request1
.load_flags
= 0;
11872 scoped_ptr
<HttpNetworkTransaction
> trans(
11873 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11875 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11877 EXPECT_EQ(OK
, callback
.WaitForResult());
11879 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11880 ASSERT_TRUE(response
!= NULL
);
11881 ASSERT_TRUE(response
->headers
.get() != NULL
);
11882 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11883 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11884 EXPECT_TRUE(response
->was_npn_negotiated
);
11886 std::string response_data
;
11887 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11888 EXPECT_EQ("hello!", response_data
);
11891 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11893 HostPortPair
host_port_pair_b("www.b.com", 443);
11894 SpdySessionKey
spdy_session_key_b(
11895 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11897 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11898 HttpRequestInfo request2
;
11899 request2
.method
= "GET";
11900 request2
.url
= GURL("https://www.b.com/");
11901 request2
.load_flags
= 0;
11902 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11904 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11905 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11906 EXPECT_EQ(OK
, callback
.WaitForResult());
11908 response
= trans
->GetResponseInfo();
11909 ASSERT_TRUE(response
!= NULL
);
11910 ASSERT_TRUE(response
->headers
.get() != NULL
);
11911 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11912 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11913 EXPECT_TRUE(response
->was_npn_negotiated
);
11914 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11915 EXPECT_EQ("hello!", response_data
);
11917 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11919 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11921 HostPortPair
host_port_pair_a1("www.a.com", 80);
11922 SpdySessionKey
spdy_session_key_a1(
11923 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11925 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11926 HttpRequestInfo request3
;
11927 request3
.method
= "GET";
11928 request3
.url
= GURL("http://www.a.com/");
11929 request3
.load_flags
= 0;
11930 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11932 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11933 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11934 EXPECT_EQ(OK
, callback
.WaitForResult());
11936 response
= trans
->GetResponseInfo();
11937 ASSERT_TRUE(response
!= NULL
);
11938 ASSERT_TRUE(response
->headers
.get() != NULL
);
11939 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11940 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11941 EXPECT_FALSE(response
->was_npn_negotiated
);
11942 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11943 EXPECT_EQ("hello!", response_data
);
11945 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11947 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11950 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11951 HttpRequestInfo request
;
11952 request
.method
= "GET";
11953 request
.url
= GURL("http://www.google.com/");
11954 request
.load_flags
= 0;
11956 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11957 scoped_ptr
<HttpTransaction
> trans(
11958 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11960 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11961 StaticSocketDataProvider data
;
11962 data
.set_connect_data(mock_connect
);
11963 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11965 TestCompletionCallback callback
;
11967 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11968 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11970 rv
= callback
.WaitForResult();
11971 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11973 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11975 // We don't care whether this succeeds or fails, but it shouldn't crash.
11976 HttpRequestHeaders request_headers
;
11977 trans
->GetFullRequestHeaders(&request_headers
);
11980 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11981 HttpRequestInfo request
;
11982 request
.method
= "GET";
11983 request
.url
= GURL("http://www.google.com/");
11984 request
.load_flags
= 0;
11986 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11987 scoped_ptr
<HttpTransaction
> trans(
11988 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11990 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11991 StaticSocketDataProvider data
;
11992 data
.set_connect_data(mock_connect
);
11993 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11995 TestCompletionCallback callback
;
11997 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11998 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12000 rv
= callback
.WaitForResult();
12001 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12003 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12005 // We don't care whether this succeeds or fails, but it shouldn't crash.
12006 HttpRequestHeaders request_headers
;
12007 trans
->GetFullRequestHeaders(&request_headers
);
12010 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12011 HttpRequestInfo request
;
12012 request
.method
= "GET";
12013 request
.url
= GURL("http://www.google.com/");
12014 request
.load_flags
= 0;
12016 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12017 scoped_ptr
<HttpTransaction
> trans(
12018 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12020 MockWrite data_writes
[] = {
12021 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12023 MockRead data_reads
[] = {
12024 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12027 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12028 data_writes
, arraysize(data_writes
));
12029 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12031 TestCompletionCallback callback
;
12033 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12034 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12036 rv
= callback
.WaitForResult();
12037 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12039 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12041 HttpRequestHeaders request_headers
;
12042 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12043 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12046 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12047 HttpRequestInfo request
;
12048 request
.method
= "GET";
12049 request
.url
= GURL("http://www.google.com/");
12050 request
.load_flags
= 0;
12052 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12053 scoped_ptr
<HttpTransaction
> trans(
12054 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12056 MockWrite data_writes
[] = {
12057 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12059 MockRead data_reads
[] = {
12060 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12063 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12064 data_writes
, arraysize(data_writes
));
12065 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12067 TestCompletionCallback callback
;
12069 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12070 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12072 rv
= callback
.WaitForResult();
12073 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12075 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12077 HttpRequestHeaders request_headers
;
12078 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12079 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12082 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12083 HttpRequestInfo request
;
12084 request
.method
= "GET";
12085 request
.url
= GURL("http://www.google.com/");
12086 request
.load_flags
= 0;
12088 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12089 scoped_ptr
<HttpTransaction
> trans(
12090 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12092 MockWrite data_writes
[] = {
12093 MockWrite("GET / HTTP/1.1\r\n"
12094 "Host: www.google.com\r\n"
12095 "Connection: keep-alive\r\n\r\n"),
12097 MockRead data_reads
[] = {
12098 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12101 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12102 data_writes
, arraysize(data_writes
));
12103 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12105 TestCompletionCallback callback
;
12107 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12108 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12110 rv
= callback
.WaitForResult();
12111 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12113 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12115 HttpRequestHeaders request_headers
;
12116 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12117 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12120 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12121 HttpRequestInfo request
;
12122 request
.method
= "GET";
12123 request
.url
= GURL("http://www.google.com/");
12124 request
.load_flags
= 0;
12126 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12127 scoped_ptr
<HttpTransaction
> trans(
12128 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12130 MockWrite data_writes
[] = {
12131 MockWrite("GET / HTTP/1.1\r\n"
12132 "Host: www.google.com\r\n"
12133 "Connection: keep-alive\r\n\r\n"),
12135 MockRead data_reads
[] = {
12136 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12139 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12140 data_writes
, arraysize(data_writes
));
12141 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12143 TestCompletionCallback callback
;
12145 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12148 rv
= callback
.WaitForResult();
12149 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12151 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12153 HttpRequestHeaders request_headers
;
12154 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12155 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12158 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12159 HttpRequestInfo request
;
12160 request
.method
= "GET";
12161 request
.url
= GURL("http://www.google.com/");
12162 request
.load_flags
= 0;
12163 request
.extra_headers
.SetHeader("X-Foo", "bar");
12165 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12166 scoped_ptr
<HttpTransaction
> trans(
12167 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12169 MockWrite data_writes
[] = {
12170 MockWrite("GET / HTTP/1.1\r\n"
12171 "Host: www.google.com\r\n"
12172 "Connection: keep-alive\r\n"
12173 "X-Foo: bar\r\n\r\n"),
12175 MockRead data_reads
[] = {
12176 MockRead("HTTP/1.1 200 OK\r\n"
12177 "Content-Length: 5\r\n\r\n"
12179 MockRead(ASYNC
, ERR_UNEXPECTED
),
12182 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12183 data_writes
, arraysize(data_writes
));
12184 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12186 TestCompletionCallback callback
;
12188 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12189 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12191 rv
= callback
.WaitForResult();
12194 HttpRequestHeaders request_headers
;
12195 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12197 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12198 EXPECT_EQ("bar", foo
);
12203 // Fake HttpStreamBase that simply records calls to SetPriority().
12204 class FakeStream
: public HttpStreamBase
,
12205 public base::SupportsWeakPtr
<FakeStream
> {
12207 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12208 virtual ~FakeStream() {}
12210 RequestPriority
priority() const { return priority_
; }
12212 virtual int InitializeStream(const HttpRequestInfo
* request_info
,
12213 RequestPriority priority
,
12214 const BoundNetLog
& net_log
,
12215 const CompletionCallback
& callback
) OVERRIDE
{
12216 return ERR_IO_PENDING
;
12219 virtual int SendRequest(const HttpRequestHeaders
& request_headers
,
12220 HttpResponseInfo
* response
,
12221 const CompletionCallback
& callback
) OVERRIDE
{
12223 return ERR_UNEXPECTED
;
12226 virtual int ReadResponseHeaders(const CompletionCallback
& callback
) OVERRIDE
{
12228 return ERR_UNEXPECTED
;
12231 virtual int ReadResponseBody(IOBuffer
* buf
, int buf_len
,
12232 const CompletionCallback
& callback
) OVERRIDE
{
12234 return ERR_UNEXPECTED
;
12237 virtual void Close(bool not_reusable
) OVERRIDE
{}
12239 virtual bool IsResponseBodyComplete() const OVERRIDE
{
12244 virtual bool CanFindEndOfResponse() const OVERRIDE
{
12248 virtual bool IsConnectionReused() const OVERRIDE
{
12253 virtual void SetConnectionReused() OVERRIDE
{
12257 virtual bool IsConnectionReusable() const OVERRIDE
{
12262 virtual int64
GetTotalReceivedBytes() const OVERRIDE
{
12267 virtual bool GetLoadTimingInfo(
12268 LoadTimingInfo
* load_timing_info
) const OVERRIDE
{
12273 virtual void GetSSLInfo(SSLInfo
* ssl_info
) OVERRIDE
{
12277 virtual void GetSSLCertRequestInfo(
12278 SSLCertRequestInfo
* cert_request_info
) OVERRIDE
{
12282 virtual bool IsSpdyHttpStream() const OVERRIDE
{
12287 virtual void Drain(HttpNetworkSession
* session
) OVERRIDE
{
12291 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12292 priority_
= priority
;
12296 RequestPriority priority_
;
12298 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12301 // Fake HttpStreamRequest that simply records calls to SetPriority()
12302 // and vends FakeStreams with its current priority.
12303 class FakeStreamRequest
: public HttpStreamRequest
,
12304 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12306 FakeStreamRequest(RequestPriority priority
,
12307 HttpStreamRequest::Delegate
* delegate
)
12308 : priority_(priority
),
12309 delegate_(delegate
),
12310 websocket_stream_create_helper_(NULL
) {}
12312 FakeStreamRequest(RequestPriority priority
,
12313 HttpStreamRequest::Delegate
* delegate
,
12314 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12315 : priority_(priority
),
12316 delegate_(delegate
),
12317 websocket_stream_create_helper_(create_helper
) {}
12319 virtual ~FakeStreamRequest() {}
12321 RequestPriority
priority() const { return priority_
; }
12323 const WebSocketHandshakeStreamBase::CreateHelper
*
12324 websocket_stream_create_helper() const {
12325 return websocket_stream_create_helper_
;
12328 // Create a new FakeStream and pass it to the request's
12329 // delegate. Returns a weak pointer to the FakeStream.
12330 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12331 FakeStream
* fake_stream
= new FakeStream(priority_
);
12332 // Do this before calling OnStreamReady() as OnStreamReady() may
12333 // immediately delete |fake_stream|.
12334 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12335 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12336 return weak_stream
;
12339 virtual int RestartTunnelWithProxyAuth(
12340 const AuthCredentials
& credentials
) OVERRIDE
{
12342 return ERR_UNEXPECTED
;
12345 virtual LoadState
GetLoadState() const OVERRIDE
{
12347 return LoadState();
12350 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12351 priority_
= priority
;
12354 virtual bool was_npn_negotiated() const OVERRIDE
{
12358 virtual NextProto
protocol_negotiated() const OVERRIDE
{
12359 return kProtoUnknown
;
12362 virtual bool using_spdy() const OVERRIDE
{
12367 RequestPriority priority_
;
12368 HttpStreamRequest::Delegate
* const delegate_
;
12369 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12371 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12374 // Fake HttpStreamFactory that vends FakeStreamRequests.
12375 class FakeStreamFactory
: public HttpStreamFactory
{
12377 FakeStreamFactory() {}
12378 virtual ~FakeStreamFactory() {}
12380 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12381 // RequestStream() (which may be NULL if it was destroyed already).
12382 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12383 return last_stream_request_
;
12386 virtual HttpStreamRequest
* RequestStream(
12387 const HttpRequestInfo
& info
,
12388 RequestPriority priority
,
12389 const SSLConfig
& server_ssl_config
,
12390 const SSLConfig
& proxy_ssl_config
,
12391 HttpStreamRequest::Delegate
* delegate
,
12392 const BoundNetLog
& net_log
) OVERRIDE
{
12393 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12394 last_stream_request_
= fake_request
->AsWeakPtr();
12395 return fake_request
;
12398 virtual HttpStreamRequest
* RequestWebSocketHandshakeStream(
12399 const HttpRequestInfo
& info
,
12400 RequestPriority priority
,
12401 const SSLConfig
& server_ssl_config
,
12402 const SSLConfig
& proxy_ssl_config
,
12403 HttpStreamRequest::Delegate
* delegate
,
12404 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12405 const BoundNetLog
& net_log
) OVERRIDE
{
12406 FakeStreamRequest
* fake_request
=
12407 new FakeStreamRequest(priority
, delegate
, create_helper
);
12408 last_stream_request_
= fake_request
->AsWeakPtr();
12409 return fake_request
;
12412 virtual void PreconnectStreams(int num_streams
,
12413 const HttpRequestInfo
& info
,
12414 RequestPriority priority
,
12415 const SSLConfig
& server_ssl_config
,
12416 const SSLConfig
& proxy_ssl_config
) OVERRIDE
{
12420 virtual const HostMappingRules
* GetHostMappingRules() const OVERRIDE
{
12426 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12428 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12431 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12433 class FakeWebSocketStreamCreateHelper
:
12434 public WebSocketHandshakeStreamBase::CreateHelper
{
12436 virtual WebSocketHandshakeStreamBase
* CreateBasicStream(
12437 scoped_ptr
<ClientSocketHandle
> connection
,
12438 bool using_proxy
) OVERRIDE
{
12443 virtual WebSocketHandshakeStreamBase
* CreateSpdyStream(
12444 const base::WeakPtr
<SpdySession
>& session
,
12445 bool use_relative_url
) OVERRIDE
{
12450 virtual ~FakeWebSocketStreamCreateHelper() {}
12452 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12454 return scoped_ptr
<WebSocketStream
>();
12460 // Make sure that HttpNetworkTransaction passes on its priority to its
12461 // stream request on start.
12462 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12463 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12464 HttpNetworkSessionPeer
peer(session
);
12465 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12466 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12468 HttpNetworkTransaction
trans(LOW
, session
);
12470 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12472 HttpRequestInfo request
;
12473 TestCompletionCallback callback
;
12474 EXPECT_EQ(ERR_IO_PENDING
,
12475 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12477 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12478 fake_factory
->last_stream_request();
12479 ASSERT_TRUE(fake_request
!= NULL
);
12480 EXPECT_EQ(LOW
, fake_request
->priority());
12483 // Make sure that HttpNetworkTransaction passes on its priority
12484 // updates to its stream request.
12485 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12486 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12487 HttpNetworkSessionPeer
peer(session
);
12488 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12489 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12491 HttpNetworkTransaction
trans(LOW
, session
);
12493 HttpRequestInfo request
;
12494 TestCompletionCallback callback
;
12495 EXPECT_EQ(ERR_IO_PENDING
,
12496 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12498 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12499 fake_factory
->last_stream_request();
12500 ASSERT_TRUE(fake_request
!= NULL
);
12501 EXPECT_EQ(LOW
, fake_request
->priority());
12503 trans
.SetPriority(LOWEST
);
12504 ASSERT_TRUE(fake_request
!= NULL
);
12505 EXPECT_EQ(LOWEST
, fake_request
->priority());
12508 // Make sure that HttpNetworkTransaction passes on its priority
12509 // updates to its stream.
12510 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12511 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12512 HttpNetworkSessionPeer
peer(session
);
12513 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12514 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12516 HttpNetworkTransaction
trans(LOW
, session
);
12518 HttpRequestInfo request
;
12519 TestCompletionCallback callback
;
12520 EXPECT_EQ(ERR_IO_PENDING
,
12521 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12523 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12524 fake_factory
->last_stream_request();
12525 ASSERT_TRUE(fake_request
!= NULL
);
12526 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12527 ASSERT_TRUE(fake_stream
!= NULL
);
12528 EXPECT_EQ(LOW
, fake_stream
->priority());
12530 trans
.SetPriority(LOWEST
);
12531 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12534 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12535 // The same logic needs to be tested for both ws: and wss: schemes, but this
12536 // test is already parameterised on NextProto, so it uses a loop to verify
12537 // that the different schemes work.
12538 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
12539 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
12540 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12541 HttpNetworkSessionPeer
peer(session
);
12542 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12543 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
12544 peer
.SetHttpStreamFactoryForWebSocket(
12545 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12547 HttpNetworkTransaction
trans(LOW
, session
);
12548 trans
.SetWebSocketHandshakeStreamCreateHelper(
12549 &websocket_stream_create_helper
);
12551 HttpRequestInfo request
;
12552 TestCompletionCallback callback
;
12553 request
.method
= "GET";
12554 request
.url
= GURL(test_cases
[i
]);
12556 EXPECT_EQ(ERR_IO_PENDING
,
12557 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12559 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12560 fake_factory
->last_stream_request();
12561 ASSERT_TRUE(fake_request
!= NULL
);
12562 EXPECT_EQ(&websocket_stream_create_helper
,
12563 fake_request
->websocket_stream_create_helper());
12567 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12568 // if the transport socket pool is stalled on the global socket limit.
12569 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
12570 ClientSocketPoolManager::set_max_sockets_per_group(
12571 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12572 ClientSocketPoolManager::set_max_sockets_per_pool(
12573 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12575 // Set up SSL request.
12577 HttpRequestInfo ssl_request
;
12578 ssl_request
.method
= "GET";
12579 ssl_request
.url
= GURL("https://www.google.com/");
12581 MockWrite ssl_writes
[] = {
12582 MockWrite("GET / HTTP/1.1\r\n"
12583 "Host: www.google.com\r\n"
12584 "Connection: keep-alive\r\n\r\n"),
12586 MockRead ssl_reads
[] = {
12587 MockRead("HTTP/1.1 200 OK\r\n"),
12588 MockRead("Content-Length: 11\r\n\r\n"),
12589 MockRead("hello world"),
12590 MockRead(SYNCHRONOUS
, OK
),
12592 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
12593 ssl_writes
, arraysize(ssl_writes
));
12594 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12596 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12597 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12599 // Set up HTTP request.
12601 HttpRequestInfo http_request
;
12602 http_request
.method
= "GET";
12603 http_request
.url
= GURL("http://www.google.com/");
12605 MockWrite http_writes
[] = {
12606 MockWrite("GET / HTTP/1.1\r\n"
12607 "Host: www.google.com\r\n"
12608 "Connection: keep-alive\r\n\r\n"),
12610 MockRead http_reads
[] = {
12611 MockRead("HTTP/1.1 200 OK\r\n"),
12612 MockRead("Content-Length: 7\r\n\r\n"),
12613 MockRead("falafel"),
12614 MockRead(SYNCHRONOUS
, OK
),
12616 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12617 http_writes
, arraysize(http_writes
));
12618 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12620 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12622 // Start the SSL request.
12623 TestCompletionCallback ssl_callback
;
12624 scoped_ptr
<HttpTransaction
> ssl_trans(
12625 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12626 ASSERT_EQ(ERR_IO_PENDING
,
12627 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
12630 // Start the HTTP request. Pool should stall.
12631 TestCompletionCallback http_callback
;
12632 scoped_ptr
<HttpTransaction
> http_trans(
12633 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12634 ASSERT_EQ(ERR_IO_PENDING
,
12635 http_trans
->Start(&http_request
, http_callback
.callback(),
12637 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12639 // Wait for response from SSL request.
12640 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
12641 std::string response_data
;
12642 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
12643 EXPECT_EQ("hello world", response_data
);
12645 // The SSL socket should automatically be closed, so the HTTP request can
12647 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12648 ASSERT_FALSE(IsTransportSocketPoolStalled(session
));
12650 // The HTTP request can now complete.
12651 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12652 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12653 EXPECT_EQ("falafel", response_data
);
12655 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12658 // Tests that when a SSL connection is established but there's no corresponding
12659 // request that needs it, the new socket is closed if the transport socket pool
12660 // is stalled on the global socket limit.
12661 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
12662 ClientSocketPoolManager::set_max_sockets_per_group(
12663 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12664 ClientSocketPoolManager::set_max_sockets_per_pool(
12665 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12667 // Set up an ssl request.
12669 HttpRequestInfo ssl_request
;
12670 ssl_request
.method
= "GET";
12671 ssl_request
.url
= GURL("https://www.foopy.com/");
12673 // No data will be sent on the SSL socket.
12674 StaticSocketDataProvider ssl_data
;
12675 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12677 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12678 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12680 // Set up HTTP request.
12682 HttpRequestInfo http_request
;
12683 http_request
.method
= "GET";
12684 http_request
.url
= GURL("http://www.google.com/");
12686 MockWrite http_writes
[] = {
12687 MockWrite("GET / HTTP/1.1\r\n"
12688 "Host: www.google.com\r\n"
12689 "Connection: keep-alive\r\n\r\n"),
12691 MockRead http_reads
[] = {
12692 MockRead("HTTP/1.1 200 OK\r\n"),
12693 MockRead("Content-Length: 7\r\n\r\n"),
12694 MockRead("falafel"),
12695 MockRead(SYNCHRONOUS
, OK
),
12697 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12698 http_writes
, arraysize(http_writes
));
12699 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12701 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12703 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12704 // cancelled when a normal transaction is cancelled.
12705 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
12706 net::SSLConfig ssl_config
;
12707 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
12708 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
12709 ssl_config
, ssl_config
);
12710 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12712 // Start the HTTP request. Pool should stall.
12713 TestCompletionCallback http_callback
;
12714 scoped_ptr
<HttpTransaction
> http_trans(
12715 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12716 ASSERT_EQ(ERR_IO_PENDING
,
12717 http_trans
->Start(&http_request
, http_callback
.callback(),
12719 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12721 // The SSL connection will automatically be closed once the connection is
12722 // established, to let the HTTP request start.
12723 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12724 std::string response_data
;
12725 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12726 EXPECT_EQ("falafel", response_data
);
12728 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12731 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
12732 ScopedVector
<UploadElementReader
> element_readers
;
12733 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12734 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12736 HttpRequestInfo request
;
12737 request
.method
= "POST";
12738 request
.url
= GURL("http://www.foo.com/");
12739 request
.upload_data_stream
= &upload_data_stream
;
12740 request
.load_flags
= 0;
12742 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12743 scoped_ptr
<HttpTransaction
> trans(
12744 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12745 // Send headers successfully, but get an error while sending the body.
12746 MockWrite data_writes
[] = {
12747 MockWrite("POST / HTTP/1.1\r\n"
12748 "Host: www.foo.com\r\n"
12749 "Connection: keep-alive\r\n"
12750 "Content-Length: 3\r\n\r\n"),
12751 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12754 MockRead data_reads
[] = {
12755 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12756 MockRead("hello world"),
12757 MockRead(SYNCHRONOUS
, OK
),
12759 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12760 arraysize(data_writes
));
12761 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12763 TestCompletionCallback callback
;
12765 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12766 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12768 rv
= callback
.WaitForResult();
12771 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12772 ASSERT_TRUE(response
!= NULL
);
12774 EXPECT_TRUE(response
->headers
.get() != NULL
);
12775 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12777 std::string response_data
;
12778 rv
= ReadTransaction(trans
.get(), &response_data
);
12780 EXPECT_EQ("hello world", response_data
);
12783 // This test makes sure the retry logic doesn't trigger when reading an error
12784 // response from a server that rejected a POST with a CONNECTION_RESET.
12785 TEST_P(HttpNetworkTransactionTest
,
12786 PostReadsErrorResponseAfterResetOnReusedSocket
) {
12787 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12788 MockWrite data_writes
[] = {
12789 MockWrite("GET / HTTP/1.1\r\n"
12790 "Host: www.foo.com\r\n"
12791 "Connection: keep-alive\r\n\r\n"),
12792 MockWrite("POST / HTTP/1.1\r\n"
12793 "Host: www.foo.com\r\n"
12794 "Connection: keep-alive\r\n"
12795 "Content-Length: 3\r\n\r\n"),
12796 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12799 MockRead data_reads
[] = {
12800 MockRead("HTTP/1.1 200 Peachy\r\n"
12801 "Content-Length: 14\r\n\r\n"),
12802 MockRead("first response"),
12803 MockRead("HTTP/1.1 400 Not OK\r\n"
12804 "Content-Length: 15\r\n\r\n"),
12805 MockRead("second response"),
12806 MockRead(SYNCHRONOUS
, OK
),
12808 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12809 arraysize(data_writes
));
12810 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12812 TestCompletionCallback callback
;
12813 HttpRequestInfo request1
;
12814 request1
.method
= "GET";
12815 request1
.url
= GURL("http://www.foo.com/");
12816 request1
.load_flags
= 0;
12818 scoped_ptr
<HttpTransaction
> trans1(
12819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12820 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
12821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12823 rv
= callback
.WaitForResult();
12826 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12827 ASSERT_TRUE(response1
!= NULL
);
12829 EXPECT_TRUE(response1
->headers
.get() != NULL
);
12830 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
12832 std::string response_data1
;
12833 rv
= ReadTransaction(trans1
.get(), &response_data1
);
12835 EXPECT_EQ("first response", response_data1
);
12836 // Delete the transaction to release the socket back into the socket pool.
12839 ScopedVector
<UploadElementReader
> element_readers
;
12840 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12841 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12843 HttpRequestInfo request2
;
12844 request2
.method
= "POST";
12845 request2
.url
= GURL("http://www.foo.com/");
12846 request2
.upload_data_stream
= &upload_data_stream
;
12847 request2
.load_flags
= 0;
12849 scoped_ptr
<HttpTransaction
> trans2(
12850 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12851 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
12852 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12854 rv
= callback
.WaitForResult();
12857 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
12858 ASSERT_TRUE(response2
!= NULL
);
12860 EXPECT_TRUE(response2
->headers
.get() != NULL
);
12861 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
12863 std::string response_data2
;
12864 rv
= ReadTransaction(trans2
.get(), &response_data2
);
12866 EXPECT_EQ("second response", response_data2
);
12869 TEST_P(HttpNetworkTransactionTest
,
12870 PostReadsErrorResponseAfterResetPartialBodySent
) {
12871 ScopedVector
<UploadElementReader
> element_readers
;
12872 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12873 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12875 HttpRequestInfo request
;
12876 request
.method
= "POST";
12877 request
.url
= GURL("http://www.foo.com/");
12878 request
.upload_data_stream
= &upload_data_stream
;
12879 request
.load_flags
= 0;
12881 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12882 scoped_ptr
<HttpTransaction
> trans(
12883 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12884 // Send headers successfully, but get an error while sending the body.
12885 MockWrite data_writes
[] = {
12886 MockWrite("POST / HTTP/1.1\r\n"
12887 "Host: www.foo.com\r\n"
12888 "Connection: keep-alive\r\n"
12889 "Content-Length: 3\r\n\r\n"
12891 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12894 MockRead data_reads
[] = {
12895 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12896 MockRead("hello world"),
12897 MockRead(SYNCHRONOUS
, OK
),
12899 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12900 arraysize(data_writes
));
12901 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12903 TestCompletionCallback callback
;
12905 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12906 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12908 rv
= callback
.WaitForResult();
12911 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12912 ASSERT_TRUE(response
!= NULL
);
12914 EXPECT_TRUE(response
->headers
.get() != NULL
);
12915 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12917 std::string response_data
;
12918 rv
= ReadTransaction(trans
.get(), &response_data
);
12920 EXPECT_EQ("hello world", response_data
);
12923 // This tests the more common case than the previous test, where headers and
12924 // body are not merged into a single request.
12925 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
12926 ScopedVector
<UploadElementReader
> element_readers
;
12927 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12928 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
12930 HttpRequestInfo request
;
12931 request
.method
= "POST";
12932 request
.url
= GURL("http://www.foo.com/");
12933 request
.upload_data_stream
= &upload_data_stream
;
12934 request
.load_flags
= 0;
12936 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12937 scoped_ptr
<HttpTransaction
> trans(
12938 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12939 // Send headers successfully, but get an error while sending the body.
12940 MockWrite data_writes
[] = {
12941 MockWrite("POST / HTTP/1.1\r\n"
12942 "Host: www.foo.com\r\n"
12943 "Connection: keep-alive\r\n"
12944 "Transfer-Encoding: chunked\r\n\r\n"),
12945 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12948 MockRead data_reads
[] = {
12949 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12950 MockRead("hello world"),
12951 MockRead(SYNCHRONOUS
, OK
),
12953 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12954 arraysize(data_writes
));
12955 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12957 TestCompletionCallback callback
;
12959 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12960 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12961 // Make sure the headers are sent before adding a chunk. This ensures that
12962 // they can't be merged with the body in a single send. Not currently
12963 // necessary since a chunked body is never merged with headers, but this makes
12964 // the test more future proof.
12965 base::RunLoop().RunUntilIdle();
12967 upload_data_stream
.AppendChunk("last chunk", 10, true);
12969 rv
= callback
.WaitForResult();
12972 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12973 ASSERT_TRUE(response
!= NULL
);
12975 EXPECT_TRUE(response
->headers
.get() != NULL
);
12976 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12978 std::string response_data
;
12979 rv
= ReadTransaction(trans
.get(), &response_data
);
12981 EXPECT_EQ("hello world", response_data
);
12984 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
12985 ScopedVector
<UploadElementReader
> element_readers
;
12986 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12987 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12989 HttpRequestInfo request
;
12990 request
.method
= "POST";
12991 request
.url
= GURL("http://www.foo.com/");
12992 request
.upload_data_stream
= &upload_data_stream
;
12993 request
.load_flags
= 0;
12995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12996 scoped_ptr
<HttpTransaction
> trans(
12997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12999 MockWrite data_writes
[] = {
13000 MockWrite("POST / HTTP/1.1\r\n"
13001 "Host: www.foo.com\r\n"
13002 "Connection: keep-alive\r\n"
13003 "Content-Length: 3\r\n\r\n"),
13004 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13007 MockRead data_reads
[] = {
13008 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13009 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13010 MockRead("hello world"),
13011 MockRead(SYNCHRONOUS
, OK
),
13013 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13014 arraysize(data_writes
));
13015 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13017 TestCompletionCallback callback
;
13019 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13020 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13022 rv
= callback
.WaitForResult();
13025 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13026 ASSERT_TRUE(response
!= NULL
);
13028 EXPECT_TRUE(response
->headers
.get() != NULL
);
13029 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13031 std::string response_data
;
13032 rv
= ReadTransaction(trans
.get(), &response_data
);
13034 EXPECT_EQ("hello world", response_data
);
13037 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13038 ScopedVector
<UploadElementReader
> element_readers
;
13039 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13040 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13042 HttpRequestInfo request
;
13043 request
.method
= "POST";
13044 request
.url
= GURL("http://www.foo.com/");
13045 request
.upload_data_stream
= &upload_data_stream
;
13046 request
.load_flags
= 0;
13048 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13049 scoped_ptr
<HttpTransaction
> trans(
13050 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13051 // Send headers successfully, but get an error while sending the body.
13052 MockWrite data_writes
[] = {
13053 MockWrite("POST / HTTP/1.1\r\n"
13054 "Host: www.foo.com\r\n"
13055 "Connection: keep-alive\r\n"
13056 "Content-Length: 3\r\n\r\n"),
13057 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13060 MockRead data_reads
[] = {
13061 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13062 MockRead("hello world"),
13063 MockRead(SYNCHRONOUS
, OK
),
13065 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13066 arraysize(data_writes
));
13067 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13069 TestCompletionCallback callback
;
13071 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13072 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13074 rv
= callback
.WaitForResult();
13075 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13077 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13078 EXPECT_TRUE(response
== NULL
);
13081 TEST_P(HttpNetworkTransactionTest
,
13082 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13083 ScopedVector
<UploadElementReader
> element_readers
;
13084 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13085 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13087 HttpRequestInfo request
;
13088 request
.method
= "POST";
13089 request
.url
= GURL("http://www.foo.com/");
13090 request
.upload_data_stream
= &upload_data_stream
;
13091 request
.load_flags
= 0;
13093 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13094 scoped_ptr
<HttpTransaction
> trans(
13095 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13096 // Send headers successfully, but get an error while sending the body.
13097 MockWrite data_writes
[] = {
13098 MockWrite("POST / HTTP/1.1\r\n"
13099 "Host: www.foo.com\r\n"
13100 "Connection: keep-alive\r\n"
13101 "Content-Length: 3\r\n\r\n"),
13102 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13105 MockRead data_reads
[] = {
13106 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13107 MockRead("HTTP/1.0 302 Redirect\r\n"),
13108 MockRead("Location: http://somewhere-else.com/\r\n"),
13109 MockRead("Content-Length: 0\r\n\r\n"),
13110 MockRead(SYNCHRONOUS
, OK
),
13112 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13113 arraysize(data_writes
));
13114 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13116 TestCompletionCallback callback
;
13118 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13119 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13121 rv
= callback
.WaitForResult();
13122 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13124 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13125 EXPECT_TRUE(response
== NULL
);
13128 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13129 ScopedVector
<UploadElementReader
> element_readers
;
13130 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13131 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13133 HttpRequestInfo request
;
13134 request
.method
= "POST";
13135 request
.url
= GURL("http://www.foo.com/");
13136 request
.upload_data_stream
= &upload_data_stream
;
13137 request
.load_flags
= 0;
13139 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13140 scoped_ptr
<HttpTransaction
> trans(
13141 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13142 // Send headers successfully, but get an error while sending the body.
13143 MockWrite data_writes
[] = {
13144 MockWrite("POST / HTTP/1.1\r\n"
13145 "Host: www.foo.com\r\n"
13146 "Connection: keep-alive\r\n"
13147 "Content-Length: 3\r\n\r\n"),
13148 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13151 MockRead data_reads
[] = {
13152 MockRead("HTTP 0.9 rocks!"),
13153 MockRead(SYNCHRONOUS
, OK
),
13155 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13156 arraysize(data_writes
));
13157 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13159 TestCompletionCallback callback
;
13161 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13162 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13164 rv
= callback
.WaitForResult();
13165 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13167 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13168 EXPECT_TRUE(response
== NULL
);
13171 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13172 ScopedVector
<UploadElementReader
> element_readers
;
13173 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13174 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13176 HttpRequestInfo request
;
13177 request
.method
= "POST";
13178 request
.url
= GURL("http://www.foo.com/");
13179 request
.upload_data_stream
= &upload_data_stream
;
13180 request
.load_flags
= 0;
13182 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13183 scoped_ptr
<HttpTransaction
> trans(
13184 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13185 // Send headers successfully, but get an error while sending the body.
13186 MockWrite data_writes
[] = {
13187 MockWrite("POST / HTTP/1.1\r\n"
13188 "Host: www.foo.com\r\n"
13189 "Connection: keep-alive\r\n"
13190 "Content-Length: 3\r\n\r\n"),
13191 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13194 MockRead data_reads
[] = {
13195 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13196 MockRead(SYNCHRONOUS
, OK
),
13198 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13199 arraysize(data_writes
));
13200 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13202 TestCompletionCallback callback
;
13204 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13207 rv
= callback
.WaitForResult();
13208 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13210 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13211 EXPECT_TRUE(response
== NULL
);