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,
590 //-----------------------------------------------------------------------------
592 // Helper functions for validating that AuthChallengeInfo's are correctly
593 // configured for common cases.
594 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
597 EXPECT_FALSE(auth_challenge
->is_proxy
);
598 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
599 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
600 EXPECT_EQ("basic", auth_challenge
->scheme
);
604 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
607 EXPECT_TRUE(auth_challenge
->is_proxy
);
608 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
609 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
610 EXPECT_EQ("basic", auth_challenge
->scheme
);
614 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
617 EXPECT_FALSE(auth_challenge
->is_proxy
);
618 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
619 EXPECT_EQ("digestive", auth_challenge
->realm
);
620 EXPECT_EQ("digest", auth_challenge
->scheme
);
624 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
627 EXPECT_FALSE(auth_challenge
->is_proxy
);
628 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
629 EXPECT_EQ(std::string(), auth_challenge
->realm
);
630 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
636 TEST_P(HttpNetworkTransactionTest
, Basic
) {
637 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
638 scoped_ptr
<HttpTransaction
> trans(
639 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
642 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
643 MockRead data_reads
[] = {
644 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
645 MockRead("hello world"),
646 MockRead(SYNCHRONOUS
, OK
),
648 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
649 arraysize(data_reads
));
650 EXPECT_EQ(OK
, out
.rv
);
651 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
652 EXPECT_EQ("hello world", out
.response_data
);
653 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
654 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
657 // Response with no status line.
658 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
659 MockRead data_reads
[] = {
660 MockRead("hello world"),
661 MockRead(SYNCHRONOUS
, OK
),
663 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
664 arraysize(data_reads
));
665 EXPECT_EQ(OK
, out
.rv
);
666 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
667 EXPECT_EQ("hello world", out
.response_data
);
668 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
669 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
672 // Allow up to 4 bytes of junk to precede status line.
673 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
674 MockRead data_reads
[] = {
675 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
676 MockRead(SYNCHRONOUS
, OK
),
678 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
679 arraysize(data_reads
));
680 EXPECT_EQ(OK
, out
.rv
);
681 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
682 EXPECT_EQ("DATA", out
.response_data
);
683 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
684 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
687 // Allow up to 4 bytes of junk to precede status line.
688 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
689 MockRead data_reads
[] = {
690 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
691 MockRead(SYNCHRONOUS
, OK
),
693 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
694 arraysize(data_reads
));
695 EXPECT_EQ(OK
, out
.rv
);
696 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
697 EXPECT_EQ("DATA", out
.response_data
);
698 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
699 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
702 // Beyond 4 bytes of slop and it should fail to find a status line.
703 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
704 MockRead data_reads
[] = {
705 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
706 MockRead(SYNCHRONOUS
, OK
),
708 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
709 arraysize(data_reads
));
710 EXPECT_EQ(OK
, out
.rv
);
711 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
712 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
713 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
714 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
717 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
718 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
719 MockRead data_reads
[] = {
724 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
725 MockRead(SYNCHRONOUS
, OK
),
727 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
728 arraysize(data_reads
));
729 EXPECT_EQ(OK
, out
.rv
);
730 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
731 EXPECT_EQ("DATA", out
.response_data
);
732 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
733 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
736 // Close the connection before enough bytes to have a status line.
737 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
738 MockRead data_reads
[] = {
740 MockRead(SYNCHRONOUS
, OK
),
742 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
743 arraysize(data_reads
));
744 EXPECT_EQ(OK
, out
.rv
);
745 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
746 EXPECT_EQ("HTT", out
.response_data
);
747 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
748 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
751 // Simulate a 204 response, lacking a Content-Length header, sent over a
752 // persistent connection. The response should still terminate since a 204
753 // cannot have a response body.
754 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
755 char junk
[] = "junk";
756 MockRead data_reads
[] = {
757 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
758 MockRead(junk
), // Should not be read!!
759 MockRead(SYNCHRONOUS
, OK
),
761 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
762 arraysize(data_reads
));
763 EXPECT_EQ(OK
, out
.rv
);
764 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
765 EXPECT_EQ("", out
.response_data
);
766 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
767 int64 response_size
= reads_size
- strlen(junk
);
768 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
771 // A simple request using chunked encoding with some extra data after.
772 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
773 std::string final_chunk
= "0\r\n\r\n";
774 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
775 std::string last_read
= final_chunk
+ extra_data
;
776 MockRead data_reads
[] = {
777 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
778 MockRead("5\r\nHello\r\n"),
781 MockRead("5\r\nworld\r\n"),
782 MockRead(last_read
.data()),
783 MockRead(SYNCHRONOUS
, OK
),
785 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
786 arraysize(data_reads
));
787 EXPECT_EQ(OK
, out
.rv
);
788 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
789 EXPECT_EQ("Hello world", out
.response_data
);
790 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
791 int64 response_size
= reads_size
- extra_data
.size();
792 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
795 // Next tests deal with http://crbug.com/56344.
797 TEST_P(HttpNetworkTransactionTest
,
798 MultipleContentLengthHeadersNoTransferEncoding
) {
799 MockRead data_reads
[] = {
800 MockRead("HTTP/1.1 200 OK\r\n"),
801 MockRead("Content-Length: 10\r\n"),
802 MockRead("Content-Length: 5\r\n\r\n"),
804 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
805 arraysize(data_reads
));
806 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
809 TEST_P(HttpNetworkTransactionTest
,
810 DuplicateContentLengthHeadersNoTransferEncoding
) {
811 MockRead data_reads
[] = {
812 MockRead("HTTP/1.1 200 OK\r\n"),
813 MockRead("Content-Length: 5\r\n"),
814 MockRead("Content-Length: 5\r\n\r\n"),
817 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
818 arraysize(data_reads
));
819 EXPECT_EQ(OK
, out
.rv
);
820 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
821 EXPECT_EQ("Hello", out
.response_data
);
824 TEST_P(HttpNetworkTransactionTest
,
825 ComplexContentLengthHeadersNoTransferEncoding
) {
826 // More than 2 dupes.
828 MockRead data_reads
[] = {
829 MockRead("HTTP/1.1 200 OK\r\n"),
830 MockRead("Content-Length: 5\r\n"),
831 MockRead("Content-Length: 5\r\n"),
832 MockRead("Content-Length: 5\r\n\r\n"),
835 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
836 arraysize(data_reads
));
837 EXPECT_EQ(OK
, out
.rv
);
838 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
839 EXPECT_EQ("Hello", out
.response_data
);
843 MockRead data_reads
[] = {
844 MockRead("HTTP/1.0 200 OK\r\n"),
845 MockRead("Content-Length: 5\r\n"),
846 MockRead("Content-Length: 5\r\n"),
847 MockRead("Content-Length: 5\r\n\r\n"),
850 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
851 arraysize(data_reads
));
852 EXPECT_EQ(OK
, out
.rv
);
853 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
854 EXPECT_EQ("Hello", out
.response_data
);
856 // 2 dupes and one mismatched.
858 MockRead data_reads
[] = {
859 MockRead("HTTP/1.1 200 OK\r\n"),
860 MockRead("Content-Length: 10\r\n"),
861 MockRead("Content-Length: 10\r\n"),
862 MockRead("Content-Length: 5\r\n\r\n"),
864 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
865 arraysize(data_reads
));
866 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
870 TEST_P(HttpNetworkTransactionTest
,
871 MultipleContentLengthHeadersTransferEncoding
) {
872 MockRead data_reads
[] = {
873 MockRead("HTTP/1.1 200 OK\r\n"),
874 MockRead("Content-Length: 666\r\n"),
875 MockRead("Content-Length: 1337\r\n"),
876 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
877 MockRead("5\r\nHello\r\n"),
880 MockRead("5\r\nworld\r\n"),
881 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
882 MockRead(SYNCHRONOUS
, OK
),
884 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
885 arraysize(data_reads
));
886 EXPECT_EQ(OK
, out
.rv
);
887 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
888 EXPECT_EQ("Hello world", out
.response_data
);
891 // Next tests deal with http://crbug.com/98895.
893 // Checks that a single Content-Disposition header results in no error.
894 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
895 MockRead data_reads
[] = {
896 MockRead("HTTP/1.1 200 OK\r\n"),
897 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
898 MockRead("Content-Length: 5\r\n\r\n"),
901 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
902 arraysize(data_reads
));
903 EXPECT_EQ(OK
, out
.rv
);
904 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
905 EXPECT_EQ("Hello", out
.response_data
);
908 // Checks that two identical Content-Disposition headers result in no error.
909 TEST_P(HttpNetworkTransactionTest
,
910 TwoIdenticalContentDispositionHeaders
) {
911 MockRead data_reads
[] = {
912 MockRead("HTTP/1.1 200 OK\r\n"),
913 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
914 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
915 MockRead("Content-Length: 5\r\n\r\n"),
918 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
919 arraysize(data_reads
));
920 EXPECT_EQ(OK
, out
.rv
);
921 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
922 EXPECT_EQ("Hello", out
.response_data
);
925 // Checks that two distinct Content-Disposition headers result in an error.
926 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
927 MockRead data_reads
[] = {
928 MockRead("HTTP/1.1 200 OK\r\n"),
929 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
930 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
931 MockRead("Content-Length: 5\r\n\r\n"),
934 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
935 arraysize(data_reads
));
936 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
939 // Checks that two identical Location headers result in no error.
940 // Also tests Location header behavior.
941 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
942 MockRead data_reads
[] = {
943 MockRead("HTTP/1.1 302 Redirect\r\n"),
944 MockRead("Location: http://good.com/\r\n"),
945 MockRead("Location: http://good.com/\r\n"),
946 MockRead("Content-Length: 0\r\n\r\n"),
947 MockRead(SYNCHRONOUS
, OK
),
950 HttpRequestInfo request
;
951 request
.method
= "GET";
952 request
.url
= GURL("http://redirect.com/");
953 request
.load_flags
= 0;
955 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
956 scoped_ptr
<HttpTransaction
> trans(
957 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
959 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
960 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
962 TestCompletionCallback callback
;
964 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
965 EXPECT_EQ(ERR_IO_PENDING
, rv
);
967 EXPECT_EQ(OK
, callback
.WaitForResult());
969 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
970 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
971 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
973 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
974 EXPECT_EQ("http://good.com/", url
);
975 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
978 // Checks that two distinct Location headers result in an error.
979 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
980 MockRead data_reads
[] = {
981 MockRead("HTTP/1.1 302 Redirect\r\n"),
982 MockRead("Location: http://good.com/\r\n"),
983 MockRead("Location: http://evil.com/\r\n"),
984 MockRead("Content-Length: 0\r\n\r\n"),
985 MockRead(SYNCHRONOUS
, OK
),
987 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
988 arraysize(data_reads
));
989 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
992 // Do a request using the HEAD method. Verify that we don't try to read the
993 // message body (since HEAD has none).
994 TEST_P(HttpNetworkTransactionTest
, Head
) {
995 HttpRequestInfo request
;
996 request
.method
= "HEAD";
997 request
.url
= GURL("http://www.google.com/");
998 request
.load_flags
= 0;
1000 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1001 scoped_ptr
<HttpTransaction
> trans(
1002 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1003 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1004 trans
->SetBeforeProxyHeadersSentCallback(
1005 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1006 base::Unretained(&proxy_headers_handler
)));
1008 MockWrite data_writes1
[] = {
1009 MockWrite("HEAD / HTTP/1.1\r\n"
1010 "Host: www.google.com\r\n"
1011 "Connection: keep-alive\r\n"
1012 "Content-Length: 0\r\n\r\n"),
1014 MockRead data_reads1
[] = {
1015 MockRead("HTTP/1.1 404 Not Found\r\n"),
1016 MockRead("Server: Blah\r\n"),
1017 MockRead("Content-Length: 1234\r\n\r\n"),
1019 // No response body because the test stops reading here.
1020 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1023 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1024 data_writes1
, arraysize(data_writes1
));
1025 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1027 TestCompletionCallback callback1
;
1029 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1030 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1032 rv
= callback1
.WaitForResult();
1035 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1036 ASSERT_TRUE(response
!= NULL
);
1038 // Check that the headers got parsed.
1039 EXPECT_TRUE(response
->headers
.get() != NULL
);
1040 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1041 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1042 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1043 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1045 std::string server_header
;
1047 bool has_server_header
= response
->headers
->EnumerateHeader(
1048 &iter
, "Server", &server_header
);
1049 EXPECT_TRUE(has_server_header
);
1050 EXPECT_EQ("Blah", server_header
);
1052 // Reading should give EOF right away, since there is no message body
1053 // (despite non-zero content-length).
1054 std::string response_data
;
1055 rv
= ReadTransaction(trans
.get(), &response_data
);
1057 EXPECT_EQ("", response_data
);
1060 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1061 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1063 MockRead data_reads
[] = {
1064 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1066 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1068 MockRead(SYNCHRONOUS
, OK
),
1070 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1071 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1073 const char* const kExpectedResponseData
[] = {
1077 for (int i
= 0; i
< 2; ++i
) {
1078 HttpRequestInfo request
;
1079 request
.method
= "GET";
1080 request
.url
= GURL("http://www.google.com/");
1081 request
.load_flags
= 0;
1083 scoped_ptr
<HttpTransaction
> trans(
1084 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1086 TestCompletionCallback callback
;
1088 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1089 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1091 rv
= callback
.WaitForResult();
1094 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1095 ASSERT_TRUE(response
!= NULL
);
1097 EXPECT_TRUE(response
->headers
.get() != NULL
);
1098 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1099 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1101 std::string response_data
;
1102 rv
= ReadTransaction(trans
.get(), &response_data
);
1104 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1108 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1109 ScopedVector
<UploadElementReader
> element_readers
;
1110 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1111 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1113 HttpRequestInfo request
;
1114 request
.method
= "POST";
1115 request
.url
= GURL("http://www.foo.com/");
1116 request
.upload_data_stream
= &upload_data_stream
;
1117 request
.load_flags
= 0;
1119 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1120 scoped_ptr
<HttpTransaction
> trans(
1121 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1123 MockRead data_reads
[] = {
1124 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1125 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1126 MockRead("hello world"),
1127 MockRead(SYNCHRONOUS
, OK
),
1129 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1130 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1132 TestCompletionCallback callback
;
1134 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1137 rv
= callback
.WaitForResult();
1140 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1141 ASSERT_TRUE(response
!= NULL
);
1143 EXPECT_TRUE(response
->headers
.get() != NULL
);
1144 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1146 std::string response_data
;
1147 rv
= ReadTransaction(trans
.get(), &response_data
);
1149 EXPECT_EQ("hello world", response_data
);
1152 // This test is almost the same as Ignores100 above, but the response contains
1153 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1154 // HTTP/1.1 and the two status headers are read in one read.
1155 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1156 HttpRequestInfo request
;
1157 request
.method
= "GET";
1158 request
.url
= GURL("http://www.foo.com/");
1159 request
.load_flags
= 0;
1161 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1162 scoped_ptr
<HttpTransaction
> trans(
1163 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1165 MockRead data_reads
[] = {
1166 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1167 "HTTP/1.1 200 OK\r\n\r\n"),
1168 MockRead("hello world"),
1169 MockRead(SYNCHRONOUS
, OK
),
1171 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1172 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1174 TestCompletionCallback callback
;
1176 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1177 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1179 rv
= callback
.WaitForResult();
1182 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1183 ASSERT_TRUE(response
!= NULL
);
1185 EXPECT_TRUE(response
->headers
.get() != NULL
);
1186 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1188 std::string response_data
;
1189 rv
= ReadTransaction(trans
.get(), &response_data
);
1191 EXPECT_EQ("hello world", response_data
);
1194 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1195 HttpRequestInfo request
;
1196 request
.method
= "POST";
1197 request
.url
= GURL("http://www.foo.com/");
1198 request
.load_flags
= 0;
1200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1201 scoped_ptr
<HttpTransaction
> trans(
1202 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1204 MockRead data_reads
[] = {
1205 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1208 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1209 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1211 TestCompletionCallback callback
;
1213 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1214 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1216 rv
= callback
.WaitForResult();
1219 std::string response_data
;
1220 rv
= ReadTransaction(trans
.get(), &response_data
);
1222 EXPECT_EQ("", response_data
);
1225 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1226 HttpRequestInfo request
;
1227 request
.method
= "POST";
1228 request
.url
= GURL("http://www.foo.com/");
1229 request
.load_flags
= 0;
1231 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1232 scoped_ptr
<HttpTransaction
> trans(
1233 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1236 MockRead data_reads
[] = {
1239 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1240 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1242 TestCompletionCallback callback
;
1244 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1245 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1247 rv
= callback
.WaitForResult();
1248 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1251 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1252 const MockWrite
* write_failure
,
1253 const MockRead
* read_failure
) {
1254 HttpRequestInfo request
;
1255 request
.method
= "GET";
1256 request
.url
= GURL("http://www.foo.com/");
1257 request
.load_flags
= 0;
1259 CapturingNetLog net_log
;
1260 session_deps_
.net_log
= &net_log
;
1261 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1263 // Written data for successfully sending both requests.
1264 MockWrite data1_writes
[] = {
1265 MockWrite("GET / HTTP/1.1\r\n"
1266 "Host: www.foo.com\r\n"
1267 "Connection: keep-alive\r\n\r\n"),
1268 MockWrite("GET / HTTP/1.1\r\n"
1269 "Host: www.foo.com\r\n"
1270 "Connection: keep-alive\r\n\r\n")
1273 // Read results for the first request.
1274 MockRead data1_reads
[] = {
1275 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1277 MockRead(ASYNC
, OK
),
1280 if (write_failure
) {
1281 ASSERT_FALSE(read_failure
);
1282 data1_writes
[1] = *write_failure
;
1284 ASSERT_TRUE(read_failure
);
1285 data1_reads
[2] = *read_failure
;
1288 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1289 data1_writes
, arraysize(data1_writes
));
1290 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1292 MockRead data2_reads
[] = {
1293 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1295 MockRead(ASYNC
, OK
),
1297 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1298 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1300 const char* kExpectedResponseData
[] = {
1304 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1305 for (int i
= 0; i
< 2; ++i
) {
1306 TestCompletionCallback callback
;
1308 scoped_ptr
<HttpTransaction
> trans(
1309 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1311 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1312 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1314 rv
= callback
.WaitForResult();
1317 LoadTimingInfo load_timing_info
;
1318 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1319 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1321 first_socket_log_id
= load_timing_info
.socket_log_id
;
1323 // The second request should be using a new socket.
1324 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1327 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1328 ASSERT_TRUE(response
!= NULL
);
1330 EXPECT_TRUE(response
->headers
.get() != NULL
);
1331 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1333 std::string response_data
;
1334 rv
= ReadTransaction(trans
.get(), &response_data
);
1336 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1340 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1341 const MockWrite
* write_failure
,
1342 const MockRead
* read_failure
,
1344 HttpRequestInfo request
;
1345 request
.method
= "GET";
1346 request
.url
= GURL("https://www.foo.com/");
1347 request
.load_flags
= 0;
1349 CapturingNetLog net_log
;
1350 session_deps_
.net_log
= &net_log
;
1351 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1353 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1354 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1356 ssl1
.SetNextProto(GetParam());
1357 ssl2
.SetNextProto(GetParam());
1359 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1360 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1362 // SPDY versions of the request and response.
1363 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1364 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1365 scoped_ptr
<SpdyFrame
> spdy_response(
1366 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1367 scoped_ptr
<SpdyFrame
> spdy_data(
1368 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1370 // HTTP/1.1 versions of the request and response.
1371 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1372 "Host: www.foo.com\r\n"
1373 "Connection: keep-alive\r\n\r\n";
1374 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1375 const char kHttpData
[] = "hello";
1377 std::vector
<MockRead
> data1_reads
;
1378 std::vector
<MockWrite
> data1_writes
;
1379 if (write_failure
) {
1380 ASSERT_FALSE(read_failure
);
1381 data1_writes
.push_back(*write_failure
);
1382 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1384 ASSERT_TRUE(read_failure
);
1386 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1388 data1_writes
.push_back(MockWrite(kHttpRequest
));
1390 data1_reads
.push_back(*read_failure
);
1393 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1394 &data1_writes
[0], data1_writes
.size());
1395 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1397 std::vector
<MockRead
> data2_reads
;
1398 std::vector
<MockWrite
> data2_writes
;
1401 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1403 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1404 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1405 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1407 data2_writes
.push_back(
1408 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1410 data2_reads
.push_back(
1411 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1412 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1413 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1415 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1416 &data2_writes
[0], data2_writes
.size());
1417 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1419 // Preconnect a socket.
1420 net::SSLConfig ssl_config
;
1421 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1422 session
->GetNextProtos(&ssl_config
.next_protos
);
1423 session
->http_stream_factory()->PreconnectStreams(
1424 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1425 // Wait for the preconnect to complete.
1426 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1427 base::RunLoop().RunUntilIdle();
1428 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1430 // Make the request.
1431 TestCompletionCallback callback
;
1433 scoped_ptr
<HttpTransaction
> trans(
1434 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1436 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1439 rv
= callback
.WaitForResult();
1442 LoadTimingInfo load_timing_info
;
1443 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1444 TestLoadTimingNotReused(
1446 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1448 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1449 ASSERT_TRUE(response
!= NULL
);
1451 EXPECT_TRUE(response
->headers
.get() != NULL
);
1452 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1454 std::string response_data
;
1455 rv
= ReadTransaction(trans
.get(), &response_data
);
1457 EXPECT_EQ(kHttpData
, response_data
);
1460 TEST_P(HttpNetworkTransactionTest
,
1461 KeepAliveConnectionNotConnectedOnWrite
) {
1462 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1463 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1466 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1467 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1468 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1471 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1472 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1473 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1476 // Make sure that on a 408 response (Request Timeout), the request is retried,
1477 // if the socket was a reused keep alive socket.
1478 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1479 MockRead
read_failure(SYNCHRONOUS
,
1480 "HTTP/1.1 408 Request Timeout\r\n"
1481 "Connection: Keep-Alive\r\n"
1482 "Content-Length: 6\r\n\r\n"
1484 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1487 TEST_P(HttpNetworkTransactionTest
,
1488 PreconnectErrorNotConnectedOnWrite
) {
1489 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1490 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1493 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1494 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1495 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1498 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1499 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1500 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1503 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1504 MockRead
read_failure(ASYNC
, OK
); // EOF
1505 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1508 // Make sure that on a 408 response (Request Timeout), the request is retried,
1509 // if the socket was a preconnected (UNUSED_IDLE) socket.
1510 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1511 MockRead
read_failure(SYNCHRONOUS
,
1512 "HTTP/1.1 408 Request Timeout\r\n"
1513 "Connection: Keep-Alive\r\n"
1514 "Content-Length: 6\r\n\r\n"
1516 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1517 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1520 TEST_P(HttpNetworkTransactionTest
,
1521 SpdyPreconnectErrorNotConnectedOnWrite
) {
1522 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1523 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1526 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1527 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1528 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1531 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1532 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1533 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1536 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1537 MockRead
read_failure(ASYNC
, OK
); // EOF
1538 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1541 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1542 HttpRequestInfo request
;
1543 request
.method
= "GET";
1544 request
.url
= GURL("http://www.google.com/");
1545 request
.load_flags
= 0;
1547 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1548 scoped_ptr
<HttpTransaction
> trans(
1549 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1551 MockRead data_reads
[] = {
1552 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1553 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1554 MockRead("hello world"),
1555 MockRead(SYNCHRONOUS
, OK
),
1557 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1558 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1560 TestCompletionCallback callback
;
1562 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1563 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1565 rv
= callback
.WaitForResult();
1566 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1568 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1569 EXPECT_TRUE(response
== NULL
);
1572 // What do various browsers do when the server closes a non-keepalive
1573 // connection without sending any response header or body?
1576 // Safari 3.1.2 (Windows): error page
1577 // Firefox 3.0.1: blank page
1578 // Opera 9.52: after five attempts, blank page
1579 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1580 // Us: error page (EMPTY_RESPONSE)
1581 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1582 MockRead data_reads
[] = {
1583 MockRead(SYNCHRONOUS
, OK
), // EOF
1584 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1585 MockRead("hello world"),
1586 MockRead(SYNCHRONOUS
, OK
),
1588 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1589 arraysize(data_reads
));
1590 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1593 // Test that network access can be deferred and resumed.
1594 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1595 HttpRequestInfo request
;
1596 request
.method
= "GET";
1597 request
.url
= GURL("http://www.google.com/");
1598 request
.load_flags
= 0;
1600 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1601 scoped_ptr
<HttpTransaction
> trans(
1602 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1604 // Defer on OnBeforeNetworkStart.
1605 BeforeNetworkStartHandler
net_start_handler(true); // defer
1606 trans
->SetBeforeNetworkStartCallback(
1607 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1608 base::Unretained(&net_start_handler
)));
1610 MockRead data_reads
[] = {
1611 MockRead("HTTP/1.0 200 OK\r\n"),
1612 MockRead("Content-Length: 5\r\n\r\n"),
1614 MockRead(SYNCHRONOUS
, 0),
1616 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1617 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1619 TestCompletionCallback callback
;
1621 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1622 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1623 base::MessageLoop::current()->RunUntilIdle();
1625 // Should have deferred for network start.
1626 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1627 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1628 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1630 trans
->ResumeNetworkStart();
1631 rv
= callback
.WaitForResult();
1633 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1635 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1636 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1637 if (rv
== ERR_IO_PENDING
)
1638 rv
= callback
.WaitForResult();
1643 // Test that network use can be deferred and canceled.
1644 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1645 HttpRequestInfo request
;
1646 request
.method
= "GET";
1647 request
.url
= GURL("http://www.google.com/");
1648 request
.load_flags
= 0;
1650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1651 scoped_ptr
<HttpTransaction
> trans(
1652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1654 // Defer on OnBeforeNetworkStart.
1655 BeforeNetworkStartHandler
net_start_handler(true); // defer
1656 trans
->SetBeforeNetworkStartCallback(
1657 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1658 base::Unretained(&net_start_handler
)));
1660 TestCompletionCallback callback
;
1662 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1663 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1664 base::MessageLoop::current()->RunUntilIdle();
1666 // Should have deferred for network start.
1667 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1668 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1669 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1672 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1673 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1674 // destructor in such situations.
1675 // See http://crbug.com/154712 and http://crbug.com/156609.
1676 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1677 HttpRequestInfo request
;
1678 request
.method
= "GET";
1679 request
.url
= GURL("http://www.google.com/");
1680 request
.load_flags
= 0;
1682 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1683 scoped_ptr
<HttpTransaction
> trans(
1684 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1686 MockRead data_reads
[] = {
1687 MockRead("HTTP/1.0 200 OK\r\n"),
1688 MockRead("Connection: keep-alive\r\n"),
1689 MockRead("Content-Length: 100\r\n\r\n"),
1691 MockRead(SYNCHRONOUS
, 0),
1693 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1694 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1696 TestCompletionCallback callback
;
1698 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1699 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1701 rv
= callback
.WaitForResult();
1704 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1705 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1706 if (rv
== ERR_IO_PENDING
)
1707 rv
= callback
.WaitForResult();
1709 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1710 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1713 base::MessageLoop::current()->RunUntilIdle();
1714 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1717 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1718 HttpRequestInfo request
;
1719 request
.method
= "GET";
1720 request
.url
= GURL("http://www.google.com/");
1721 request
.load_flags
= 0;
1723 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1724 scoped_ptr
<HttpTransaction
> trans(
1725 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1727 MockRead data_reads
[] = {
1728 MockRead("HTTP/1.0 200 OK\r\n"),
1729 MockRead("Connection: keep-alive\r\n"),
1730 MockRead("Content-Length: 100\r\n\r\n"),
1731 MockRead(SYNCHRONOUS
, 0),
1733 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1734 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1736 TestCompletionCallback callback
;
1738 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1741 rv
= callback
.WaitForResult();
1744 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1745 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1746 if (rv
== ERR_IO_PENDING
)
1747 rv
= callback
.WaitForResult();
1748 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1751 base::MessageLoop::current()->RunUntilIdle();
1752 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1755 // Test that we correctly reuse a keep-alive connection after not explicitly
1756 // reading the body.
1757 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1758 HttpRequestInfo request
;
1759 request
.method
= "GET";
1760 request
.url
= GURL("http://www.foo.com/");
1761 request
.load_flags
= 0;
1763 CapturingNetLog net_log
;
1764 session_deps_
.net_log
= &net_log
;
1765 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1767 // Note that because all these reads happen in the same
1768 // StaticSocketDataProvider, it shows that the same socket is being reused for
1769 // all transactions.
1770 MockRead data1_reads
[] = {
1771 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1772 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1773 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1774 MockRead("HTTP/1.1 302 Found\r\n"
1775 "Content-Length: 0\r\n\r\n"),
1776 MockRead("HTTP/1.1 302 Found\r\n"
1777 "Content-Length: 5\r\n\r\n"
1779 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1780 "Content-Length: 0\r\n\r\n"),
1781 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1782 "Content-Length: 5\r\n\r\n"
1784 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1787 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1788 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1790 MockRead data2_reads
[] = {
1791 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1793 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1794 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1796 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1797 std::string response_lines
[kNumUnreadBodies
];
1799 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1800 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1801 TestCompletionCallback callback
;
1803 scoped_ptr
<HttpTransaction
> trans(
1804 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1806 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1809 rv
= callback
.WaitForResult();
1812 LoadTimingInfo load_timing_info
;
1813 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1815 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1816 first_socket_log_id
= load_timing_info
.socket_log_id
;
1818 TestLoadTimingReused(load_timing_info
);
1819 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1822 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1823 ASSERT_TRUE(response
!= NULL
);
1825 ASSERT_TRUE(response
->headers
.get() != NULL
);
1826 response_lines
[i
] = response
->headers
->GetStatusLine();
1828 // We intentionally don't read the response bodies.
1831 const char* const kStatusLines
[] = {
1832 "HTTP/1.1 204 No Content",
1833 "HTTP/1.1 205 Reset Content",
1834 "HTTP/1.1 304 Not Modified",
1835 "HTTP/1.1 302 Found",
1836 "HTTP/1.1 302 Found",
1837 "HTTP/1.1 301 Moved Permanently",
1838 "HTTP/1.1 301 Moved Permanently",
1841 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1842 forgot_to_update_kStatusLines
);
1844 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1845 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1847 TestCompletionCallback callback
;
1848 scoped_ptr
<HttpTransaction
> trans(
1849 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1850 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1851 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1852 rv
= callback
.WaitForResult();
1854 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1855 ASSERT_TRUE(response
!= NULL
);
1856 ASSERT_TRUE(response
->headers
.get() != NULL
);
1857 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1858 std::string response_data
;
1859 rv
= ReadTransaction(trans
.get(), &response_data
);
1861 EXPECT_EQ("hello", response_data
);
1864 // Test the request-challenge-retry sequence for basic auth.
1865 // (basic auth is the easiest to mock, because it has no randomness).
1866 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1867 HttpRequestInfo request
;
1868 request
.method
= "GET";
1869 request
.url
= GURL("http://www.google.com/");
1870 request
.load_flags
= 0;
1872 CapturingNetLog log
;
1873 session_deps_
.net_log
= &log
;
1874 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1875 scoped_ptr
<HttpTransaction
> trans(
1876 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1878 MockWrite data_writes1
[] = {
1879 MockWrite("GET / HTTP/1.1\r\n"
1880 "Host: www.google.com\r\n"
1881 "Connection: keep-alive\r\n\r\n"),
1884 MockRead data_reads1
[] = {
1885 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1886 // Give a couple authenticate options (only the middle one is actually
1888 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1889 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1890 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1891 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1892 // Large content-length -- won't matter, as connection will be reset.
1893 MockRead("Content-Length: 10000\r\n\r\n"),
1894 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1897 // After calling trans->RestartWithAuth(), this is the request we should
1898 // be issuing -- the final header line contains the credentials.
1899 MockWrite data_writes2
[] = {
1900 MockWrite("GET / HTTP/1.1\r\n"
1901 "Host: www.google.com\r\n"
1902 "Connection: keep-alive\r\n"
1903 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1906 // Lastly, the server responds with the actual content.
1907 MockRead data_reads2
[] = {
1908 MockRead("HTTP/1.0 200 OK\r\n"),
1909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1910 MockRead("Content-Length: 100\r\n\r\n"),
1911 MockRead(SYNCHRONOUS
, OK
),
1914 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1915 data_writes1
, arraysize(data_writes1
));
1916 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1917 data_writes2
, arraysize(data_writes2
));
1918 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1919 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1921 TestCompletionCallback callback1
;
1923 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1926 rv
= callback1
.WaitForResult();
1929 LoadTimingInfo load_timing_info1
;
1930 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1931 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1933 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1934 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1936 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1937 ASSERT_TRUE(response
!= NULL
);
1938 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1940 TestCompletionCallback callback2
;
1942 rv
= trans
->RestartWithAuth(
1943 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1944 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1946 rv
= callback2
.WaitForResult();
1949 LoadTimingInfo load_timing_info2
;
1950 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1951 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1952 // The load timing after restart should have a new socket ID, and times after
1953 // those of the first load timing.
1954 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1955 load_timing_info2
.connect_timing
.connect_start
);
1956 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1958 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1959 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1961 response
= trans
->GetResponseInfo();
1962 ASSERT_TRUE(response
!= NULL
);
1963 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1964 EXPECT_EQ(100, response
->headers
->GetContentLength());
1967 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1968 HttpRequestInfo request
;
1969 request
.method
= "GET";
1970 request
.url
= GURL("http://www.google.com/");
1971 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1973 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1974 scoped_ptr
<HttpTransaction
> trans(
1975 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1977 MockWrite data_writes
[] = {
1978 MockWrite("GET / HTTP/1.1\r\n"
1979 "Host: www.google.com\r\n"
1980 "Connection: keep-alive\r\n\r\n"),
1983 MockRead data_reads
[] = {
1984 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1985 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1987 // Large content-length -- won't matter, as connection will be reset.
1988 MockRead("Content-Length: 10000\r\n\r\n"),
1989 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1992 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1993 data_writes
, arraysize(data_writes
));
1994 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1995 TestCompletionCallback callback
;
1997 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1998 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2000 rv
= callback
.WaitForResult();
2003 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2004 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2006 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2007 ASSERT_TRUE(response
!= NULL
);
2008 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2011 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2013 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2014 HttpRequestInfo request
;
2015 request
.method
= "GET";
2016 request
.url
= GURL("http://www.google.com/");
2017 request
.load_flags
= 0;
2019 CapturingNetLog log
;
2020 session_deps_
.net_log
= &log
;
2021 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2023 MockWrite data_writes1
[] = {
2024 MockWrite("GET / HTTP/1.1\r\n"
2025 "Host: www.google.com\r\n"
2026 "Connection: keep-alive\r\n\r\n"),
2028 // After calling trans->RestartWithAuth(), this is the request we should
2029 // be issuing -- the final header line contains the credentials.
2030 MockWrite("GET / HTTP/1.1\r\n"
2031 "Host: www.google.com\r\n"
2032 "Connection: keep-alive\r\n"
2033 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2036 MockRead data_reads1
[] = {
2037 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2038 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2039 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2040 MockRead("Content-Length: 14\r\n\r\n"),
2041 MockRead("Unauthorized\r\n"),
2043 // Lastly, the server responds with the actual content.
2044 MockRead("HTTP/1.1 200 OK\r\n"),
2045 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2046 MockRead("Content-Length: 5\r\n\r\n"),
2050 // If there is a regression where we disconnect a Keep-Alive
2051 // connection during an auth roundtrip, we'll end up reading this.
2052 MockRead data_reads2
[] = {
2053 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2056 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2057 data_writes1
, arraysize(data_writes1
));
2058 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2060 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2061 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2063 TestCompletionCallback callback1
;
2065 scoped_ptr
<HttpTransaction
> trans(
2066 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2067 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2068 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2070 rv
= callback1
.WaitForResult();
2073 LoadTimingInfo load_timing_info1
;
2074 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2075 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2077 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2078 ASSERT_TRUE(response
!= NULL
);
2079 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2081 TestCompletionCallback callback2
;
2083 rv
= trans
->RestartWithAuth(
2084 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2087 rv
= callback2
.WaitForResult();
2090 LoadTimingInfo load_timing_info2
;
2091 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2092 TestLoadTimingReused(load_timing_info2
);
2093 // The load timing after restart should have the same socket ID, and times
2094 // those of the first load timing.
2095 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2096 load_timing_info2
.send_start
);
2097 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2099 response
= trans
->GetResponseInfo();
2100 ASSERT_TRUE(response
!= NULL
);
2101 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2102 EXPECT_EQ(5, response
->headers
->GetContentLength());
2104 std::string response_data
;
2105 rv
= ReadTransaction(trans
.get(), &response_data
);
2107 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2108 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2111 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2112 // connection and with no response body to drain.
2113 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2114 HttpRequestInfo request
;
2115 request
.method
= "GET";
2116 request
.url
= GURL("http://www.google.com/");
2117 request
.load_flags
= 0;
2119 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2121 MockWrite data_writes1
[] = {
2122 MockWrite("GET / HTTP/1.1\r\n"
2123 "Host: www.google.com\r\n"
2124 "Connection: keep-alive\r\n\r\n"),
2126 // After calling trans->RestartWithAuth(), this is the request we should
2127 // be issuing -- the final header line contains the credentials.
2128 MockWrite("GET / HTTP/1.1\r\n"
2129 "Host: www.google.com\r\n"
2130 "Connection: keep-alive\r\n"
2131 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2134 MockRead data_reads1
[] = {
2135 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2136 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2137 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2139 // Lastly, the server responds with the actual content.
2140 MockRead("HTTP/1.1 200 OK\r\n"),
2141 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2142 MockRead("Content-Length: 5\r\n\r\n"),
2146 // An incorrect reconnect would cause this to be read.
2147 MockRead data_reads2
[] = {
2148 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2151 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2152 data_writes1
, arraysize(data_writes1
));
2153 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2155 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2156 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2158 TestCompletionCallback callback1
;
2160 scoped_ptr
<HttpTransaction
> trans(
2161 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2162 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2163 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2165 rv
= callback1
.WaitForResult();
2168 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2169 ASSERT_TRUE(response
!= NULL
);
2170 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2172 TestCompletionCallback callback2
;
2174 rv
= trans
->RestartWithAuth(
2175 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2176 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2178 rv
= callback2
.WaitForResult();
2181 response
= trans
->GetResponseInfo();
2182 ASSERT_TRUE(response
!= NULL
);
2183 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2184 EXPECT_EQ(5, response
->headers
->GetContentLength());
2187 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2188 // connection and with a large response body to drain.
2189 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2190 HttpRequestInfo request
;
2191 request
.method
= "GET";
2192 request
.url
= GURL("http://www.google.com/");
2193 request
.load_flags
= 0;
2195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2197 MockWrite data_writes1
[] = {
2198 MockWrite("GET / HTTP/1.1\r\n"
2199 "Host: www.google.com\r\n"
2200 "Connection: keep-alive\r\n\r\n"),
2202 // After calling trans->RestartWithAuth(), this is the request we should
2203 // be issuing -- the final header line contains the credentials.
2204 MockWrite("GET / HTTP/1.1\r\n"
2205 "Host: www.google.com\r\n"
2206 "Connection: keep-alive\r\n"
2207 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2210 // Respond with 5 kb of response body.
2211 std::string
large_body_string("Unauthorized");
2212 large_body_string
.append(5 * 1024, ' ');
2213 large_body_string
.append("\r\n");
2215 MockRead data_reads1
[] = {
2216 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2217 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2218 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2219 // 5134 = 12 + 5 * 1024 + 2
2220 MockRead("Content-Length: 5134\r\n\r\n"),
2221 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2223 // Lastly, the server responds with the actual content.
2224 MockRead("HTTP/1.1 200 OK\r\n"),
2225 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2226 MockRead("Content-Length: 5\r\n\r\n"),
2230 // An incorrect reconnect would cause this to be read.
2231 MockRead data_reads2
[] = {
2232 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2235 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2236 data_writes1
, arraysize(data_writes1
));
2237 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2239 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2240 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2242 TestCompletionCallback callback1
;
2244 scoped_ptr
<HttpTransaction
> trans(
2245 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2246 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2247 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2249 rv
= callback1
.WaitForResult();
2252 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2253 ASSERT_TRUE(response
!= NULL
);
2254 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2256 TestCompletionCallback callback2
;
2258 rv
= trans
->RestartWithAuth(
2259 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2260 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2262 rv
= callback2
.WaitForResult();
2265 response
= trans
->GetResponseInfo();
2266 ASSERT_TRUE(response
!= NULL
);
2267 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2268 EXPECT_EQ(5, response
->headers
->GetContentLength());
2271 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2272 // connection, but the server gets impatient and closes the connection.
2273 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2274 HttpRequestInfo request
;
2275 request
.method
= "GET";
2276 request
.url
= GURL("http://www.google.com/");
2277 request
.load_flags
= 0;
2279 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2281 MockWrite data_writes1
[] = {
2282 MockWrite("GET / HTTP/1.1\r\n"
2283 "Host: www.google.com\r\n"
2284 "Connection: keep-alive\r\n\r\n"),
2285 // This simulates the seemingly successful write to a closed connection
2286 // if the bug is not fixed.
2287 MockWrite("GET / HTTP/1.1\r\n"
2288 "Host: www.google.com\r\n"
2289 "Connection: keep-alive\r\n"
2290 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2293 MockRead data_reads1
[] = {
2294 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2295 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2296 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2297 MockRead("Content-Length: 14\r\n\r\n"),
2298 // Tell MockTCPClientSocket to simulate the server closing the connection.
2299 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2300 MockRead("Unauthorized\r\n"),
2301 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2304 // After calling trans->RestartWithAuth(), this is the request we should
2305 // be issuing -- the final header line contains the credentials.
2306 MockWrite data_writes2
[] = {
2307 MockWrite("GET / HTTP/1.1\r\n"
2308 "Host: www.google.com\r\n"
2309 "Connection: keep-alive\r\n"
2310 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2313 // Lastly, the server responds with the actual content.
2314 MockRead data_reads2
[] = {
2315 MockRead("HTTP/1.1 200 OK\r\n"),
2316 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2317 MockRead("Content-Length: 5\r\n\r\n"),
2321 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2322 data_writes1
, arraysize(data_writes1
));
2323 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2324 data_writes2
, arraysize(data_writes2
));
2325 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2326 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2328 TestCompletionCallback callback1
;
2330 scoped_ptr
<HttpTransaction
> trans(
2331 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2332 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2333 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2335 rv
= callback1
.WaitForResult();
2338 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2339 ASSERT_TRUE(response
!= NULL
);
2340 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2342 TestCompletionCallback callback2
;
2344 rv
= trans
->RestartWithAuth(
2345 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2346 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2348 rv
= callback2
.WaitForResult();
2351 response
= trans
->GetResponseInfo();
2352 ASSERT_TRUE(response
!= NULL
);
2353 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2354 EXPECT_EQ(5, response
->headers
->GetContentLength());
2357 // Test the request-challenge-retry sequence for basic auth, over a connection
2358 // that requires a restart when setting up an SSL tunnel.
2359 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
2360 HttpRequestInfo request
;
2361 request
.method
= "GET";
2362 request
.url
= GURL("https://www.google.com/");
2363 // when the no authentication data flag is set.
2364 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2366 // Configure against proxy server "myproxy:70".
2367 session_deps_
.proxy_service
.reset(
2368 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2369 CapturingBoundNetLog log
;
2370 session_deps_
.net_log
= log
.bound().net_log();
2371 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2373 // Since we have proxy, should try to establish tunnel.
2374 MockWrite data_writes1
[] = {
2375 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2376 "Host: www.google.com\r\n"
2377 "Proxy-Connection: keep-alive\r\n\r\n"),
2379 // After calling trans->RestartWithAuth(), this is the request we should
2380 // be issuing -- the final header line contains the credentials.
2381 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2382 "Host: www.google.com\r\n"
2383 "Proxy-Connection: keep-alive\r\n"
2384 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2386 MockWrite("GET / HTTP/1.1\r\n"
2387 "Host: www.google.com\r\n"
2388 "Connection: keep-alive\r\n\r\n"),
2391 // The proxy responds to the connect with a 407, using a persistent
2393 MockRead data_reads1
[] = {
2395 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2396 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2397 MockRead("Proxy-Connection: close\r\n\r\n"),
2399 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2401 MockRead("HTTP/1.1 200 OK\r\n"),
2402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2403 MockRead("Content-Length: 5\r\n\r\n"),
2404 MockRead(SYNCHRONOUS
, "hello"),
2407 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2408 data_writes1
, arraysize(data_writes1
));
2409 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2410 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2411 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2413 TestCompletionCallback callback1
;
2415 scoped_ptr
<HttpTransaction
> trans(
2416 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2418 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2419 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2421 rv
= callback1
.WaitForResult();
2423 net::CapturingNetLog::CapturedEntryList entries
;
2424 log
.GetEntries(&entries
);
2425 size_t pos
= ExpectLogContainsSomewhere(
2426 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2427 NetLog::PHASE_NONE
);
2428 ExpectLogContainsSomewhere(
2430 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2431 NetLog::PHASE_NONE
);
2433 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2434 ASSERT_TRUE(response
!= NULL
);
2435 ASSERT_FALSE(response
->headers
.get() == NULL
);
2436 EXPECT_EQ(407, response
->headers
->response_code());
2437 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2438 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2440 LoadTimingInfo load_timing_info
;
2441 // CONNECT requests and responses are handled at the connect job level, so
2442 // the transaction does not yet have a connection.
2443 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2445 TestCompletionCallback callback2
;
2447 rv
= trans
->RestartWithAuth(
2448 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2449 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2451 rv
= callback2
.WaitForResult();
2454 response
= trans
->GetResponseInfo();
2455 ASSERT_TRUE(response
!= NULL
);
2457 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2458 EXPECT_EQ(200, response
->headers
->response_code());
2459 EXPECT_EQ(5, response
->headers
->GetContentLength());
2460 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2462 // The password prompt info should not be set.
2463 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2465 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2466 TestLoadTimingNotReusedWithPac(load_timing_info
,
2467 CONNECT_TIMING_HAS_SSL_TIMES
);
2470 session
->CloseAllConnections();
2473 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2474 // proxy connection, when setting up an SSL tunnel.
2475 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2476 HttpRequestInfo request
;
2477 request
.method
= "GET";
2478 request
.url
= GURL("https://www.google.com/");
2479 // Ensure that proxy authentication is attempted even
2480 // when the no authentication data flag is set.
2481 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2483 // Configure against proxy server "myproxy:70".
2484 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2485 CapturingBoundNetLog log
;
2486 session_deps_
.net_log
= log
.bound().net_log();
2487 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2489 scoped_ptr
<HttpTransaction
> trans(
2490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2492 // Since we have proxy, should try to establish tunnel.
2493 MockWrite data_writes1
[] = {
2494 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2495 "Host: www.google.com\r\n"
2496 "Proxy-Connection: keep-alive\r\n\r\n"),
2498 // After calling trans->RestartWithAuth(), this is the request we should
2499 // be issuing -- the final header line contains the credentials.
2500 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2501 "Host: www.google.com\r\n"
2502 "Proxy-Connection: keep-alive\r\n"
2503 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2506 // The proxy responds to the connect with a 407, using a persistent
2508 MockRead data_reads1
[] = {
2510 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2511 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2512 MockRead("Content-Length: 10\r\n\r\n"),
2513 MockRead("0123456789"),
2515 // Wrong credentials (wrong password).
2516 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2517 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2518 MockRead("Content-Length: 10\r\n\r\n"),
2519 // No response body because the test stops reading here.
2520 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2523 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2524 data_writes1
, arraysize(data_writes1
));
2525 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2527 TestCompletionCallback callback1
;
2529 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2530 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2532 rv
= callback1
.WaitForResult();
2534 net::CapturingNetLog::CapturedEntryList entries
;
2535 log
.GetEntries(&entries
);
2536 size_t pos
= ExpectLogContainsSomewhere(
2537 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2538 NetLog::PHASE_NONE
);
2539 ExpectLogContainsSomewhere(
2541 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2542 NetLog::PHASE_NONE
);
2544 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2545 ASSERT_TRUE(response
!= NULL
);
2546 ASSERT_FALSE(response
->headers
.get() == NULL
);
2547 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2548 EXPECT_EQ(407, response
->headers
->response_code());
2549 EXPECT_EQ(10, response
->headers
->GetContentLength());
2550 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2551 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2553 TestCompletionCallback callback2
;
2555 // Wrong password (should be "bar").
2556 rv
= trans
->RestartWithAuth(
2557 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2560 rv
= callback2
.WaitForResult();
2563 response
= trans
->GetResponseInfo();
2564 ASSERT_TRUE(response
!= NULL
);
2565 ASSERT_FALSE(response
->headers
.get() == NULL
);
2566 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2567 EXPECT_EQ(407, response
->headers
->response_code());
2568 EXPECT_EQ(10, response
->headers
->GetContentLength());
2569 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2570 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2572 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2574 session
->CloseAllConnections();
2577 // Test that we don't read the response body when we fail to establish a tunnel,
2578 // even if the user cancels the proxy's auth attempt.
2579 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2580 HttpRequestInfo request
;
2581 request
.method
= "GET";
2582 request
.url
= GURL("https://www.google.com/");
2583 request
.load_flags
= 0;
2585 // Configure against proxy server "myproxy:70".
2586 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2588 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2590 scoped_ptr
<HttpTransaction
> trans(
2591 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2593 // Since we have proxy, should try to establish tunnel.
2594 MockWrite data_writes
[] = {
2595 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2596 "Host: www.google.com\r\n"
2597 "Proxy-Connection: keep-alive\r\n\r\n"),
2600 // The proxy responds to the connect with a 407.
2601 MockRead data_reads
[] = {
2602 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2603 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2604 MockRead("Content-Length: 10\r\n\r\n"),
2605 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2608 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2609 data_writes
, arraysize(data_writes
));
2610 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2612 TestCompletionCallback callback
;
2614 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2615 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2617 rv
= callback
.WaitForResult();
2620 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2621 ASSERT_TRUE(response
!= NULL
);
2623 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2624 EXPECT_EQ(407, response
->headers
->response_code());
2625 EXPECT_EQ(10, response
->headers
->GetContentLength());
2626 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2628 std::string response_data
;
2629 rv
= ReadTransaction(trans
.get(), &response_data
);
2630 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2632 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2633 session
->CloseAllConnections();
2636 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2637 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2638 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2639 HttpRequestInfo request
;
2640 request
.method
= "GET";
2641 request
.url
= GURL("http://www.google.com/");
2642 request
.load_flags
= 0;
2644 // We are using a DIRECT connection (i.e. no proxy) for this session.
2645 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2646 scoped_ptr
<HttpTransaction
> trans(
2647 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
2649 MockWrite data_writes1
[] = {
2650 MockWrite("GET / HTTP/1.1\r\n"
2651 "Host: www.google.com\r\n"
2652 "Connection: keep-alive\r\n\r\n"),
2655 MockRead data_reads1
[] = {
2656 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2657 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2658 // Large content-length -- won't matter, as connection will be reset.
2659 MockRead("Content-Length: 10000\r\n\r\n"),
2660 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2663 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2664 data_writes1
, arraysize(data_writes1
));
2665 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2667 TestCompletionCallback callback
;
2669 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2670 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2672 rv
= callback
.WaitForResult();
2673 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2676 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2677 // through a non-authenticating proxy. The request should fail with
2678 // ERR_UNEXPECTED_PROXY_AUTH.
2679 // Note that it is impossible to detect if an HTTP server returns a 407 through
2680 // a non-authenticating proxy - there is nothing to indicate whether the
2681 // response came from the proxy or the server, so it is treated as if the proxy
2682 // issued the challenge.
2683 TEST_P(HttpNetworkTransactionTest
,
2684 HttpsServerRequestsProxyAuthThroughProxy
) {
2685 HttpRequestInfo request
;
2686 request
.method
= "GET";
2687 request
.url
= GURL("https://www.google.com/");
2689 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2690 CapturingBoundNetLog log
;
2691 session_deps_
.net_log
= log
.bound().net_log();
2692 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2694 // Since we have proxy, should try to establish tunnel.
2695 MockWrite data_writes1
[] = {
2696 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2697 "Host: www.google.com\r\n"
2698 "Proxy-Connection: keep-alive\r\n\r\n"),
2700 MockWrite("GET / HTTP/1.1\r\n"
2701 "Host: www.google.com\r\n"
2702 "Connection: keep-alive\r\n\r\n"),
2705 MockRead data_reads1
[] = {
2706 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2708 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2709 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2711 MockRead(SYNCHRONOUS
, OK
),
2714 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2715 data_writes1
, arraysize(data_writes1
));
2716 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2717 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2718 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2720 TestCompletionCallback callback1
;
2722 scoped_ptr
<HttpTransaction
> trans(
2723 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2725 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2726 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2728 rv
= callback1
.WaitForResult();
2729 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2730 net::CapturingNetLog::CapturedEntryList entries
;
2731 log
.GetEntries(&entries
);
2732 size_t pos
= ExpectLogContainsSomewhere(
2733 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2734 NetLog::PHASE_NONE
);
2735 ExpectLogContainsSomewhere(
2737 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2738 NetLog::PHASE_NONE
);
2741 // Test the load timing for HTTPS requests with an HTTP proxy.
2742 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2743 HttpRequestInfo request1
;
2744 request1
.method
= "GET";
2745 request1
.url
= GURL("https://www.google.com/1");
2747 HttpRequestInfo request2
;
2748 request2
.method
= "GET";
2749 request2
.url
= GURL("https://www.google.com/2");
2751 // Configure against proxy server "myproxy:70".
2752 session_deps_
.proxy_service
.reset(
2753 ProxyService::CreateFixed("PROXY myproxy:70"));
2754 CapturingBoundNetLog log
;
2755 session_deps_
.net_log
= log
.bound().net_log();
2756 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2758 // Since we have proxy, should try to establish tunnel.
2759 MockWrite data_writes1
[] = {
2760 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2761 "Host: www.google.com\r\n"
2762 "Proxy-Connection: keep-alive\r\n\r\n"),
2764 MockWrite("GET /1 HTTP/1.1\r\n"
2765 "Host: www.google.com\r\n"
2766 "Connection: keep-alive\r\n\r\n"),
2768 MockWrite("GET /2 HTTP/1.1\r\n"
2769 "Host: www.google.com\r\n"
2770 "Connection: keep-alive\r\n\r\n"),
2773 // The proxy responds to the connect with a 407, using a persistent
2775 MockRead data_reads1
[] = {
2776 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2778 MockRead("HTTP/1.1 200 OK\r\n"),
2779 MockRead("Content-Length: 1\r\n\r\n"),
2780 MockRead(SYNCHRONOUS
, "1"),
2782 MockRead("HTTP/1.1 200 OK\r\n"),
2783 MockRead("Content-Length: 2\r\n\r\n"),
2784 MockRead(SYNCHRONOUS
, "22"),
2787 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2788 data_writes1
, arraysize(data_writes1
));
2789 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2790 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2791 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2793 TestCompletionCallback callback1
;
2794 scoped_ptr
<HttpTransaction
> trans1(
2795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2797 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2798 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2800 rv
= callback1
.WaitForResult();
2803 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2804 ASSERT_TRUE(response1
!= NULL
);
2805 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2806 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2808 LoadTimingInfo load_timing_info1
;
2809 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2810 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2814 TestCompletionCallback callback2
;
2815 scoped_ptr
<HttpTransaction
> trans2(
2816 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2818 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2821 rv
= callback2
.WaitForResult();
2824 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2825 ASSERT_TRUE(response2
!= NULL
);
2826 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2827 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2829 LoadTimingInfo load_timing_info2
;
2830 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2831 TestLoadTimingReused(load_timing_info2
);
2833 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2836 session
->CloseAllConnections();
2839 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2840 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2841 HttpRequestInfo request1
;
2842 request1
.method
= "GET";
2843 request1
.url
= GURL("https://www.google.com/1");
2845 HttpRequestInfo request2
;
2846 request2
.method
= "GET";
2847 request2
.url
= GURL("https://www.google.com/2");
2849 // Configure against proxy server "myproxy:70".
2850 session_deps_
.proxy_service
.reset(
2851 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2852 CapturingBoundNetLog log
;
2853 session_deps_
.net_log
= log
.bound().net_log();
2854 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2856 // Since we have proxy, should try to establish tunnel.
2857 MockWrite data_writes1
[] = {
2858 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2859 "Host: www.google.com\r\n"
2860 "Proxy-Connection: keep-alive\r\n\r\n"),
2862 MockWrite("GET /1 HTTP/1.1\r\n"
2863 "Host: www.google.com\r\n"
2864 "Connection: keep-alive\r\n\r\n"),
2866 MockWrite("GET /2 HTTP/1.1\r\n"
2867 "Host: www.google.com\r\n"
2868 "Connection: keep-alive\r\n\r\n"),
2871 // The proxy responds to the connect with a 407, using a persistent
2873 MockRead data_reads1
[] = {
2874 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2876 MockRead("HTTP/1.1 200 OK\r\n"),
2877 MockRead("Content-Length: 1\r\n\r\n"),
2878 MockRead(SYNCHRONOUS
, "1"),
2880 MockRead("HTTP/1.1 200 OK\r\n"),
2881 MockRead("Content-Length: 2\r\n\r\n"),
2882 MockRead(SYNCHRONOUS
, "22"),
2885 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2886 data_writes1
, arraysize(data_writes1
));
2887 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2888 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2889 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2891 TestCompletionCallback callback1
;
2892 scoped_ptr
<HttpTransaction
> trans1(
2893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2895 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2896 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2898 rv
= callback1
.WaitForResult();
2901 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2902 ASSERT_TRUE(response1
!= NULL
);
2903 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2904 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2906 LoadTimingInfo load_timing_info1
;
2907 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2908 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2909 CONNECT_TIMING_HAS_SSL_TIMES
);
2913 TestCompletionCallback callback2
;
2914 scoped_ptr
<HttpTransaction
> trans2(
2915 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2917 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2918 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2920 rv
= callback2
.WaitForResult();
2923 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2924 ASSERT_TRUE(response2
!= NULL
);
2925 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2926 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2928 LoadTimingInfo load_timing_info2
;
2929 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2930 TestLoadTimingReusedWithPac(load_timing_info2
);
2932 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2935 session
->CloseAllConnections();
2938 // Test a simple get through an HTTPS Proxy.
2939 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2940 HttpRequestInfo request
;
2941 request
.method
= "GET";
2942 request
.url
= GURL("http://www.google.com/");
2944 // Configure against https proxy server "proxy:70".
2945 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2946 "https://proxy:70"));
2947 CapturingBoundNetLog log
;
2948 session_deps_
.net_log
= log
.bound().net_log();
2949 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2951 // Since we have proxy, should use full url
2952 MockWrite data_writes1
[] = {
2953 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2954 "Host: www.google.com\r\n"
2955 "Proxy-Connection: keep-alive\r\n\r\n"),
2958 MockRead data_reads1
[] = {
2959 MockRead("HTTP/1.1 200 OK\r\n"),
2960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2961 MockRead("Content-Length: 100\r\n\r\n"),
2962 MockRead(SYNCHRONOUS
, OK
),
2965 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2966 data_writes1
, arraysize(data_writes1
));
2967 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2968 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2969 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2971 TestCompletionCallback callback1
;
2973 scoped_ptr
<HttpTransaction
> trans(
2974 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2976 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2977 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2979 rv
= callback1
.WaitForResult();
2982 LoadTimingInfo load_timing_info
;
2983 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2984 TestLoadTimingNotReused(load_timing_info
,
2985 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2987 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2988 ASSERT_TRUE(response
!= NULL
);
2990 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2991 EXPECT_EQ(200, response
->headers
->response_code());
2992 EXPECT_EQ(100, response
->headers
->GetContentLength());
2993 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2995 // The password prompt info should not be set.
2996 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2999 // Test a SPDY get through an HTTPS Proxy.
3000 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3001 HttpRequestInfo request
;
3002 request
.method
= "GET";
3003 request
.url
= GURL("http://www.google.com/");
3004 request
.load_flags
= 0;
3006 // Configure against https proxy server "proxy:70".
3007 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3008 "https://proxy:70"));
3009 CapturingBoundNetLog log
;
3010 session_deps_
.net_log
= log
.bound().net_log();
3011 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3013 // fetch http://www.google.com/ via SPDY
3014 scoped_ptr
<SpdyFrame
> req(
3015 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3016 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
3018 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3019 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3020 MockRead spdy_reads
[] = {
3021 CreateMockRead(*resp
),
3022 CreateMockRead(*data
),
3023 MockRead(ASYNC
, 0, 0),
3026 DelayedSocketData
spdy_data(
3027 1, // wait for one write to finish before reading.
3028 spdy_reads
, arraysize(spdy_reads
),
3029 spdy_writes
, arraysize(spdy_writes
));
3030 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3032 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3033 ssl
.SetNextProto(GetParam());
3034 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3036 TestCompletionCallback callback1
;
3038 scoped_ptr
<HttpTransaction
> trans(
3039 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3041 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3044 rv
= callback1
.WaitForResult();
3047 LoadTimingInfo load_timing_info
;
3048 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3049 TestLoadTimingNotReused(load_timing_info
,
3050 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3052 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3053 ASSERT_TRUE(response
!= NULL
);
3054 ASSERT_TRUE(response
->headers
.get() != NULL
);
3055 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3057 std::string response_data
;
3058 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3059 EXPECT_EQ(kUploadData
, response_data
);
3062 // Verifies that a session which races and wins against the owning transaction
3063 // (completing prior to host resolution), doesn't fail the transaction.
3064 // Regression test for crbug.com/334413.
3065 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3066 HttpRequestInfo request
;
3067 request
.method
= "GET";
3068 request
.url
= GURL("http://www.google.com/");
3069 request
.load_flags
= 0;
3071 // Configure SPDY proxy server "proxy:70".
3072 session_deps_
.proxy_service
.reset(
3073 ProxyService::CreateFixed("https://proxy:70"));
3074 CapturingBoundNetLog log
;
3075 session_deps_
.net_log
= log
.bound().net_log();
3076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3078 // Fetch http://www.google.com/ through the SPDY proxy.
3079 scoped_ptr
<SpdyFrame
> req(
3080 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3081 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3083 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3084 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3085 MockRead spdy_reads
[] = {
3086 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3089 DelayedSocketData
spdy_data(
3090 1, // wait for one write to finish before reading.
3092 arraysize(spdy_reads
),
3094 arraysize(spdy_writes
));
3095 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3097 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3098 ssl
.SetNextProto(GetParam());
3099 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3101 TestCompletionCallback callback1
;
3103 scoped_ptr
<HttpTransaction
> trans(
3104 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3106 // Stall the hostname resolution begun by the transaction.
3107 session_deps_
.host_resolver
->set_synchronous_mode(false);
3108 session_deps_
.host_resolver
->set_ondemand_mode(true);
3110 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3111 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3113 // Race a session to the proxy, which completes first.
3114 session_deps_
.host_resolver
->set_ondemand_mode(false);
3116 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3117 base::WeakPtr
<SpdySession
> spdy_session
=
3118 CreateSecureSpdySession(session
, key
, log
.bound());
3120 // Unstall the resolution begun by the transaction.
3121 session_deps_
.host_resolver
->set_ondemand_mode(true);
3122 session_deps_
.host_resolver
->ResolveAllPending();
3124 EXPECT_FALSE(callback1
.have_result());
3125 rv
= callback1
.WaitForResult();
3128 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3129 ASSERT_TRUE(response
!= NULL
);
3130 ASSERT_TRUE(response
->headers
.get() != NULL
);
3131 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3133 std::string response_data
;
3134 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3135 EXPECT_EQ(kUploadData
, response_data
);
3138 // Test a SPDY get through an HTTPS Proxy.
3139 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3140 HttpRequestInfo request
;
3141 request
.method
= "GET";
3142 request
.url
= GURL("http://www.google.com/");
3143 request
.load_flags
= 0;
3145 // Configure against https proxy server "myproxy:70".
3146 session_deps_
.proxy_service
.reset(
3147 ProxyService::CreateFixed("https://myproxy:70"));
3148 CapturingBoundNetLog log
;
3149 session_deps_
.net_log
= log
.bound().net_log();
3150 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3152 // The first request will be a bare GET, the second request will be a
3153 // GET with a Proxy-Authorization header.
3154 scoped_ptr
<SpdyFrame
> req_get(
3155 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3156 const char* const kExtraAuthorizationHeaders
[] = {
3157 "proxy-authorization", "Basic Zm9vOmJhcg=="
3159 scoped_ptr
<SpdyFrame
> req_get_authorization(
3160 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3161 arraysize(kExtraAuthorizationHeaders
) / 2,
3166 MockWrite spdy_writes
[] = {
3167 CreateMockWrite(*req_get
, 1),
3168 CreateMockWrite(*req_get_authorization
, 4),
3171 // The first response is a 407 proxy authentication challenge, and the second
3172 // response will be a 200 response since the second request includes a valid
3173 // Authorization header.
3174 const char* const kExtraAuthenticationHeaders
[] = {
3175 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3177 scoped_ptr
<SpdyFrame
> resp_authentication(
3178 spdy_util_
.ConstructSpdySynReplyError(
3179 "407 Proxy Authentication Required",
3180 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3182 scoped_ptr
<SpdyFrame
> body_authentication(
3183 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3184 scoped_ptr
<SpdyFrame
> resp_data(
3185 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3186 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3187 MockRead spdy_reads
[] = {
3188 CreateMockRead(*resp_authentication
, 2),
3189 CreateMockRead(*body_authentication
, 3),
3190 CreateMockRead(*resp_data
, 5),
3191 CreateMockRead(*body_data
, 6),
3192 MockRead(ASYNC
, 0, 7),
3195 OrderedSocketData
data(
3196 spdy_reads
, arraysize(spdy_reads
),
3197 spdy_writes
, arraysize(spdy_writes
));
3198 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3200 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3201 ssl
.SetNextProto(GetParam());
3202 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3204 TestCompletionCallback callback1
;
3206 scoped_ptr
<HttpTransaction
> trans(
3207 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3209 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3212 rv
= callback1
.WaitForResult();
3215 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3217 ASSERT_TRUE(response
!= NULL
);
3218 ASSERT_TRUE(response
->headers
.get() != NULL
);
3219 EXPECT_EQ(407, response
->headers
->response_code());
3220 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3221 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3223 TestCompletionCallback callback2
;
3225 rv
= trans
->RestartWithAuth(
3226 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3229 rv
= callback2
.WaitForResult();
3232 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3234 ASSERT_TRUE(response_restart
!= NULL
);
3235 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3236 EXPECT_EQ(200, response_restart
->headers
->response_code());
3237 // The password prompt info should not be set.
3238 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3241 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3242 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3243 HttpRequestInfo request
;
3244 request
.method
= "GET";
3245 request
.url
= GURL("https://www.google.com/");
3246 request
.load_flags
= 0;
3248 // Configure against https proxy server "proxy:70".
3249 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3250 "https://proxy:70"));
3251 CapturingBoundNetLog log
;
3252 session_deps_
.net_log
= log
.bound().net_log();
3253 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3255 scoped_ptr
<HttpTransaction
> trans(
3256 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3258 // CONNECT to www.google.com:443 via SPDY
3259 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3261 // fetch https://www.google.com/ via HTTP
3263 const char get
[] = "GET / HTTP/1.1\r\n"
3264 "Host: www.google.com\r\n"
3265 "Connection: keep-alive\r\n\r\n";
3266 scoped_ptr
<SpdyFrame
> wrapped_get(
3267 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3268 scoped_ptr
<SpdyFrame
> conn_resp(
3269 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3270 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3271 "Content-Length: 10\r\n\r\n";
3272 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3273 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3274 scoped_ptr
<SpdyFrame
> wrapped_body(
3275 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3276 scoped_ptr
<SpdyFrame
> window_update(
3277 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3279 MockWrite spdy_writes
[] = {
3280 CreateMockWrite(*connect
, 1),
3281 CreateMockWrite(*wrapped_get
, 3),
3282 CreateMockWrite(*window_update
, 5),
3285 MockRead spdy_reads
[] = {
3286 CreateMockRead(*conn_resp
, 2, ASYNC
),
3287 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3288 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3289 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3290 MockRead(ASYNC
, 0, 8),
3293 OrderedSocketData
spdy_data(
3294 spdy_reads
, arraysize(spdy_reads
),
3295 spdy_writes
, arraysize(spdy_writes
));
3296 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3298 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3299 ssl
.SetNextProto(GetParam());
3300 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3301 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3302 ssl2
.was_npn_negotiated
= false;
3303 ssl2
.protocol_negotiated
= kProtoUnknown
;
3304 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3306 TestCompletionCallback callback1
;
3308 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3311 rv
= callback1
.WaitForResult();
3314 LoadTimingInfo load_timing_info
;
3315 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3316 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3318 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3319 ASSERT_TRUE(response
!= NULL
);
3320 ASSERT_TRUE(response
->headers
.get() != NULL
);
3321 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3323 std::string response_data
;
3324 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3325 EXPECT_EQ("1234567890", response_data
);
3328 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3329 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3330 HttpRequestInfo request
;
3331 request
.method
= "GET";
3332 request
.url
= GURL("https://www.google.com/");
3333 request
.load_flags
= 0;
3335 // Configure against https proxy server "proxy:70".
3336 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3337 "https://proxy:70"));
3338 CapturingBoundNetLog log
;
3339 session_deps_
.net_log
= log
.bound().net_log();
3340 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3342 scoped_ptr
<HttpTransaction
> trans(
3343 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3345 // CONNECT to www.google.com:443 via SPDY
3346 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3348 // fetch https://www.google.com/ via SPDY
3349 const char* const kMyUrl
= "https://www.google.com/";
3350 scoped_ptr
<SpdyFrame
> get(
3351 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3352 scoped_ptr
<SpdyFrame
> wrapped_get(
3353 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3354 scoped_ptr
<SpdyFrame
> conn_resp(
3355 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3356 scoped_ptr
<SpdyFrame
> get_resp(
3357 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3358 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3359 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3360 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3361 scoped_ptr
<SpdyFrame
> wrapped_body(
3362 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3363 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3364 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3365 scoped_ptr
<SpdyFrame
> window_update_body(
3366 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3368 MockWrite spdy_writes
[] = {
3369 CreateMockWrite(*connect
, 1),
3370 CreateMockWrite(*wrapped_get
, 3),
3371 CreateMockWrite(*window_update_get_resp
, 5),
3372 CreateMockWrite(*window_update_body
, 7),
3375 MockRead spdy_reads
[] = {
3376 CreateMockRead(*conn_resp
, 2, ASYNC
),
3377 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3378 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3379 MockRead(ASYNC
, 0, 8),
3382 OrderedSocketData
spdy_data(
3383 spdy_reads
, arraysize(spdy_reads
),
3384 spdy_writes
, arraysize(spdy_writes
));
3385 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3387 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3388 ssl
.SetNextProto(GetParam());
3389 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3390 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3391 ssl2
.SetNextProto(GetParam());
3392 ssl2
.protocol_negotiated
= GetParam();
3393 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3395 TestCompletionCallback callback1
;
3397 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3398 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3400 rv
= callback1
.WaitForResult();
3403 LoadTimingInfo load_timing_info
;
3404 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3405 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3407 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3408 ASSERT_TRUE(response
!= NULL
);
3409 ASSERT_TRUE(response
->headers
.get() != NULL
);
3410 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3412 std::string response_data
;
3413 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3414 EXPECT_EQ(kUploadData
, response_data
);
3417 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3418 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3419 HttpRequestInfo request
;
3420 request
.method
= "GET";
3421 request
.url
= GURL("https://www.google.com/");
3422 request
.load_flags
= 0;
3424 // Configure against https proxy server "proxy:70".
3425 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3426 "https://proxy:70"));
3427 CapturingBoundNetLog log
;
3428 session_deps_
.net_log
= log
.bound().net_log();
3429 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3431 scoped_ptr
<HttpTransaction
> trans(
3432 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3434 // CONNECT to www.google.com:443 via SPDY
3435 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3437 scoped_ptr
<SpdyFrame
> get(
3438 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3440 MockWrite spdy_writes
[] = {
3441 CreateMockWrite(*connect
, 1),
3442 CreateMockWrite(*get
, 3),
3445 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3446 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3447 MockRead spdy_reads
[] = {
3448 CreateMockRead(*resp
, 2, ASYNC
),
3449 MockRead(ASYNC
, 0, 4),
3452 OrderedSocketData
spdy_data(
3453 spdy_reads
, arraysize(spdy_reads
),
3454 spdy_writes
, arraysize(spdy_writes
));
3455 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3457 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3458 ssl
.SetNextProto(GetParam());
3459 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3460 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3461 ssl2
.SetNextProto(GetParam());
3462 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3464 TestCompletionCallback callback1
;
3466 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3467 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3469 rv
= callback1
.WaitForResult();
3470 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3472 // TODO(ttuttle): Anything else to check here?
3475 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3476 // HTTPS Proxy to different servers.
3477 TEST_P(HttpNetworkTransactionTest
,
3478 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3479 // Configure against https proxy server "proxy:70".
3480 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3481 "https://proxy:70"));
3482 CapturingBoundNetLog log
;
3483 session_deps_
.net_log
= log
.bound().net_log();
3484 scoped_refptr
<HttpNetworkSession
> session(
3485 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3487 HttpRequestInfo request1
;
3488 request1
.method
= "GET";
3489 request1
.url
= GURL("https://www.google.com/");
3490 request1
.load_flags
= 0;
3492 HttpRequestInfo request2
;
3493 request2
.method
= "GET";
3494 request2
.url
= GURL("https://news.google.com/");
3495 request2
.load_flags
= 0;
3497 // CONNECT to www.google.com:443 via SPDY.
3498 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3500 scoped_ptr
<SpdyFrame
> conn_resp1(
3501 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3503 // Fetch https://www.google.com/ via HTTP.
3504 const char get1
[] = "GET / HTTP/1.1\r\n"
3505 "Host: www.google.com\r\n"
3506 "Connection: keep-alive\r\n\r\n";
3507 scoped_ptr
<SpdyFrame
> wrapped_get1(
3508 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3509 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3510 "Content-Length: 1\r\n\r\n";
3511 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3512 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3513 scoped_ptr
<SpdyFrame
> wrapped_body1(
3514 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3515 scoped_ptr
<SpdyFrame
> window_update(
3516 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3518 // CONNECT to news.google.com:443 via SPDY.
3519 SpdyHeaderBlock connect2_block
;
3520 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3521 connect2_block
[spdy_util_
.GetPathKey()] = "news.google.com:443";
3522 connect2_block
[spdy_util_
.GetHostKey()] = "news.google.com";
3523 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3524 scoped_ptr
<SpdyFrame
> connect2(
3525 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3527 scoped_ptr
<SpdyFrame
> conn_resp2(
3528 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3530 // Fetch https://news.google.com/ via HTTP.
3531 const char get2
[] = "GET / HTTP/1.1\r\n"
3532 "Host: news.google.com\r\n"
3533 "Connection: keep-alive\r\n\r\n";
3534 scoped_ptr
<SpdyFrame
> wrapped_get2(
3535 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3536 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3537 "Content-Length: 2\r\n\r\n";
3538 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3539 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3540 scoped_ptr
<SpdyFrame
> wrapped_body2(
3541 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3543 MockWrite spdy_writes
[] = {
3544 CreateMockWrite(*connect1
, 0),
3545 CreateMockWrite(*wrapped_get1
, 2),
3546 CreateMockWrite(*connect2
, 5),
3547 CreateMockWrite(*wrapped_get2
, 7),
3550 MockRead spdy_reads
[] = {
3551 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3552 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3553 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3554 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3555 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3556 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3557 MockRead(ASYNC
, 0, 10),
3560 DeterministicSocketData
spdy_data(
3561 spdy_reads
, arraysize(spdy_reads
),
3562 spdy_writes
, arraysize(spdy_writes
));
3563 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3565 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3566 ssl
.SetNextProto(GetParam());
3567 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3568 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3569 ssl2
.was_npn_negotiated
= false;
3570 ssl2
.protocol_negotiated
= kProtoUnknown
;
3571 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3572 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3573 ssl3
.was_npn_negotiated
= false;
3574 ssl3
.protocol_negotiated
= kProtoUnknown
;
3575 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3577 TestCompletionCallback callback
;
3579 scoped_ptr
<HttpTransaction
> trans(
3580 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3581 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3583 // The first connect and request, each of their responses, and the body.
3584 spdy_data
.RunFor(5);
3586 rv
= callback
.WaitForResult();
3589 LoadTimingInfo load_timing_info
;
3590 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3591 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3593 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3594 ASSERT_TRUE(response
!= NULL
);
3595 ASSERT_TRUE(response
->headers
.get() != NULL
);
3596 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3598 std::string response_data
;
3599 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3600 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3602 scoped_ptr
<HttpTransaction
> trans2(
3603 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3604 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3605 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3607 // The second connect and request, each of their responses, and the body.
3608 spdy_data
.RunFor(5);
3609 rv
= callback
.WaitForResult();
3612 LoadTimingInfo load_timing_info2
;
3613 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3614 // Even though the SPDY connection is reused, a new tunnelled connection has
3615 // to be created, so the socket's load timing looks like a fresh connection.
3616 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3618 // The requests should have different IDs, since they each are using their own
3620 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3622 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3625 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3626 // HTTPS Proxy to the same server.
3627 TEST_P(HttpNetworkTransactionTest
,
3628 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3629 // Configure against https proxy server "proxy:70".
3630 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3631 "https://proxy:70"));
3632 CapturingBoundNetLog log
;
3633 session_deps_
.net_log
= log
.bound().net_log();
3634 scoped_refptr
<HttpNetworkSession
> session(
3635 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3637 HttpRequestInfo request1
;
3638 request1
.method
= "GET";
3639 request1
.url
= GURL("https://www.google.com/");
3640 request1
.load_flags
= 0;
3642 HttpRequestInfo request2
;
3643 request2
.method
= "GET";
3644 request2
.url
= GURL("https://www.google.com/2");
3645 request2
.load_flags
= 0;
3647 // CONNECT to www.google.com:443 via SPDY.
3648 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3650 scoped_ptr
<SpdyFrame
> conn_resp1(
3651 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3653 // Fetch https://www.google.com/ via HTTP.
3654 const char get1
[] = "GET / HTTP/1.1\r\n"
3655 "Host: www.google.com\r\n"
3656 "Connection: keep-alive\r\n\r\n";
3657 scoped_ptr
<SpdyFrame
> wrapped_get1(
3658 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3659 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3660 "Content-Length: 1\r\n\r\n";
3661 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3662 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3663 scoped_ptr
<SpdyFrame
> wrapped_body1(
3664 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3665 scoped_ptr
<SpdyFrame
> window_update(
3666 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3668 // Fetch https://www.google.com/2 via HTTP.
3669 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3670 "Host: www.google.com\r\n"
3671 "Connection: keep-alive\r\n\r\n";
3672 scoped_ptr
<SpdyFrame
> wrapped_get2(
3673 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3674 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3675 "Content-Length: 2\r\n\r\n";
3676 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3677 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3678 scoped_ptr
<SpdyFrame
> wrapped_body2(
3679 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3681 MockWrite spdy_writes
[] = {
3682 CreateMockWrite(*connect1
, 0),
3683 CreateMockWrite(*wrapped_get1
, 2),
3684 CreateMockWrite(*wrapped_get2
, 5),
3687 MockRead spdy_reads
[] = {
3688 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3689 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3690 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3691 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3692 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3693 MockRead(ASYNC
, 0, 8),
3696 DeterministicSocketData
spdy_data(
3697 spdy_reads
, arraysize(spdy_reads
),
3698 spdy_writes
, arraysize(spdy_writes
));
3699 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3701 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3702 ssl
.SetNextProto(GetParam());
3703 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3704 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3705 ssl2
.was_npn_negotiated
= false;
3706 ssl2
.protocol_negotiated
= kProtoUnknown
;
3707 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3709 TestCompletionCallback callback
;
3711 scoped_ptr
<HttpTransaction
> trans(
3712 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3713 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3715 // The first connect and request, each of their responses, and the body.
3716 spdy_data
.RunFor(5);
3718 rv
= callback
.WaitForResult();
3721 LoadTimingInfo load_timing_info
;
3722 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3723 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3725 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3726 ASSERT_TRUE(response
!= NULL
);
3727 ASSERT_TRUE(response
->headers
.get() != NULL
);
3728 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3730 std::string response_data
;
3731 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3732 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3735 scoped_ptr
<HttpTransaction
> trans2(
3736 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3737 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3738 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3740 // The second request, response, and body. There should not be a second
3742 spdy_data
.RunFor(3);
3743 rv
= callback
.WaitForResult();
3746 LoadTimingInfo load_timing_info2
;
3747 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3748 TestLoadTimingReused(load_timing_info2
);
3750 // The requests should have the same ID.
3751 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3753 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3756 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3757 // Proxy to different servers.
3758 TEST_P(HttpNetworkTransactionTest
,
3759 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3760 // Configure against https proxy server "proxy:70".
3761 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3762 "https://proxy:70"));
3763 CapturingBoundNetLog log
;
3764 session_deps_
.net_log
= log
.bound().net_log();
3765 scoped_refptr
<HttpNetworkSession
> session(
3766 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3768 HttpRequestInfo request1
;
3769 request1
.method
= "GET";
3770 request1
.url
= GURL("http://www.google.com/");
3771 request1
.load_flags
= 0;
3773 HttpRequestInfo request2
;
3774 request2
.method
= "GET";
3775 request2
.url
= GURL("http://news.google.com/");
3776 request2
.load_flags
= 0;
3778 // http://www.google.com/
3779 scoped_ptr
<SpdyHeaderBlock
> headers(
3780 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3781 scoped_ptr
<SpdyFrame
> get1(
3782 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
3783 scoped_ptr
<SpdyFrame
> get_resp1(
3784 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3785 scoped_ptr
<SpdyFrame
> body1(
3786 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3788 // http://news.google.com/
3789 scoped_ptr
<SpdyHeaderBlock
> headers2(
3790 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3791 scoped_ptr
<SpdyFrame
> get2(
3792 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
3793 scoped_ptr
<SpdyFrame
> get_resp2(
3794 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3795 scoped_ptr
<SpdyFrame
> body2(
3796 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3798 MockWrite spdy_writes
[] = {
3799 CreateMockWrite(*get1
, 0),
3800 CreateMockWrite(*get2
, 3),
3803 MockRead spdy_reads
[] = {
3804 CreateMockRead(*get_resp1
, 1, ASYNC
),
3805 CreateMockRead(*body1
, 2, ASYNC
),
3806 CreateMockRead(*get_resp2
, 4, ASYNC
),
3807 CreateMockRead(*body2
, 5, ASYNC
),
3808 MockRead(ASYNC
, 0, 6),
3811 DeterministicSocketData
spdy_data(
3812 spdy_reads
, arraysize(spdy_reads
),
3813 spdy_writes
, arraysize(spdy_writes
));
3814 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3816 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3817 ssl
.SetNextProto(GetParam());
3818 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3820 TestCompletionCallback callback
;
3822 scoped_ptr
<HttpTransaction
> trans(
3823 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3824 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3825 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3826 spdy_data
.RunFor(2);
3828 rv
= callback
.WaitForResult();
3831 LoadTimingInfo load_timing_info
;
3832 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3833 TestLoadTimingNotReused(load_timing_info
,
3834 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3836 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3837 ASSERT_TRUE(response
!= NULL
);
3838 ASSERT_TRUE(response
->headers
.get() != NULL
);
3839 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3841 std::string response_data
;
3842 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3843 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3844 spdy_data
.RunFor(1);
3845 EXPECT_EQ(1, callback
.WaitForResult());
3846 // Delete the first request, so the second one can reuse the socket.
3849 scoped_ptr
<HttpTransaction
> trans2(
3850 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3851 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3852 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3854 spdy_data
.RunFor(2);
3855 rv
= callback
.WaitForResult();
3858 LoadTimingInfo load_timing_info2
;
3859 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3860 TestLoadTimingReused(load_timing_info2
);
3862 // The requests should have the same ID.
3863 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3865 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3866 spdy_data
.RunFor(1);
3867 EXPECT_EQ(2, callback
.WaitForResult());
3870 // Test the challenge-response-retry sequence through an HTTPS Proxy
3871 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3872 HttpRequestInfo request
;
3873 request
.method
= "GET";
3874 request
.url
= GURL("http://www.google.com/");
3875 // when the no authentication data flag is set.
3876 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3878 // Configure against https proxy server "myproxy:70".
3879 session_deps_
.proxy_service
.reset(
3880 ProxyService::CreateFixed("https://myproxy:70"));
3881 CapturingBoundNetLog log
;
3882 session_deps_
.net_log
= log
.bound().net_log();
3883 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3885 // Since we have proxy, should use full url
3886 MockWrite data_writes1
[] = {
3887 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3888 "Host: www.google.com\r\n"
3889 "Proxy-Connection: keep-alive\r\n\r\n"),
3891 // After calling trans->RestartWithAuth(), this is the request we should
3892 // be issuing -- the final header line contains the credentials.
3893 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3894 "Host: www.google.com\r\n"
3895 "Proxy-Connection: keep-alive\r\n"
3896 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3899 // The proxy responds to the GET with a 407, using a persistent
3901 MockRead data_reads1
[] = {
3903 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3904 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3905 MockRead("Proxy-Connection: keep-alive\r\n"),
3906 MockRead("Content-Length: 0\r\n\r\n"),
3908 MockRead("HTTP/1.1 200 OK\r\n"),
3909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3910 MockRead("Content-Length: 100\r\n\r\n"),
3911 MockRead(SYNCHRONOUS
, OK
),
3914 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3915 data_writes1
, arraysize(data_writes1
));
3916 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3917 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3918 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3920 TestCompletionCallback callback1
;
3922 scoped_ptr
<HttpTransaction
> trans(
3923 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3925 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3928 rv
= callback1
.WaitForResult();
3931 LoadTimingInfo load_timing_info
;
3932 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3933 TestLoadTimingNotReused(load_timing_info
,
3934 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3936 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3937 ASSERT_TRUE(response
!= NULL
);
3938 ASSERT_FALSE(response
->headers
.get() == NULL
);
3939 EXPECT_EQ(407, response
->headers
->response_code());
3940 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3941 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3943 TestCompletionCallback callback2
;
3945 rv
= trans
->RestartWithAuth(
3946 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3947 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3949 rv
= callback2
.WaitForResult();
3952 load_timing_info
= LoadTimingInfo();
3953 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3954 // Retrying with HTTP AUTH is considered to be reusing a socket.
3955 TestLoadTimingReused(load_timing_info
);
3957 response
= trans
->GetResponseInfo();
3958 ASSERT_TRUE(response
!= NULL
);
3960 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3961 EXPECT_EQ(200, response
->headers
->response_code());
3962 EXPECT_EQ(100, response
->headers
->GetContentLength());
3963 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3965 // The password prompt info should not be set.
3966 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3969 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3970 const MockRead
& status
, int expected_status
) {
3971 HttpRequestInfo request
;
3972 request
.method
= "GET";
3973 request
.url
= GURL("https://www.google.com/");
3974 request
.load_flags
= 0;
3976 // Configure against proxy server "myproxy:70".
3977 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3978 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3980 // Since we have proxy, should try to establish tunnel.
3981 MockWrite data_writes
[] = {
3982 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3983 "Host: www.google.com\r\n"
3984 "Proxy-Connection: keep-alive\r\n\r\n"),
3987 MockRead data_reads
[] = {
3989 MockRead("Content-Length: 10\r\n\r\n"),
3990 // No response body because the test stops reading here.
3991 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3994 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3995 data_writes
, arraysize(data_writes
));
3996 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3998 TestCompletionCallback callback
;
4000 scoped_ptr
<HttpTransaction
> trans(
4001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4003 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4004 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4006 rv
= callback
.WaitForResult();
4007 EXPECT_EQ(expected_status
, rv
);
4010 void HttpNetworkTransactionTest::ConnectStatusHelper(
4011 const MockRead
& status
) {
4012 ConnectStatusHelperWithExpectedStatus(
4013 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4016 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4017 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4020 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4021 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4024 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4025 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4028 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4029 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4032 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4033 ConnectStatusHelper(
4034 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4037 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4038 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4041 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4042 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4045 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4046 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4049 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4050 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4053 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4054 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4057 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4058 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4061 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4062 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4065 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4066 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4069 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4070 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4073 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4074 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4077 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4078 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4081 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4082 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4085 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4086 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4089 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4090 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4093 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4094 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4097 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4098 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4101 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4102 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4105 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4106 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4109 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4110 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4113 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4114 ConnectStatusHelperWithExpectedStatus(
4115 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4116 ERR_PROXY_AUTH_UNSUPPORTED
);
4119 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4120 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4123 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4124 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4127 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4128 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4131 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4132 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4135 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4136 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4139 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4140 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4143 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4144 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4147 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4148 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4151 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4152 ConnectStatusHelper(
4153 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4156 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4157 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4160 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4161 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4164 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4165 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4168 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4169 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4172 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4173 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4176 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4177 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4180 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4181 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4184 // Test the flow when both the proxy server AND origin server require
4185 // authentication. Again, this uses basic auth for both since that is
4186 // the simplest to mock.
4187 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4188 HttpRequestInfo request
;
4189 request
.method
= "GET";
4190 request
.url
= GURL("http://www.google.com/");
4191 request
.load_flags
= 0;
4193 // Configure against proxy server "myproxy:70".
4194 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4197 scoped_ptr
<HttpTransaction
> trans(
4198 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4200 MockWrite data_writes1
[] = {
4201 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4202 "Host: www.google.com\r\n"
4203 "Proxy-Connection: keep-alive\r\n\r\n"),
4206 MockRead data_reads1
[] = {
4207 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4208 // Give a couple authenticate options (only the middle one is actually
4210 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4211 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4212 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4213 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4214 // Large content-length -- won't matter, as connection will be reset.
4215 MockRead("Content-Length: 10000\r\n\r\n"),
4216 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4219 // After calling trans->RestartWithAuth() the first time, this is the
4220 // request we should be issuing -- the final header line contains the
4221 // proxy's credentials.
4222 MockWrite data_writes2
[] = {
4223 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4224 "Host: www.google.com\r\n"
4225 "Proxy-Connection: keep-alive\r\n"
4226 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4229 // Now the proxy server lets the request pass through to origin server.
4230 // The origin server responds with a 401.
4231 MockRead data_reads2
[] = {
4232 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4233 // Note: We are using the same realm-name as the proxy server. This is
4234 // completely valid, as realms are unique across hosts.
4235 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4236 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4237 MockRead("Content-Length: 2000\r\n\r\n"),
4238 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4241 // After calling trans->RestartWithAuth() the second time, we should send
4242 // the credentials for both the proxy and origin server.
4243 MockWrite data_writes3
[] = {
4244 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4245 "Host: www.google.com\r\n"
4246 "Proxy-Connection: keep-alive\r\n"
4247 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4248 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4251 // Lastly we get the desired content.
4252 MockRead data_reads3
[] = {
4253 MockRead("HTTP/1.0 200 OK\r\n"),
4254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4255 MockRead("Content-Length: 100\r\n\r\n"),
4256 MockRead(SYNCHRONOUS
, OK
),
4259 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4260 data_writes1
, arraysize(data_writes1
));
4261 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4262 data_writes2
, arraysize(data_writes2
));
4263 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4264 data_writes3
, arraysize(data_writes3
));
4265 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4266 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4267 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4269 TestCompletionCallback callback1
;
4271 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4274 rv
= callback1
.WaitForResult();
4277 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4278 ASSERT_TRUE(response
!= NULL
);
4279 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4281 TestCompletionCallback callback2
;
4283 rv
= trans
->RestartWithAuth(
4284 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4285 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4287 rv
= callback2
.WaitForResult();
4290 response
= trans
->GetResponseInfo();
4291 ASSERT_TRUE(response
!= NULL
);
4292 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4294 TestCompletionCallback callback3
;
4296 rv
= trans
->RestartWithAuth(
4297 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4298 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4300 rv
= callback3
.WaitForResult();
4303 response
= trans
->GetResponseInfo();
4304 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4305 EXPECT_EQ(100, response
->headers
->GetContentLength());
4308 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4309 // can't hook into its internals to cause it to generate predictable NTLM
4310 // authorization headers.
4311 #if defined(NTLM_PORTABLE)
4312 // The NTLM authentication unit tests were generated by capturing the HTTP
4313 // requests and responses using Fiddler 2 and inspecting the generated random
4314 // bytes in the debugger.
4316 // Enter the correct password and authenticate successfully.
4317 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4318 HttpRequestInfo request
;
4319 request
.method
= "GET";
4320 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4322 // Ensure load is not disrupted by flags which suppress behaviour specific
4323 // to other auth schemes.
4324 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4326 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4328 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4330 MockWrite data_writes1
[] = {
4331 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4332 "Host: 172.22.68.17\r\n"
4333 "Connection: keep-alive\r\n\r\n"),
4336 MockRead data_reads1
[] = {
4337 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4338 // Negotiate and NTLM are often requested together. However, we only want
4339 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4340 // the header that requests Negotiate for this test.
4341 MockRead("WWW-Authenticate: NTLM\r\n"),
4342 MockRead("Connection: close\r\n"),
4343 MockRead("Content-Length: 42\r\n"),
4344 MockRead("Content-Type: text/html\r\n\r\n"),
4345 // Missing content -- won't matter, as connection will be reset.
4346 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4349 MockWrite data_writes2
[] = {
4350 // After restarting with a null identity, this is the
4351 // request we should be issuing -- the final header line contains a Type
4353 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4354 "Host: 172.22.68.17\r\n"
4355 "Connection: keep-alive\r\n"
4356 "Authorization: NTLM "
4357 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4359 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4360 // (the credentials for the origin server). The second request continues
4361 // on the same connection.
4362 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4363 "Host: 172.22.68.17\r\n"
4364 "Connection: keep-alive\r\n"
4365 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4366 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4367 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4368 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4369 "ahlhx5I=\r\n\r\n"),
4372 MockRead data_reads2
[] = {
4373 // The origin server responds with a Type 2 message.
4374 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4375 MockRead("WWW-Authenticate: NTLM "
4376 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4377 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4378 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4379 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4380 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4381 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4383 MockRead("Content-Length: 42\r\n"),
4384 MockRead("Content-Type: text/html\r\n\r\n"),
4385 MockRead("You are not authorized to view this page\r\n"),
4387 // Lastly we get the desired content.
4388 MockRead("HTTP/1.1 200 OK\r\n"),
4389 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4390 MockRead("Content-Length: 13\r\n\r\n"),
4391 MockRead("Please Login\r\n"),
4392 MockRead(SYNCHRONOUS
, OK
),
4395 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4396 data_writes1
, arraysize(data_writes1
));
4397 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4398 data_writes2
, arraysize(data_writes2
));
4399 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4400 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4402 TestCompletionCallback callback1
;
4404 scoped_ptr
<HttpTransaction
> trans(
4405 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4407 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4408 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4410 rv
= callback1
.WaitForResult();
4413 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4415 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4416 ASSERT_FALSE(response
== NULL
);
4417 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4419 TestCompletionCallback callback2
;
4421 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4422 callback2
.callback());
4423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4425 rv
= callback2
.WaitForResult();
4428 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4430 response
= trans
->GetResponseInfo();
4431 ASSERT_TRUE(response
!= NULL
);
4432 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4434 TestCompletionCallback callback3
;
4436 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4439 rv
= callback3
.WaitForResult();
4442 response
= trans
->GetResponseInfo();
4443 ASSERT_TRUE(response
!= NULL
);
4444 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4445 EXPECT_EQ(13, response
->headers
->GetContentLength());
4448 // Enter a wrong password, and then the correct one.
4449 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4450 HttpRequestInfo request
;
4451 request
.method
= "GET";
4452 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4453 request
.load_flags
= 0;
4455 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4457 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4459 MockWrite data_writes1
[] = {
4460 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4461 "Host: 172.22.68.17\r\n"
4462 "Connection: keep-alive\r\n\r\n"),
4465 MockRead data_reads1
[] = {
4466 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4467 // Negotiate and NTLM are often requested together. However, we only want
4468 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4469 // the header that requests Negotiate for this test.
4470 MockRead("WWW-Authenticate: NTLM\r\n"),
4471 MockRead("Connection: close\r\n"),
4472 MockRead("Content-Length: 42\r\n"),
4473 MockRead("Content-Type: text/html\r\n\r\n"),
4474 // Missing content -- won't matter, as connection will be reset.
4475 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4478 MockWrite data_writes2
[] = {
4479 // After restarting with a null identity, this is the
4480 // request we should be issuing -- the final header line contains a Type
4482 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4483 "Host: 172.22.68.17\r\n"
4484 "Connection: keep-alive\r\n"
4485 "Authorization: NTLM "
4486 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4488 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4489 // (the credentials for the origin server). The second request continues
4490 // on the same connection.
4491 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4492 "Host: 172.22.68.17\r\n"
4493 "Connection: keep-alive\r\n"
4494 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4495 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4496 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4497 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4498 "4Ww7b7E=\r\n\r\n"),
4501 MockRead data_reads2
[] = {
4502 // The origin server responds with a Type 2 message.
4503 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4504 MockRead("WWW-Authenticate: NTLM "
4505 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4506 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4507 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4508 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4509 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4510 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4512 MockRead("Content-Length: 42\r\n"),
4513 MockRead("Content-Type: text/html\r\n\r\n"),
4514 MockRead("You are not authorized to view this page\r\n"),
4517 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4518 MockRead("WWW-Authenticate: NTLM\r\n"),
4519 MockRead("Connection: close\r\n"),
4520 MockRead("Content-Length: 42\r\n"),
4521 MockRead("Content-Type: text/html\r\n\r\n"),
4522 // Missing content -- won't matter, as connection will be reset.
4523 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4526 MockWrite data_writes3
[] = {
4527 // After restarting with a null identity, this is the
4528 // request we should be issuing -- the final header line contains a Type
4530 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4531 "Host: 172.22.68.17\r\n"
4532 "Connection: keep-alive\r\n"
4533 "Authorization: NTLM "
4534 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4536 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4537 // (the credentials for the origin server). The second request continues
4538 // on the same connection.
4539 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4540 "Host: 172.22.68.17\r\n"
4541 "Connection: keep-alive\r\n"
4542 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4543 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4544 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4545 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4546 "+4MUm7c=\r\n\r\n"),
4549 MockRead data_reads3
[] = {
4550 // The origin server responds with a Type 2 message.
4551 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4552 MockRead("WWW-Authenticate: NTLM "
4553 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4554 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4555 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4556 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4557 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4558 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4560 MockRead("Content-Length: 42\r\n"),
4561 MockRead("Content-Type: text/html\r\n\r\n"),
4562 MockRead("You are not authorized to view this page\r\n"),
4564 // Lastly we get the desired content.
4565 MockRead("HTTP/1.1 200 OK\r\n"),
4566 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4567 MockRead("Content-Length: 13\r\n\r\n"),
4568 MockRead("Please Login\r\n"),
4569 MockRead(SYNCHRONOUS
, OK
),
4572 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4573 data_writes1
, arraysize(data_writes1
));
4574 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4575 data_writes2
, arraysize(data_writes2
));
4576 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4577 data_writes3
, arraysize(data_writes3
));
4578 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4579 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4580 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4582 TestCompletionCallback callback1
;
4584 scoped_ptr
<HttpTransaction
> trans(
4585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4587 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4588 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4590 rv
= callback1
.WaitForResult();
4593 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4595 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4596 ASSERT_TRUE(response
!= NULL
);
4597 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4599 TestCompletionCallback callback2
;
4601 // Enter the wrong password.
4602 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4603 callback2
.callback());
4604 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4606 rv
= callback2
.WaitForResult();
4609 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4610 TestCompletionCallback callback3
;
4611 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4612 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4613 rv
= callback3
.WaitForResult();
4615 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4617 response
= trans
->GetResponseInfo();
4618 ASSERT_FALSE(response
== NULL
);
4619 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4621 TestCompletionCallback callback4
;
4623 // Now enter the right password.
4624 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4625 callback4
.callback());
4626 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4628 rv
= callback4
.WaitForResult();
4631 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4633 TestCompletionCallback callback5
;
4635 // One more roundtrip
4636 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4637 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4639 rv
= callback5
.WaitForResult();
4642 response
= trans
->GetResponseInfo();
4643 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4644 EXPECT_EQ(13, response
->headers
->GetContentLength());
4646 #endif // NTLM_PORTABLE
4648 // Test reading a server response which has only headers, and no body.
4649 // After some maximum number of bytes is consumed, the transaction should
4650 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4651 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4652 HttpRequestInfo request
;
4653 request
.method
= "GET";
4654 request
.url
= GURL("http://www.google.com/");
4655 request
.load_flags
= 0;
4657 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4658 scoped_ptr
<HttpTransaction
> trans(
4659 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4661 // Respond with 300 kb of headers (we should fail after 256 kb).
4662 std::string large_headers_string
;
4663 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4665 MockRead data_reads
[] = {
4666 MockRead("HTTP/1.0 200 OK\r\n"),
4667 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4668 MockRead("\r\nBODY"),
4669 MockRead(SYNCHRONOUS
, OK
),
4671 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4672 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4674 TestCompletionCallback callback
;
4676 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4677 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4679 rv
= callback
.WaitForResult();
4680 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4682 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4683 EXPECT_TRUE(response
== NULL
);
4686 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4687 // establish tunnel.
4688 // http://code.google.com/p/chromium/issues/detail?id=3772
4689 TEST_P(HttpNetworkTransactionTest
,
4690 DontRecycleTransportSocketForSSLTunnel
) {
4691 HttpRequestInfo request
;
4692 request
.method
= "GET";
4693 request
.url
= GURL("https://www.google.com/");
4694 request
.load_flags
= 0;
4696 // Configure against proxy server "myproxy:70".
4697 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4699 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4701 scoped_ptr
<HttpTransaction
> trans(
4702 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4704 // Since we have proxy, should try to establish tunnel.
4705 MockWrite data_writes1
[] = {
4706 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4707 "Host: www.google.com\r\n"
4708 "Proxy-Connection: keep-alive\r\n\r\n"),
4711 // The proxy responds to the connect with a 404, using a persistent
4712 // connection. Usually a proxy would return 501 (not implemented),
4713 // or 200 (tunnel established).
4714 MockRead data_reads1
[] = {
4715 MockRead("HTTP/1.1 404 Not Found\r\n"),
4716 MockRead("Content-Length: 10\r\n\r\n"),
4717 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4720 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4721 data_writes1
, arraysize(data_writes1
));
4722 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4724 TestCompletionCallback callback1
;
4726 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4727 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4729 rv
= callback1
.WaitForResult();
4730 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4732 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4733 EXPECT_TRUE(response
== NULL
);
4735 // Empty the current queue. This is necessary because idle sockets are
4736 // added to the connection pool asynchronously with a PostTask.
4737 base::MessageLoop::current()->RunUntilIdle();
4739 // We now check to make sure the TCPClientSocket was not added back to
4741 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4743 base::MessageLoop::current()->RunUntilIdle();
4744 // Make sure that the socket didn't get recycled after calling the destructor.
4745 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4748 // Make sure that we recycle a socket after reading all of the response body.
4749 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4750 HttpRequestInfo request
;
4751 request
.method
= "GET";
4752 request
.url
= GURL("http://www.google.com/");
4753 request
.load_flags
= 0;
4755 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4757 scoped_ptr
<HttpTransaction
> trans(
4758 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4760 MockRead data_reads
[] = {
4761 // A part of the response body is received with the response headers.
4762 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4763 // The rest of the response body is received in two parts.
4766 MockRead("junk"), // Should not be read!!
4767 MockRead(SYNCHRONOUS
, OK
),
4770 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4771 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4773 TestCompletionCallback callback
;
4775 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4778 rv
= callback
.WaitForResult();
4781 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4782 ASSERT_TRUE(response
!= NULL
);
4784 EXPECT_TRUE(response
->headers
.get() != NULL
);
4785 std::string status_line
= response
->headers
->GetStatusLine();
4786 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4788 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4790 std::string response_data
;
4791 rv
= ReadTransaction(trans
.get(), &response_data
);
4793 EXPECT_EQ("hello world", response_data
);
4795 // Empty the current queue. This is necessary because idle sockets are
4796 // added to the connection pool asynchronously with a PostTask.
4797 base::MessageLoop::current()->RunUntilIdle();
4799 // We now check to make sure the socket was added back to the pool.
4800 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4803 // Make sure that we recycle a SSL socket after reading all of the response
4805 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4806 HttpRequestInfo request
;
4807 request
.method
= "GET";
4808 request
.url
= GURL("https://www.google.com/");
4809 request
.load_flags
= 0;
4811 MockWrite data_writes
[] = {
4812 MockWrite("GET / HTTP/1.1\r\n"
4813 "Host: www.google.com\r\n"
4814 "Connection: keep-alive\r\n\r\n"),
4817 MockRead data_reads
[] = {
4818 MockRead("HTTP/1.1 200 OK\r\n"),
4819 MockRead("Content-Length: 11\r\n\r\n"),
4820 MockRead("hello world"),
4821 MockRead(SYNCHRONOUS
, OK
),
4824 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4825 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4827 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4828 data_writes
, arraysize(data_writes
));
4829 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4831 TestCompletionCallback callback
;
4833 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4834 scoped_ptr
<HttpTransaction
> trans(
4835 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4837 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4839 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4840 EXPECT_EQ(OK
, callback
.WaitForResult());
4842 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4843 ASSERT_TRUE(response
!= NULL
);
4844 ASSERT_TRUE(response
->headers
.get() != NULL
);
4845 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4847 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4849 std::string response_data
;
4850 rv
= ReadTransaction(trans
.get(), &response_data
);
4852 EXPECT_EQ("hello world", response_data
);
4854 // Empty the current queue. This is necessary because idle sockets are
4855 // added to the connection pool asynchronously with a PostTask.
4856 base::MessageLoop::current()->RunUntilIdle();
4858 // We now check to make sure the socket was added back to the pool.
4859 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4862 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4863 // from the pool and make sure that we recover okay.
4864 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4865 HttpRequestInfo request
;
4866 request
.method
= "GET";
4867 request
.url
= GURL("https://www.google.com/");
4868 request
.load_flags
= 0;
4870 MockWrite data_writes
[] = {
4871 MockWrite("GET / HTTP/1.1\r\n"
4872 "Host: www.google.com\r\n"
4873 "Connection: keep-alive\r\n\r\n"),
4874 MockWrite("GET / HTTP/1.1\r\n"
4875 "Host: www.google.com\r\n"
4876 "Connection: keep-alive\r\n\r\n"),
4879 MockRead data_reads
[] = {
4880 MockRead("HTTP/1.1 200 OK\r\n"),
4881 MockRead("Content-Length: 11\r\n\r\n"),
4882 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4883 MockRead("hello world"),
4884 MockRead(ASYNC
, 0, 0) // EOF
4887 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4888 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4889 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4890 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4892 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4893 data_writes
, arraysize(data_writes
));
4894 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4895 data_writes
, arraysize(data_writes
));
4896 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4897 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4899 TestCompletionCallback callback
;
4901 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4902 scoped_ptr
<HttpTransaction
> trans(
4903 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4905 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4907 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4908 EXPECT_EQ(OK
, callback
.WaitForResult());
4910 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4911 ASSERT_TRUE(response
!= NULL
);
4912 ASSERT_TRUE(response
->headers
.get() != NULL
);
4913 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4915 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4917 std::string response_data
;
4918 rv
= ReadTransaction(trans
.get(), &response_data
);
4920 EXPECT_EQ("hello world", response_data
);
4922 // Empty the current queue. This is necessary because idle sockets are
4923 // added to the connection pool asynchronously with a PostTask.
4924 base::MessageLoop::current()->RunUntilIdle();
4926 // We now check to make sure the socket was added back to the pool.
4927 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4929 // Now start the second transaction, which should reuse the previous socket.
4931 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4933 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4935 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4936 EXPECT_EQ(OK
, callback
.WaitForResult());
4938 response
= trans
->GetResponseInfo();
4939 ASSERT_TRUE(response
!= NULL
);
4940 ASSERT_TRUE(response
->headers
.get() != NULL
);
4941 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4943 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4945 rv
= ReadTransaction(trans
.get(), &response_data
);
4947 EXPECT_EQ("hello world", response_data
);
4949 // Empty the current queue. This is necessary because idle sockets are
4950 // added to the connection pool asynchronously with a PostTask.
4951 base::MessageLoop::current()->RunUntilIdle();
4953 // We now check to make sure the socket was added back to the pool.
4954 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4957 // Make sure that we recycle a socket after a zero-length response.
4958 // http://crbug.com/9880
4959 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4960 HttpRequestInfo request
;
4961 request
.method
= "GET";
4962 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4963 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4964 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4965 "rt=prt.2642,ol.2649,xjs.2951");
4966 request
.load_flags
= 0;
4968 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4970 scoped_ptr
<HttpTransaction
> trans(
4971 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4973 MockRead data_reads
[] = {
4974 MockRead("HTTP/1.1 204 No Content\r\n"
4975 "Content-Length: 0\r\n"
4976 "Content-Type: text/html\r\n\r\n"),
4977 MockRead("junk"), // Should not be read!!
4978 MockRead(SYNCHRONOUS
, OK
),
4981 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4982 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4984 TestCompletionCallback callback
;
4986 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4987 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4989 rv
= callback
.WaitForResult();
4992 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4993 ASSERT_TRUE(response
!= NULL
);
4995 EXPECT_TRUE(response
->headers
.get() != NULL
);
4996 std::string status_line
= response
->headers
->GetStatusLine();
4997 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
4999 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5001 std::string response_data
;
5002 rv
= ReadTransaction(trans
.get(), &response_data
);
5004 EXPECT_EQ("", response_data
);
5006 // Empty the current queue. This is necessary because idle sockets are
5007 // added to the connection pool asynchronously with a PostTask.
5008 base::MessageLoop::current()->RunUntilIdle();
5010 // We now check to make sure the socket was added back to the pool.
5011 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5014 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5015 ScopedVector
<UploadElementReader
> element_readers
;
5016 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5017 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5019 HttpRequestInfo request
[2];
5020 // Transaction 1: a GET request that succeeds. The socket is recycled
5022 request
[0].method
= "GET";
5023 request
[0].url
= GURL("http://www.google.com/");
5024 request
[0].load_flags
= 0;
5025 // Transaction 2: a POST request. Reuses the socket kept alive from
5026 // transaction 1. The first attempts fails when writing the POST data.
5027 // This causes the transaction to retry with a new socket. The second
5028 // attempt succeeds.
5029 request
[1].method
= "POST";
5030 request
[1].url
= GURL("http://www.google.com/login.cgi");
5031 request
[1].upload_data_stream
= &upload_data_stream
;
5032 request
[1].load_flags
= 0;
5034 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5036 // The first socket is used for transaction 1 and the first attempt of
5039 // The response of transaction 1.
5040 MockRead data_reads1
[] = {
5041 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5042 MockRead("hello world"),
5043 MockRead(SYNCHRONOUS
, OK
),
5045 // The mock write results of transaction 1 and the first attempt of
5047 MockWrite data_writes1
[] = {
5048 MockWrite(SYNCHRONOUS
, 64), // GET
5049 MockWrite(SYNCHRONOUS
, 93), // POST
5050 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5052 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5053 data_writes1
, arraysize(data_writes1
));
5055 // The second socket is used for the second attempt of transaction 2.
5057 // The response of transaction 2.
5058 MockRead data_reads2
[] = {
5059 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5060 MockRead("welcome"),
5061 MockRead(SYNCHRONOUS
, OK
),
5063 // The mock write results of the second attempt of transaction 2.
5064 MockWrite data_writes2
[] = {
5065 MockWrite(SYNCHRONOUS
, 93), // POST
5066 MockWrite(SYNCHRONOUS
, 3), // POST data
5068 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5069 data_writes2
, arraysize(data_writes2
));
5071 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5072 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5074 const char* kExpectedResponseData
[] = {
5075 "hello world", "welcome"
5078 for (int i
= 0; i
< 2; ++i
) {
5079 scoped_ptr
<HttpTransaction
> trans(
5080 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5082 TestCompletionCallback callback
;
5084 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5087 rv
= callback
.WaitForResult();
5090 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5091 ASSERT_TRUE(response
!= NULL
);
5093 EXPECT_TRUE(response
->headers
.get() != NULL
);
5094 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5096 std::string response_data
;
5097 rv
= ReadTransaction(trans
.get(), &response_data
);
5099 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5103 // Test the request-challenge-retry sequence for basic auth when there is
5104 // an identity in the URL. The request should be sent as normal, but when
5105 // it fails the identity from the URL is used to answer the challenge.
5106 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5107 HttpRequestInfo request
;
5108 request
.method
= "GET";
5109 request
.url
= GURL("http://foo:b@r@www.google.com/");
5110 request
.load_flags
= LOAD_NORMAL
;
5112 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5113 scoped_ptr
<HttpTransaction
> trans(
5114 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5116 // The password contains an escaped character -- for this test to pass it
5117 // will need to be unescaped by HttpNetworkTransaction.
5118 EXPECT_EQ("b%40r", request
.url
.password());
5120 MockWrite data_writes1
[] = {
5121 MockWrite("GET / HTTP/1.1\r\n"
5122 "Host: www.google.com\r\n"
5123 "Connection: keep-alive\r\n\r\n"),
5126 MockRead data_reads1
[] = {
5127 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5128 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5129 MockRead("Content-Length: 10\r\n\r\n"),
5130 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5133 // After the challenge above, the transaction will be restarted using the
5134 // identity from the url (foo, b@r) to answer the challenge.
5135 MockWrite data_writes2
[] = {
5136 MockWrite("GET / HTTP/1.1\r\n"
5137 "Host: www.google.com\r\n"
5138 "Connection: keep-alive\r\n"
5139 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5142 MockRead data_reads2
[] = {
5143 MockRead("HTTP/1.0 200 OK\r\n"),
5144 MockRead("Content-Length: 100\r\n\r\n"),
5145 MockRead(SYNCHRONOUS
, OK
),
5148 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5149 data_writes1
, arraysize(data_writes1
));
5150 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5151 data_writes2
, arraysize(data_writes2
));
5152 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5153 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5155 TestCompletionCallback callback1
;
5156 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5158 rv
= callback1
.WaitForResult();
5160 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5162 TestCompletionCallback callback2
;
5163 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5164 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5165 rv
= callback2
.WaitForResult();
5167 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5169 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5170 ASSERT_TRUE(response
!= NULL
);
5172 // There is no challenge info, since the identity in URL worked.
5173 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5175 EXPECT_EQ(100, response
->headers
->GetContentLength());
5177 // Empty the current queue.
5178 base::MessageLoop::current()->RunUntilIdle();
5181 // Test the request-challenge-retry sequence for basic auth when there is an
5182 // incorrect identity in the URL. The identity from the URL should be used only
5184 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5185 HttpRequestInfo request
;
5186 request
.method
= "GET";
5187 // Note: the URL has a username:password in it. The password "baz" is
5188 // wrong (should be "bar").
5189 request
.url
= GURL("http://foo:baz@www.google.com/");
5191 request
.load_flags
= LOAD_NORMAL
;
5193 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5194 scoped_ptr
<HttpTransaction
> trans(
5195 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5197 MockWrite data_writes1
[] = {
5198 MockWrite("GET / HTTP/1.1\r\n"
5199 "Host: www.google.com\r\n"
5200 "Connection: keep-alive\r\n\r\n"),
5203 MockRead data_reads1
[] = {
5204 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5205 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5206 MockRead("Content-Length: 10\r\n\r\n"),
5207 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5210 // After the challenge above, the transaction will be restarted using the
5211 // identity from the url (foo, baz) to answer the challenge.
5212 MockWrite data_writes2
[] = {
5213 MockWrite("GET / HTTP/1.1\r\n"
5214 "Host: www.google.com\r\n"
5215 "Connection: keep-alive\r\n"
5216 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5219 MockRead data_reads2
[] = {
5220 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5221 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5222 MockRead("Content-Length: 10\r\n\r\n"),
5223 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5226 // After the challenge above, the transaction will be restarted using the
5227 // identity supplied by the user (foo, bar) to answer the challenge.
5228 MockWrite data_writes3
[] = {
5229 MockWrite("GET / HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n"
5232 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5235 MockRead data_reads3
[] = {
5236 MockRead("HTTP/1.0 200 OK\r\n"),
5237 MockRead("Content-Length: 100\r\n\r\n"),
5238 MockRead(SYNCHRONOUS
, OK
),
5241 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5242 data_writes1
, arraysize(data_writes1
));
5243 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5244 data_writes2
, arraysize(data_writes2
));
5245 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5246 data_writes3
, arraysize(data_writes3
));
5247 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5248 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5249 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5251 TestCompletionCallback callback1
;
5253 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5256 rv
= callback1
.WaitForResult();
5259 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5260 TestCompletionCallback callback2
;
5261 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5262 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5263 rv
= callback2
.WaitForResult();
5265 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5267 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5268 ASSERT_TRUE(response
!= NULL
);
5269 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5271 TestCompletionCallback callback3
;
5272 rv
= trans
->RestartWithAuth(
5273 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5275 rv
= callback3
.WaitForResult();
5277 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5279 response
= trans
->GetResponseInfo();
5280 ASSERT_TRUE(response
!= NULL
);
5282 // There is no challenge info, since the identity worked.
5283 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5285 EXPECT_EQ(100, response
->headers
->GetContentLength());
5287 // Empty the current queue.
5288 base::MessageLoop::current()->RunUntilIdle();
5292 // Test the request-challenge-retry sequence for basic auth when there is a
5293 // correct identity in the URL, but its use is being suppressed. The identity
5294 // from the URL should never be used.
5295 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5296 HttpRequestInfo request
;
5297 request
.method
= "GET";
5298 request
.url
= GURL("http://foo:bar@www.google.com/");
5299 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5301 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5302 scoped_ptr
<HttpTransaction
> trans(
5303 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5305 MockWrite data_writes1
[] = {
5306 MockWrite("GET / HTTP/1.1\r\n"
5307 "Host: www.google.com\r\n"
5308 "Connection: keep-alive\r\n\r\n"),
5311 MockRead data_reads1
[] = {
5312 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5313 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5314 MockRead("Content-Length: 10\r\n\r\n"),
5315 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5318 // After the challenge above, the transaction will be restarted using the
5319 // identity supplied by the user, not the one in the URL, to answer the
5321 MockWrite data_writes3
[] = {
5322 MockWrite("GET / HTTP/1.1\r\n"
5323 "Host: www.google.com\r\n"
5324 "Connection: keep-alive\r\n"
5325 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5328 MockRead data_reads3
[] = {
5329 MockRead("HTTP/1.0 200 OK\r\n"),
5330 MockRead("Content-Length: 100\r\n\r\n"),
5331 MockRead(SYNCHRONOUS
, OK
),
5334 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5335 data_writes1
, arraysize(data_writes1
));
5336 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5337 data_writes3
, arraysize(data_writes3
));
5338 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5339 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5341 TestCompletionCallback callback1
;
5342 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5343 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5344 rv
= callback1
.WaitForResult();
5346 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5348 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5349 ASSERT_TRUE(response
!= NULL
);
5350 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5352 TestCompletionCallback callback3
;
5353 rv
= trans
->RestartWithAuth(
5354 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5355 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5356 rv
= callback3
.WaitForResult();
5358 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5360 response
= trans
->GetResponseInfo();
5361 ASSERT_TRUE(response
!= NULL
);
5363 // There is no challenge info, since the identity worked.
5364 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5365 EXPECT_EQ(100, response
->headers
->GetContentLength());
5367 // Empty the current queue.
5368 base::MessageLoop::current()->RunUntilIdle();
5371 // Test that previously tried username/passwords for a realm get re-used.
5372 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5373 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5375 // Transaction 1: authenticate (foo, bar) on MyRealm1
5377 HttpRequestInfo request
;
5378 request
.method
= "GET";
5379 request
.url
= GURL("http://www.google.com/x/y/z");
5380 request
.load_flags
= 0;
5382 scoped_ptr
<HttpTransaction
> trans(
5383 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5385 MockWrite data_writes1
[] = {
5386 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5387 "Host: www.google.com\r\n"
5388 "Connection: keep-alive\r\n\r\n"),
5391 MockRead data_reads1
[] = {
5392 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5393 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5394 MockRead("Content-Length: 10000\r\n\r\n"),
5395 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5398 // Resend with authorization (username=foo, password=bar)
5399 MockWrite data_writes2
[] = {
5400 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5401 "Host: www.google.com\r\n"
5402 "Connection: keep-alive\r\n"
5403 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5406 // Sever accepts the authorization.
5407 MockRead data_reads2
[] = {
5408 MockRead("HTTP/1.0 200 OK\r\n"),
5409 MockRead("Content-Length: 100\r\n\r\n"),
5410 MockRead(SYNCHRONOUS
, OK
),
5413 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5414 data_writes1
, arraysize(data_writes1
));
5415 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5416 data_writes2
, arraysize(data_writes2
));
5417 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5418 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5420 TestCompletionCallback callback1
;
5422 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5425 rv
= callback1
.WaitForResult();
5428 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5429 ASSERT_TRUE(response
!= NULL
);
5430 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5432 TestCompletionCallback callback2
;
5434 rv
= trans
->RestartWithAuth(
5435 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5438 rv
= callback2
.WaitForResult();
5441 response
= trans
->GetResponseInfo();
5442 ASSERT_TRUE(response
!= NULL
);
5443 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5444 EXPECT_EQ(100, response
->headers
->GetContentLength());
5447 // ------------------------------------------------------------------------
5449 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5451 HttpRequestInfo request
;
5452 request
.method
= "GET";
5453 // Note that Transaction 1 was at /x/y/z, so this is in the same
5454 // protection space as MyRealm1.
5455 request
.url
= GURL("http://www.google.com/x/y/a/b");
5456 request
.load_flags
= 0;
5458 scoped_ptr
<HttpTransaction
> trans(
5459 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5461 MockWrite data_writes1
[] = {
5462 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5463 "Host: www.google.com\r\n"
5464 "Connection: keep-alive\r\n"
5465 // Send preemptive authorization for MyRealm1
5466 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5469 // The server didn't like the preemptive authorization, and
5470 // challenges us for a different realm (MyRealm2).
5471 MockRead data_reads1
[] = {
5472 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5474 MockRead("Content-Length: 10000\r\n\r\n"),
5475 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5478 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5479 MockWrite data_writes2
[] = {
5480 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5481 "Host: www.google.com\r\n"
5482 "Connection: keep-alive\r\n"
5483 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5486 // Sever accepts the authorization.
5487 MockRead data_reads2
[] = {
5488 MockRead("HTTP/1.0 200 OK\r\n"),
5489 MockRead("Content-Length: 100\r\n\r\n"),
5490 MockRead(SYNCHRONOUS
, OK
),
5493 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5494 data_writes1
, arraysize(data_writes1
));
5495 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5496 data_writes2
, arraysize(data_writes2
));
5497 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5498 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5500 TestCompletionCallback callback1
;
5502 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5505 rv
= callback1
.WaitForResult();
5508 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5509 ASSERT_TRUE(response
!= NULL
);
5510 ASSERT_TRUE(response
->auth_challenge
.get());
5511 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5512 EXPECT_EQ("www.google.com:80",
5513 response
->auth_challenge
->challenger
.ToString());
5514 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5515 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5517 TestCompletionCallback callback2
;
5519 rv
= trans
->RestartWithAuth(
5520 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5521 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5523 rv
= callback2
.WaitForResult();
5526 response
= trans
->GetResponseInfo();
5527 ASSERT_TRUE(response
!= NULL
);
5528 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5529 EXPECT_EQ(100, response
->headers
->GetContentLength());
5532 // ------------------------------------------------------------------------
5534 // Transaction 3: Resend a request in MyRealm's protection space --
5535 // succeed with preemptive authorization.
5537 HttpRequestInfo request
;
5538 request
.method
= "GET";
5539 request
.url
= GURL("http://www.google.com/x/y/z2");
5540 request
.load_flags
= 0;
5542 scoped_ptr
<HttpTransaction
> trans(
5543 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5545 MockWrite data_writes1
[] = {
5546 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5547 "Host: www.google.com\r\n"
5548 "Connection: keep-alive\r\n"
5549 // The authorization for MyRealm1 gets sent preemptively
5550 // (since the url is in the same protection space)
5551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5554 // Sever accepts the preemptive authorization
5555 MockRead data_reads1
[] = {
5556 MockRead("HTTP/1.0 200 OK\r\n"),
5557 MockRead("Content-Length: 100\r\n\r\n"),
5558 MockRead(SYNCHRONOUS
, OK
),
5561 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5562 data_writes1
, arraysize(data_writes1
));
5563 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5565 TestCompletionCallback callback1
;
5567 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5570 rv
= callback1
.WaitForResult();
5573 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5574 ASSERT_TRUE(response
!= NULL
);
5576 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5577 EXPECT_EQ(100, response
->headers
->GetContentLength());
5580 // ------------------------------------------------------------------------
5582 // Transaction 4: request another URL in MyRealm (however the
5583 // url is not known to belong to the protection space, so no pre-auth).
5585 HttpRequestInfo request
;
5586 request
.method
= "GET";
5587 request
.url
= GURL("http://www.google.com/x/1");
5588 request
.load_flags
= 0;
5590 scoped_ptr
<HttpTransaction
> trans(
5591 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5593 MockWrite data_writes1
[] = {
5594 MockWrite("GET /x/1 HTTP/1.1\r\n"
5595 "Host: www.google.com\r\n"
5596 "Connection: keep-alive\r\n\r\n"),
5599 MockRead data_reads1
[] = {
5600 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5601 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5602 MockRead("Content-Length: 10000\r\n\r\n"),
5603 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5606 // Resend with authorization from MyRealm's cache.
5607 MockWrite data_writes2
[] = {
5608 MockWrite("GET /x/1 HTTP/1.1\r\n"
5609 "Host: www.google.com\r\n"
5610 "Connection: keep-alive\r\n"
5611 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5614 // Sever accepts the authorization.
5615 MockRead data_reads2
[] = {
5616 MockRead("HTTP/1.0 200 OK\r\n"),
5617 MockRead("Content-Length: 100\r\n\r\n"),
5618 MockRead(SYNCHRONOUS
, OK
),
5621 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5622 data_writes1
, arraysize(data_writes1
));
5623 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5624 data_writes2
, arraysize(data_writes2
));
5625 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5626 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5628 TestCompletionCallback callback1
;
5630 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5631 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5633 rv
= callback1
.WaitForResult();
5636 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5637 TestCompletionCallback callback2
;
5638 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5640 rv
= callback2
.WaitForResult();
5642 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5644 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5645 ASSERT_TRUE(response
!= NULL
);
5646 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5647 EXPECT_EQ(100, response
->headers
->GetContentLength());
5650 // ------------------------------------------------------------------------
5652 // Transaction 5: request a URL in MyRealm, but the server rejects the
5653 // cached identity. Should invalidate and re-prompt.
5655 HttpRequestInfo request
;
5656 request
.method
= "GET";
5657 request
.url
= GURL("http://www.google.com/p/q/t");
5658 request
.load_flags
= 0;
5660 scoped_ptr
<HttpTransaction
> trans(
5661 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5663 MockWrite data_writes1
[] = {
5664 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5665 "Host: www.google.com\r\n"
5666 "Connection: keep-alive\r\n\r\n"),
5669 MockRead data_reads1
[] = {
5670 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5671 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5672 MockRead("Content-Length: 10000\r\n\r\n"),
5673 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5676 // Resend with authorization from cache for MyRealm.
5677 MockWrite data_writes2
[] = {
5678 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5679 "Host: www.google.com\r\n"
5680 "Connection: keep-alive\r\n"
5681 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5684 // Sever rejects the authorization.
5685 MockRead data_reads2
[] = {
5686 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5687 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5688 MockRead("Content-Length: 10000\r\n\r\n"),
5689 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5692 // At this point we should prompt for new credentials for MyRealm.
5693 // Restart with username=foo3, password=foo4.
5694 MockWrite data_writes3
[] = {
5695 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5696 "Host: www.google.com\r\n"
5697 "Connection: keep-alive\r\n"
5698 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5701 // Sever accepts the authorization.
5702 MockRead data_reads3
[] = {
5703 MockRead("HTTP/1.0 200 OK\r\n"),
5704 MockRead("Content-Length: 100\r\n\r\n"),
5705 MockRead(SYNCHRONOUS
, OK
),
5708 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5709 data_writes1
, arraysize(data_writes1
));
5710 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5711 data_writes2
, arraysize(data_writes2
));
5712 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5713 data_writes3
, arraysize(data_writes3
));
5714 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5715 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5716 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5718 TestCompletionCallback callback1
;
5720 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5721 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5723 rv
= callback1
.WaitForResult();
5726 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5727 TestCompletionCallback callback2
;
5728 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5730 rv
= callback2
.WaitForResult();
5732 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5734 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5735 ASSERT_TRUE(response
!= NULL
);
5736 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5738 TestCompletionCallback callback3
;
5740 rv
= trans
->RestartWithAuth(
5741 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5742 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5744 rv
= callback3
.WaitForResult();
5747 response
= trans
->GetResponseInfo();
5748 ASSERT_TRUE(response
!= NULL
);
5749 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5750 EXPECT_EQ(100, response
->headers
->GetContentLength());
5754 // Tests that nonce count increments when multiple auth attempts
5755 // are started with the same nonce.
5756 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5757 HttpAuthHandlerDigest::Factory
* digest_factory
=
5758 new HttpAuthHandlerDigest::Factory();
5759 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5760 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5761 digest_factory
->set_nonce_generator(nonce_generator
);
5762 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5763 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5765 // Transaction 1: authenticate (foo, bar) on MyRealm1
5767 HttpRequestInfo request
;
5768 request
.method
= "GET";
5769 request
.url
= GURL("http://www.google.com/x/y/z");
5770 request
.load_flags
= 0;
5772 scoped_ptr
<HttpTransaction
> trans(
5773 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5775 MockWrite data_writes1
[] = {
5776 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5777 "Host: www.google.com\r\n"
5778 "Connection: keep-alive\r\n\r\n"),
5781 MockRead data_reads1
[] = {
5782 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5783 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5784 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5785 MockRead(SYNCHRONOUS
, OK
),
5788 // Resend with authorization (username=foo, password=bar)
5789 MockWrite data_writes2
[] = {
5790 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5791 "Host: www.google.com\r\n"
5792 "Connection: keep-alive\r\n"
5793 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5794 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5795 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5796 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5799 // Sever accepts the authorization.
5800 MockRead data_reads2
[] = {
5801 MockRead("HTTP/1.0 200 OK\r\n"),
5802 MockRead(SYNCHRONOUS
, OK
),
5805 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5806 data_writes1
, arraysize(data_writes1
));
5807 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5808 data_writes2
, arraysize(data_writes2
));
5809 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5810 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5812 TestCompletionCallback callback1
;
5814 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5815 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5817 rv
= callback1
.WaitForResult();
5820 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5821 ASSERT_TRUE(response
!= NULL
);
5822 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5824 TestCompletionCallback callback2
;
5826 rv
= trans
->RestartWithAuth(
5827 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5828 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5830 rv
= callback2
.WaitForResult();
5833 response
= trans
->GetResponseInfo();
5834 ASSERT_TRUE(response
!= NULL
);
5835 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5838 // ------------------------------------------------------------------------
5840 // Transaction 2: Request another resource in digestive's protection space.
5841 // This will preemptively add an Authorization header which should have an
5842 // "nc" value of 2 (as compared to 1 in the first use.
5844 HttpRequestInfo request
;
5845 request
.method
= "GET";
5846 // Note that Transaction 1 was at /x/y/z, so this is in the same
5847 // protection space as digest.
5848 request
.url
= GURL("http://www.google.com/x/y/a/b");
5849 request
.load_flags
= 0;
5851 scoped_ptr
<HttpTransaction
> trans(
5852 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5854 MockWrite data_writes1
[] = {
5855 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5856 "Host: www.google.com\r\n"
5857 "Connection: keep-alive\r\n"
5858 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5859 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5860 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5861 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5864 // Sever accepts the authorization.
5865 MockRead data_reads1
[] = {
5866 MockRead("HTTP/1.0 200 OK\r\n"),
5867 MockRead("Content-Length: 100\r\n\r\n"),
5868 MockRead(SYNCHRONOUS
, OK
),
5871 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5872 data_writes1
, arraysize(data_writes1
));
5873 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5875 TestCompletionCallback callback1
;
5877 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5880 rv
= callback1
.WaitForResult();
5883 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5884 ASSERT_TRUE(response
!= NULL
);
5885 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5889 // Test the ResetStateForRestart() private method.
5890 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5891 // Create a transaction (the dependencies aren't important).
5892 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5893 scoped_ptr
<HttpNetworkTransaction
> trans(
5894 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5896 // Setup some state (which we expect ResetStateForRestart() will clear).
5897 trans
->read_buf_
= new IOBuffer(15);
5898 trans
->read_buf_len_
= 15;
5899 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5901 // Setup state in response_
5902 HttpResponseInfo
* response
= &trans
->response_
;
5903 response
->auth_challenge
= new AuthChallengeInfo();
5904 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5905 response
->response_time
= base::Time::Now();
5906 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5908 { // Setup state for response_.vary_data
5909 HttpRequestInfo request
;
5910 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5911 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5912 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5913 request
.extra_headers
.SetHeader("Foo", "1");
5914 request
.extra_headers
.SetHeader("bar", "23");
5915 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5918 // Cause the above state to be reset.
5919 trans
->ResetStateForRestart();
5921 // Verify that the state that needed to be reset, has been reset.
5922 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5923 EXPECT_EQ(0, trans
->read_buf_len_
);
5924 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5925 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5926 EXPECT_TRUE(response
->headers
.get() == NULL
);
5927 EXPECT_FALSE(response
->was_cached
);
5928 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5929 EXPECT_FALSE(response
->vary_data
.is_valid());
5932 // Test HTTPS connections to a site with a bad certificate
5933 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5934 HttpRequestInfo request
;
5935 request
.method
= "GET";
5936 request
.url
= GURL("https://www.google.com/");
5937 request
.load_flags
= 0;
5939 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5940 scoped_ptr
<HttpTransaction
> trans(
5941 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5943 MockWrite data_writes
[] = {
5944 MockWrite("GET / HTTP/1.1\r\n"
5945 "Host: www.google.com\r\n"
5946 "Connection: keep-alive\r\n\r\n"),
5949 MockRead data_reads
[] = {
5950 MockRead("HTTP/1.0 200 OK\r\n"),
5951 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5952 MockRead("Content-Length: 100\r\n\r\n"),
5953 MockRead(SYNCHRONOUS
, OK
),
5956 StaticSocketDataProvider ssl_bad_certificate
;
5957 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5958 data_writes
, arraysize(data_writes
));
5959 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5960 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5962 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5963 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5964 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5965 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5967 TestCompletionCallback callback
;
5969 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5970 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5972 rv
= callback
.WaitForResult();
5973 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5975 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5978 rv
= callback
.WaitForResult();
5981 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5983 ASSERT_TRUE(response
!= NULL
);
5984 EXPECT_EQ(100, response
->headers
->GetContentLength());
5987 // Test HTTPS connections to a site with a bad certificate, going through a
5989 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5990 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5992 HttpRequestInfo request
;
5993 request
.method
= "GET";
5994 request
.url
= GURL("https://www.google.com/");
5995 request
.load_flags
= 0;
5997 MockWrite proxy_writes
[] = {
5998 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5999 "Host: www.google.com\r\n"
6000 "Proxy-Connection: keep-alive\r\n\r\n"),
6003 MockRead proxy_reads
[] = {
6004 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6005 MockRead(SYNCHRONOUS
, OK
)
6008 MockWrite data_writes
[] = {
6009 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6010 "Host: www.google.com\r\n"
6011 "Proxy-Connection: keep-alive\r\n\r\n"),
6012 MockWrite("GET / HTTP/1.1\r\n"
6013 "Host: www.google.com\r\n"
6014 "Connection: keep-alive\r\n\r\n"),
6017 MockRead data_reads
[] = {
6018 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6019 MockRead("HTTP/1.0 200 OK\r\n"),
6020 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6021 MockRead("Content-Length: 100\r\n\r\n"),
6022 MockRead(SYNCHRONOUS
, OK
),
6025 StaticSocketDataProvider
ssl_bad_certificate(
6026 proxy_reads
, arraysize(proxy_reads
),
6027 proxy_writes
, arraysize(proxy_writes
));
6028 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6029 data_writes
, arraysize(data_writes
));
6030 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6031 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6033 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6034 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6035 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6036 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6038 TestCompletionCallback callback
;
6040 for (int i
= 0; i
< 2; i
++) {
6041 session_deps_
.socket_factory
->ResetNextMockIndexes();
6043 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6044 scoped_ptr
<HttpTransaction
> trans(
6045 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6047 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6048 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6050 rv
= callback
.WaitForResult();
6051 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6053 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6054 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6056 rv
= callback
.WaitForResult();
6059 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6061 ASSERT_TRUE(response
!= NULL
);
6062 EXPECT_EQ(100, response
->headers
->GetContentLength());
6067 // Test HTTPS connections to a site, going through an HTTPS proxy
6068 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6069 session_deps_
.proxy_service
.reset(
6070 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6071 CapturingNetLog net_log
;
6072 session_deps_
.net_log
= &net_log
;
6074 HttpRequestInfo request
;
6075 request
.method
= "GET";
6076 request
.url
= GURL("https://www.google.com/");
6077 request
.load_flags
= 0;
6079 MockWrite data_writes
[] = {
6080 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6081 "Host: www.google.com\r\n"
6082 "Proxy-Connection: keep-alive\r\n\r\n"),
6083 MockWrite("GET / HTTP/1.1\r\n"
6084 "Host: www.google.com\r\n"
6085 "Connection: keep-alive\r\n\r\n"),
6088 MockRead data_reads
[] = {
6089 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6090 MockRead("HTTP/1.1 200 OK\r\n"),
6091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6092 MockRead("Content-Length: 100\r\n\r\n"),
6093 MockRead(SYNCHRONOUS
, OK
),
6096 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6097 data_writes
, arraysize(data_writes
));
6098 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6099 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6102 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6103 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6105 TestCompletionCallback callback
;
6107 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6108 scoped_ptr
<HttpTransaction
> trans(
6109 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6111 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6114 rv
= callback
.WaitForResult();
6116 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6118 ASSERT_TRUE(response
!= NULL
);
6120 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6121 EXPECT_EQ(200, response
->headers
->response_code());
6122 EXPECT_EQ(100, response
->headers
->GetContentLength());
6123 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6125 LoadTimingInfo load_timing_info
;
6126 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6127 TestLoadTimingNotReusedWithPac(load_timing_info
,
6128 CONNECT_TIMING_HAS_SSL_TIMES
);
6131 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6132 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6133 session_deps_
.proxy_service
.reset(
6134 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6135 CapturingNetLog net_log
;
6136 session_deps_
.net_log
= &net_log
;
6138 HttpRequestInfo request
;
6139 request
.method
= "GET";
6140 request
.url
= GURL("https://www.google.com/");
6141 request
.load_flags
= 0;
6143 MockWrite data_writes
[] = {
6144 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6145 "Host: www.google.com\r\n"
6146 "Proxy-Connection: keep-alive\r\n\r\n"),
6149 MockRead data_reads
[] = {
6150 MockRead("HTTP/1.1 302 Redirect\r\n"),
6151 MockRead("Location: http://login.example.com/\r\n"),
6152 MockRead("Content-Length: 0\r\n\r\n"),
6153 MockRead(SYNCHRONOUS
, OK
),
6156 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6157 data_writes
, arraysize(data_writes
));
6158 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6160 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6161 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6163 TestCompletionCallback callback
;
6165 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6166 scoped_ptr
<HttpTransaction
> trans(
6167 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6169 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6172 rv
= callback
.WaitForResult();
6174 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6176 ASSERT_TRUE(response
!= NULL
);
6178 EXPECT_EQ(302, response
->headers
->response_code());
6180 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6181 EXPECT_EQ("http://login.example.com/", url
);
6183 // In the case of redirects from proxies, HttpNetworkTransaction returns
6184 // timing for the proxy connection instead of the connection to the host,
6185 // and no send / receive times.
6186 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6187 LoadTimingInfo load_timing_info
;
6188 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6190 EXPECT_FALSE(load_timing_info
.socket_reused
);
6191 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6193 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6194 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6195 load_timing_info
.proxy_resolve_end
);
6196 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6197 load_timing_info
.connect_timing
.connect_start
);
6198 ExpectConnectTimingHasTimes(
6199 load_timing_info
.connect_timing
,
6200 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6202 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6203 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6204 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6207 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6208 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6209 session_deps_
.proxy_service
.reset(
6210 ProxyService::CreateFixed("https://proxy:70"));
6212 HttpRequestInfo request
;
6213 request
.method
= "GET";
6214 request
.url
= GURL("https://www.google.com/");
6215 request
.load_flags
= 0;
6217 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6219 scoped_ptr
<SpdyFrame
> goaway(
6220 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6221 MockWrite data_writes
[] = {
6222 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6223 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6226 static const char* const kExtraHeaders
[] = {
6228 "http://login.example.com/",
6230 scoped_ptr
<SpdyFrame
> resp(
6231 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6232 arraysize(kExtraHeaders
)/2, 1));
6233 MockRead data_reads
[] = {
6234 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6235 MockRead(ASYNC
, 0, 2), // EOF
6238 DelayedSocketData
data(
6239 1, // wait for one write to finish before reading.
6240 data_reads
, arraysize(data_reads
),
6241 data_writes
, arraysize(data_writes
));
6242 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6243 proxy_ssl
.SetNextProto(GetParam());
6245 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6246 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6248 TestCompletionCallback callback
;
6250 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6251 scoped_ptr
<HttpTransaction
> trans(
6252 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6254 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6255 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6257 rv
= callback
.WaitForResult();
6259 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6261 ASSERT_TRUE(response
!= NULL
);
6263 EXPECT_EQ(302, response
->headers
->response_code());
6265 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6266 EXPECT_EQ("http://login.example.com/", url
);
6269 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6270 TEST_P(HttpNetworkTransactionTest
,
6271 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6272 session_deps_
.proxy_service
.reset(
6273 ProxyService::CreateFixed("https://proxy:70"));
6275 HttpRequestInfo request
;
6276 request
.method
= "GET";
6277 request
.url
= GURL("https://www.google.com/");
6278 request
.load_flags
= 0;
6280 MockWrite data_writes
[] = {
6281 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6282 "Host: www.google.com\r\n"
6283 "Proxy-Connection: keep-alive\r\n\r\n"),
6286 MockRead data_reads
[] = {
6287 MockRead("HTTP/1.1 404 Not Found\r\n"),
6288 MockRead("Content-Length: 23\r\n\r\n"),
6289 MockRead("The host does not exist"),
6290 MockRead(SYNCHRONOUS
, OK
),
6293 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6294 data_writes
, arraysize(data_writes
));
6295 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6297 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6298 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6300 TestCompletionCallback callback
;
6302 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6303 scoped_ptr
<HttpTransaction
> trans(
6304 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6306 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6307 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6309 rv
= callback
.WaitForResult();
6310 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6312 // TODO(ttuttle): Anything else to check here?
6315 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6316 TEST_P(HttpNetworkTransactionTest
,
6317 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6318 session_deps_
.proxy_service
.reset(
6319 ProxyService::CreateFixed("https://proxy:70"));
6321 HttpRequestInfo request
;
6322 request
.method
= "GET";
6323 request
.url
= GURL("https://www.google.com/");
6324 request
.load_flags
= 0;
6326 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6328 scoped_ptr
<SpdyFrame
> rst(
6329 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6330 MockWrite data_writes
[] = {
6331 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6332 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6335 static const char* const kExtraHeaders
[] = {
6337 "http://login.example.com/",
6339 scoped_ptr
<SpdyFrame
> resp(
6340 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6341 arraysize(kExtraHeaders
)/2, 1));
6342 scoped_ptr
<SpdyFrame
> body(
6343 spdy_util_
.ConstructSpdyBodyFrame(
6344 1, "The host does not exist", 23, true));
6345 MockRead data_reads
[] = {
6346 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6347 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6348 MockRead(ASYNC
, 0, 4), // EOF
6351 DelayedSocketData
data(
6352 1, // wait for one write to finish before reading.
6353 data_reads
, arraysize(data_reads
),
6354 data_writes
, arraysize(data_writes
));
6355 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6356 proxy_ssl
.SetNextProto(GetParam());
6358 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6359 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6361 TestCompletionCallback callback
;
6363 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6364 scoped_ptr
<HttpTransaction
> trans(
6365 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6367 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6370 rv
= callback
.WaitForResult();
6371 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6373 // TODO(ttuttle): Anything else to check here?
6376 // Test the request-challenge-retry sequence for basic auth, through
6377 // a SPDY proxy over a single SPDY session.
6378 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6379 HttpRequestInfo request
;
6380 request
.method
= "GET";
6381 request
.url
= GURL("https://www.google.com/");
6382 // when the no authentication data flag is set.
6383 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6385 // Configure against https proxy server "myproxy:70".
6386 session_deps_
.proxy_service
.reset(
6387 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6388 CapturingBoundNetLog log
;
6389 session_deps_
.net_log
= log
.bound().net_log();
6390 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6392 // Since we have proxy, should try to establish tunnel.
6393 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6395 scoped_ptr
<SpdyFrame
> rst(
6396 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6398 // After calling trans->RestartWithAuth(), this is the request we should
6399 // be issuing -- the final header line contains the credentials.
6400 const char* const kAuthCredentials
[] = {
6401 "proxy-authorization", "Basic Zm9vOmJhcg==",
6403 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6404 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
));
6405 // fetch https://www.google.com/ via HTTP
6406 const char get
[] = "GET / HTTP/1.1\r\n"
6407 "Host: www.google.com\r\n"
6408 "Connection: keep-alive\r\n\r\n";
6409 scoped_ptr
<SpdyFrame
> wrapped_get(
6410 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6412 MockWrite spdy_writes
[] = {
6413 CreateMockWrite(*req
, 1, ASYNC
),
6414 CreateMockWrite(*rst
, 4, ASYNC
),
6415 CreateMockWrite(*connect2
, 5),
6416 CreateMockWrite(*wrapped_get
, 8),
6419 // The proxy responds to the connect with a 407, using a persistent
6421 const char* const kAuthStatus
= "407";
6422 const char* const kAuthChallenge
[] = {
6423 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6425 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6426 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6428 scoped_ptr
<SpdyFrame
> conn_resp(
6429 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6430 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6431 "Content-Length: 5\r\n\r\n";
6433 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6434 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6435 scoped_ptr
<SpdyFrame
> wrapped_body(
6436 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6437 MockRead spdy_reads
[] = {
6438 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6439 CreateMockRead(*conn_resp
, 6, ASYNC
),
6440 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6441 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6442 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6445 OrderedSocketData
spdy_data(
6446 spdy_reads
, arraysize(spdy_reads
),
6447 spdy_writes
, arraysize(spdy_writes
));
6448 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6449 // Negotiate SPDY to the proxy
6450 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6451 proxy
.SetNextProto(GetParam());
6452 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6453 // Vanilla SSL to the server
6454 SSLSocketDataProvider
server(ASYNC
, OK
);
6455 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6457 TestCompletionCallback callback1
;
6459 scoped_ptr
<HttpTransaction
> trans(
6460 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6462 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6463 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6465 rv
= callback1
.WaitForResult();
6467 net::CapturingNetLog::CapturedEntryList entries
;
6468 log
.GetEntries(&entries
);
6469 size_t pos
= ExpectLogContainsSomewhere(
6470 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6471 NetLog::PHASE_NONE
);
6472 ExpectLogContainsSomewhere(
6474 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6475 NetLog::PHASE_NONE
);
6477 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6478 ASSERT_TRUE(response
!= NULL
);
6479 ASSERT_FALSE(response
->headers
.get() == NULL
);
6480 EXPECT_EQ(407, response
->headers
->response_code());
6481 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6482 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6483 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6485 TestCompletionCallback callback2
;
6487 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6488 callback2
.callback());
6489 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6491 rv
= callback2
.WaitForResult();
6494 response
= trans
->GetResponseInfo();
6495 ASSERT_TRUE(response
!= NULL
);
6497 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6498 EXPECT_EQ(200, response
->headers
->response_code());
6499 EXPECT_EQ(5, response
->headers
->GetContentLength());
6500 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6502 // The password prompt info should not be set.
6503 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6505 LoadTimingInfo load_timing_info
;
6506 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6507 TestLoadTimingNotReusedWithPac(load_timing_info
,
6508 CONNECT_TIMING_HAS_SSL_TIMES
);
6511 session
->CloseAllConnections();
6514 // Test that an explicitly trusted SPDY proxy can push a resource from an
6515 // origin that is different from that of its associated resource.
6516 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6517 HttpRequestInfo request
;
6518 HttpRequestInfo push_request
;
6520 request
.method
= "GET";
6521 request
.url
= GURL("http://www.google.com/");
6522 push_request
.method
= "GET";
6523 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6525 // Configure against https proxy server "myproxy:70".
6526 session_deps_
.proxy_service
.reset(
6527 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6528 CapturingBoundNetLog log
;
6529 session_deps_
.net_log
= log
.bound().net_log();
6531 // Enable cross-origin push.
6532 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6534 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6536 scoped_ptr
<SpdyFrame
> stream1_syn(
6537 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6539 MockWrite spdy_writes
[] = {
6540 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6543 scoped_ptr
<SpdyFrame
>
6544 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6546 scoped_ptr
<SpdyFrame
>
6547 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6549 scoped_ptr
<SpdyFrame
>
6550 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6554 "http://www.another-origin.com/foo.dat"));
6555 const char kPushedData
[] = "pushed";
6556 scoped_ptr
<SpdyFrame
> stream2_body(
6557 spdy_util_
.ConstructSpdyBodyFrame(
6558 2, kPushedData
, strlen(kPushedData
), true));
6560 MockRead spdy_reads
[] = {
6561 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6562 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6563 CreateMockRead(*stream1_body
, 4, ASYNC
),
6564 CreateMockRead(*stream2_body
, 5, ASYNC
),
6565 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6568 OrderedSocketData
spdy_data(
6569 spdy_reads
, arraysize(spdy_reads
),
6570 spdy_writes
, arraysize(spdy_writes
));
6571 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6572 // Negotiate SPDY to the proxy
6573 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6574 proxy
.SetNextProto(GetParam());
6575 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6577 scoped_ptr
<HttpTransaction
> trans(
6578 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6579 TestCompletionCallback callback
;
6580 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6581 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6583 rv
= callback
.WaitForResult();
6585 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6587 scoped_ptr
<HttpTransaction
> push_trans(
6588 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6589 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6590 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6592 rv
= callback
.WaitForResult();
6594 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6596 ASSERT_TRUE(response
!= NULL
);
6597 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6599 EXPECT_EQ(200, response
->headers
->response_code());
6600 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6602 std::string response_data
;
6603 rv
= ReadTransaction(trans
.get(), &response_data
);
6605 EXPECT_EQ("hello!", response_data
);
6607 LoadTimingInfo load_timing_info
;
6608 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6609 TestLoadTimingNotReusedWithPac(load_timing_info
,
6610 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6612 // Verify the pushed stream.
6613 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6614 EXPECT_EQ(200, push_response
->headers
->response_code());
6616 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6618 EXPECT_EQ("pushed", response_data
);
6620 LoadTimingInfo push_load_timing_info
;
6621 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6622 TestLoadTimingReusedWithPac(push_load_timing_info
);
6623 // The transactions should share a socket ID, despite being for different
6625 EXPECT_EQ(load_timing_info
.socket_log_id
,
6626 push_load_timing_info
.socket_log_id
);
6630 session
->CloseAllConnections();
6633 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6634 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6635 HttpRequestInfo request
;
6637 request
.method
= "GET";
6638 request
.url
= GURL("http://www.google.com/");
6640 // Configure against https proxy server "myproxy:70".
6641 session_deps_
.proxy_service
.reset(
6642 ProxyService::CreateFixed("https://myproxy:70"));
6643 CapturingBoundNetLog log
;
6644 session_deps_
.net_log
= log
.bound().net_log();
6646 // Enable cross-origin push.
6647 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6649 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6651 scoped_ptr
<SpdyFrame
> stream1_syn(
6652 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6654 scoped_ptr
<SpdyFrame
> push_rst(
6655 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6657 MockWrite spdy_writes
[] = {
6658 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6659 CreateMockWrite(*push_rst
, 4),
6662 scoped_ptr
<SpdyFrame
>
6663 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6665 scoped_ptr
<SpdyFrame
>
6666 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6668 scoped_ptr
<SpdyFrame
>
6669 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6673 "https://www.another-origin.com/foo.dat"));
6675 MockRead spdy_reads
[] = {
6676 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6677 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6678 CreateMockRead(*stream1_body
, 5, ASYNC
),
6679 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6682 OrderedSocketData
spdy_data(
6683 spdy_reads
, arraysize(spdy_reads
),
6684 spdy_writes
, arraysize(spdy_writes
));
6685 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6686 // Negotiate SPDY to the proxy
6687 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6688 proxy
.SetNextProto(GetParam());
6689 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6691 scoped_ptr
<HttpTransaction
> trans(
6692 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6693 TestCompletionCallback callback
;
6694 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6697 rv
= callback
.WaitForResult();
6699 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6701 ASSERT_TRUE(response
!= NULL
);
6702 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6704 EXPECT_EQ(200, response
->headers
->response_code());
6705 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6707 std::string response_data
;
6708 rv
= ReadTransaction(trans
.get(), &response_data
);
6710 EXPECT_EQ("hello!", response_data
);
6713 session
->CloseAllConnections();
6716 // Test HTTPS connections to a site with a bad certificate, going through an
6718 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6719 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6720 "https://proxy:70"));
6722 HttpRequestInfo request
;
6723 request
.method
= "GET";
6724 request
.url
= GURL("https://www.google.com/");
6725 request
.load_flags
= 0;
6727 // Attempt to fetch the URL from a server with a bad cert
6728 MockWrite bad_cert_writes
[] = {
6729 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6730 "Host: www.google.com\r\n"
6731 "Proxy-Connection: keep-alive\r\n\r\n"),
6734 MockRead bad_cert_reads
[] = {
6735 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6736 MockRead(SYNCHRONOUS
, OK
)
6739 // Attempt to fetch the URL with a good cert
6740 MockWrite good_data_writes
[] = {
6741 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6742 "Host: www.google.com\r\n"
6743 "Proxy-Connection: keep-alive\r\n\r\n"),
6744 MockWrite("GET / HTTP/1.1\r\n"
6745 "Host: www.google.com\r\n"
6746 "Connection: keep-alive\r\n\r\n"),
6749 MockRead good_cert_reads
[] = {
6750 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6751 MockRead("HTTP/1.0 200 OK\r\n"),
6752 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6753 MockRead("Content-Length: 100\r\n\r\n"),
6754 MockRead(SYNCHRONOUS
, OK
),
6757 StaticSocketDataProvider
ssl_bad_certificate(
6758 bad_cert_reads
, arraysize(bad_cert_reads
),
6759 bad_cert_writes
, arraysize(bad_cert_writes
));
6760 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6761 good_data_writes
, arraysize(good_data_writes
));
6762 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6763 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6765 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6766 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6767 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6768 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6770 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6771 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6772 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6773 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6775 TestCompletionCallback callback
;
6777 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6778 scoped_ptr
<HttpTransaction
> trans(
6779 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6781 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6782 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6784 rv
= callback
.WaitForResult();
6785 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6787 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6790 rv
= callback
.WaitForResult();
6793 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6795 ASSERT_TRUE(response
!= NULL
);
6796 EXPECT_EQ(100, response
->headers
->GetContentLength());
6799 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6800 HttpRequestInfo request
;
6801 request
.method
= "GET";
6802 request
.url
= GURL("http://www.google.com/");
6803 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6804 "Chromium Ultra Awesome X Edition");
6806 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6807 scoped_ptr
<HttpTransaction
> trans(
6808 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6810 MockWrite data_writes
[] = {
6811 MockWrite("GET / HTTP/1.1\r\n"
6812 "Host: www.google.com\r\n"
6813 "Connection: keep-alive\r\n"
6814 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6817 // Lastly, the server responds with the actual content.
6818 MockRead data_reads
[] = {
6819 MockRead("HTTP/1.0 200 OK\r\n"),
6820 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6821 MockRead("Content-Length: 100\r\n\r\n"),
6822 MockRead(SYNCHRONOUS
, OK
),
6825 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6826 data_writes
, arraysize(data_writes
));
6827 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6829 TestCompletionCallback callback
;
6831 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6832 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6834 rv
= callback
.WaitForResult();
6838 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6839 HttpRequestInfo request
;
6840 request
.method
= "GET";
6841 request
.url
= GURL("https://www.google.com/");
6842 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6843 "Chromium Ultra Awesome X Edition");
6845 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6846 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6847 scoped_ptr
<HttpTransaction
> trans(
6848 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6850 MockWrite data_writes
[] = {
6851 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6852 "Host: www.google.com\r\n"
6853 "Proxy-Connection: keep-alive\r\n"
6854 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6856 MockRead data_reads
[] = {
6857 // Return an error, so the transaction stops here (this test isn't
6858 // interested in the rest).
6859 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6860 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6861 MockRead("Proxy-Connection: close\r\n\r\n"),
6864 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6865 data_writes
, arraysize(data_writes
));
6866 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6868 TestCompletionCallback callback
;
6870 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6871 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6873 rv
= callback
.WaitForResult();
6877 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6878 HttpRequestInfo request
;
6879 request
.method
= "GET";
6880 request
.url
= GURL("http://www.google.com/");
6881 request
.load_flags
= 0;
6882 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6883 "http://the.previous.site.com/");
6885 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6886 scoped_ptr
<HttpTransaction
> trans(
6887 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6889 MockWrite data_writes
[] = {
6890 MockWrite("GET / HTTP/1.1\r\n"
6891 "Host: www.google.com\r\n"
6892 "Connection: keep-alive\r\n"
6893 "Referer: http://the.previous.site.com/\r\n\r\n"),
6896 // Lastly, the server responds with the actual content.
6897 MockRead data_reads
[] = {
6898 MockRead("HTTP/1.0 200 OK\r\n"),
6899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6900 MockRead("Content-Length: 100\r\n\r\n"),
6901 MockRead(SYNCHRONOUS
, OK
),
6904 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6905 data_writes
, arraysize(data_writes
));
6906 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6908 TestCompletionCallback callback
;
6910 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6911 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6913 rv
= callback
.WaitForResult();
6917 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6918 HttpRequestInfo request
;
6919 request
.method
= "POST";
6920 request
.url
= GURL("http://www.google.com/");
6922 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6923 scoped_ptr
<HttpTransaction
> trans(
6924 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6926 MockWrite data_writes
[] = {
6927 MockWrite("POST / HTTP/1.1\r\n"
6928 "Host: www.google.com\r\n"
6929 "Connection: keep-alive\r\n"
6930 "Content-Length: 0\r\n\r\n"),
6933 // Lastly, the server responds with the actual content.
6934 MockRead data_reads
[] = {
6935 MockRead("HTTP/1.0 200 OK\r\n"),
6936 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6937 MockRead("Content-Length: 100\r\n\r\n"),
6938 MockRead(SYNCHRONOUS
, OK
),
6941 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6942 data_writes
, arraysize(data_writes
));
6943 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6945 TestCompletionCallback callback
;
6947 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6948 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6950 rv
= callback
.WaitForResult();
6954 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6955 HttpRequestInfo request
;
6956 request
.method
= "PUT";
6957 request
.url
= GURL("http://www.google.com/");
6959 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6960 scoped_ptr
<HttpTransaction
> trans(
6961 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6963 MockWrite data_writes
[] = {
6964 MockWrite("PUT / HTTP/1.1\r\n"
6965 "Host: www.google.com\r\n"
6966 "Connection: keep-alive\r\n"
6967 "Content-Length: 0\r\n\r\n"),
6970 // Lastly, the server responds with the actual content.
6971 MockRead data_reads
[] = {
6972 MockRead("HTTP/1.0 200 OK\r\n"),
6973 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6974 MockRead("Content-Length: 100\r\n\r\n"),
6975 MockRead(SYNCHRONOUS
, OK
),
6978 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6979 data_writes
, arraysize(data_writes
));
6980 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6982 TestCompletionCallback callback
;
6984 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6985 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6987 rv
= callback
.WaitForResult();
6991 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6992 HttpRequestInfo request
;
6993 request
.method
= "HEAD";
6994 request
.url
= GURL("http://www.google.com/");
6996 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6997 scoped_ptr
<HttpTransaction
> trans(
6998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7000 MockWrite data_writes
[] = {
7001 MockWrite("HEAD / HTTP/1.1\r\n"
7002 "Host: www.google.com\r\n"
7003 "Connection: keep-alive\r\n"
7004 "Content-Length: 0\r\n\r\n"),
7007 // Lastly, the server responds with the actual content.
7008 MockRead data_reads
[] = {
7009 MockRead("HTTP/1.0 200 OK\r\n"),
7010 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7011 MockRead("Content-Length: 100\r\n\r\n"),
7012 MockRead(SYNCHRONOUS
, OK
),
7015 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7016 data_writes
, arraysize(data_writes
));
7017 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7019 TestCompletionCallback callback
;
7021 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7024 rv
= callback
.WaitForResult();
7028 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7029 HttpRequestInfo request
;
7030 request
.method
= "GET";
7031 request
.url
= GURL("http://www.google.com/");
7032 request
.load_flags
= LOAD_BYPASS_CACHE
;
7034 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7035 scoped_ptr
<HttpTransaction
> trans(
7036 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7038 MockWrite data_writes
[] = {
7039 MockWrite("GET / HTTP/1.1\r\n"
7040 "Host: www.google.com\r\n"
7041 "Connection: keep-alive\r\n"
7042 "Pragma: no-cache\r\n"
7043 "Cache-Control: no-cache\r\n\r\n"),
7046 // Lastly, the server responds with the actual content.
7047 MockRead data_reads
[] = {
7048 MockRead("HTTP/1.0 200 OK\r\n"),
7049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7050 MockRead("Content-Length: 100\r\n\r\n"),
7051 MockRead(SYNCHRONOUS
, OK
),
7054 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7055 data_writes
, arraysize(data_writes
));
7056 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7058 TestCompletionCallback callback
;
7060 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7061 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7063 rv
= callback
.WaitForResult();
7067 TEST_P(HttpNetworkTransactionTest
,
7068 BuildRequest_CacheControlValidateCache
) {
7069 HttpRequestInfo request
;
7070 request
.method
= "GET";
7071 request
.url
= GURL("http://www.google.com/");
7072 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7074 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7075 scoped_ptr
<HttpTransaction
> trans(
7076 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7078 MockWrite data_writes
[] = {
7079 MockWrite("GET / HTTP/1.1\r\n"
7080 "Host: www.google.com\r\n"
7081 "Connection: keep-alive\r\n"
7082 "Cache-Control: max-age=0\r\n\r\n"),
7085 // Lastly, the server responds with the actual content.
7086 MockRead data_reads
[] = {
7087 MockRead("HTTP/1.0 200 OK\r\n"),
7088 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7089 MockRead("Content-Length: 100\r\n\r\n"),
7090 MockRead(SYNCHRONOUS
, OK
),
7093 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7094 data_writes
, arraysize(data_writes
));
7095 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7097 TestCompletionCallback callback
;
7099 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7100 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7102 rv
= callback
.WaitForResult();
7106 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7107 HttpRequestInfo request
;
7108 request
.method
= "GET";
7109 request
.url
= GURL("http://www.google.com/");
7110 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7112 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7113 scoped_ptr
<HttpTransaction
> trans(
7114 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7116 MockWrite data_writes
[] = {
7117 MockWrite("GET / HTTP/1.1\r\n"
7118 "Host: www.google.com\r\n"
7119 "Connection: keep-alive\r\n"
7120 "FooHeader: Bar\r\n\r\n"),
7123 // Lastly, the server responds with the actual content.
7124 MockRead data_reads
[] = {
7125 MockRead("HTTP/1.0 200 OK\r\n"),
7126 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7127 MockRead("Content-Length: 100\r\n\r\n"),
7128 MockRead(SYNCHRONOUS
, OK
),
7131 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7132 data_writes
, arraysize(data_writes
));
7133 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7135 TestCompletionCallback callback
;
7137 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7138 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7140 rv
= callback
.WaitForResult();
7144 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7145 HttpRequestInfo request
;
7146 request
.method
= "GET";
7147 request
.url
= GURL("http://www.google.com/");
7148 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7149 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7150 request
.extra_headers
.SetHeader("FoO", "bar");
7152 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7153 scoped_ptr
<HttpTransaction
> trans(
7154 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7156 MockWrite data_writes
[] = {
7157 MockWrite("GET / HTTP/1.1\r\n"
7158 "Host: www.google.com\r\n"
7159 "Connection: keep-alive\r\n"
7160 "referer: www.foo.com\r\n"
7162 "FoO: bar\r\n\r\n"),
7165 // Lastly, the server responds with the actual content.
7166 MockRead data_reads
[] = {
7167 MockRead("HTTP/1.0 200 OK\r\n"),
7168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7169 MockRead("Content-Length: 100\r\n\r\n"),
7170 MockRead(SYNCHRONOUS
, OK
),
7173 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7174 data_writes
, arraysize(data_writes
));
7175 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7177 TestCompletionCallback callback
;
7179 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7182 rv
= callback
.WaitForResult();
7186 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7187 HttpRequestInfo request
;
7188 request
.method
= "GET";
7189 request
.url
= GURL("http://www.google.com/");
7190 request
.load_flags
= 0;
7192 session_deps_
.proxy_service
.reset(
7193 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7194 CapturingNetLog net_log
;
7195 session_deps_
.net_log
= &net_log
;
7197 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7198 scoped_ptr
<HttpTransaction
> trans(
7199 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7201 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7202 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7204 MockWrite data_writes
[] = {
7205 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7206 MockWrite("GET / HTTP/1.1\r\n"
7207 "Host: www.google.com\r\n"
7208 "Connection: keep-alive\r\n\r\n")
7211 MockRead data_reads
[] = {
7212 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7213 MockRead("HTTP/1.0 200 OK\r\n"),
7214 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7215 MockRead("Payload"),
7216 MockRead(SYNCHRONOUS
, OK
)
7219 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7220 data_writes
, arraysize(data_writes
));
7221 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7223 TestCompletionCallback callback
;
7225 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7226 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7228 rv
= callback
.WaitForResult();
7231 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7232 ASSERT_TRUE(response
!= NULL
);
7234 LoadTimingInfo load_timing_info
;
7235 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7236 TestLoadTimingNotReusedWithPac(load_timing_info
,
7237 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7239 std::string response_text
;
7240 rv
= ReadTransaction(trans
.get(), &response_text
);
7242 EXPECT_EQ("Payload", response_text
);
7245 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7246 HttpRequestInfo request
;
7247 request
.method
= "GET";
7248 request
.url
= GURL("https://www.google.com/");
7249 request
.load_flags
= 0;
7251 session_deps_
.proxy_service
.reset(
7252 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7253 CapturingNetLog net_log
;
7254 session_deps_
.net_log
= &net_log
;
7256 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7257 scoped_ptr
<HttpTransaction
> trans(
7258 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7260 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7261 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7263 MockWrite data_writes
[] = {
7264 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7265 arraysize(write_buffer
)),
7266 MockWrite("GET / HTTP/1.1\r\n"
7267 "Host: www.google.com\r\n"
7268 "Connection: keep-alive\r\n\r\n")
7271 MockRead data_reads
[] = {
7272 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7273 arraysize(read_buffer
)),
7274 MockRead("HTTP/1.0 200 OK\r\n"),
7275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7276 MockRead("Payload"),
7277 MockRead(SYNCHRONOUS
, OK
)
7280 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7281 data_writes
, arraysize(data_writes
));
7282 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7284 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7285 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7287 TestCompletionCallback callback
;
7289 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7290 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7292 rv
= callback
.WaitForResult();
7295 LoadTimingInfo load_timing_info
;
7296 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7297 TestLoadTimingNotReusedWithPac(load_timing_info
,
7298 CONNECT_TIMING_HAS_SSL_TIMES
);
7300 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7301 ASSERT_TRUE(response
!= NULL
);
7303 std::string response_text
;
7304 rv
= ReadTransaction(trans
.get(), &response_text
);
7306 EXPECT_EQ("Payload", response_text
);
7309 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7310 HttpRequestInfo request
;
7311 request
.method
= "GET";
7312 request
.url
= GURL("http://www.google.com/");
7313 request
.load_flags
= 0;
7315 session_deps_
.proxy_service
.reset(
7316 ProxyService::CreateFixed("socks4://myproxy:1080"));
7317 CapturingNetLog net_log
;
7318 session_deps_
.net_log
= &net_log
;
7320 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7321 scoped_ptr
<HttpTransaction
> trans(
7322 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7324 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7325 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7327 MockWrite data_writes
[] = {
7328 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7329 MockWrite("GET / HTTP/1.1\r\n"
7330 "Host: www.google.com\r\n"
7331 "Connection: keep-alive\r\n\r\n")
7334 MockRead data_reads
[] = {
7335 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7336 MockRead("HTTP/1.0 200 OK\r\n"),
7337 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7338 MockRead("Payload"),
7339 MockRead(SYNCHRONOUS
, OK
)
7342 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7343 data_writes
, arraysize(data_writes
));
7344 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7346 TestCompletionCallback callback
;
7348 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7349 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7351 rv
= callback
.WaitForResult();
7354 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7355 ASSERT_TRUE(response
!= NULL
);
7357 LoadTimingInfo load_timing_info
;
7358 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7359 TestLoadTimingNotReused(load_timing_info
,
7360 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7362 std::string response_text
;
7363 rv
= ReadTransaction(trans
.get(), &response_text
);
7365 EXPECT_EQ("Payload", response_text
);
7368 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7369 HttpRequestInfo request
;
7370 request
.method
= "GET";
7371 request
.url
= GURL("http://www.google.com/");
7372 request
.load_flags
= 0;
7374 session_deps_
.proxy_service
.reset(
7375 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7376 CapturingNetLog net_log
;
7377 session_deps_
.net_log
= &net_log
;
7379 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7380 scoped_ptr
<HttpTransaction
> trans(
7381 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7383 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7384 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7385 const char kSOCKS5OkRequest
[] = {
7387 0x01, // Command (CONNECT)
7389 0x03, // Address type (DOMAINNAME).
7390 0x0E, // Length of domain (14)
7392 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7393 0x00, 0x50, // 16-bit port (80)
7395 const char kSOCKS5OkResponse
[] =
7396 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7398 MockWrite data_writes
[] = {
7399 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7400 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7401 MockWrite("GET / HTTP/1.1\r\n"
7402 "Host: www.google.com\r\n"
7403 "Connection: keep-alive\r\n\r\n")
7406 MockRead data_reads
[] = {
7407 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7408 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7409 MockRead("HTTP/1.0 200 OK\r\n"),
7410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7411 MockRead("Payload"),
7412 MockRead(SYNCHRONOUS
, OK
)
7415 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7416 data_writes
, arraysize(data_writes
));
7417 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7419 TestCompletionCallback callback
;
7421 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7424 rv
= callback
.WaitForResult();
7427 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7428 ASSERT_TRUE(response
!= NULL
);
7430 LoadTimingInfo load_timing_info
;
7431 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7432 TestLoadTimingNotReusedWithPac(load_timing_info
,
7433 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7435 std::string response_text
;
7436 rv
= ReadTransaction(trans
.get(), &response_text
);
7438 EXPECT_EQ("Payload", response_text
);
7441 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7442 HttpRequestInfo request
;
7443 request
.method
= "GET";
7444 request
.url
= GURL("https://www.google.com/");
7445 request
.load_flags
= 0;
7447 session_deps_
.proxy_service
.reset(
7448 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7449 CapturingNetLog net_log
;
7450 session_deps_
.net_log
= &net_log
;
7452 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7453 scoped_ptr
<HttpTransaction
> trans(
7454 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7456 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7457 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7458 const unsigned char kSOCKS5OkRequest
[] = {
7460 0x01, // Command (CONNECT)
7462 0x03, // Address type (DOMAINNAME).
7463 0x0E, // Length of domain (14)
7465 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7466 0x01, 0xBB, // 16-bit port (443)
7469 const char kSOCKS5OkResponse
[] =
7470 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7472 MockWrite data_writes
[] = {
7473 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7474 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7475 arraysize(kSOCKS5OkRequest
)),
7476 MockWrite("GET / HTTP/1.1\r\n"
7477 "Host: www.google.com\r\n"
7478 "Connection: keep-alive\r\n\r\n")
7481 MockRead data_reads
[] = {
7482 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7483 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7484 MockRead("HTTP/1.0 200 OK\r\n"),
7485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7486 MockRead("Payload"),
7487 MockRead(SYNCHRONOUS
, OK
)
7490 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7491 data_writes
, arraysize(data_writes
));
7492 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7494 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7495 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7497 TestCompletionCallback callback
;
7499 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7500 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7502 rv
= callback
.WaitForResult();
7505 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7506 ASSERT_TRUE(response
!= NULL
);
7508 LoadTimingInfo load_timing_info
;
7509 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7510 TestLoadTimingNotReusedWithPac(load_timing_info
,
7511 CONNECT_TIMING_HAS_SSL_TIMES
);
7513 std::string response_text
;
7514 rv
= ReadTransaction(trans
.get(), &response_text
);
7516 EXPECT_EQ("Payload", response_text
);
7521 // Tests that for connection endpoints the group names are correctly set.
7523 struct GroupNameTest
{
7524 std::string proxy_server
;
7526 std::string expected_group_name
;
7530 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7531 NextProto next_proto
,
7532 SpdySessionDependencies
* session_deps_
) {
7533 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7535 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7536 session
->http_server_properties();
7537 http_server_properties
->SetAlternateProtocol(
7538 HostPortPair("host.with.alternate", 80), 443,
7539 AlternateProtocolFromNextProto(next_proto
), 1);
7544 int GroupNameTransactionHelper(
7545 const std::string
& url
,
7546 const scoped_refptr
<HttpNetworkSession
>& session
) {
7547 HttpRequestInfo request
;
7548 request
.method
= "GET";
7549 request
.url
= GURL(url
);
7550 request
.load_flags
= 0;
7552 scoped_ptr
<HttpTransaction
> trans(
7553 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7555 TestCompletionCallback callback
;
7557 // We do not complete this request, the dtor will clean the transaction up.
7558 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7563 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7564 const GroupNameTest tests
[] = {
7567 "http://www.google.com/direct",
7568 "www.google.com:80",
7573 "http://[2001:1418:13:1::25]/direct",
7574 "[2001:1418:13:1::25]:80",
7581 "https://www.google.com/direct_ssl",
7582 "ssl/www.google.com:443",
7587 "https://[2001:1418:13:1::25]/direct",
7588 "ssl/[2001:1418:13:1::25]:443",
7593 "http://host.with.alternate/direct",
7594 "ssl/host.with.alternate:443",
7599 session_deps_
.use_alternate_protocols
= true;
7601 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7602 session_deps_
.proxy_service
.reset(
7603 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7604 scoped_refptr
<HttpNetworkSession
> session(
7605 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7607 HttpNetworkSessionPeer
peer(session
);
7608 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7609 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7610 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7611 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7612 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7613 new MockClientSocketPoolManager
);
7614 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7615 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7616 peer
.SetClientSocketPoolManager(
7617 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7619 EXPECT_EQ(ERR_IO_PENDING
,
7620 GroupNameTransactionHelper(tests
[i
].url
, session
));
7622 EXPECT_EQ(tests
[i
].expected_group_name
,
7623 ssl_conn_pool
->last_group_name_received());
7625 EXPECT_EQ(tests
[i
].expected_group_name
,
7626 transport_conn_pool
->last_group_name_received());
7631 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7632 const GroupNameTest tests
[] = {
7635 "http://www.google.com/http_proxy_normal",
7636 "www.google.com:80",
7643 "https://www.google.com/http_connect_ssl",
7644 "ssl/www.google.com:443",
7650 "http://host.with.alternate/direct",
7651 "ssl/host.with.alternate:443",
7657 "ftp://ftp.google.com/http_proxy_normal",
7658 "ftp/ftp.google.com:21",
7663 session_deps_
.use_alternate_protocols
= true;
7665 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7666 session_deps_
.proxy_service
.reset(
7667 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7668 scoped_refptr
<HttpNetworkSession
> session(
7669 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7671 HttpNetworkSessionPeer
peer(session
);
7673 HostPortPair
proxy_host("http_proxy", 80);
7674 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7675 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7676 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7677 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7679 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7680 new MockClientSocketPoolManager
);
7681 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7682 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7683 peer
.SetClientSocketPoolManager(
7684 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7686 EXPECT_EQ(ERR_IO_PENDING
,
7687 GroupNameTransactionHelper(tests
[i
].url
, session
));
7689 EXPECT_EQ(tests
[i
].expected_group_name
,
7690 ssl_conn_pool
->last_group_name_received());
7692 EXPECT_EQ(tests
[i
].expected_group_name
,
7693 http_proxy_pool
->last_group_name_received());
7697 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7698 const GroupNameTest tests
[] = {
7700 "socks4://socks_proxy:1080",
7701 "http://www.google.com/socks4_direct",
7702 "socks4/www.google.com:80",
7706 "socks5://socks_proxy:1080",
7707 "http://www.google.com/socks5_direct",
7708 "socks5/www.google.com:80",
7714 "socks4://socks_proxy:1080",
7715 "https://www.google.com/socks4_ssl",
7716 "socks4/ssl/www.google.com:443",
7720 "socks5://socks_proxy:1080",
7721 "https://www.google.com/socks5_ssl",
7722 "socks5/ssl/www.google.com:443",
7727 "socks4://socks_proxy:1080",
7728 "http://host.with.alternate/direct",
7729 "socks4/ssl/host.with.alternate:443",
7734 session_deps_
.use_alternate_protocols
= true;
7736 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7737 session_deps_
.proxy_service
.reset(
7738 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7739 scoped_refptr
<HttpNetworkSession
> session(
7740 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7742 HttpNetworkSessionPeer
peer(session
);
7744 HostPortPair
proxy_host("socks_proxy", 1080);
7745 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7746 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7747 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7748 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7750 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7751 new MockClientSocketPoolManager
);
7752 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7753 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7754 peer
.SetClientSocketPoolManager(
7755 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7757 scoped_ptr
<HttpTransaction
> trans(
7758 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7760 EXPECT_EQ(ERR_IO_PENDING
,
7761 GroupNameTransactionHelper(tests
[i
].url
, session
));
7763 EXPECT_EQ(tests
[i
].expected_group_name
,
7764 ssl_conn_pool
->last_group_name_received());
7766 EXPECT_EQ(tests
[i
].expected_group_name
,
7767 socks_conn_pool
->last_group_name_received());
7771 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
7772 HttpRequestInfo request
;
7773 request
.method
= "GET";
7774 request
.url
= GURL("http://www.google.com/");
7776 session_deps_
.proxy_service
.reset(
7777 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7779 // This simulates failure resolving all hostnames; that means we will fail
7780 // connecting to both proxies (myproxy:70 and foobar:80).
7781 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
7783 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7784 scoped_ptr
<HttpTransaction
> trans(
7785 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7787 TestCompletionCallback callback
;
7789 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7790 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7792 rv
= callback
.WaitForResult();
7793 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
7796 // Base test to make sure that when the load flags for a request specify to
7797 // bypass the cache, the DNS cache is not used.
7798 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7800 // Issue a request, asking to bypass the cache(s).
7801 HttpRequestInfo request
;
7802 request
.method
= "GET";
7803 request
.load_flags
= load_flags
;
7804 request
.url
= GURL("http://www.google.com/");
7806 // Select a host resolver that does caching.
7807 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
7809 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7810 scoped_ptr
<HttpTransaction
> trans(
7811 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7813 // Warm up the host cache so it has an entry for "www.google.com".
7814 AddressList addrlist
;
7815 TestCompletionCallback callback
;
7816 int rv
= session_deps_
.host_resolver
->Resolve(
7817 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7820 callback
.callback(),
7823 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7824 rv
= callback
.WaitForResult();
7827 // Verify that it was added to host cache, by doing a subsequent async lookup
7828 // and confirming it completes synchronously.
7829 rv
= session_deps_
.host_resolver
->Resolve(
7830 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7833 callback
.callback(),
7838 // Inject a failure the next time that "www.google.com" is resolved. This way
7839 // we can tell if the next lookup hit the cache, or the "network".
7840 // (cache --> success, "network" --> failure).
7841 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
7843 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7844 // first read -- this won't be reached as the host resolution will fail first.
7845 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
7846 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7847 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7850 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7851 ASSERT_EQ(ERR_IO_PENDING
, rv
);
7852 rv
= callback
.WaitForResult();
7854 // If we bypassed the cache, we would have gotten a failure while resolving
7855 // "www.google.com".
7856 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
7859 // There are multiple load flags that should trigger the host cache bypass.
7860 // Test each in isolation:
7861 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
7862 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
7865 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
7866 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
7869 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
7870 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
7873 // Make sure we can handle an error when writing the request.
7874 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
7875 HttpRequestInfo request
;
7876 request
.method
= "GET";
7877 request
.url
= GURL("http://www.foo.com/");
7878 request
.load_flags
= 0;
7880 MockWrite write_failure
[] = {
7881 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
7883 StaticSocketDataProvider
data(NULL
, 0,
7884 write_failure
, arraysize(write_failure
));
7885 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7886 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7888 TestCompletionCallback callback
;
7890 scoped_ptr
<HttpTransaction
> trans(
7891 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7893 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7894 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7896 rv
= callback
.WaitForResult();
7897 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
7900 // Check that a connection closed after the start of the headers finishes ok.
7901 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
7902 HttpRequestInfo request
;
7903 request
.method
= "GET";
7904 request
.url
= GURL("http://www.foo.com/");
7905 request
.load_flags
= 0;
7907 MockRead data_reads
[] = {
7908 MockRead("HTTP/1."),
7909 MockRead(SYNCHRONOUS
, OK
),
7912 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7913 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7914 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7916 TestCompletionCallback callback
;
7918 scoped_ptr
<HttpTransaction
> trans(
7919 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7921 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7922 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7924 rv
= callback
.WaitForResult();
7927 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7928 ASSERT_TRUE(response
!= NULL
);
7930 EXPECT_TRUE(response
->headers
.get() != NULL
);
7931 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7933 std::string response_data
;
7934 rv
= ReadTransaction(trans
.get(), &response_data
);
7936 EXPECT_EQ("", response_data
);
7939 // Make sure that a dropped connection while draining the body for auth
7940 // restart does the right thing.
7941 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
7942 HttpRequestInfo request
;
7943 request
.method
= "GET";
7944 request
.url
= GURL("http://www.google.com/");
7945 request
.load_flags
= 0;
7947 MockWrite data_writes1
[] = {
7948 MockWrite("GET / HTTP/1.1\r\n"
7949 "Host: www.google.com\r\n"
7950 "Connection: keep-alive\r\n\r\n"),
7953 MockRead data_reads1
[] = {
7954 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7955 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7956 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7957 MockRead("Content-Length: 14\r\n\r\n"),
7959 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
7962 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7963 data_writes1
, arraysize(data_writes1
));
7964 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7966 // After calling trans->RestartWithAuth(), this is the request we should
7967 // be issuing -- the final header line contains the credentials.
7968 MockWrite data_writes2
[] = {
7969 MockWrite("GET / HTTP/1.1\r\n"
7970 "Host: www.google.com\r\n"
7971 "Connection: keep-alive\r\n"
7972 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7975 // Lastly, the server responds with the actual content.
7976 MockRead data_reads2
[] = {
7977 MockRead("HTTP/1.1 200 OK\r\n"),
7978 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7979 MockRead("Content-Length: 100\r\n\r\n"),
7980 MockRead(SYNCHRONOUS
, OK
),
7983 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7984 data_writes2
, arraysize(data_writes2
));
7985 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7986 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7988 TestCompletionCallback callback1
;
7990 scoped_ptr
<HttpTransaction
> trans(
7991 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7993 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7994 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7996 rv
= callback1
.WaitForResult();
7999 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8000 ASSERT_TRUE(response
!= NULL
);
8001 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8003 TestCompletionCallback callback2
;
8005 rv
= trans
->RestartWithAuth(
8006 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8007 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8009 rv
= callback2
.WaitForResult();
8012 response
= trans
->GetResponseInfo();
8013 ASSERT_TRUE(response
!= NULL
);
8014 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8015 EXPECT_EQ(100, response
->headers
->GetContentLength());
8018 // Test HTTPS connections going through a proxy that sends extra data.
8019 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8020 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8022 HttpRequestInfo request
;
8023 request
.method
= "GET";
8024 request
.url
= GURL("https://www.google.com/");
8025 request
.load_flags
= 0;
8027 MockRead proxy_reads
[] = {
8028 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8029 MockRead(SYNCHRONOUS
, OK
)
8032 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8033 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8035 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8036 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8038 TestCompletionCallback callback
;
8040 session_deps_
.socket_factory
->ResetNextMockIndexes();
8042 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8043 scoped_ptr
<HttpTransaction
> trans(
8044 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8046 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8047 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8049 rv
= callback
.WaitForResult();
8050 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8053 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8054 HttpRequestInfo request
;
8055 request
.method
= "GET";
8056 request
.url
= GURL("http://www.google.com/");
8057 request
.load_flags
= 0;
8059 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8060 scoped_ptr
<HttpTransaction
> trans(
8061 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8063 MockRead data_reads
[] = {
8064 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8065 MockRead(SYNCHRONOUS
, OK
),
8068 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8069 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8071 TestCompletionCallback callback
;
8073 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8074 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8076 EXPECT_EQ(OK
, callback
.WaitForResult());
8078 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8079 ASSERT_TRUE(response
!= NULL
);
8081 EXPECT_TRUE(response
->headers
.get() != NULL
);
8082 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8084 std::string response_data
;
8085 rv
= ReadTransaction(trans
.get(), &response_data
);
8086 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8089 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8090 base::FilePath temp_file_path
;
8091 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8092 const uint64 kFakeSize
= 100000; // file is actually blank
8093 UploadFileElementReader::ScopedOverridingContentLengthForTests
8094 overriding_content_length(kFakeSize
);
8096 ScopedVector
<UploadElementReader
> element_readers
;
8097 element_readers
.push_back(
8098 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8103 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8105 HttpRequestInfo request
;
8106 request
.method
= "POST";
8107 request
.url
= GURL("http://www.google.com/upload");
8108 request
.upload_data_stream
= &upload_data_stream
;
8109 request
.load_flags
= 0;
8111 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8112 scoped_ptr
<HttpTransaction
> trans(
8113 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8115 MockRead data_reads
[] = {
8116 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8117 MockRead("hello world"),
8118 MockRead(SYNCHRONOUS
, OK
),
8120 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8121 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8123 TestCompletionCallback callback
;
8125 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8126 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8128 rv
= callback
.WaitForResult();
8131 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8132 ASSERT_TRUE(response
!= NULL
);
8134 EXPECT_TRUE(response
->headers
.get() != NULL
);
8135 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8137 std::string response_data
;
8138 rv
= ReadTransaction(trans
.get(), &response_data
);
8140 EXPECT_EQ("hello world", response_data
);
8142 base::DeleteFile(temp_file_path
, false);
8145 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8146 base::FilePath temp_file
;
8147 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8148 std::string
temp_file_content("Unreadable file.");
8149 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8150 temp_file_content
.length()));
8151 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file
));
8153 ScopedVector
<UploadElementReader
> element_readers
;
8154 element_readers
.push_back(
8155 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8160 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8162 HttpRequestInfo request
;
8163 request
.method
= "POST";
8164 request
.url
= GURL("http://www.google.com/upload");
8165 request
.upload_data_stream
= &upload_data_stream
;
8166 request
.load_flags
= 0;
8168 // If we try to upload an unreadable file, the transaction should fail.
8169 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8170 scoped_ptr
<HttpTransaction
> trans(
8171 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8173 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8174 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8176 TestCompletionCallback callback
;
8178 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8181 rv
= callback
.WaitForResult();
8182 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8184 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8185 EXPECT_FALSE(response
);
8187 base::DeleteFile(temp_file
, false);
8190 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8191 class FakeUploadElementReader
: public UploadElementReader
{
8193 FakeUploadElementReader() {}
8194 virtual ~FakeUploadElementReader() {}
8196 const CompletionCallback
& callback() const { return callback_
; }
8198 // UploadElementReader overrides:
8199 virtual int Init(const CompletionCallback
& callback
) OVERRIDE
{
8200 callback_
= callback
;
8201 return ERR_IO_PENDING
;
8203 virtual uint64
GetContentLength() const OVERRIDE
{ return 0; }
8204 virtual uint64
BytesRemaining() const OVERRIDE
{ return 0; }
8205 virtual int Read(IOBuffer
* buf
,
8207 const CompletionCallback
& callback
) OVERRIDE
{
8212 CompletionCallback callback_
;
8215 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8216 ScopedVector
<UploadElementReader
> element_readers
;
8217 element_readers
.push_back(fake_reader
);
8218 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8220 HttpRequestInfo request
;
8221 request
.method
= "POST";
8222 request
.url
= GURL("http://www.google.com/upload");
8223 request
.upload_data_stream
= &upload_data_stream
;
8224 request
.load_flags
= 0;
8226 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8227 scoped_ptr
<HttpTransaction
> trans(
8228 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8230 StaticSocketDataProvider data
;
8231 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8233 TestCompletionCallback callback
;
8234 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8235 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8236 base::MessageLoop::current()->RunUntilIdle();
8238 // Transaction is pending on request body initialization.
8239 ASSERT_FALSE(fake_reader
->callback().is_null());
8241 // Return Init()'s result after the transaction gets destroyed.
8243 fake_reader
->callback().Run(OK
); // Should not crash.
8246 // Tests that changes to Auth realms are treated like auth rejections.
8247 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8249 HttpRequestInfo request
;
8250 request
.method
= "GET";
8251 request
.url
= GURL("http://www.google.com/");
8252 request
.load_flags
= 0;
8254 // First transaction will request a resource and receive a Basic challenge
8255 // with realm="first_realm".
8256 MockWrite data_writes1
[] = {
8257 MockWrite("GET / HTTP/1.1\r\n"
8258 "Host: www.google.com\r\n"
8259 "Connection: keep-alive\r\n"
8262 MockRead data_reads1
[] = {
8263 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8264 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8268 // After calling trans->RestartWithAuth(), provide an Authentication header
8269 // for first_realm. The server will reject and provide a challenge with
8271 MockWrite data_writes2
[] = {
8272 MockWrite("GET / HTTP/1.1\r\n"
8273 "Host: www.google.com\r\n"
8274 "Connection: keep-alive\r\n"
8275 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8278 MockRead data_reads2
[] = {
8279 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8280 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8284 // This again fails, and goes back to first_realm. Make sure that the
8285 // entry is removed from cache.
8286 MockWrite data_writes3
[] = {
8287 MockWrite("GET / HTTP/1.1\r\n"
8288 "Host: www.google.com\r\n"
8289 "Connection: keep-alive\r\n"
8290 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8293 MockRead data_reads3
[] = {
8294 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8295 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8299 // Try one last time (with the correct password) and get the resource.
8300 MockWrite data_writes4
[] = {
8301 MockWrite("GET / HTTP/1.1\r\n"
8302 "Host: www.google.com\r\n"
8303 "Connection: keep-alive\r\n"
8304 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8307 MockRead data_reads4
[] = {
8308 MockRead("HTTP/1.1 200 OK\r\n"
8309 "Content-Type: text/html; charset=iso-8859-1\r\n"
8310 "Content-Length: 5\r\n"
8315 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8316 data_writes1
, arraysize(data_writes1
));
8317 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8318 data_writes2
, arraysize(data_writes2
));
8319 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8320 data_writes3
, arraysize(data_writes3
));
8321 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8322 data_writes4
, arraysize(data_writes4
));
8323 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8324 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8325 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8326 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8328 TestCompletionCallback callback1
;
8330 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8331 scoped_ptr
<HttpTransaction
> trans(
8332 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8334 // Issue the first request with Authorize headers. There should be a
8335 // password prompt for first_realm waiting to be filled in after the
8336 // transaction completes.
8337 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8338 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8339 rv
= callback1
.WaitForResult();
8341 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8342 ASSERT_TRUE(response
!= NULL
);
8343 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8344 ASSERT_FALSE(challenge
== NULL
);
8345 EXPECT_FALSE(challenge
->is_proxy
);
8346 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8347 EXPECT_EQ("first_realm", challenge
->realm
);
8348 EXPECT_EQ("basic", challenge
->scheme
);
8350 // Issue the second request with an incorrect password. There should be a
8351 // password prompt for second_realm waiting to be filled in after the
8352 // transaction completes.
8353 TestCompletionCallback callback2
;
8354 rv
= trans
->RestartWithAuth(
8355 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8357 rv
= callback2
.WaitForResult();
8359 response
= trans
->GetResponseInfo();
8360 ASSERT_TRUE(response
!= NULL
);
8361 challenge
= response
->auth_challenge
.get();
8362 ASSERT_FALSE(challenge
== NULL
);
8363 EXPECT_FALSE(challenge
->is_proxy
);
8364 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8365 EXPECT_EQ("second_realm", challenge
->realm
);
8366 EXPECT_EQ("basic", challenge
->scheme
);
8368 // Issue the third request with another incorrect password. There should be
8369 // a password prompt for first_realm waiting to be filled in. If the password
8370 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8371 // first_realm was not correctly removed.
8372 TestCompletionCallback callback3
;
8373 rv
= trans
->RestartWithAuth(
8374 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8376 rv
= callback3
.WaitForResult();
8378 response
= trans
->GetResponseInfo();
8379 ASSERT_TRUE(response
!= NULL
);
8380 challenge
= response
->auth_challenge
.get();
8381 ASSERT_FALSE(challenge
== NULL
);
8382 EXPECT_FALSE(challenge
->is_proxy
);
8383 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8384 EXPECT_EQ("first_realm", challenge
->realm
);
8385 EXPECT_EQ("basic", challenge
->scheme
);
8387 // Issue the fourth request with the correct password and username.
8388 TestCompletionCallback callback4
;
8389 rv
= trans
->RestartWithAuth(
8390 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8391 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8392 rv
= callback4
.WaitForResult();
8394 response
= trans
->GetResponseInfo();
8395 ASSERT_TRUE(response
!= NULL
);
8396 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8399 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8400 session_deps_
.next_protos
= SpdyNextProtos();
8401 session_deps_
.use_alternate_protocols
= true;
8403 std::string alternate_protocol_http_header
=
8404 GetAlternateProtocolHttpHeader();
8406 MockRead data_reads
[] = {
8407 MockRead("HTTP/1.1 200 OK\r\n"),
8408 MockRead(alternate_protocol_http_header
.c_str()),
8409 MockRead("hello world"),
8410 MockRead(SYNCHRONOUS
, OK
),
8413 HttpRequestInfo request
;
8414 request
.method
= "GET";
8415 request
.url
= GURL("http://www.google.com/");
8416 request
.load_flags
= 0;
8418 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8420 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8422 TestCompletionCallback callback
;
8424 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8425 scoped_ptr
<HttpTransaction
> trans(
8426 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8428 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8429 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8431 HostPortPair
http_host_port_pair("www.google.com", 80);
8432 HttpServerProperties
& http_server_properties
=
8433 *session
->http_server_properties();
8435 http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8437 EXPECT_EQ(OK
, callback
.WaitForResult());
8439 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8440 ASSERT_TRUE(response
!= NULL
);
8441 ASSERT_TRUE(response
->headers
.get() != NULL
);
8442 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8443 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8444 EXPECT_FALSE(response
->was_npn_negotiated
);
8446 std::string response_data
;
8447 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8448 EXPECT_EQ("hello world", response_data
);
8450 ASSERT_TRUE(http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8451 const AlternateProtocolInfo alternate
=
8452 http_server_properties
.GetAlternateProtocol(http_host_port_pair
);
8453 AlternateProtocolInfo
expected_alternate(
8454 443, AlternateProtocolFromNextProto(GetParam()), 1);
8455 EXPECT_TRUE(expected_alternate
.Equals(alternate
));
8458 TEST_P(HttpNetworkTransactionTest
,
8459 MarkBrokenAlternateProtocolAndFallback
) {
8460 session_deps_
.use_alternate_protocols
= true;
8462 HttpRequestInfo request
;
8463 request
.method
= "GET";
8464 request
.url
= GURL("http://www.google.com/");
8465 request
.load_flags
= 0;
8467 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8468 StaticSocketDataProvider first_data
;
8469 first_data
.set_connect_data(mock_connect
);
8470 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8472 MockRead data_reads
[] = {
8473 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8474 MockRead("hello world"),
8475 MockRead(ASYNC
, OK
),
8477 StaticSocketDataProvider
second_data(
8478 data_reads
, arraysize(data_reads
), NULL
, 0);
8479 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8481 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8483 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8484 session
->http_server_properties();
8485 // Port must be < 1024, or the header will be ignored (since initial port was
8486 // port 80 (another restricted port).
8487 http_server_properties
->SetAlternateProtocol(
8488 HostPortPair::FromURL(request
.url
),
8489 666 /* port is ignored by MockConnect anyway */,
8490 AlternateProtocolFromNextProto(GetParam()), 1);
8492 scoped_ptr
<HttpTransaction
> trans(
8493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8494 TestCompletionCallback callback
;
8496 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8497 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8498 EXPECT_EQ(OK
, callback
.WaitForResult());
8500 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8501 ASSERT_TRUE(response
!= NULL
);
8502 ASSERT_TRUE(response
->headers
.get() != NULL
);
8503 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8505 std::string response_data
;
8506 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8507 EXPECT_EQ("hello world", response_data
);
8509 ASSERT_TRUE(http_server_properties
->HasAlternateProtocol(
8510 HostPortPair::FromURL(request
.url
)));
8511 const AlternateProtocolInfo alternate
=
8512 http_server_properties
->GetAlternateProtocol(
8513 HostPortPair::FromURL(request
.url
));
8514 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN
, alternate
.protocol
);
8517 TEST_P(HttpNetworkTransactionTest
,
8518 AlternateProtocolPortRestrictedBlocked
) {
8519 // Ensure that we're not allowed to redirect traffic via an alternate
8520 // protocol to an unrestricted (port >= 1024) when the original traffic was
8521 // on a restricted port (port < 1024). Ensure that we can redirect in all
8523 session_deps_
.use_alternate_protocols
= true;
8525 HttpRequestInfo restricted_port_request
;
8526 restricted_port_request
.method
= "GET";
8527 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8528 restricted_port_request
.load_flags
= 0;
8530 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8531 StaticSocketDataProvider first_data
;
8532 first_data
.set_connect_data(mock_connect
);
8533 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8535 MockRead data_reads
[] = {
8536 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8537 MockRead("hello world"),
8538 MockRead(ASYNC
, OK
),
8540 StaticSocketDataProvider
second_data(
8541 data_reads
, arraysize(data_reads
), NULL
, 0);
8542 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8544 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8546 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8547 session
->http_server_properties();
8548 const int kUnrestrictedAlternatePort
= 1024;
8549 http_server_properties
->SetAlternateProtocol(
8550 HostPortPair::FromURL(restricted_port_request
.url
),
8551 kUnrestrictedAlternatePort
,
8552 AlternateProtocolFromNextProto(GetParam()), 1);
8554 scoped_ptr
<HttpTransaction
> trans(
8555 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8556 TestCompletionCallback callback
;
8558 int rv
= trans
->Start(
8559 &restricted_port_request
,
8560 callback
.callback(), BoundNetLog());
8561 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8562 // Invalid change to unrestricted port should fail.
8563 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8566 TEST_P(HttpNetworkTransactionTest
,
8567 AlternateProtocolPortRestrictedPermitted
) {
8568 // Ensure that we're allowed to redirect traffic via an alternate
8569 // protocol to an unrestricted (port >= 1024) when the original traffic was
8570 // on a restricted port (port < 1024) if we set
8571 // enable_user_alternate_protocol_ports.
8573 session_deps_
.use_alternate_protocols
= true;
8574 session_deps_
.enable_user_alternate_protocol_ports
= true;
8576 HttpRequestInfo restricted_port_request
;
8577 restricted_port_request
.method
= "GET";
8578 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8579 restricted_port_request
.load_flags
= 0;
8581 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8582 StaticSocketDataProvider first_data
;
8583 first_data
.set_connect_data(mock_connect
);
8584 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8586 MockRead data_reads
[] = {
8587 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8588 MockRead("hello world"),
8589 MockRead(ASYNC
, OK
),
8591 StaticSocketDataProvider
second_data(
8592 data_reads
, arraysize(data_reads
), NULL
, 0);
8593 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8595 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8597 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8598 session
->http_server_properties();
8599 const int kUnrestrictedAlternatePort
= 1024;
8600 http_server_properties
->SetAlternateProtocol(
8601 HostPortPair::FromURL(restricted_port_request
.url
),
8602 kUnrestrictedAlternatePort
,
8603 AlternateProtocolFromNextProto(GetParam()), 1);
8605 scoped_ptr
<HttpTransaction
> trans(
8606 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8607 TestCompletionCallback callback
;
8609 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8610 &restricted_port_request
,
8611 callback
.callback(), BoundNetLog()));
8612 // Change to unrestricted port should succeed.
8613 EXPECT_EQ(OK
, callback
.WaitForResult());
8616 TEST_P(HttpNetworkTransactionTest
,
8617 AlternateProtocolPortRestrictedAllowed
) {
8618 // Ensure that we're not allowed to redirect traffic via an alternate
8619 // protocol to an unrestricted (port >= 1024) when the original traffic was
8620 // on a restricted port (port < 1024). Ensure that we can redirect in all
8622 session_deps_
.use_alternate_protocols
= true;
8624 HttpRequestInfo restricted_port_request
;
8625 restricted_port_request
.method
= "GET";
8626 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8627 restricted_port_request
.load_flags
= 0;
8629 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8630 StaticSocketDataProvider first_data
;
8631 first_data
.set_connect_data(mock_connect
);
8632 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8634 MockRead data_reads
[] = {
8635 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8636 MockRead("hello world"),
8637 MockRead(ASYNC
, OK
),
8639 StaticSocketDataProvider
second_data(
8640 data_reads
, arraysize(data_reads
), NULL
, 0);
8641 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8643 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8645 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8646 session
->http_server_properties();
8647 const int kRestrictedAlternatePort
= 80;
8648 http_server_properties
->SetAlternateProtocol(
8649 HostPortPair::FromURL(restricted_port_request
.url
),
8650 kRestrictedAlternatePort
,
8651 AlternateProtocolFromNextProto(GetParam()), 1);
8653 scoped_ptr
<HttpTransaction
> trans(
8654 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8655 TestCompletionCallback callback
;
8657 int rv
= trans
->Start(
8658 &restricted_port_request
,
8659 callback
.callback(), BoundNetLog());
8660 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8661 // Valid change to restricted port should pass.
8662 EXPECT_EQ(OK
, callback
.WaitForResult());
8665 TEST_P(HttpNetworkTransactionTest
,
8666 AlternateProtocolPortUnrestrictedAllowed1
) {
8667 // Ensure that we're not allowed to redirect traffic via an alternate
8668 // protocol to an unrestricted (port >= 1024) when the original traffic was
8669 // on a restricted port (port < 1024). Ensure that we can redirect in all
8671 session_deps_
.use_alternate_protocols
= true;
8673 HttpRequestInfo unrestricted_port_request
;
8674 unrestricted_port_request
.method
= "GET";
8675 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8676 unrestricted_port_request
.load_flags
= 0;
8678 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8679 StaticSocketDataProvider first_data
;
8680 first_data
.set_connect_data(mock_connect
);
8681 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8683 MockRead data_reads
[] = {
8684 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8685 MockRead("hello world"),
8686 MockRead(ASYNC
, OK
),
8688 StaticSocketDataProvider
second_data(
8689 data_reads
, arraysize(data_reads
), NULL
, 0);
8690 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8692 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8694 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8695 session
->http_server_properties();
8696 const int kRestrictedAlternatePort
= 80;
8697 http_server_properties
->SetAlternateProtocol(
8698 HostPortPair::FromURL(unrestricted_port_request
.url
),
8699 kRestrictedAlternatePort
,
8700 AlternateProtocolFromNextProto(GetParam()), 1);
8702 scoped_ptr
<HttpTransaction
> trans(
8703 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8704 TestCompletionCallback callback
;
8706 int rv
= trans
->Start(
8707 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8708 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8709 // Valid change to restricted port should pass.
8710 EXPECT_EQ(OK
, callback
.WaitForResult());
8713 TEST_P(HttpNetworkTransactionTest
,
8714 AlternateProtocolPortUnrestrictedAllowed2
) {
8715 // Ensure that we're not allowed to redirect traffic via an alternate
8716 // protocol to an unrestricted (port >= 1024) when the original traffic was
8717 // on a restricted port (port < 1024). Ensure that we can redirect in all
8719 session_deps_
.use_alternate_protocols
= true;
8721 HttpRequestInfo unrestricted_port_request
;
8722 unrestricted_port_request
.method
= "GET";
8723 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8724 unrestricted_port_request
.load_flags
= 0;
8726 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8727 StaticSocketDataProvider first_data
;
8728 first_data
.set_connect_data(mock_connect
);
8729 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8731 MockRead data_reads
[] = {
8732 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8733 MockRead("hello world"),
8734 MockRead(ASYNC
, OK
),
8736 StaticSocketDataProvider
second_data(
8737 data_reads
, arraysize(data_reads
), NULL
, 0);
8738 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8740 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8742 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8743 session
->http_server_properties();
8744 const int kUnrestrictedAlternatePort
= 1024;
8745 http_server_properties
->SetAlternateProtocol(
8746 HostPortPair::FromURL(unrestricted_port_request
.url
),
8747 kUnrestrictedAlternatePort
,
8748 AlternateProtocolFromNextProto(GetParam()), 1);
8750 scoped_ptr
<HttpTransaction
> trans(
8751 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8752 TestCompletionCallback callback
;
8754 int rv
= trans
->Start(
8755 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8757 // Valid change to an unrestricted port should pass.
8758 EXPECT_EQ(OK
, callback
.WaitForResult());
8761 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
8762 // Ensure that we're not allowed to redirect traffic via an alternate
8763 // protocol to an unsafe port, and that we resume the second
8764 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8765 session_deps_
.use_alternate_protocols
= true;
8767 HttpRequestInfo request
;
8768 request
.method
= "GET";
8769 request
.url
= GURL("http://www.google.com/");
8770 request
.load_flags
= 0;
8772 // The alternate protocol request will error out before we attempt to connect,
8773 // so only the standard HTTP request will try to connect.
8774 MockRead data_reads
[] = {
8775 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8776 MockRead("hello world"),
8777 MockRead(ASYNC
, OK
),
8779 StaticSocketDataProvider
data(
8780 data_reads
, arraysize(data_reads
), NULL
, 0);
8781 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8783 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8785 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8786 session
->http_server_properties();
8787 const int kUnsafePort
= 7;
8788 http_server_properties
->SetAlternateProtocol(
8789 HostPortPair::FromURL(request
.url
),
8791 AlternateProtocolFromNextProto(GetParam()), 1);
8793 scoped_ptr
<HttpTransaction
> trans(
8794 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8795 TestCompletionCallback callback
;
8797 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8798 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8799 // The HTTP request should succeed.
8800 EXPECT_EQ(OK
, callback
.WaitForResult());
8802 // Disable alternate protocol before the asserts.
8803 // HttpStreamFactory::set_use_alternate_protocols(false);
8805 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8806 ASSERT_TRUE(response
!= NULL
);
8807 ASSERT_TRUE(response
->headers
.get() != NULL
);
8808 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8810 std::string response_data
;
8811 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8812 EXPECT_EQ("hello world", response_data
);
8815 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
8816 session_deps_
.use_alternate_protocols
= true;
8817 session_deps_
.next_protos
= SpdyNextProtos();
8819 HttpRequestInfo request
;
8820 request
.method
= "GET";
8821 request
.url
= GURL("http://www.google.com/");
8822 request
.load_flags
= 0;
8824 std::string alternate_protocol_http_header
=
8825 GetAlternateProtocolHttpHeader();
8827 MockRead data_reads
[] = {
8828 MockRead("HTTP/1.1 200 OK\r\n"),
8829 MockRead(alternate_protocol_http_header
.c_str()),
8830 MockRead("hello world"),
8831 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8835 StaticSocketDataProvider
first_transaction(
8836 data_reads
, arraysize(data_reads
), NULL
, 0);
8837 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8839 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8840 ssl
.SetNextProto(GetParam());
8841 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8843 scoped_ptr
<SpdyFrame
> req(
8844 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8845 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8847 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8848 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8849 MockRead spdy_reads
[] = {
8850 CreateMockRead(*resp
),
8851 CreateMockRead(*data
),
8852 MockRead(ASYNC
, 0, 0),
8855 DelayedSocketData
spdy_data(
8856 1, // wait for one write to finish before reading.
8857 spdy_reads
, arraysize(spdy_reads
),
8858 spdy_writes
, arraysize(spdy_writes
));
8859 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8861 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8862 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8864 hanging_non_alternate_protocol_socket
.set_connect_data(
8865 never_finishing_connect
);
8866 session_deps_
.socket_factory
->AddSocketDataProvider(
8867 &hanging_non_alternate_protocol_socket
);
8869 TestCompletionCallback callback
;
8871 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8872 scoped_ptr
<HttpTransaction
> trans(
8873 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8875 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8877 EXPECT_EQ(OK
, callback
.WaitForResult());
8879 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8880 ASSERT_TRUE(response
!= NULL
);
8881 ASSERT_TRUE(response
->headers
.get() != NULL
);
8882 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8884 std::string response_data
;
8885 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8886 EXPECT_EQ("hello world", response_data
);
8888 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8890 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8891 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8892 EXPECT_EQ(OK
, callback
.WaitForResult());
8894 response
= trans
->GetResponseInfo();
8895 ASSERT_TRUE(response
!= NULL
);
8896 ASSERT_TRUE(response
->headers
.get() != NULL
);
8897 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8898 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8899 EXPECT_TRUE(response
->was_npn_negotiated
);
8901 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8902 EXPECT_EQ("hello!", response_data
);
8905 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
8906 session_deps_
.use_alternate_protocols
= true;
8907 session_deps_
.next_protos
= SpdyNextProtos();
8909 HttpRequestInfo request
;
8910 request
.method
= "GET";
8911 request
.url
= GURL("http://www.google.com/");
8912 request
.load_flags
= 0;
8914 std::string alternate_protocol_http_header
=
8915 GetAlternateProtocolHttpHeader();
8917 MockRead data_reads
[] = {
8918 MockRead("HTTP/1.1 200 OK\r\n"),
8919 MockRead(alternate_protocol_http_header
.c_str()),
8920 MockRead("hello world"),
8921 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8922 MockRead(ASYNC
, OK
),
8925 StaticSocketDataProvider
first_transaction(
8926 data_reads
, arraysize(data_reads
), NULL
, 0);
8927 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8928 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8930 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8931 StaticSocketDataProvider
hanging_socket(
8933 hanging_socket
.set_connect_data(never_finishing_connect
);
8934 // Socket 2 and 3 are the hanging Alternate-Protocol and
8935 // non-Alternate-Protocol jobs from the 2nd transaction.
8936 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8937 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8939 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8940 ssl
.SetNextProto(GetParam());
8941 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8943 scoped_ptr
<SpdyFrame
> req1(
8944 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8945 scoped_ptr
<SpdyFrame
> req2(
8946 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
8947 MockWrite spdy_writes
[] = {
8948 CreateMockWrite(*req1
),
8949 CreateMockWrite(*req2
),
8951 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8952 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8953 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
8954 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
8955 MockRead spdy_reads
[] = {
8956 CreateMockRead(*resp1
),
8957 CreateMockRead(*data1
),
8958 CreateMockRead(*resp2
),
8959 CreateMockRead(*data2
),
8960 MockRead(ASYNC
, 0, 0),
8963 DelayedSocketData
spdy_data(
8964 2, // wait for writes to finish before reading.
8965 spdy_reads
, arraysize(spdy_reads
),
8966 spdy_writes
, arraysize(spdy_writes
));
8967 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8968 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8970 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8971 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8973 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8974 TestCompletionCallback callback1
;
8975 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
8977 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
8978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8979 EXPECT_EQ(OK
, callback1
.WaitForResult());
8981 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
8982 ASSERT_TRUE(response
!= NULL
);
8983 ASSERT_TRUE(response
->headers
.get() != NULL
);
8984 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8986 std::string response_data
;
8987 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
8988 EXPECT_EQ("hello world", response_data
);
8990 TestCompletionCallback callback2
;
8991 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
8992 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
8993 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8995 TestCompletionCallback callback3
;
8996 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
8997 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
8998 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9000 EXPECT_EQ(OK
, callback2
.WaitForResult());
9001 EXPECT_EQ(OK
, callback3
.WaitForResult());
9003 response
= trans2
.GetResponseInfo();
9004 ASSERT_TRUE(response
!= NULL
);
9005 ASSERT_TRUE(response
->headers
.get() != NULL
);
9006 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9007 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9008 EXPECT_TRUE(response
->was_npn_negotiated
);
9009 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9010 EXPECT_EQ("hello!", response_data
);
9012 response
= trans3
.GetResponseInfo();
9013 ASSERT_TRUE(response
!= NULL
);
9014 ASSERT_TRUE(response
->headers
.get() != NULL
);
9015 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9016 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9017 EXPECT_TRUE(response
->was_npn_negotiated
);
9018 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9019 EXPECT_EQ("hello!", response_data
);
9022 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9023 session_deps_
.use_alternate_protocols
= true;
9024 session_deps_
.next_protos
= SpdyNextProtos();
9026 HttpRequestInfo request
;
9027 request
.method
= "GET";
9028 request
.url
= GURL("http://www.google.com/");
9029 request
.load_flags
= 0;
9031 std::string alternate_protocol_http_header
=
9032 GetAlternateProtocolHttpHeader();
9034 MockRead data_reads
[] = {
9035 MockRead("HTTP/1.1 200 OK\r\n"),
9036 MockRead(alternate_protocol_http_header
.c_str()),
9037 MockRead("hello world"),
9038 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9039 MockRead(ASYNC
, OK
),
9042 StaticSocketDataProvider
first_transaction(
9043 data_reads
, arraysize(data_reads
), NULL
, 0);
9044 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9046 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9047 ssl
.SetNextProto(GetParam());
9048 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9050 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9051 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9053 hanging_alternate_protocol_socket
.set_connect_data(
9054 never_finishing_connect
);
9055 session_deps_
.socket_factory
->AddSocketDataProvider(
9056 &hanging_alternate_protocol_socket
);
9058 // 2nd request is just a copy of the first one, over HTTP again.
9059 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9061 TestCompletionCallback callback
;
9063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9064 scoped_ptr
<HttpTransaction
> trans(
9065 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9067 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9068 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9069 EXPECT_EQ(OK
, callback
.WaitForResult());
9071 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9072 ASSERT_TRUE(response
!= NULL
);
9073 ASSERT_TRUE(response
->headers
.get() != NULL
);
9074 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9076 std::string response_data
;
9077 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9078 EXPECT_EQ("hello world", response_data
);
9080 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9082 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9083 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9084 EXPECT_EQ(OK
, callback
.WaitForResult());
9086 response
= trans
->GetResponseInfo();
9087 ASSERT_TRUE(response
!= NULL
);
9088 ASSERT_TRUE(response
->headers
.get() != NULL
);
9089 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9090 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9091 EXPECT_FALSE(response
->was_npn_negotiated
);
9093 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9094 EXPECT_EQ("hello world", response_data
);
9097 class CapturingProxyResolver
: public ProxyResolver
{
9099 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9100 virtual ~CapturingProxyResolver() {}
9102 virtual int GetProxyForURL(const GURL
& url
,
9104 const CompletionCallback
& callback
,
9105 RequestHandle
* request
,
9106 const BoundNetLog
& net_log
) OVERRIDE
{
9107 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9108 HostPortPair("myproxy", 80));
9109 results
->UseProxyServer(proxy_server
);
9110 resolved_
.push_back(url
);
9114 virtual void CancelRequest(RequestHandle request
) OVERRIDE
{
9118 virtual LoadState
GetLoadState(RequestHandle request
) const OVERRIDE
{
9120 return LOAD_STATE_IDLE
;
9123 virtual void CancelSetPacScript() OVERRIDE
{
9127 virtual int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9128 const CompletionCallback
& /*callback*/) OVERRIDE
{
9132 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9135 std::vector
<GURL
> resolved_
;
9137 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9140 TEST_P(HttpNetworkTransactionTest
,
9141 UseAlternateProtocolForTunneledNpnSpdy
) {
9142 session_deps_
.use_alternate_protocols
= true;
9143 session_deps_
.next_protos
= SpdyNextProtos();
9145 ProxyConfig proxy_config
;
9146 proxy_config
.set_auto_detect(true);
9147 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9149 CapturingProxyResolver
* capturing_proxy_resolver
=
9150 new CapturingProxyResolver();
9151 session_deps_
.proxy_service
.reset(new ProxyService(
9152 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
9154 CapturingNetLog net_log
;
9155 session_deps_
.net_log
= &net_log
;
9157 HttpRequestInfo request
;
9158 request
.method
= "GET";
9159 request
.url
= GURL("http://www.google.com/");
9160 request
.load_flags
= 0;
9162 std::string alternate_protocol_http_header
=
9163 GetAlternateProtocolHttpHeader();
9165 MockRead data_reads
[] = {
9166 MockRead("HTTP/1.1 200 OK\r\n"),
9167 MockRead(alternate_protocol_http_header
.c_str()),
9168 MockRead("hello world"),
9169 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9170 MockRead(ASYNC
, OK
),
9173 StaticSocketDataProvider
first_transaction(
9174 data_reads
, arraysize(data_reads
), NULL
, 0);
9175 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9177 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9178 ssl
.SetNextProto(GetParam());
9179 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9181 scoped_ptr
<SpdyFrame
> req(
9182 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9183 MockWrite spdy_writes
[] = {
9184 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9185 "Host: www.google.com\r\n"
9186 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9187 CreateMockWrite(*req
), // 3
9190 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9192 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9193 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9194 MockRead spdy_reads
[] = {
9195 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9196 CreateMockRead(*resp
.get(), 4), // 2, 4
9197 CreateMockRead(*data
.get(), 4), // 5
9198 MockRead(ASYNC
, 0, 0, 4), // 6
9201 OrderedSocketData
spdy_data(
9202 spdy_reads
, arraysize(spdy_reads
),
9203 spdy_writes
, arraysize(spdy_writes
));
9204 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9206 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9207 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9209 hanging_non_alternate_protocol_socket
.set_connect_data(
9210 never_finishing_connect
);
9211 session_deps_
.socket_factory
->AddSocketDataProvider(
9212 &hanging_non_alternate_protocol_socket
);
9214 TestCompletionCallback callback
;
9216 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9217 scoped_ptr
<HttpTransaction
> trans(
9218 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9220 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9221 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9222 EXPECT_EQ(OK
, callback
.WaitForResult());
9224 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9225 ASSERT_TRUE(response
!= NULL
);
9226 ASSERT_TRUE(response
->headers
.get() != NULL
);
9227 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9228 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9229 EXPECT_FALSE(response
->was_npn_negotiated
);
9231 std::string response_data
;
9232 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9233 EXPECT_EQ("hello world", response_data
);
9235 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9237 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9238 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9239 EXPECT_EQ(OK
, callback
.WaitForResult());
9241 response
= trans
->GetResponseInfo();
9242 ASSERT_TRUE(response
!= NULL
);
9243 ASSERT_TRUE(response
->headers
.get() != NULL
);
9244 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9245 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9246 EXPECT_TRUE(response
->was_npn_negotiated
);
9248 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9249 EXPECT_EQ("hello!", response_data
);
9250 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
9251 EXPECT_EQ("http://www.google.com/",
9252 capturing_proxy_resolver
->resolved()[0].spec());
9253 EXPECT_EQ("https://www.google.com/",
9254 capturing_proxy_resolver
->resolved()[1].spec());
9256 LoadTimingInfo load_timing_info
;
9257 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9258 TestLoadTimingNotReusedWithPac(load_timing_info
,
9259 CONNECT_TIMING_HAS_SSL_TIMES
);
9262 TEST_P(HttpNetworkTransactionTest
,
9263 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9264 session_deps_
.use_alternate_protocols
= true;
9265 session_deps_
.next_protos
= SpdyNextProtos();
9267 HttpRequestInfo request
;
9268 request
.method
= "GET";
9269 request
.url
= GURL("http://www.google.com/");
9270 request
.load_flags
= 0;
9272 std::string alternate_protocol_http_header
=
9273 GetAlternateProtocolHttpHeader();
9275 MockRead data_reads
[] = {
9276 MockRead("HTTP/1.1 200 OK\r\n"),
9277 MockRead(alternate_protocol_http_header
.c_str()),
9278 MockRead("hello world"),
9279 MockRead(ASYNC
, OK
),
9282 StaticSocketDataProvider
first_transaction(
9283 data_reads
, arraysize(data_reads
), NULL
, 0);
9284 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9286 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9287 ssl
.SetNextProto(GetParam());
9288 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9290 scoped_ptr
<SpdyFrame
> req(
9291 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9292 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9294 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9295 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9296 MockRead spdy_reads
[] = {
9297 CreateMockRead(*resp
),
9298 CreateMockRead(*data
),
9299 MockRead(ASYNC
, 0, 0),
9302 DelayedSocketData
spdy_data(
9303 1, // wait for one write to finish before reading.
9304 spdy_reads
, arraysize(spdy_reads
),
9305 spdy_writes
, arraysize(spdy_writes
));
9306 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9308 TestCompletionCallback callback
;
9310 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9312 scoped_ptr
<HttpTransaction
> trans(
9313 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9315 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9316 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9317 EXPECT_EQ(OK
, callback
.WaitForResult());
9319 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9320 ASSERT_TRUE(response
!= NULL
);
9321 ASSERT_TRUE(response
->headers
.get() != NULL
);
9322 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9324 std::string response_data
;
9325 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9326 EXPECT_EQ("hello world", response_data
);
9328 // Set up an initial SpdySession in the pool to reuse.
9329 HostPortPair
host_port_pair("www.google.com", 443);
9330 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9331 PRIVACY_MODE_DISABLED
);
9332 base::WeakPtr
<SpdySession
> spdy_session
=
9333 CreateSecureSpdySession(session
, key
, BoundNetLog());
9335 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9337 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9338 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9339 EXPECT_EQ(OK
, callback
.WaitForResult());
9341 response
= trans
->GetResponseInfo();
9342 ASSERT_TRUE(response
!= NULL
);
9343 ASSERT_TRUE(response
->headers
.get() != NULL
);
9344 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9345 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9346 EXPECT_TRUE(response
->was_npn_negotiated
);
9348 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9349 EXPECT_EQ("hello!", response_data
);
9352 // GenerateAuthToken is a mighty big test.
9353 // It tests all permutation of GenerateAuthToken behavior:
9354 // - Synchronous and Asynchronous completion.
9355 // - OK or error on completion.
9356 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9357 // - HTTP or HTTPS backend (to include proxy tunneling).
9358 // - Non-authenticating and authenticating backend.
9360 // In all, there are 44 reasonable permuations (for example, if there are
9361 // problems generating an auth token for an authenticating proxy, we don't
9362 // need to test all permutations of the backend server).
9364 // The test proceeds by going over each of the configuration cases, and
9365 // potentially running up to three rounds in each of the tests. The TestConfig
9366 // specifies both the configuration for the test as well as the expectations
9368 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9369 static const char kServer
[] = "http://www.example.com";
9370 static const char kSecureServer
[] = "https://www.example.com";
9371 static const char kProxy
[] = "myproxy:70";
9372 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9380 const MockWrite
kGet(
9381 "GET / HTTP/1.1\r\n"
9382 "Host: www.example.com\r\n"
9383 "Connection: keep-alive\r\n\r\n");
9384 const MockWrite
kGetProxy(
9385 "GET http://www.example.com/ HTTP/1.1\r\n"
9386 "Host: www.example.com\r\n"
9387 "Proxy-Connection: keep-alive\r\n\r\n");
9388 const MockWrite
kGetAuth(
9389 "GET / HTTP/1.1\r\n"
9390 "Host: www.example.com\r\n"
9391 "Connection: keep-alive\r\n"
9392 "Authorization: auth_token\r\n\r\n");
9393 const MockWrite
kGetProxyAuth(
9394 "GET http://www.example.com/ HTTP/1.1\r\n"
9395 "Host: www.example.com\r\n"
9396 "Proxy-Connection: keep-alive\r\n"
9397 "Proxy-Authorization: auth_token\r\n\r\n");
9398 const MockWrite
kGetAuthThroughProxy(
9399 "GET http://www.example.com/ HTTP/1.1\r\n"
9400 "Host: www.example.com\r\n"
9401 "Proxy-Connection: keep-alive\r\n"
9402 "Authorization: auth_token\r\n\r\n");
9403 const MockWrite
kGetAuthWithProxyAuth(
9404 "GET http://www.example.com/ HTTP/1.1\r\n"
9405 "Host: www.example.com\r\n"
9406 "Proxy-Connection: keep-alive\r\n"
9407 "Proxy-Authorization: auth_token\r\n"
9408 "Authorization: auth_token\r\n\r\n");
9409 const MockWrite
kConnect(
9410 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9411 "Host: www.example.com\r\n"
9412 "Proxy-Connection: keep-alive\r\n\r\n");
9413 const MockWrite
kConnectProxyAuth(
9414 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9415 "Host: www.example.com\r\n"
9416 "Proxy-Connection: keep-alive\r\n"
9417 "Proxy-Authorization: auth_token\r\n\r\n");
9419 const MockRead
kSuccess(
9420 "HTTP/1.1 200 OK\r\n"
9421 "Content-Type: text/html; charset=iso-8859-1\r\n"
9422 "Content-Length: 3\r\n\r\n"
9424 const MockRead
kFailure(
9425 "Should not be called.");
9426 const MockRead
kServerChallenge(
9427 "HTTP/1.1 401 Unauthorized\r\n"
9428 "WWW-Authenticate: Mock realm=server\r\n"
9429 "Content-Type: text/html; charset=iso-8859-1\r\n"
9430 "Content-Length: 14\r\n\r\n"
9431 "Unauthorized\r\n");
9432 const MockRead
kProxyChallenge(
9433 "HTTP/1.1 407 Unauthorized\r\n"
9434 "Proxy-Authenticate: Mock realm=proxy\r\n"
9435 "Proxy-Connection: close\r\n"
9436 "Content-Type: text/html; charset=iso-8859-1\r\n"
9437 "Content-Length: 14\r\n\r\n"
9438 "Unauthorized\r\n");
9439 const MockRead
kProxyConnected(
9440 "HTTP/1.1 200 Connection Established\r\n\r\n");
9442 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9443 // no constructors, but the C++ compiler on Windows warns about
9444 // unspecified data in compound literals. So, moved to using constructors,
9445 // and TestRound's created with the default constructor should not be used.
9448 : expected_rv(ERR_UNEXPECTED
),
9452 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9453 int expected_rv_arg
)
9456 expected_rv(expected_rv_arg
),
9460 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9461 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9462 const MockRead
* extra_read_arg
)
9465 expected_rv(expected_rv_arg
),
9466 extra_write(extra_write_arg
),
9467 extra_read(extra_read_arg
) {
9472 const MockWrite
* extra_write
;
9473 const MockRead
* extra_read
;
9476 static const int kNoSSL
= 500;
9479 const char* proxy_url
;
9480 AuthTiming proxy_auth_timing
;
9482 const char* server_url
;
9483 AuthTiming server_auth_timing
;
9485 int num_auth_rounds
;
9486 int first_ssl_round
;
9487 TestRound rounds
[3];
9488 } test_configs
[] = {
9489 // Non-authenticating HTTP server with a direct connection.
9490 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9491 { TestRound(kGet
, kSuccess
, OK
)}},
9492 // Authenticating HTTP server with a direct connection.
9493 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9494 { TestRound(kGet
, kServerChallenge
, OK
),
9495 TestRound(kGetAuth
, kSuccess
, OK
)}},
9496 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9497 { TestRound(kGet
, kServerChallenge
, OK
),
9498 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9499 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9500 { TestRound(kGet
, kServerChallenge
, OK
),
9501 TestRound(kGetAuth
, kSuccess
, OK
)}},
9502 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9503 { TestRound(kGet
, kServerChallenge
, OK
),
9504 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9505 // Non-authenticating HTTP server through a non-authenticating proxy.
9506 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9507 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9508 // Authenticating HTTP server through a non-authenticating proxy.
9509 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9510 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9511 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9512 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9513 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9514 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9515 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9516 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9517 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9518 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9519 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9520 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9521 // Non-authenticating HTTP server through an authenticating proxy.
9522 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9523 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9524 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9525 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9526 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9527 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9528 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9529 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9530 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9531 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9532 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9533 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9534 // Authenticating HTTP server through an authenticating proxy.
9535 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9536 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9537 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9538 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9539 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9540 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9541 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9542 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9543 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9544 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9545 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9546 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9547 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9548 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9549 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9550 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9551 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9552 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9553 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9554 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9555 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9556 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9557 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9558 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9559 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9560 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9561 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9562 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9563 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9564 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9565 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9566 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9567 // Non-authenticating HTTPS server with a direct connection.
9568 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9569 { TestRound(kGet
, kSuccess
, OK
)}},
9570 // Authenticating HTTPS server with a direct connection.
9571 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9572 { TestRound(kGet
, kServerChallenge
, OK
),
9573 TestRound(kGetAuth
, kSuccess
, OK
)}},
9574 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9575 { TestRound(kGet
, kServerChallenge
, OK
),
9576 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9577 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9578 { TestRound(kGet
, kServerChallenge
, OK
),
9579 TestRound(kGetAuth
, kSuccess
, OK
)}},
9580 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9581 { TestRound(kGet
, kServerChallenge
, OK
),
9582 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9583 // Non-authenticating HTTPS server with a non-authenticating proxy.
9584 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9585 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9586 // Authenticating HTTPS server through a non-authenticating proxy.
9587 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9588 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9589 TestRound(kGetAuth
, kSuccess
, OK
)}},
9590 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9591 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9592 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9593 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9594 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9595 TestRound(kGetAuth
, kSuccess
, OK
)}},
9596 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9597 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9598 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9599 // Non-Authenticating HTTPS server through an authenticating proxy.
9600 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9601 { TestRound(kConnect
, kProxyChallenge
, OK
),
9602 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9603 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9604 { TestRound(kConnect
, kProxyChallenge
, OK
),
9605 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9606 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9607 { TestRound(kConnect
, kProxyChallenge
, OK
),
9608 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9609 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9610 { TestRound(kConnect
, kProxyChallenge
, OK
),
9611 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9612 // Authenticating HTTPS server through an authenticating proxy.
9613 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9614 { TestRound(kConnect
, kProxyChallenge
, OK
),
9615 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9616 &kGet
, &kServerChallenge
),
9617 TestRound(kGetAuth
, kSuccess
, OK
)}},
9618 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9619 { TestRound(kConnect
, kProxyChallenge
, OK
),
9620 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9621 &kGet
, &kServerChallenge
),
9622 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9623 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9624 { TestRound(kConnect
, kProxyChallenge
, OK
),
9625 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9626 &kGet
, &kServerChallenge
),
9627 TestRound(kGetAuth
, kSuccess
, OK
)}},
9628 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9629 { TestRound(kConnect
, kProxyChallenge
, OK
),
9630 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9631 &kGet
, &kServerChallenge
),
9632 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9633 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9634 { TestRound(kConnect
, kProxyChallenge
, OK
),
9635 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9636 &kGet
, &kServerChallenge
),
9637 TestRound(kGetAuth
, kSuccess
, OK
)}},
9638 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9639 { TestRound(kConnect
, kProxyChallenge
, OK
),
9640 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9641 &kGet
, &kServerChallenge
),
9642 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9643 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9644 { TestRound(kConnect
, kProxyChallenge
, OK
),
9645 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9646 &kGet
, &kServerChallenge
),
9647 TestRound(kGetAuth
, kSuccess
, OK
)}},
9648 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9649 { TestRound(kConnect
, kProxyChallenge
, OK
),
9650 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9651 &kGet
, &kServerChallenge
),
9652 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9655 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_configs
); ++i
) {
9656 HttpAuthHandlerMock::Factory
* auth_factory(
9657 new HttpAuthHandlerMock::Factory());
9658 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9659 const TestConfig
& test_config
= test_configs
[i
];
9661 // Set up authentication handlers as necessary.
9662 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9663 for (int n
= 0; n
< 2; n
++) {
9664 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9665 std::string auth_challenge
= "Mock realm=proxy";
9666 GURL
origin(test_config
.proxy_url
);
9667 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9668 auth_challenge
.end());
9669 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9670 origin
, BoundNetLog());
9671 auth_handler
->SetGenerateExpectation(
9672 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9673 test_config
.proxy_auth_rv
);
9674 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9677 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9678 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9679 std::string auth_challenge
= "Mock realm=server";
9680 GURL
origin(test_config
.server_url
);
9681 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9682 auth_challenge
.end());
9683 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9684 origin
, BoundNetLog());
9685 auth_handler
->SetGenerateExpectation(
9686 test_config
.server_auth_timing
== AUTH_ASYNC
,
9687 test_config
.server_auth_rv
);
9688 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9690 if (test_config
.proxy_url
) {
9691 session_deps_
.proxy_service
.reset(
9692 ProxyService::CreateFixed(test_config
.proxy_url
));
9694 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9697 HttpRequestInfo request
;
9698 request
.method
= "GET";
9699 request
.url
= GURL(test_config
.server_url
);
9700 request
.load_flags
= 0;
9702 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9703 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
9705 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9706 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9708 // Set up expected reads and writes.
9710 reads
[0] = read_write_round
.read
;
9711 size_t length_reads
= 1;
9712 if (read_write_round
.extra_read
) {
9713 reads
[1] = *read_write_round
.extra_read
;
9717 MockWrite writes
[2];
9718 writes
[0] = read_write_round
.write
;
9719 size_t length_writes
= 1;
9720 if (read_write_round
.extra_write
) {
9721 writes
[1] = *read_write_round
.extra_write
;
9724 StaticSocketDataProvider
data_provider(
9725 reads
, length_reads
, writes
, length_writes
);
9726 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9728 // Add an SSL sequence if necessary.
9729 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9730 if (round
>= test_config
.first_ssl_round
)
9731 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9732 &ssl_socket_data_provider
);
9734 // Start or restart the transaction.
9735 TestCompletionCallback callback
;
9738 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9740 rv
= trans
.RestartWithAuth(
9741 AuthCredentials(kFoo
, kBar
), callback
.callback());
9743 if (rv
== ERR_IO_PENDING
)
9744 rv
= callback
.WaitForResult();
9746 // Compare results with expected data.
9747 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9748 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9749 if (read_write_round
.expected_rv
== OK
) {
9750 ASSERT_TRUE(response
!= NULL
);
9752 EXPECT_TRUE(response
== NULL
);
9753 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9756 if (round
+ 1 < test_config
.num_auth_rounds
) {
9757 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9759 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9765 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9766 // Do multi-round authentication and make sure it works correctly.
9767 HttpAuthHandlerMock::Factory
* auth_factory(
9768 new HttpAuthHandlerMock::Factory());
9769 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9770 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9771 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9772 session_deps_
.host_resolver
->set_synchronous_mode(true);
9774 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9775 auth_handler
->set_connection_based(true);
9776 std::string auth_challenge
= "Mock realm=server";
9777 GURL
origin("http://www.example.com");
9778 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9779 auth_challenge
.end());
9780 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9781 origin
, BoundNetLog());
9782 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9785 const HttpResponseInfo
* response
= NULL
;
9786 HttpRequestInfo request
;
9787 request
.method
= "GET";
9788 request
.url
= origin
;
9789 request
.load_flags
= 0;
9791 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9793 // Use a TCP Socket Pool with only one connection per group. This is used
9794 // to validate that the TCP socket is not released to the pool between
9795 // each round of multi-round authentication.
9796 HttpNetworkSessionPeer
session_peer(session
);
9797 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9798 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9799 50, // Max sockets for pool
9800 1, // Max sockets per group
9801 &transport_pool_histograms
,
9802 session_deps_
.host_resolver
.get(),
9803 session_deps_
.socket_factory
.get(),
9804 session_deps_
.net_log
);
9805 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
9806 new MockClientSocketPoolManager
);
9807 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9808 session_peer
.SetClientSocketPoolManager(
9809 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
9811 scoped_ptr
<HttpTransaction
> trans(
9812 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9813 TestCompletionCallback callback
;
9815 const MockWrite
kGet(
9816 "GET / HTTP/1.1\r\n"
9817 "Host: www.example.com\r\n"
9818 "Connection: keep-alive\r\n\r\n");
9819 const MockWrite
kGetAuth(
9820 "GET / HTTP/1.1\r\n"
9821 "Host: www.example.com\r\n"
9822 "Connection: keep-alive\r\n"
9823 "Authorization: auth_token\r\n\r\n");
9825 const MockRead
kServerChallenge(
9826 "HTTP/1.1 401 Unauthorized\r\n"
9827 "WWW-Authenticate: Mock realm=server\r\n"
9828 "Content-Type: text/html; charset=iso-8859-1\r\n"
9829 "Content-Length: 14\r\n\r\n"
9830 "Unauthorized\r\n");
9831 const MockRead
kSuccess(
9832 "HTTP/1.1 200 OK\r\n"
9833 "Content-Type: text/html; charset=iso-8859-1\r\n"
9834 "Content-Length: 3\r\n\r\n"
9837 MockWrite writes
[] = {
9846 // Competing request
9849 MockRead reads
[] = {
9858 // Competing response
9861 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9862 writes
, arraysize(writes
));
9863 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9865 const char* const kSocketGroup
= "www.example.com:80";
9867 // First round of authentication.
9868 auth_handler
->SetGenerateExpectation(false, OK
);
9869 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9870 if (rv
== ERR_IO_PENDING
)
9871 rv
= callback
.WaitForResult();
9873 response
= trans
->GetResponseInfo();
9874 ASSERT_TRUE(response
!= NULL
);
9875 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9876 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9878 // In between rounds, another request comes in for the same domain.
9879 // It should not be able to grab the TCP socket that trans has already
9881 scoped_ptr
<HttpTransaction
> trans_compete(
9882 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9883 TestCompletionCallback callback_compete
;
9884 rv
= trans_compete
->Start(
9885 &request
, callback_compete
.callback(), BoundNetLog());
9886 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9887 // callback_compete.WaitForResult at this point would stall forever,
9888 // since the HttpNetworkTransaction does not release the request back to
9889 // the pool until after authentication completes.
9891 // Second round of authentication.
9892 auth_handler
->SetGenerateExpectation(false, OK
);
9893 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9894 if (rv
== ERR_IO_PENDING
)
9895 rv
= callback
.WaitForResult();
9897 response
= trans
->GetResponseInfo();
9898 ASSERT_TRUE(response
!= NULL
);
9899 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9900 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9902 // Third round of authentication.
9903 auth_handler
->SetGenerateExpectation(false, OK
);
9904 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9905 if (rv
== ERR_IO_PENDING
)
9906 rv
= callback
.WaitForResult();
9908 response
= trans
->GetResponseInfo();
9909 ASSERT_TRUE(response
!= NULL
);
9910 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9911 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9913 // Fourth round of authentication, which completes successfully.
9914 auth_handler
->SetGenerateExpectation(false, OK
);
9915 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9916 if (rv
== ERR_IO_PENDING
)
9917 rv
= callback
.WaitForResult();
9919 response
= trans
->GetResponseInfo();
9920 ASSERT_TRUE(response
!= NULL
);
9921 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9922 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9924 // Read the body since the fourth round was successful. This will also
9925 // release the socket back to the pool.
9926 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9927 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9928 if (rv
== ERR_IO_PENDING
)
9929 rv
= callback
.WaitForResult();
9931 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9933 // There are still 0 idle sockets, since the trans_compete transaction
9934 // will be handed it immediately after trans releases it to the group.
9935 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9937 // The competing request can now finish. Wait for the headers and then
9939 rv
= callback_compete
.WaitForResult();
9941 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9942 if (rv
== ERR_IO_PENDING
)
9943 rv
= callback
.WaitForResult();
9945 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9948 // Finally, the socket is released to the group.
9949 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9952 // This tests the case that a request is issued via http instead of spdy after
9953 // npn is negotiated.
9954 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9955 session_deps_
.use_alternate_protocols
= true;
9956 NextProtoVector next_protos
;
9957 next_protos
.push_back(kProtoHTTP11
);
9958 session_deps_
.next_protos
= next_protos
;
9960 HttpRequestInfo request
;
9961 request
.method
= "GET";
9962 request
.url
= GURL("https://www.google.com/");
9963 request
.load_flags
= 0;
9965 MockWrite data_writes
[] = {
9966 MockWrite("GET / HTTP/1.1\r\n"
9967 "Host: www.google.com\r\n"
9968 "Connection: keep-alive\r\n\r\n"),
9971 std::string alternate_protocol_http_header
=
9972 GetAlternateProtocolHttpHeader();
9974 MockRead data_reads
[] = {
9975 MockRead("HTTP/1.1 200 OK\r\n"),
9976 MockRead(alternate_protocol_http_header
.c_str()),
9977 MockRead("hello world"),
9978 MockRead(SYNCHRONOUS
, OK
),
9981 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9982 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9983 ssl
.next_proto
= "http/1.1";
9984 ssl
.protocol_negotiated
= kProtoHTTP11
;
9986 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9988 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9989 data_writes
, arraysize(data_writes
));
9990 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9992 TestCompletionCallback callback
;
9994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9995 scoped_ptr
<HttpTransaction
> trans(
9996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9998 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10001 EXPECT_EQ(OK
, callback
.WaitForResult());
10003 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10004 ASSERT_TRUE(response
!= NULL
);
10005 ASSERT_TRUE(response
->headers
.get() != NULL
);
10006 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10008 std::string response_data
;
10009 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10010 EXPECT_EQ("hello world", response_data
);
10012 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10013 EXPECT_TRUE(response
->was_npn_negotiated
);
10016 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10017 // Simulate the SSL handshake completing with an NPN negotiation
10018 // followed by an immediate server closing of the socket.
10019 // Fix crash: http://crbug.com/46369
10020 session_deps_
.use_alternate_protocols
= true;
10021 session_deps_
.next_protos
= SpdyNextProtos();
10023 HttpRequestInfo request
;
10024 request
.method
= "GET";
10025 request
.url
= GURL("https://www.google.com/");
10026 request
.load_flags
= 0;
10028 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10029 ssl
.SetNextProto(GetParam());
10030 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10032 scoped_ptr
<SpdyFrame
> req(
10033 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10034 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10036 MockRead spdy_reads
[] = {
10037 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10040 DelayedSocketData
spdy_data(
10041 0, // don't wait in this case, immediate hangup.
10042 spdy_reads
, arraysize(spdy_reads
),
10043 spdy_writes
, arraysize(spdy_writes
));
10044 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10046 TestCompletionCallback callback
;
10048 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10049 scoped_ptr
<HttpTransaction
> trans(
10050 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10052 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10054 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10057 // A subclass of HttpAuthHandlerMock that records the request URL when
10058 // it gets it. This is needed since the auth handler may get destroyed
10059 // before we get a chance to query it.
10060 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10062 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10064 virtual ~UrlRecordingHttpAuthHandlerMock() {}
10067 virtual int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10068 const HttpRequestInfo
* request
,
10069 const CompletionCallback
& callback
,
10070 std::string
* auth_token
) OVERRIDE
{
10071 *url_
= request
->url
;
10072 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10073 credentials
, request
, callback
, auth_token
);
10080 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10081 // This test ensures that the URL passed into the proxy is upgraded
10082 // to https when doing an Alternate Protocol upgrade.
10083 session_deps_
.use_alternate_protocols
= true;
10084 session_deps_
.next_protos
= SpdyNextProtos();
10086 session_deps_
.proxy_service
.reset(
10087 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10088 CapturingNetLog net_log
;
10089 session_deps_
.net_log
= &net_log
;
10092 HttpAuthHandlerMock::Factory
* auth_factory
=
10093 new HttpAuthHandlerMock::Factory();
10094 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10095 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10096 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10097 auth_factory
->set_do_init_from_challenge(true);
10098 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10101 HttpRequestInfo request
;
10102 request
.method
= "GET";
10103 request
.url
= GURL("http://www.google.com");
10104 request
.load_flags
= 0;
10106 // First round goes unauthenticated through the proxy.
10107 MockWrite data_writes_1
[] = {
10108 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10109 "Host: www.google.com\r\n"
10110 "Proxy-Connection: keep-alive\r\n"
10113 MockRead data_reads_1
[] = {
10114 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10115 MockRead("HTTP/1.1 200 OK\r\n"
10116 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10117 "Proxy-Connection: close\r\n"
10120 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10121 data_writes_1
, arraysize(data_writes_1
));
10123 // Second round tries to tunnel to www.google.com due to the
10124 // Alternate-Protocol announcement in the first round. It fails due
10125 // to a proxy authentication challenge.
10126 // After the failure, a tunnel is established to www.google.com using
10127 // Proxy-Authorization headers. There is then a SPDY request round.
10129 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10130 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10131 // does a Disconnect and Connect on the same socket, rather than trying
10132 // to obtain a new one.
10134 // NOTE: Originally, the proxy response to the second CONNECT request
10135 // simply returned another 407 so the unit test could skip the SSL connection
10136 // establishment and SPDY framing issues. Alas, the
10137 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10138 // complicated to set up expectations for than the SPDY session.
10140 scoped_ptr
<SpdyFrame
> req(
10141 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10142 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10143 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10145 MockWrite data_writes_2
[] = {
10146 // First connection attempt without Proxy-Authorization.
10147 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10148 "Host: www.google.com\r\n"
10149 "Proxy-Connection: keep-alive\r\n"
10152 // Second connection attempt with Proxy-Authorization.
10153 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10154 "Host: www.google.com\r\n"
10155 "Proxy-Connection: keep-alive\r\n"
10156 "Proxy-Authorization: auth_token\r\n"
10160 CreateMockWrite(*req
),
10162 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10163 "Proxy-Authenticate: Mock\r\n"
10164 "Proxy-Connection: close\r\n"
10166 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10167 MockRead data_reads_2
[] = {
10168 // First connection attempt fails
10169 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10170 MockRead(ASYNC
, kRejectConnectResponse
,
10171 arraysize(kRejectConnectResponse
) - 1, 1),
10173 // Second connection attempt passes
10174 MockRead(ASYNC
, kAcceptConnectResponse
,
10175 arraysize(kAcceptConnectResponse
) -1, 4),
10178 CreateMockRead(*resp
.get(), 6),
10179 CreateMockRead(*data
.get(), 6),
10180 MockRead(ASYNC
, 0, 0, 6),
10182 OrderedSocketData
data_2(
10183 data_reads_2
, arraysize(data_reads_2
),
10184 data_writes_2
, arraysize(data_writes_2
));
10186 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10187 ssl
.SetNextProto(GetParam());
10189 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10190 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10192 hanging_non_alternate_protocol_socket
.set_connect_data(
10193 never_finishing_connect
);
10195 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10196 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10197 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10198 session_deps_
.socket_factory
->AddSocketDataProvider(
10199 &hanging_non_alternate_protocol_socket
);
10200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10202 // First round should work and provide the Alternate-Protocol state.
10203 TestCompletionCallback callback_1
;
10204 scoped_ptr
<HttpTransaction
> trans_1(
10205 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10206 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10208 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10210 // Second round should attempt a tunnel connect and get an auth challenge.
10211 TestCompletionCallback callback_2
;
10212 scoped_ptr
<HttpTransaction
> trans_2(
10213 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10214 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10215 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10216 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10217 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10218 ASSERT_TRUE(response
!= NULL
);
10219 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10221 // Restart with auth. Tunnel should work and response received.
10222 TestCompletionCallback callback_3
;
10223 rv
= trans_2
->RestartWithAuth(
10224 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10225 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10226 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10228 // After all that work, these two lines (or actually, just the scheme) are
10229 // what this test is all about. Make sure it happens correctly.
10230 EXPECT_EQ("https", request_url
.scheme());
10231 EXPECT_EQ("www.google.com", request_url
.host());
10233 LoadTimingInfo load_timing_info
;
10234 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10235 TestLoadTimingNotReusedWithPac(load_timing_info
,
10236 CONNECT_TIMING_HAS_SSL_TIMES
);
10239 // Test that if we cancel the transaction as the connection is completing, that
10240 // everything tears down correctly.
10241 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10242 // Setup everything about the connection to complete synchronously, so that
10243 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10244 // for is the callback from the HttpStreamRequest.
10245 // Then cancel the transaction.
10246 // Verify that we don't crash.
10247 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10248 MockRead data_reads
[] = {
10249 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10250 MockRead(SYNCHRONOUS
, "hello world"),
10251 MockRead(SYNCHRONOUS
, OK
),
10254 HttpRequestInfo request
;
10255 request
.method
= "GET";
10256 request
.url
= GURL("http://www.google.com/");
10257 request
.load_flags
= 0;
10259 session_deps_
.host_resolver
->set_synchronous_mode(true);
10260 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10261 scoped_ptr
<HttpTransaction
> trans(
10262 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
10264 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10265 data
.set_connect_data(mock_connect
);
10266 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10268 TestCompletionCallback callback
;
10270 CapturingBoundNetLog log
;
10271 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10273 trans
.reset(); // Cancel the transaction here.
10275 base::MessageLoop::current()->RunUntilIdle();
10278 // Test that if a transaction is cancelled after receiving the headers, the
10279 // stream is drained properly and added back to the socket pool. The main
10280 // purpose of this test is to make sure that an HttpStreamParser can be read
10281 // from after the HttpNetworkTransaction and the objects it owns have been
10283 // See http://crbug.com/368418
10284 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10285 MockRead data_reads
[] = {
10286 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10287 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10288 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10289 MockRead(ASYNC
, "1"),
10290 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10291 // HttpNetworkTransaction has been deleted.
10292 MockRead(ASYNC
, "2"),
10293 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10295 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10296 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10298 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10301 HttpRequestInfo request
;
10302 request
.method
= "GET";
10303 request
.url
= GURL("http://www.google.com/");
10304 request
.load_flags
= 0;
10306 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
10307 TestCompletionCallback callback
;
10309 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10311 callback
.WaitForResult();
10313 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10314 ASSERT_TRUE(response
!= NULL
);
10315 EXPECT_TRUE(response
->headers
.get() != NULL
);
10316 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10318 // The transaction and HttpRequestInfo are deleted.
10321 // Let the HttpResponseBodyDrainer drain the socket.
10322 base::MessageLoop::current()->RunUntilIdle();
10324 // Socket should now be idle, waiting to be reused.
10325 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
10328 // Test a basic GET request through a proxy.
10329 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10330 session_deps_
.proxy_service
.reset(
10331 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10332 CapturingBoundNetLog log
;
10333 session_deps_
.net_log
= log
.bound().net_log();
10334 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10336 HttpRequestInfo request
;
10337 request
.method
= "GET";
10338 request
.url
= GURL("http://www.google.com/");
10340 MockWrite data_writes1
[] = {
10341 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10342 "Host: www.google.com\r\n"
10343 "Proxy-Connection: keep-alive\r\n\r\n"),
10346 MockRead data_reads1
[] = {
10347 MockRead("HTTP/1.1 200 OK\r\n"),
10348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10349 MockRead("Content-Length: 100\r\n\r\n"),
10350 MockRead(SYNCHRONOUS
, OK
),
10353 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10354 data_writes1
, arraysize(data_writes1
));
10355 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10357 TestCompletionCallback callback1
;
10359 scoped_ptr
<HttpTransaction
> trans(
10360 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10361 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10362 trans
->SetBeforeProxyHeadersSentCallback(
10363 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10364 base::Unretained(&proxy_headers_handler
)));
10366 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10367 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10369 rv
= callback1
.WaitForResult();
10372 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10373 ASSERT_TRUE(response
!= NULL
);
10375 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10376 EXPECT_EQ(200, response
->headers
->response_code());
10377 EXPECT_EQ(100, response
->headers
->GetContentLength());
10378 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10380 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10381 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10382 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10383 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10385 LoadTimingInfo load_timing_info
;
10386 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10387 TestLoadTimingNotReusedWithPac(load_timing_info
,
10388 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10391 // Test a basic HTTPS GET request through a proxy.
10392 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10393 session_deps_
.proxy_service
.reset(
10394 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10395 CapturingBoundNetLog log
;
10396 session_deps_
.net_log
= log
.bound().net_log();
10397 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10399 HttpRequestInfo request
;
10400 request
.method
= "GET";
10401 request
.url
= GURL("https://www.google.com/");
10403 // Since we have proxy, should try to establish tunnel.
10404 MockWrite data_writes1
[] = {
10405 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10406 "Host: www.google.com\r\n"
10407 "Proxy-Connection: keep-alive\r\n\r\n"),
10409 MockWrite("GET / HTTP/1.1\r\n"
10410 "Host: www.google.com\r\n"
10411 "Connection: keep-alive\r\n\r\n"),
10414 MockRead data_reads1
[] = {
10415 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10417 MockRead("HTTP/1.1 200 OK\r\n"),
10418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10419 MockRead("Content-Length: 100\r\n\r\n"),
10420 MockRead(SYNCHRONOUS
, OK
),
10423 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10424 data_writes1
, arraysize(data_writes1
));
10425 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10426 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10427 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10429 TestCompletionCallback callback1
;
10431 scoped_ptr
<HttpTransaction
> trans(
10432 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10434 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10435 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10437 rv
= callback1
.WaitForResult();
10439 net::CapturingNetLog::CapturedEntryList entries
;
10440 log
.GetEntries(&entries
);
10441 size_t pos
= ExpectLogContainsSomewhere(
10442 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10443 NetLog::PHASE_NONE
);
10444 ExpectLogContainsSomewhere(
10446 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10447 NetLog::PHASE_NONE
);
10449 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10450 ASSERT_TRUE(response
!= NULL
);
10452 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10453 EXPECT_EQ(200, response
->headers
->response_code());
10454 EXPECT_EQ(100, response
->headers
->GetContentLength());
10455 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10456 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10458 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10460 LoadTimingInfo load_timing_info
;
10461 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10462 TestLoadTimingNotReusedWithPac(load_timing_info
,
10463 CONNECT_TIMING_HAS_SSL_TIMES
);
10466 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10467 // while establishing the tunnel.
10468 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10469 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10470 CapturingBoundNetLog log
;
10471 session_deps_
.net_log
= log
.bound().net_log();
10472 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10474 HttpRequestInfo request
;
10475 request
.method
= "GET";
10476 request
.url
= GURL("https://www.google.com/");
10478 // Since we have proxy, should try to establish tunnel.
10479 MockWrite data_writes1
[] = {
10480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10481 "Host: www.google.com\r\n"
10482 "Proxy-Connection: keep-alive\r\n\r\n"),
10484 MockWrite("GET / HTTP/1.1\r\n"
10485 "Host: www.google.com\r\n"
10486 "Connection: keep-alive\r\n\r\n"),
10489 MockRead data_reads1
[] = {
10490 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10491 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10492 MockRead(ASYNC
, 0, 0), // EOF
10495 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10496 data_writes1
, arraysize(data_writes1
));
10497 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10498 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10499 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10501 TestCompletionCallback callback1
;
10503 scoped_ptr
<HttpTransaction
> trans(
10504 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10506 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10507 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10509 rv
= callback1
.WaitForResult();
10510 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10511 net::CapturingNetLog::CapturedEntryList entries
;
10512 log
.GetEntries(&entries
);
10513 size_t pos
= ExpectLogContainsSomewhere(
10514 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10515 NetLog::PHASE_NONE
);
10516 ExpectLogContainsSomewhere(
10518 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10519 NetLog::PHASE_NONE
);
10522 // Test for crbug.com/55424.
10523 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10524 scoped_ptr
<SpdyFrame
> req(
10525 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10526 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10528 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10529 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10530 MockRead spdy_reads
[] = {
10531 CreateMockRead(*resp
),
10532 CreateMockRead(*data
),
10533 MockRead(ASYNC
, 0, 0),
10536 DelayedSocketData
spdy_data(
10537 1, // wait for one write to finish before reading.
10538 spdy_reads
, arraysize(spdy_reads
),
10539 spdy_writes
, arraysize(spdy_writes
));
10540 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10542 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10543 ssl
.SetNextProto(GetParam());
10544 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10546 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10548 // Set up an initial SpdySession in the pool to reuse.
10549 HostPortPair
host_port_pair("www.google.com", 443);
10550 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10551 PRIVACY_MODE_DISABLED
);
10552 base::WeakPtr
<SpdySession
> spdy_session
=
10553 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10555 HttpRequestInfo request
;
10556 request
.method
= "GET";
10557 request
.url
= GURL("https://www.google.com/");
10558 request
.load_flags
= 0;
10560 // This is the important line that marks this as a preconnect.
10561 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10563 scoped_ptr
<HttpTransaction
> trans(
10564 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10566 TestCompletionCallback callback
;
10567 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10569 EXPECT_EQ(OK
, callback
.WaitForResult());
10572 // Given a net error, cause that error to be returned from the first Write()
10573 // call and verify that the HttpTransaction fails with that error.
10574 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10575 int error
, IoMode mode
) {
10576 net::HttpRequestInfo request_info
;
10577 request_info
.url
= GURL("https://www.example.com/");
10578 request_info
.method
= "GET";
10579 request_info
.load_flags
= net::LOAD_NORMAL
;
10581 SSLSocketDataProvider
ssl_data(mode
, OK
);
10582 net::MockWrite data_writes
[] = {
10583 net::MockWrite(mode
, error
),
10585 net::StaticSocketDataProvider
data(NULL
, 0,
10586 data_writes
, arraysize(data_writes
));
10587 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10588 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10590 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10591 scoped_ptr
<HttpTransaction
> trans(
10592 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10594 TestCompletionCallback callback
;
10595 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10596 if (rv
== net::ERR_IO_PENDING
)
10597 rv
= callback
.WaitForResult();
10598 ASSERT_EQ(error
, rv
);
10601 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10602 // Just check a grab bag of cert errors.
10603 static const int kErrors
[] = {
10604 ERR_CERT_COMMON_NAME_INVALID
,
10605 ERR_CERT_AUTHORITY_INVALID
,
10606 ERR_CERT_DATE_INVALID
,
10608 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10609 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10610 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10614 // Ensure that a client certificate is removed from the SSL client auth
10616 // 1) No proxy is involved.
10617 // 2) TLS False Start is disabled.
10618 // 3) The initial TLS handshake requests a client certificate.
10619 // 4) The client supplies an invalid/unacceptable certificate.
10620 TEST_P(HttpNetworkTransactionTest
,
10621 ClientAuthCertCache_Direct_NoFalseStart
) {
10622 net::HttpRequestInfo request_info
;
10623 request_info
.url
= GURL("https://www.example.com/");
10624 request_info
.method
= "GET";
10625 request_info
.load_flags
= net::LOAD_NORMAL
;
10627 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10628 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10630 // [ssl_]data1 contains the data for the first SSL handshake. When a
10631 // CertificateRequest is received for the first time, the handshake will
10632 // be aborted to allow the caller to provide a certificate.
10633 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10634 ssl_data1
.cert_request_info
= cert_request
.get();
10635 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10636 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10637 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10639 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10640 // False Start is not being used, the result of the SSL handshake will be
10641 // returned as part of the SSLClientSocket::Connect() call. This test
10642 // matches the result of a server sending a handshake_failure alert,
10643 // rather than a Finished message, because it requires a client
10644 // certificate and none was supplied.
10645 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10646 ssl_data2
.cert_request_info
= cert_request
.get();
10647 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10648 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10649 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10651 // [ssl_]data3 contains the data for the third SSL handshake. When a
10652 // connection to a server fails during an SSL handshake,
10653 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10654 // connection was attempted with TLSv1.1. This is transparent to the caller
10655 // of the HttpNetworkTransaction. Because this test failure is due to
10656 // requiring a client certificate, this fallback handshake should also
10658 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10659 ssl_data3
.cert_request_info
= cert_request
.get();
10660 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10661 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10662 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10664 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10665 // connection to a server fails during an SSL handshake,
10666 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10667 // connection was attempted with TLSv1. This is transparent to the caller
10668 // of the HttpNetworkTransaction. Because this test failure is due to
10669 // requiring a client certificate, this fallback handshake should also
10671 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10672 ssl_data4
.cert_request_info
= cert_request
.get();
10673 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10674 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10675 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10677 // Need one more if TLSv1.2 is enabled.
10678 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10679 ssl_data5
.cert_request_info
= cert_request
.get();
10680 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10681 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10682 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10684 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10685 scoped_ptr
<HttpTransaction
> trans(
10686 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10688 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10689 TestCompletionCallback callback
;
10690 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10691 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10693 // Complete the SSL handshake, which should abort due to requiring a
10694 // client certificate.
10695 rv
= callback
.WaitForResult();
10696 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10698 // Indicate that no certificate should be supplied. From the perspective
10699 // of SSLClientCertCache, NULL is just as meaningful as a real
10700 // certificate, so this is the same as supply a
10701 // legitimate-but-unacceptable certificate.
10702 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10703 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10705 // Ensure the certificate was added to the client auth cache before
10706 // allowing the connection to continue restarting.
10707 scoped_refptr
<X509Certificate
> client_cert
;
10708 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10709 HostPortPair("www.example.com", 443), &client_cert
));
10710 ASSERT_EQ(NULL
, client_cert
.get());
10712 // Restart the handshake. This will consume ssl_data2, which fails, and
10713 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10714 // The result code is checked against what ssl_data4 should return.
10715 rv
= callback
.WaitForResult();
10716 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10718 // Ensure that the client certificate is removed from the cache on a
10719 // handshake failure.
10720 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10721 HostPortPair("www.example.com", 443), &client_cert
));
10724 // Ensure that a client certificate is removed from the SSL client auth
10726 // 1) No proxy is involved.
10727 // 2) TLS False Start is enabled.
10728 // 3) The initial TLS handshake requests a client certificate.
10729 // 4) The client supplies an invalid/unacceptable certificate.
10730 TEST_P(HttpNetworkTransactionTest
,
10731 ClientAuthCertCache_Direct_FalseStart
) {
10732 net::HttpRequestInfo request_info
;
10733 request_info
.url
= GURL("https://www.example.com/");
10734 request_info
.method
= "GET";
10735 request_info
.load_flags
= net::LOAD_NORMAL
;
10737 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10738 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10740 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10741 // return successfully after reading up to the peer's Certificate message.
10742 // This is to allow the caller to call SSLClientSocket::Write(), which can
10743 // enqueue application data to be sent in the same packet as the
10744 // ChangeCipherSpec and Finished messages.
10745 // The actual handshake will be finished when SSLClientSocket::Read() is
10746 // called, which expects to process the peer's ChangeCipherSpec and
10747 // Finished messages. If there was an error negotiating with the peer,
10748 // such as due to the peer requiring a client certificate when none was
10749 // supplied, the alert sent by the peer won't be processed until Read() is
10752 // Like the non-False Start case, when a client certificate is requested by
10753 // the peer, the handshake is aborted during the Connect() call.
10754 // [ssl_]data1 represents the initial SSL handshake with the peer.
10755 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10756 ssl_data1
.cert_request_info
= cert_request
.get();
10757 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10758 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10759 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10761 // When a client certificate is supplied, Connect() will not be aborted
10762 // when the peer requests the certificate. Instead, the handshake will
10763 // artificially succeed, allowing the caller to write the HTTP request to
10764 // the socket. The handshake messages are not processed until Read() is
10765 // called, which then detects that the handshake was aborted, due to the
10766 // peer sending a handshake_failure because it requires a client
10768 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10769 ssl_data2
.cert_request_info
= cert_request
.get();
10770 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10771 net::MockRead data2_reads
[] = {
10772 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10774 net::StaticSocketDataProvider
data2(
10775 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10776 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10778 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10779 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10780 // TLSv1. It has the same behaviour as [ssl_]data2.
10781 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10782 ssl_data3
.cert_request_info
= cert_request
.get();
10783 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10784 net::StaticSocketDataProvider
data3(
10785 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10786 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10788 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10789 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10790 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10791 ssl_data4
.cert_request_info
= cert_request
.get();
10792 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10793 net::StaticSocketDataProvider
data4(
10794 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10795 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10797 // Need one more if TLSv1.2 is enabled.
10798 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10799 ssl_data5
.cert_request_info
= cert_request
.get();
10800 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10801 net::StaticSocketDataProvider
data5(
10802 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10803 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10805 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10806 scoped_ptr
<HttpTransaction
> trans(
10807 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10809 // Begin the initial SSL handshake.
10810 TestCompletionCallback callback
;
10811 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10812 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10814 // Complete the SSL handshake, which should abort due to requiring a
10815 // client certificate.
10816 rv
= callback
.WaitForResult();
10817 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10819 // Indicate that no certificate should be supplied. From the perspective
10820 // of SSLClientCertCache, NULL is just as meaningful as a real
10821 // certificate, so this is the same as supply a
10822 // legitimate-but-unacceptable certificate.
10823 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10824 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10826 // Ensure the certificate was added to the client auth cache before
10827 // allowing the connection to continue restarting.
10828 scoped_refptr
<X509Certificate
> client_cert
;
10829 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10830 HostPortPair("www.example.com", 443), &client_cert
));
10831 ASSERT_EQ(NULL
, client_cert
.get());
10833 // Restart the handshake. This will consume ssl_data2, which fails, and
10834 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10835 // The result code is checked against what ssl_data4 should return.
10836 rv
= callback
.WaitForResult();
10837 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10839 // Ensure that the client certificate is removed from the cache on a
10840 // handshake failure.
10841 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10842 HostPortPair("www.example.com", 443), &client_cert
));
10845 // Ensure that a client certificate is removed from the SSL client auth
10847 // 1) An HTTPS proxy is involved.
10848 // 3) The HTTPS proxy requests a client certificate.
10849 // 4) The client supplies an invalid/unacceptable certificate for the
10851 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10852 // then for connecting to an HTTP endpoint.
10853 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10854 session_deps_
.proxy_service
.reset(
10855 ProxyService::CreateFixed("https://proxy:70"));
10856 CapturingBoundNetLog log
;
10857 session_deps_
.net_log
= log
.bound().net_log();
10859 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10860 cert_request
->host_and_port
= HostPortPair("proxy", 70);
10862 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10863 // [ssl_]data[1-3]. Rather than represending the endpoint
10864 // (www.example.com:443), they represent failures with the HTTPS proxy
10866 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10867 ssl_data1
.cert_request_info
= cert_request
.get();
10868 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10869 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10870 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10872 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10873 ssl_data2
.cert_request_info
= cert_request
.get();
10874 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10875 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10876 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10878 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10880 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10881 ssl_data3
.cert_request_info
= cert_request
.get();
10882 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10883 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10884 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10887 net::HttpRequestInfo requests
[2];
10888 requests
[0].url
= GURL("https://www.example.com/");
10889 requests
[0].method
= "GET";
10890 requests
[0].load_flags
= net::LOAD_NORMAL
;
10892 requests
[1].url
= GURL("http://www.example.com/");
10893 requests
[1].method
= "GET";
10894 requests
[1].load_flags
= net::LOAD_NORMAL
;
10896 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10897 session_deps_
.socket_factory
->ResetNextMockIndexes();
10898 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10899 scoped_ptr
<HttpNetworkTransaction
> trans(
10900 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10902 // Begin the SSL handshake with the proxy.
10903 TestCompletionCallback callback
;
10904 int rv
= trans
->Start(
10905 &requests
[i
], callback
.callback(), net::BoundNetLog());
10906 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10908 // Complete the SSL handshake, which should abort due to requiring a
10909 // client certificate.
10910 rv
= callback
.WaitForResult();
10911 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10913 // Indicate that no certificate should be supplied. From the perspective
10914 // of SSLClientCertCache, NULL is just as meaningful as a real
10915 // certificate, so this is the same as supply a
10916 // legitimate-but-unacceptable certificate.
10917 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10918 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10920 // Ensure the certificate was added to the client auth cache before
10921 // allowing the connection to continue restarting.
10922 scoped_refptr
<X509Certificate
> client_cert
;
10923 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10924 HostPortPair("proxy", 70), &client_cert
));
10925 ASSERT_EQ(NULL
, client_cert
.get());
10926 // Ensure the certificate was NOT cached for the endpoint. This only
10927 // applies to HTTPS requests, but is fine to check for HTTP requests.
10928 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10929 HostPortPair("www.example.com", 443), &client_cert
));
10931 // Restart the handshake. This will consume ssl_data2, which fails, and
10932 // then consume ssl_data3, which should also fail. The result code is
10933 // checked against what ssl_data3 should return.
10934 rv
= callback
.WaitForResult();
10935 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10937 // Now that the new handshake has failed, ensure that the client
10938 // certificate was removed from the client auth cache.
10939 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10940 HostPortPair("proxy", 70), &client_cert
));
10941 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10942 HostPortPair("www.example.com", 443), &client_cert
));
10946 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10947 // TEST_P is a macro that expands directly to code that stringizes the
10948 // arguments. As a result, macros passed as parameters (such as prefix
10949 // or test_case_name) will not be expanded by the preprocessor. To
10950 // work around this, indirect the macro for TEST_P, so that the
10951 // pre-processor will expand macros such as MAYBE_test_name before
10952 // instantiating the test.
10953 #define WRAPPED_TEST_P(test_case_name, test_name) \
10954 TEST_P(test_case_name, test_name)
10956 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10957 #if defined(OS_WIN)
10958 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10960 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10962 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10963 session_deps_
.use_alternate_protocols
= true;
10964 session_deps_
.next_protos
= SpdyNextProtos();
10966 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10967 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10968 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10969 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10970 pool_peer
.DisableDomainAuthenticationVerification();
10972 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10973 ssl
.SetNextProto(GetParam());
10974 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10976 scoped_ptr
<SpdyFrame
> host1_req(
10977 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10978 scoped_ptr
<SpdyFrame
> host2_req(
10979 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10980 MockWrite spdy_writes
[] = {
10981 CreateMockWrite(*host1_req
, 1),
10982 CreateMockWrite(*host2_req
, 4),
10984 scoped_ptr
<SpdyFrame
> host1_resp(
10985 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10986 scoped_ptr
<SpdyFrame
> host1_resp_body(
10987 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10988 scoped_ptr
<SpdyFrame
> host2_resp(
10989 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10990 scoped_ptr
<SpdyFrame
> host2_resp_body(
10991 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10992 MockRead spdy_reads
[] = {
10993 CreateMockRead(*host1_resp
, 2),
10994 CreateMockRead(*host1_resp_body
, 3),
10995 CreateMockRead(*host2_resp
, 5),
10996 CreateMockRead(*host2_resp_body
, 6),
10997 MockRead(ASYNC
, 0, 7),
11000 IPAddressNumber ip
;
11001 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11002 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11003 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11004 OrderedSocketData
spdy_data(
11006 spdy_reads
, arraysize(spdy_reads
),
11007 spdy_writes
, arraysize(spdy_writes
));
11008 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11010 TestCompletionCallback callback
;
11011 HttpRequestInfo request1
;
11012 request1
.method
= "GET";
11013 request1
.url
= GURL("https://www.google.com/");
11014 request1
.load_flags
= 0;
11015 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11017 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11018 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11019 EXPECT_EQ(OK
, callback
.WaitForResult());
11021 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11022 ASSERT_TRUE(response
!= NULL
);
11023 ASSERT_TRUE(response
->headers
.get() != NULL
);
11024 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11026 std::string response_data
;
11027 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11028 EXPECT_EQ("hello!", response_data
);
11030 // Preload www.gmail.com into HostCache.
11031 HostPortPair
host_port("www.gmail.com", 443);
11032 HostResolver::RequestInfo
resolve_info(host_port
);
11033 AddressList ignored
;
11034 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11037 callback
.callback(),
11040 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11041 rv
= callback
.WaitForResult();
11044 HttpRequestInfo request2
;
11045 request2
.method
= "GET";
11046 request2
.url
= GURL("https://www.gmail.com/");
11047 request2
.load_flags
= 0;
11048 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11050 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11051 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11052 EXPECT_EQ(OK
, callback
.WaitForResult());
11054 response
= trans2
.GetResponseInfo();
11055 ASSERT_TRUE(response
!= NULL
);
11056 ASSERT_TRUE(response
->headers
.get() != NULL
);
11057 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11058 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11059 EXPECT_TRUE(response
->was_npn_negotiated
);
11060 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11061 EXPECT_EQ("hello!", response_data
);
11063 #undef MAYBE_UseIPConnectionPooling
11065 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11066 session_deps_
.use_alternate_protocols
= true;
11067 session_deps_
.next_protos
= SpdyNextProtos();
11069 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11070 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11071 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11072 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11073 pool_peer
.DisableDomainAuthenticationVerification();
11075 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11076 ssl
.SetNextProto(GetParam());
11077 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11079 scoped_ptr
<SpdyFrame
> host1_req(
11080 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11081 scoped_ptr
<SpdyFrame
> host2_req(
11082 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11083 MockWrite spdy_writes
[] = {
11084 CreateMockWrite(*host1_req
, 1),
11085 CreateMockWrite(*host2_req
, 4),
11087 scoped_ptr
<SpdyFrame
> host1_resp(
11088 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11089 scoped_ptr
<SpdyFrame
> host1_resp_body(
11090 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11091 scoped_ptr
<SpdyFrame
> host2_resp(
11092 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11093 scoped_ptr
<SpdyFrame
> host2_resp_body(
11094 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11095 MockRead spdy_reads
[] = {
11096 CreateMockRead(*host1_resp
, 2),
11097 CreateMockRead(*host1_resp_body
, 3),
11098 CreateMockRead(*host2_resp
, 5),
11099 CreateMockRead(*host2_resp_body
, 6),
11100 MockRead(ASYNC
, 0, 7),
11103 IPAddressNumber ip
;
11104 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11105 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11106 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11107 OrderedSocketData
spdy_data(
11109 spdy_reads
, arraysize(spdy_reads
),
11110 spdy_writes
, arraysize(spdy_writes
));
11111 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11113 TestCompletionCallback callback
;
11114 HttpRequestInfo request1
;
11115 request1
.method
= "GET";
11116 request1
.url
= GURL("https://www.google.com/");
11117 request1
.load_flags
= 0;
11118 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11120 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11121 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11122 EXPECT_EQ(OK
, callback
.WaitForResult());
11124 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11125 ASSERT_TRUE(response
!= NULL
);
11126 ASSERT_TRUE(response
->headers
.get() != NULL
);
11127 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11129 std::string response_data
;
11130 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11131 EXPECT_EQ("hello!", response_data
);
11133 HttpRequestInfo request2
;
11134 request2
.method
= "GET";
11135 request2
.url
= GURL("https://www.gmail.com/");
11136 request2
.load_flags
= 0;
11137 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11139 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11140 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11141 EXPECT_EQ(OK
, callback
.WaitForResult());
11143 response
= trans2
.GetResponseInfo();
11144 ASSERT_TRUE(response
!= NULL
);
11145 ASSERT_TRUE(response
->headers
.get() != NULL
);
11146 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11147 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11148 EXPECT_TRUE(response
->was_npn_negotiated
);
11149 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11150 EXPECT_EQ("hello!", response_data
);
11153 class OneTimeCachingHostResolver
: public net::HostResolver
{
11155 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11156 : host_port_(host_port
) {}
11157 virtual ~OneTimeCachingHostResolver() {}
11159 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11161 // HostResolver methods:
11162 virtual int Resolve(const RequestInfo
& info
,
11163 RequestPriority priority
,
11164 AddressList
* addresses
,
11165 const CompletionCallback
& callback
,
11166 RequestHandle
* out_req
,
11167 const BoundNetLog
& net_log
) OVERRIDE
{
11168 return host_resolver_
.Resolve(
11169 info
, priority
, addresses
, callback
, out_req
, net_log
);
11172 virtual int ResolveFromCache(const RequestInfo
& info
,
11173 AddressList
* addresses
,
11174 const BoundNetLog
& net_log
) OVERRIDE
{
11175 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11176 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11177 host_resolver_
.GetHostCache()->clear();
11181 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
11182 host_resolver_
.CancelRequest(req
);
11185 MockCachingHostResolver
* GetMockHostResolver() {
11186 return &host_resolver_
;
11190 MockCachingHostResolver host_resolver_
;
11191 const HostPortPair host_port_
;
11194 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11195 #if defined(OS_WIN)
11196 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11197 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11199 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11200 UseIPConnectionPoolingWithHostCacheExpiration
11202 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11203 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11204 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11205 // prefix doesn't work with parametrized tests).
11206 #if defined(OS_WIN)
11209 session_deps_
.use_alternate_protocols
= true;
11210 session_deps_
.next_protos
= SpdyNextProtos();
11212 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11213 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11214 HttpNetworkSession::Params params
=
11215 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11216 params
.host_resolver
= &host_resolver
;
11217 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11218 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11219 pool_peer
.DisableDomainAuthenticationVerification();
11221 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11222 ssl
.SetNextProto(GetParam());
11223 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11225 scoped_ptr
<SpdyFrame
> host1_req(
11226 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11227 scoped_ptr
<SpdyFrame
> host2_req(
11228 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11229 MockWrite spdy_writes
[] = {
11230 CreateMockWrite(*host1_req
, 1),
11231 CreateMockWrite(*host2_req
, 4),
11233 scoped_ptr
<SpdyFrame
> host1_resp(
11234 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11235 scoped_ptr
<SpdyFrame
> host1_resp_body(
11236 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11237 scoped_ptr
<SpdyFrame
> host2_resp(
11238 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11239 scoped_ptr
<SpdyFrame
> host2_resp_body(
11240 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11241 MockRead spdy_reads
[] = {
11242 CreateMockRead(*host1_resp
, 2),
11243 CreateMockRead(*host1_resp_body
, 3),
11244 CreateMockRead(*host2_resp
, 5),
11245 CreateMockRead(*host2_resp_body
, 6),
11246 MockRead(ASYNC
, 0, 7),
11249 IPAddressNumber ip
;
11250 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11251 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11252 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11253 OrderedSocketData
spdy_data(
11255 spdy_reads
, arraysize(spdy_reads
),
11256 spdy_writes
, arraysize(spdy_writes
));
11257 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11259 TestCompletionCallback callback
;
11260 HttpRequestInfo request1
;
11261 request1
.method
= "GET";
11262 request1
.url
= GURL("https://www.google.com/");
11263 request1
.load_flags
= 0;
11264 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11266 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11268 EXPECT_EQ(OK
, callback
.WaitForResult());
11270 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11271 ASSERT_TRUE(response
!= NULL
);
11272 ASSERT_TRUE(response
->headers
.get() != NULL
);
11273 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11275 std::string response_data
;
11276 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11277 EXPECT_EQ("hello!", response_data
);
11279 // Preload cache entries into HostCache.
11280 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11281 AddressList ignored
;
11282 rv
= host_resolver
.Resolve(resolve_info
,
11285 callback
.callback(),
11288 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11289 rv
= callback
.WaitForResult();
11292 HttpRequestInfo request2
;
11293 request2
.method
= "GET";
11294 request2
.url
= GURL("https://www.gmail.com/");
11295 request2
.load_flags
= 0;
11296 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11298 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11299 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11300 EXPECT_EQ(OK
, callback
.WaitForResult());
11302 response
= trans2
.GetResponseInfo();
11303 ASSERT_TRUE(response
!= NULL
);
11304 ASSERT_TRUE(response
->headers
.get() != NULL
);
11305 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11306 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11307 EXPECT_TRUE(response
->was_npn_negotiated
);
11308 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11309 EXPECT_EQ("hello!", response_data
);
11312 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11314 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11315 const std::string https_url
= "https://www.google.com/";
11316 const std::string http_url
= "http://www.google.com:443/";
11318 // SPDY GET for HTTPS URL
11319 scoped_ptr
<SpdyFrame
> req1(
11320 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11322 MockWrite writes1
[] = {
11323 CreateMockWrite(*req1
, 0),
11326 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11327 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11328 MockRead reads1
[] = {
11329 CreateMockRead(*resp1
, 1),
11330 CreateMockRead(*body1
, 2),
11331 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11334 DelayedSocketData
data1(
11335 1, reads1
, arraysize(reads1
),
11336 writes1
, arraysize(writes1
));
11337 MockConnect
connect_data1(ASYNC
, OK
);
11338 data1
.set_connect_data(connect_data1
);
11340 // HTTP GET for the HTTP URL
11341 MockWrite writes2
[] = {
11342 MockWrite(ASYNC
, 4,
11343 "GET / HTTP/1.1\r\n"
11344 "Host: www.google.com:443\r\n"
11345 "Connection: keep-alive\r\n\r\n"),
11348 MockRead reads2
[] = {
11349 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11350 MockRead(ASYNC
, 6, "hello"),
11351 MockRead(ASYNC
, 7, OK
),
11354 DelayedSocketData
data2(
11355 1, reads2
, arraysize(reads2
),
11356 writes2
, arraysize(writes2
));
11358 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11359 ssl
.SetNextProto(GetParam());
11360 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11361 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11362 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11366 // Start the first transaction to set up the SpdySession
11367 HttpRequestInfo request1
;
11368 request1
.method
= "GET";
11369 request1
.url
= GURL(https_url
);
11370 request1
.load_flags
= 0;
11371 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11372 TestCompletionCallback callback1
;
11373 EXPECT_EQ(ERR_IO_PENDING
,
11374 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11375 base::MessageLoop::current()->RunUntilIdle();
11377 EXPECT_EQ(OK
, callback1
.WaitForResult());
11378 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11380 // Now, start the HTTP request
11381 HttpRequestInfo request2
;
11382 request2
.method
= "GET";
11383 request2
.url
= GURL(http_url
);
11384 request2
.load_flags
= 0;
11385 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11386 TestCompletionCallback callback2
;
11387 EXPECT_EQ(ERR_IO_PENDING
,
11388 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11389 base::MessageLoop::current()->RunUntilIdle();
11391 EXPECT_EQ(OK
, callback2
.WaitForResult());
11392 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11395 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11396 const std::string https_url
= "https://www.google.com/";
11397 const std::string http_url
= "http://www.google.com:443/";
11399 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11400 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
11402 scoped_ptr
<SpdyFrame
> req1(
11403 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11404 scoped_ptr
<SpdyFrame
> wrapped_req1(
11405 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11407 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11408 SpdyHeaderBlock req2_block
;
11409 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11410 req2_block
[spdy_util_
.GetPathKey()] =
11411 spdy_util_
.is_spdy2() ? http_url
.c_str() : "/";
11412 req2_block
[spdy_util_
.GetHostKey()] = "www.google.com:443";
11413 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11414 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11415 scoped_ptr
<SpdyFrame
> req2(
11416 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11418 MockWrite writes1
[] = {
11419 CreateMockWrite(*connect
, 0),
11420 CreateMockWrite(*wrapped_req1
, 2),
11421 CreateMockWrite(*req2
, 5),
11424 scoped_ptr
<SpdyFrame
> conn_resp(
11425 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11426 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11427 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11428 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11429 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11430 scoped_ptr
<SpdyFrame
> wrapped_body1(
11431 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11432 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11433 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11434 MockRead reads1
[] = {
11435 CreateMockRead(*conn_resp
, 1),
11436 CreateMockRead(*wrapped_resp1
, 3),
11437 CreateMockRead(*wrapped_body1
, 4),
11438 CreateMockRead(*resp2
, 6),
11439 CreateMockRead(*body2
, 7),
11440 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11443 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11444 writes1
, arraysize(writes1
));
11445 MockConnect
connect_data1(ASYNC
, OK
);
11446 data1
.set_connect_data(connect_data1
);
11448 session_deps_
.proxy_service
.reset(
11449 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11450 CapturingNetLog log
;
11451 session_deps_
.net_log
= &log
;
11452 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11453 ssl1
.SetNextProto(GetParam());
11454 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11455 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11456 ssl2
.SetNextProto(GetParam());
11457 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11458 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11460 scoped_refptr
<HttpNetworkSession
> session(
11461 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11463 // Start the first transaction to set up the SpdySession
11464 HttpRequestInfo request1
;
11465 request1
.method
= "GET";
11466 request1
.url
= GURL(https_url
);
11467 request1
.load_flags
= 0;
11468 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11469 TestCompletionCallback callback1
;
11470 EXPECT_EQ(ERR_IO_PENDING
,
11471 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11472 base::MessageLoop::current()->RunUntilIdle();
11475 EXPECT_EQ(OK
, callback1
.WaitForResult());
11476 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11478 LoadTimingInfo load_timing_info1
;
11479 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11480 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11481 CONNECT_TIMING_HAS_SSL_TIMES
);
11483 // Now, start the HTTP request
11484 HttpRequestInfo request2
;
11485 request2
.method
= "GET";
11486 request2
.url
= GURL(http_url
);
11487 request2
.load_flags
= 0;
11488 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11489 TestCompletionCallback callback2
;
11490 EXPECT_EQ(ERR_IO_PENDING
,
11491 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11492 base::MessageLoop::current()->RunUntilIdle();
11495 EXPECT_EQ(OK
, callback2
.WaitForResult());
11496 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11498 LoadTimingInfo load_timing_info2
;
11499 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11500 // The established SPDY sessions is considered reused by the HTTP request.
11501 TestLoadTimingReusedWithPac(load_timing_info2
);
11502 // HTTP requests over a SPDY session should have a different connection
11503 // socket_log_id than requests over a tunnel.
11504 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11507 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11508 session_deps_
.force_spdy_always
= true;
11509 const std::string https_url
= "https://www.google.com/";
11510 const std::string http_url
= "http://www.google.com:443/";
11512 // SPDY GET for HTTPS URL
11513 scoped_ptr
<SpdyFrame
> req1(
11514 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11515 // SPDY GET for the HTTP URL
11516 scoped_ptr
<SpdyFrame
> req2(
11517 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11519 MockWrite writes
[] = {
11520 CreateMockWrite(*req1
, 1),
11521 CreateMockWrite(*req2
, 4),
11524 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11525 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11526 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11527 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11528 MockRead reads
[] = {
11529 CreateMockRead(*resp1
, 2),
11530 CreateMockRead(*body1
, 3),
11531 CreateMockRead(*resp2
, 5),
11532 CreateMockRead(*body2
, 6),
11533 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11536 OrderedSocketData
data(reads
, arraysize(reads
),
11537 writes
, arraysize(writes
));
11539 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11540 ssl
.SetNextProto(GetParam());
11541 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11542 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11544 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11546 // Start the first transaction to set up the SpdySession
11547 HttpRequestInfo request1
;
11548 request1
.method
= "GET";
11549 request1
.url
= GURL(https_url
);
11550 request1
.load_flags
= 0;
11551 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11552 TestCompletionCallback callback1
;
11553 EXPECT_EQ(ERR_IO_PENDING
,
11554 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11555 base::MessageLoop::current()->RunUntilIdle();
11557 EXPECT_EQ(OK
, callback1
.WaitForResult());
11558 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11560 // Now, start the HTTP request
11561 HttpRequestInfo request2
;
11562 request2
.method
= "GET";
11563 request2
.url
= GURL(http_url
);
11564 request2
.load_flags
= 0;
11565 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11566 TestCompletionCallback callback2
;
11567 EXPECT_EQ(ERR_IO_PENDING
,
11568 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11569 base::MessageLoop::current()->RunUntilIdle();
11571 EXPECT_EQ(OK
, callback2
.WaitForResult());
11572 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11575 // Test that in the case where we have a SPDY session to a SPDY proxy
11576 // that we do not pool other origins that resolve to the same IP when
11577 // the certificate does not match the new origin.
11578 // http://crbug.com/134690
11579 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11580 const std::string url1
= "http://www.google.com/";
11581 const std::string url2
= "https://mail.google.com/";
11582 const std::string ip_addr
= "1.2.3.4";
11584 // SPDY GET for HTTP URL (through SPDY proxy)
11585 scoped_ptr
<SpdyHeaderBlock
> headers(
11586 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11587 scoped_ptr
<SpdyFrame
> req1(
11588 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
11590 MockWrite writes1
[] = {
11591 CreateMockWrite(*req1
, 0),
11594 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11595 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11596 MockRead reads1
[] = {
11597 CreateMockRead(*resp1
, 1),
11598 CreateMockRead(*body1
, 2),
11599 MockRead(ASYNC
, OK
, 3) // EOF
11602 scoped_ptr
<DeterministicSocketData
> data1(
11603 new DeterministicSocketData(reads1
, arraysize(reads1
),
11604 writes1
, arraysize(writes1
)));
11605 IPAddressNumber ip
;
11606 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11607 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11608 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11609 data1
->set_connect_data(connect_data1
);
11611 // SPDY GET for HTTPS URL (direct)
11612 scoped_ptr
<SpdyFrame
> req2(
11613 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11615 MockWrite writes2
[] = {
11616 CreateMockWrite(*req2
, 0),
11619 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11620 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11621 MockRead reads2
[] = {
11622 CreateMockRead(*resp2
, 1),
11623 CreateMockRead(*body2
, 2),
11624 MockRead(ASYNC
, OK
, 3) // EOF
11627 scoped_ptr
<DeterministicSocketData
> data2(
11628 new DeterministicSocketData(reads2
, arraysize(reads2
),
11629 writes2
, arraysize(writes2
)));
11630 MockConnect
connect_data2(ASYNC
, OK
);
11631 data2
->set_connect_data(connect_data2
);
11633 // Set up a proxy config that sends HTTP requests to a proxy, and
11634 // all others direct.
11635 ProxyConfig proxy_config
;
11636 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11637 CapturingProxyResolver
* capturing_proxy_resolver
=
11638 new CapturingProxyResolver();
11639 session_deps_
.proxy_service
.reset(new ProxyService(
11640 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11643 // Load a valid cert. Note, that this does not need to
11644 // be valid for proxy because the MockSSLClientSocket does
11645 // not actually verify it. But SpdySession will use this
11646 // to see if it is valid for the new origin
11647 base::FilePath certs_dir
= GetTestCertsDirectory();
11648 scoped_refptr
<X509Certificate
> server_cert(
11649 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11650 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
);
11652 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11653 ssl1
.SetNextProto(GetParam());
11654 ssl1
.cert
= server_cert
;
11655 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11656 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11659 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11660 ssl2
.SetNextProto(GetParam());
11661 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11662 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11665 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11666 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11667 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11669 scoped_refptr
<HttpNetworkSession
> session(
11670 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11672 // Start the first transaction to set up the SpdySession
11673 HttpRequestInfo request1
;
11674 request1
.method
= "GET";
11675 request1
.url
= GURL(url1
);
11676 request1
.load_flags
= 0;
11677 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11678 TestCompletionCallback callback1
;
11679 ASSERT_EQ(ERR_IO_PENDING
,
11680 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11683 ASSERT_TRUE(callback1
.have_result());
11684 EXPECT_EQ(OK
, callback1
.WaitForResult());
11685 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11687 // Now, start the HTTP request
11688 HttpRequestInfo request2
;
11689 request2
.method
= "GET";
11690 request2
.url
= GURL(url2
);
11691 request2
.load_flags
= 0;
11692 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11693 TestCompletionCallback callback2
;
11694 EXPECT_EQ(ERR_IO_PENDING
,
11695 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11696 base::MessageLoop::current()->RunUntilIdle();
11699 ASSERT_TRUE(callback2
.have_result());
11700 EXPECT_EQ(OK
, callback2
.WaitForResult());
11701 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11704 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11705 // error) in SPDY session, removes the socket from pool and closes the SPDY
11706 // session. Verify that new url's from the same HttpNetworkSession (and a new
11707 // SpdySession) do work. http://crbug.com/224701
11708 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11709 const std::string https_url
= "https://www.google.com/";
11711 MockRead reads1
[] = {
11712 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11715 scoped_ptr
<DeterministicSocketData
> data1(
11716 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11719 scoped_ptr
<SpdyFrame
> req2(
11720 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11721 MockWrite writes2
[] = {
11722 CreateMockWrite(*req2
, 0),
11725 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11726 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11727 MockRead reads2
[] = {
11728 CreateMockRead(*resp2
, 1),
11729 CreateMockRead(*body2
, 2),
11730 MockRead(ASYNC
, OK
, 3) // EOF
11733 scoped_ptr
<DeterministicSocketData
> data2(
11734 new DeterministicSocketData(reads2
, arraysize(reads2
),
11735 writes2
, arraysize(writes2
)));
11737 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11738 ssl1
.SetNextProto(GetParam());
11739 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11740 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11743 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11744 ssl2
.SetNextProto(GetParam());
11745 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11746 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11749 scoped_refptr
<HttpNetworkSession
> session(
11750 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11752 // Start the first transaction to set up the SpdySession and verify that
11753 // connection was closed.
11754 HttpRequestInfo request1
;
11755 request1
.method
= "GET";
11756 request1
.url
= GURL(https_url
);
11757 request1
.load_flags
= 0;
11758 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11759 TestCompletionCallback callback1
;
11760 EXPECT_EQ(ERR_IO_PENDING
,
11761 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11762 base::MessageLoop::current()->RunUntilIdle();
11763 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11765 // Now, start the second request and make sure it succeeds.
11766 HttpRequestInfo request2
;
11767 request2
.method
= "GET";
11768 request2
.url
= GURL(https_url
);
11769 request2
.load_flags
= 0;
11770 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11771 TestCompletionCallback callback2
;
11772 EXPECT_EQ(ERR_IO_PENDING
,
11773 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11774 base::MessageLoop::current()->RunUntilIdle();
11777 ASSERT_TRUE(callback2
.have_result());
11778 EXPECT_EQ(OK
, callback2
.WaitForResult());
11779 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11782 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11783 session_deps_
.next_protos
= SpdyNextProtos();
11784 ClientSocketPoolManager::set_max_sockets_per_group(
11785 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11786 ClientSocketPoolManager::set_max_sockets_per_pool(
11787 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11789 // Use two different hosts with different IPs so they don't get pooled.
11790 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11791 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11792 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11794 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11795 ssl1
.SetNextProto(GetParam());
11796 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11797 ssl2
.SetNextProto(GetParam());
11798 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11799 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11801 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11802 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11803 MockWrite spdy1_writes
[] = {
11804 CreateMockWrite(*host1_req
, 1),
11806 scoped_ptr
<SpdyFrame
> host1_resp(
11807 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11808 scoped_ptr
<SpdyFrame
> host1_resp_body(
11809 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11810 MockRead spdy1_reads
[] = {
11811 CreateMockRead(*host1_resp
, 2),
11812 CreateMockRead(*host1_resp_body
, 3),
11813 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11816 scoped_ptr
<OrderedSocketData
> spdy1_data(
11817 new OrderedSocketData(
11818 spdy1_reads
, arraysize(spdy1_reads
),
11819 spdy1_writes
, arraysize(spdy1_writes
)));
11820 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11822 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11823 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11824 MockWrite spdy2_writes
[] = {
11825 CreateMockWrite(*host2_req
, 1),
11827 scoped_ptr
<SpdyFrame
> host2_resp(
11828 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11829 scoped_ptr
<SpdyFrame
> host2_resp_body(
11830 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11831 MockRead spdy2_reads
[] = {
11832 CreateMockRead(*host2_resp
, 2),
11833 CreateMockRead(*host2_resp_body
, 3),
11834 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11837 scoped_ptr
<OrderedSocketData
> spdy2_data(
11838 new OrderedSocketData(
11839 spdy2_reads
, arraysize(spdy2_reads
),
11840 spdy2_writes
, arraysize(spdy2_writes
)));
11841 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11843 MockWrite http_write
[] = {
11844 MockWrite("GET / HTTP/1.1\r\n"
11845 "Host: www.a.com\r\n"
11846 "Connection: keep-alive\r\n\r\n"),
11849 MockRead http_read
[] = {
11850 MockRead("HTTP/1.1 200 OK\r\n"),
11851 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11852 MockRead("Content-Length: 6\r\n\r\n"),
11853 MockRead("hello!"),
11855 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11856 http_write
, arraysize(http_write
));
11857 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11859 HostPortPair
host_port_pair_a("www.a.com", 443);
11860 SpdySessionKey
spdy_session_key_a(
11861 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11863 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11865 TestCompletionCallback callback
;
11866 HttpRequestInfo request1
;
11867 request1
.method
= "GET";
11868 request1
.url
= GURL("https://www.a.com/");
11869 request1
.load_flags
= 0;
11870 scoped_ptr
<HttpNetworkTransaction
> trans(
11871 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11873 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11874 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11875 EXPECT_EQ(OK
, callback
.WaitForResult());
11877 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11878 ASSERT_TRUE(response
!= NULL
);
11879 ASSERT_TRUE(response
->headers
.get() != NULL
);
11880 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11881 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11882 EXPECT_TRUE(response
->was_npn_negotiated
);
11884 std::string response_data
;
11885 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11886 EXPECT_EQ("hello!", response_data
);
11889 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11891 HostPortPair
host_port_pair_b("www.b.com", 443);
11892 SpdySessionKey
spdy_session_key_b(
11893 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11895 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11896 HttpRequestInfo request2
;
11897 request2
.method
= "GET";
11898 request2
.url
= GURL("https://www.b.com/");
11899 request2
.load_flags
= 0;
11900 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11902 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11903 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11904 EXPECT_EQ(OK
, callback
.WaitForResult());
11906 response
= trans
->GetResponseInfo();
11907 ASSERT_TRUE(response
!= NULL
);
11908 ASSERT_TRUE(response
->headers
.get() != NULL
);
11909 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11910 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11911 EXPECT_TRUE(response
->was_npn_negotiated
);
11912 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11913 EXPECT_EQ("hello!", response_data
);
11915 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11917 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11919 HostPortPair
host_port_pair_a1("www.a.com", 80);
11920 SpdySessionKey
spdy_session_key_a1(
11921 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11923 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11924 HttpRequestInfo request3
;
11925 request3
.method
= "GET";
11926 request3
.url
= GURL("http://www.a.com/");
11927 request3
.load_flags
= 0;
11928 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11930 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11931 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11932 EXPECT_EQ(OK
, callback
.WaitForResult());
11934 response
= trans
->GetResponseInfo();
11935 ASSERT_TRUE(response
!= NULL
);
11936 ASSERT_TRUE(response
->headers
.get() != NULL
);
11937 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11938 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11939 EXPECT_FALSE(response
->was_npn_negotiated
);
11940 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11941 EXPECT_EQ("hello!", response_data
);
11943 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11945 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11948 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11949 HttpRequestInfo request
;
11950 request
.method
= "GET";
11951 request
.url
= GURL("http://www.google.com/");
11952 request
.load_flags
= 0;
11954 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11955 scoped_ptr
<HttpTransaction
> trans(
11956 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11958 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11959 StaticSocketDataProvider data
;
11960 data
.set_connect_data(mock_connect
);
11961 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11963 TestCompletionCallback callback
;
11965 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11966 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11968 rv
= callback
.WaitForResult();
11969 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11971 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11973 // We don't care whether this succeeds or fails, but it shouldn't crash.
11974 HttpRequestHeaders request_headers
;
11975 trans
->GetFullRequestHeaders(&request_headers
);
11978 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11979 HttpRequestInfo request
;
11980 request
.method
= "GET";
11981 request
.url
= GURL("http://www.google.com/");
11982 request
.load_flags
= 0;
11984 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11985 scoped_ptr
<HttpTransaction
> trans(
11986 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11988 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11989 StaticSocketDataProvider data
;
11990 data
.set_connect_data(mock_connect
);
11991 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11993 TestCompletionCallback callback
;
11995 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11996 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11998 rv
= callback
.WaitForResult();
11999 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12001 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12003 // We don't care whether this succeeds or fails, but it shouldn't crash.
12004 HttpRequestHeaders request_headers
;
12005 trans
->GetFullRequestHeaders(&request_headers
);
12008 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12009 HttpRequestInfo request
;
12010 request
.method
= "GET";
12011 request
.url
= GURL("http://www.google.com/");
12012 request
.load_flags
= 0;
12014 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12015 scoped_ptr
<HttpTransaction
> trans(
12016 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12018 MockWrite data_writes
[] = {
12019 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12021 MockRead data_reads
[] = {
12022 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12025 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12026 data_writes
, arraysize(data_writes
));
12027 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12029 TestCompletionCallback callback
;
12031 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12034 rv
= callback
.WaitForResult();
12035 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12037 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12039 HttpRequestHeaders request_headers
;
12040 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12041 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12044 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12045 HttpRequestInfo request
;
12046 request
.method
= "GET";
12047 request
.url
= GURL("http://www.google.com/");
12048 request
.load_flags
= 0;
12050 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12051 scoped_ptr
<HttpTransaction
> trans(
12052 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12054 MockWrite data_writes
[] = {
12055 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12057 MockRead data_reads
[] = {
12058 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12061 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12062 data_writes
, arraysize(data_writes
));
12063 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12065 TestCompletionCallback callback
;
12067 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12068 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12070 rv
= callback
.WaitForResult();
12071 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12073 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12075 HttpRequestHeaders request_headers
;
12076 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12077 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12080 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12081 HttpRequestInfo request
;
12082 request
.method
= "GET";
12083 request
.url
= GURL("http://www.google.com/");
12084 request
.load_flags
= 0;
12086 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12087 scoped_ptr
<HttpTransaction
> trans(
12088 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12090 MockWrite data_writes
[] = {
12091 MockWrite("GET / HTTP/1.1\r\n"
12092 "Host: www.google.com\r\n"
12093 "Connection: keep-alive\r\n\r\n"),
12095 MockRead data_reads
[] = {
12096 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12099 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12100 data_writes
, arraysize(data_writes
));
12101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12103 TestCompletionCallback callback
;
12105 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12108 rv
= callback
.WaitForResult();
12109 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12111 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12113 HttpRequestHeaders request_headers
;
12114 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12115 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12118 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12119 HttpRequestInfo request
;
12120 request
.method
= "GET";
12121 request
.url
= GURL("http://www.google.com/");
12122 request
.load_flags
= 0;
12124 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12125 scoped_ptr
<HttpTransaction
> trans(
12126 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12128 MockWrite data_writes
[] = {
12129 MockWrite("GET / HTTP/1.1\r\n"
12130 "Host: www.google.com\r\n"
12131 "Connection: keep-alive\r\n\r\n"),
12133 MockRead data_reads
[] = {
12134 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12137 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12138 data_writes
, arraysize(data_writes
));
12139 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12141 TestCompletionCallback callback
;
12143 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12146 rv
= callback
.WaitForResult();
12147 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12149 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12151 HttpRequestHeaders request_headers
;
12152 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12153 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12156 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12157 HttpRequestInfo request
;
12158 request
.method
= "GET";
12159 request
.url
= GURL("http://www.google.com/");
12160 request
.load_flags
= 0;
12161 request
.extra_headers
.SetHeader("X-Foo", "bar");
12163 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12164 scoped_ptr
<HttpTransaction
> trans(
12165 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12167 MockWrite data_writes
[] = {
12168 MockWrite("GET / HTTP/1.1\r\n"
12169 "Host: www.google.com\r\n"
12170 "Connection: keep-alive\r\n"
12171 "X-Foo: bar\r\n\r\n"),
12173 MockRead data_reads
[] = {
12174 MockRead("HTTP/1.1 200 OK\r\n"
12175 "Content-Length: 5\r\n\r\n"
12177 MockRead(ASYNC
, ERR_UNEXPECTED
),
12180 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12181 data_writes
, arraysize(data_writes
));
12182 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12184 TestCompletionCallback callback
;
12186 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12187 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12189 rv
= callback
.WaitForResult();
12192 HttpRequestHeaders request_headers
;
12193 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12195 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12196 EXPECT_EQ("bar", foo
);
12201 // Fake HttpStreamBase that simply records calls to SetPriority().
12202 class FakeStream
: public HttpStreamBase
,
12203 public base::SupportsWeakPtr
<FakeStream
> {
12205 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12206 virtual ~FakeStream() {}
12208 RequestPriority
priority() const { return priority_
; }
12210 virtual int InitializeStream(const HttpRequestInfo
* request_info
,
12211 RequestPriority priority
,
12212 const BoundNetLog
& net_log
,
12213 const CompletionCallback
& callback
) OVERRIDE
{
12214 return ERR_IO_PENDING
;
12217 virtual int SendRequest(const HttpRequestHeaders
& request_headers
,
12218 HttpResponseInfo
* response
,
12219 const CompletionCallback
& callback
) OVERRIDE
{
12221 return ERR_UNEXPECTED
;
12224 virtual int ReadResponseHeaders(const CompletionCallback
& callback
) OVERRIDE
{
12226 return ERR_UNEXPECTED
;
12229 virtual int ReadResponseBody(IOBuffer
* buf
, int buf_len
,
12230 const CompletionCallback
& callback
) OVERRIDE
{
12232 return ERR_UNEXPECTED
;
12235 virtual void Close(bool not_reusable
) OVERRIDE
{}
12237 virtual bool IsResponseBodyComplete() const OVERRIDE
{
12242 virtual bool CanFindEndOfResponse() const OVERRIDE
{
12246 virtual bool IsConnectionReused() const OVERRIDE
{
12251 virtual void SetConnectionReused() OVERRIDE
{
12255 virtual bool IsConnectionReusable() const OVERRIDE
{
12260 virtual int64
GetTotalReceivedBytes() const OVERRIDE
{
12265 virtual bool GetLoadTimingInfo(
12266 LoadTimingInfo
* load_timing_info
) const OVERRIDE
{
12271 virtual void GetSSLInfo(SSLInfo
* ssl_info
) OVERRIDE
{
12275 virtual void GetSSLCertRequestInfo(
12276 SSLCertRequestInfo
* cert_request_info
) OVERRIDE
{
12280 virtual bool IsSpdyHttpStream() const OVERRIDE
{
12285 virtual void Drain(HttpNetworkSession
* session
) OVERRIDE
{
12289 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12290 priority_
= priority
;
12294 RequestPriority priority_
;
12296 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12299 // Fake HttpStreamRequest that simply records calls to SetPriority()
12300 // and vends FakeStreams with its current priority.
12301 class FakeStreamRequest
: public HttpStreamRequest
,
12302 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12304 FakeStreamRequest(RequestPriority priority
,
12305 HttpStreamRequest::Delegate
* delegate
)
12306 : priority_(priority
),
12307 delegate_(delegate
),
12308 websocket_stream_create_helper_(NULL
) {}
12310 FakeStreamRequest(RequestPriority priority
,
12311 HttpStreamRequest::Delegate
* delegate
,
12312 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12313 : priority_(priority
),
12314 delegate_(delegate
),
12315 websocket_stream_create_helper_(create_helper
) {}
12317 virtual ~FakeStreamRequest() {}
12319 RequestPriority
priority() const { return priority_
; }
12321 const WebSocketHandshakeStreamBase::CreateHelper
*
12322 websocket_stream_create_helper() const {
12323 return websocket_stream_create_helper_
;
12326 // Create a new FakeStream and pass it to the request's
12327 // delegate. Returns a weak pointer to the FakeStream.
12328 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12329 FakeStream
* fake_stream
= new FakeStream(priority_
);
12330 // Do this before calling OnStreamReady() as OnStreamReady() may
12331 // immediately delete |fake_stream|.
12332 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12333 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12334 return weak_stream
;
12337 virtual int RestartTunnelWithProxyAuth(
12338 const AuthCredentials
& credentials
) OVERRIDE
{
12340 return ERR_UNEXPECTED
;
12343 virtual LoadState
GetLoadState() const OVERRIDE
{
12345 return LoadState();
12348 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12349 priority_
= priority
;
12352 virtual bool was_npn_negotiated() const OVERRIDE
{
12356 virtual NextProto
protocol_negotiated() const OVERRIDE
{
12357 return kProtoUnknown
;
12360 virtual bool using_spdy() const OVERRIDE
{
12365 RequestPriority priority_
;
12366 HttpStreamRequest::Delegate
* const delegate_
;
12367 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12369 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12372 // Fake HttpStreamFactory that vends FakeStreamRequests.
12373 class FakeStreamFactory
: public HttpStreamFactory
{
12375 FakeStreamFactory() {}
12376 virtual ~FakeStreamFactory() {}
12378 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12379 // RequestStream() (which may be NULL if it was destroyed already).
12380 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12381 return last_stream_request_
;
12384 virtual HttpStreamRequest
* RequestStream(
12385 const HttpRequestInfo
& info
,
12386 RequestPriority priority
,
12387 const SSLConfig
& server_ssl_config
,
12388 const SSLConfig
& proxy_ssl_config
,
12389 HttpStreamRequest::Delegate
* delegate
,
12390 const BoundNetLog
& net_log
) OVERRIDE
{
12391 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12392 last_stream_request_
= fake_request
->AsWeakPtr();
12393 return fake_request
;
12396 virtual HttpStreamRequest
* RequestWebSocketHandshakeStream(
12397 const HttpRequestInfo
& info
,
12398 RequestPriority priority
,
12399 const SSLConfig
& server_ssl_config
,
12400 const SSLConfig
& proxy_ssl_config
,
12401 HttpStreamRequest::Delegate
* delegate
,
12402 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12403 const BoundNetLog
& net_log
) OVERRIDE
{
12404 FakeStreamRequest
* fake_request
=
12405 new FakeStreamRequest(priority
, delegate
, create_helper
);
12406 last_stream_request_
= fake_request
->AsWeakPtr();
12407 return fake_request
;
12410 virtual void PreconnectStreams(int num_streams
,
12411 const HttpRequestInfo
& info
,
12412 RequestPriority priority
,
12413 const SSLConfig
& server_ssl_config
,
12414 const SSLConfig
& proxy_ssl_config
) OVERRIDE
{
12418 virtual const HostMappingRules
* GetHostMappingRules() const OVERRIDE
{
12424 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12426 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12429 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12431 class FakeWebSocketStreamCreateHelper
:
12432 public WebSocketHandshakeStreamBase::CreateHelper
{
12434 virtual WebSocketHandshakeStreamBase
* CreateBasicStream(
12435 scoped_ptr
<ClientSocketHandle
> connection
,
12436 bool using_proxy
) OVERRIDE
{
12441 virtual WebSocketHandshakeStreamBase
* CreateSpdyStream(
12442 const base::WeakPtr
<SpdySession
>& session
,
12443 bool use_relative_url
) OVERRIDE
{
12448 virtual ~FakeWebSocketStreamCreateHelper() {}
12450 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12452 return scoped_ptr
<WebSocketStream
>();
12458 // Make sure that HttpNetworkTransaction passes on its priority to its
12459 // stream request on start.
12460 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12461 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12462 HttpNetworkSessionPeer
peer(session
);
12463 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12464 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12466 HttpNetworkTransaction
trans(LOW
, session
);
12468 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12470 HttpRequestInfo request
;
12471 TestCompletionCallback callback
;
12472 EXPECT_EQ(ERR_IO_PENDING
,
12473 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12475 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12476 fake_factory
->last_stream_request();
12477 ASSERT_TRUE(fake_request
!= NULL
);
12478 EXPECT_EQ(LOW
, fake_request
->priority());
12481 // Make sure that HttpNetworkTransaction passes on its priority
12482 // updates to its stream request.
12483 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12484 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12485 HttpNetworkSessionPeer
peer(session
);
12486 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12487 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12489 HttpNetworkTransaction
trans(LOW
, session
);
12491 HttpRequestInfo request
;
12492 TestCompletionCallback callback
;
12493 EXPECT_EQ(ERR_IO_PENDING
,
12494 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12496 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12497 fake_factory
->last_stream_request();
12498 ASSERT_TRUE(fake_request
!= NULL
);
12499 EXPECT_EQ(LOW
, fake_request
->priority());
12501 trans
.SetPriority(LOWEST
);
12502 ASSERT_TRUE(fake_request
!= NULL
);
12503 EXPECT_EQ(LOWEST
, fake_request
->priority());
12506 // Make sure that HttpNetworkTransaction passes on its priority
12507 // updates to its stream.
12508 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12509 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12510 HttpNetworkSessionPeer
peer(session
);
12511 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12512 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12514 HttpNetworkTransaction
trans(LOW
, session
);
12516 HttpRequestInfo request
;
12517 TestCompletionCallback callback
;
12518 EXPECT_EQ(ERR_IO_PENDING
,
12519 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12521 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12522 fake_factory
->last_stream_request();
12523 ASSERT_TRUE(fake_request
!= NULL
);
12524 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12525 ASSERT_TRUE(fake_stream
!= NULL
);
12526 EXPECT_EQ(LOW
, fake_stream
->priority());
12528 trans
.SetPriority(LOWEST
);
12529 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12532 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12533 // The same logic needs to be tested for both ws: and wss: schemes, but this
12534 // test is already parameterised on NextProto, so it uses a loop to verify
12535 // that the different schemes work.
12536 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
12537 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
12538 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12539 HttpNetworkSessionPeer
peer(session
);
12540 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12541 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
12542 peer
.SetHttpStreamFactoryForWebSocket(
12543 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12545 HttpNetworkTransaction
trans(LOW
, session
);
12546 trans
.SetWebSocketHandshakeStreamCreateHelper(
12547 &websocket_stream_create_helper
);
12549 HttpRequestInfo request
;
12550 TestCompletionCallback callback
;
12551 request
.method
= "GET";
12552 request
.url
= GURL(test_cases
[i
]);
12554 EXPECT_EQ(ERR_IO_PENDING
,
12555 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12557 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12558 fake_factory
->last_stream_request();
12559 ASSERT_TRUE(fake_request
!= NULL
);
12560 EXPECT_EQ(&websocket_stream_create_helper
,
12561 fake_request
->websocket_stream_create_helper());
12565 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12566 // if the transport socket pool is stalled on the global socket limit.
12567 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
12568 ClientSocketPoolManager::set_max_sockets_per_group(
12569 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12570 ClientSocketPoolManager::set_max_sockets_per_pool(
12571 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12573 // Set up SSL request.
12575 HttpRequestInfo ssl_request
;
12576 ssl_request
.method
= "GET";
12577 ssl_request
.url
= GURL("https://www.google.com/");
12579 MockWrite ssl_writes
[] = {
12580 MockWrite("GET / HTTP/1.1\r\n"
12581 "Host: www.google.com\r\n"
12582 "Connection: keep-alive\r\n\r\n"),
12584 MockRead ssl_reads
[] = {
12585 MockRead("HTTP/1.1 200 OK\r\n"),
12586 MockRead("Content-Length: 11\r\n\r\n"),
12587 MockRead("hello world"),
12588 MockRead(SYNCHRONOUS
, OK
),
12590 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
12591 ssl_writes
, arraysize(ssl_writes
));
12592 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12594 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12595 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12597 // Set up HTTP request.
12599 HttpRequestInfo http_request
;
12600 http_request
.method
= "GET";
12601 http_request
.url
= GURL("http://www.google.com/");
12603 MockWrite http_writes
[] = {
12604 MockWrite("GET / HTTP/1.1\r\n"
12605 "Host: www.google.com\r\n"
12606 "Connection: keep-alive\r\n\r\n"),
12608 MockRead http_reads
[] = {
12609 MockRead("HTTP/1.1 200 OK\r\n"),
12610 MockRead("Content-Length: 7\r\n\r\n"),
12611 MockRead("falafel"),
12612 MockRead(SYNCHRONOUS
, OK
),
12614 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12615 http_writes
, arraysize(http_writes
));
12616 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12618 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12620 // Start the SSL request.
12621 TestCompletionCallback ssl_callback
;
12622 scoped_ptr
<HttpTransaction
> ssl_trans(
12623 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12624 ASSERT_EQ(ERR_IO_PENDING
,
12625 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
12628 // Start the HTTP request. Pool should stall.
12629 TestCompletionCallback http_callback
;
12630 scoped_ptr
<HttpTransaction
> http_trans(
12631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12632 ASSERT_EQ(ERR_IO_PENDING
,
12633 http_trans
->Start(&http_request
, http_callback
.callback(),
12635 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12637 // Wait for response from SSL request.
12638 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
12639 std::string response_data
;
12640 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
12641 EXPECT_EQ("hello world", response_data
);
12643 // The SSL socket should automatically be closed, so the HTTP request can
12645 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12646 ASSERT_FALSE(IsTransportSocketPoolStalled(session
));
12648 // The HTTP request can now complete.
12649 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12650 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12651 EXPECT_EQ("falafel", response_data
);
12653 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12656 // Tests that when a SSL connection is established but there's no corresponding
12657 // request that needs it, the new socket is closed if the transport socket pool
12658 // is stalled on the global socket limit.
12659 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
12660 ClientSocketPoolManager::set_max_sockets_per_group(
12661 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12662 ClientSocketPoolManager::set_max_sockets_per_pool(
12663 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12665 // Set up an ssl request.
12667 HttpRequestInfo ssl_request
;
12668 ssl_request
.method
= "GET";
12669 ssl_request
.url
= GURL("https://www.foopy.com/");
12671 // No data will be sent on the SSL socket.
12672 StaticSocketDataProvider ssl_data
;
12673 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12675 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12676 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12678 // Set up HTTP request.
12680 HttpRequestInfo http_request
;
12681 http_request
.method
= "GET";
12682 http_request
.url
= GURL("http://www.google.com/");
12684 MockWrite http_writes
[] = {
12685 MockWrite("GET / HTTP/1.1\r\n"
12686 "Host: www.google.com\r\n"
12687 "Connection: keep-alive\r\n\r\n"),
12689 MockRead http_reads
[] = {
12690 MockRead("HTTP/1.1 200 OK\r\n"),
12691 MockRead("Content-Length: 7\r\n\r\n"),
12692 MockRead("falafel"),
12693 MockRead(SYNCHRONOUS
, OK
),
12695 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12696 http_writes
, arraysize(http_writes
));
12697 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12699 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12701 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12702 // cancelled when a normal transaction is cancelled.
12703 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
12704 net::SSLConfig ssl_config
;
12705 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
12706 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
12707 ssl_config
, ssl_config
);
12708 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12710 // Start the HTTP request. Pool should stall.
12711 TestCompletionCallback http_callback
;
12712 scoped_ptr
<HttpTransaction
> http_trans(
12713 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12714 ASSERT_EQ(ERR_IO_PENDING
,
12715 http_trans
->Start(&http_request
, http_callback
.callback(),
12717 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12719 // The SSL connection will automatically be closed once the connection is
12720 // established, to let the HTTP request start.
12721 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12722 std::string response_data
;
12723 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12724 EXPECT_EQ("falafel", response_data
);
12726 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12729 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
12730 ScopedVector
<UploadElementReader
> element_readers
;
12731 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12732 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12734 HttpRequestInfo request
;
12735 request
.method
= "POST";
12736 request
.url
= GURL("http://www.foo.com/");
12737 request
.upload_data_stream
= &upload_data_stream
;
12738 request
.load_flags
= 0;
12740 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12741 scoped_ptr
<HttpTransaction
> trans(
12742 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12743 // Send headers successfully, but get an error while sending the body.
12744 MockWrite data_writes
[] = {
12745 MockWrite("POST / HTTP/1.1\r\n"
12746 "Host: www.foo.com\r\n"
12747 "Connection: keep-alive\r\n"
12748 "Content-Length: 3\r\n\r\n"),
12749 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12752 MockRead data_reads
[] = {
12753 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12754 MockRead("hello world"),
12755 MockRead(SYNCHRONOUS
, OK
),
12757 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12758 arraysize(data_writes
));
12759 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12761 TestCompletionCallback callback
;
12763 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12764 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12766 rv
= callback
.WaitForResult();
12769 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12770 ASSERT_TRUE(response
!= NULL
);
12772 EXPECT_TRUE(response
->headers
.get() != NULL
);
12773 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12775 std::string response_data
;
12776 rv
= ReadTransaction(trans
.get(), &response_data
);
12778 EXPECT_EQ("hello world", response_data
);
12781 // This test makes sure the retry logic doesn't trigger when reading an error
12782 // response from a server that rejected a POST with a CONNECTION_RESET.
12783 TEST_P(HttpNetworkTransactionTest
,
12784 PostReadsErrorResponseAfterResetOnReusedSocket
) {
12785 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12786 MockWrite data_writes
[] = {
12787 MockWrite("GET / HTTP/1.1\r\n"
12788 "Host: www.foo.com\r\n"
12789 "Connection: keep-alive\r\n\r\n"),
12790 MockWrite("POST / HTTP/1.1\r\n"
12791 "Host: www.foo.com\r\n"
12792 "Connection: keep-alive\r\n"
12793 "Content-Length: 3\r\n\r\n"),
12794 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12797 MockRead data_reads
[] = {
12798 MockRead("HTTP/1.1 200 Peachy\r\n"
12799 "Content-Length: 14\r\n\r\n"),
12800 MockRead("first response"),
12801 MockRead("HTTP/1.1 400 Not OK\r\n"
12802 "Content-Length: 15\r\n\r\n"),
12803 MockRead("second response"),
12804 MockRead(SYNCHRONOUS
, OK
),
12806 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12807 arraysize(data_writes
));
12808 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12810 TestCompletionCallback callback
;
12811 HttpRequestInfo request1
;
12812 request1
.method
= "GET";
12813 request1
.url
= GURL("http://www.foo.com/");
12814 request1
.load_flags
= 0;
12816 scoped_ptr
<HttpTransaction
> trans1(
12817 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12818 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
12819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12821 rv
= callback
.WaitForResult();
12824 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12825 ASSERT_TRUE(response1
!= NULL
);
12827 EXPECT_TRUE(response1
->headers
.get() != NULL
);
12828 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
12830 std::string response_data1
;
12831 rv
= ReadTransaction(trans1
.get(), &response_data1
);
12833 EXPECT_EQ("first response", response_data1
);
12834 // Delete the transaction to release the socket back into the socket pool.
12837 ScopedVector
<UploadElementReader
> element_readers
;
12838 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12839 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12841 HttpRequestInfo request2
;
12842 request2
.method
= "POST";
12843 request2
.url
= GURL("http://www.foo.com/");
12844 request2
.upload_data_stream
= &upload_data_stream
;
12845 request2
.load_flags
= 0;
12847 scoped_ptr
<HttpTransaction
> trans2(
12848 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12849 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
12850 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12852 rv
= callback
.WaitForResult();
12855 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
12856 ASSERT_TRUE(response2
!= NULL
);
12858 EXPECT_TRUE(response2
->headers
.get() != NULL
);
12859 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
12861 std::string response_data2
;
12862 rv
= ReadTransaction(trans2
.get(), &response_data2
);
12864 EXPECT_EQ("second response", response_data2
);
12867 TEST_P(HttpNetworkTransactionTest
,
12868 PostReadsErrorResponseAfterResetPartialBodySent
) {
12869 ScopedVector
<UploadElementReader
> element_readers
;
12870 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12871 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12873 HttpRequestInfo request
;
12874 request
.method
= "POST";
12875 request
.url
= GURL("http://www.foo.com/");
12876 request
.upload_data_stream
= &upload_data_stream
;
12877 request
.load_flags
= 0;
12879 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12880 scoped_ptr
<HttpTransaction
> trans(
12881 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12882 // Send headers successfully, but get an error while sending the body.
12883 MockWrite data_writes
[] = {
12884 MockWrite("POST / HTTP/1.1\r\n"
12885 "Host: www.foo.com\r\n"
12886 "Connection: keep-alive\r\n"
12887 "Content-Length: 3\r\n\r\n"
12889 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12892 MockRead data_reads
[] = {
12893 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12894 MockRead("hello world"),
12895 MockRead(SYNCHRONOUS
, OK
),
12897 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12898 arraysize(data_writes
));
12899 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12901 TestCompletionCallback callback
;
12903 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12904 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12906 rv
= callback
.WaitForResult();
12909 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12910 ASSERT_TRUE(response
!= NULL
);
12912 EXPECT_TRUE(response
->headers
.get() != NULL
);
12913 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12915 std::string response_data
;
12916 rv
= ReadTransaction(trans
.get(), &response_data
);
12918 EXPECT_EQ("hello world", response_data
);
12921 // This tests the more common case than the previous test, where headers and
12922 // body are not merged into a single request.
12923 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
12924 ScopedVector
<UploadElementReader
> element_readers
;
12925 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12926 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
12928 HttpRequestInfo request
;
12929 request
.method
= "POST";
12930 request
.url
= GURL("http://www.foo.com/");
12931 request
.upload_data_stream
= &upload_data_stream
;
12932 request
.load_flags
= 0;
12934 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12935 scoped_ptr
<HttpTransaction
> trans(
12936 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12937 // Send headers successfully, but get an error while sending the body.
12938 MockWrite data_writes
[] = {
12939 MockWrite("POST / HTTP/1.1\r\n"
12940 "Host: www.foo.com\r\n"
12941 "Connection: keep-alive\r\n"
12942 "Transfer-Encoding: chunked\r\n\r\n"),
12943 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12946 MockRead data_reads
[] = {
12947 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12948 MockRead("hello world"),
12949 MockRead(SYNCHRONOUS
, OK
),
12951 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12952 arraysize(data_writes
));
12953 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12955 TestCompletionCallback callback
;
12957 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12958 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12959 // Make sure the headers are sent before adding a chunk. This ensures that
12960 // they can't be merged with the body in a single send. Not currently
12961 // necessary since a chunked body is never merged with headers, but this makes
12962 // the test more future proof.
12963 base::RunLoop().RunUntilIdle();
12965 upload_data_stream
.AppendChunk("last chunk", 10, true);
12967 rv
= callback
.WaitForResult();
12970 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12971 ASSERT_TRUE(response
!= NULL
);
12973 EXPECT_TRUE(response
->headers
.get() != NULL
);
12974 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12976 std::string response_data
;
12977 rv
= ReadTransaction(trans
.get(), &response_data
);
12979 EXPECT_EQ("hello world", response_data
);
12982 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
12983 ScopedVector
<UploadElementReader
> element_readers
;
12984 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12985 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12987 HttpRequestInfo request
;
12988 request
.method
= "POST";
12989 request
.url
= GURL("http://www.foo.com/");
12990 request
.upload_data_stream
= &upload_data_stream
;
12991 request
.load_flags
= 0;
12993 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12994 scoped_ptr
<HttpTransaction
> trans(
12995 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12997 MockWrite data_writes
[] = {
12998 MockWrite("POST / HTTP/1.1\r\n"
12999 "Host: www.foo.com\r\n"
13000 "Connection: keep-alive\r\n"
13001 "Content-Length: 3\r\n\r\n"),
13002 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13005 MockRead data_reads
[] = {
13006 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13007 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13008 MockRead("hello world"),
13009 MockRead(SYNCHRONOUS
, OK
),
13011 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13012 arraysize(data_writes
));
13013 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13015 TestCompletionCallback callback
;
13017 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13018 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13020 rv
= callback
.WaitForResult();
13023 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13024 ASSERT_TRUE(response
!= NULL
);
13026 EXPECT_TRUE(response
->headers
.get() != NULL
);
13027 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13029 std::string response_data
;
13030 rv
= ReadTransaction(trans
.get(), &response_data
);
13032 EXPECT_EQ("hello world", response_data
);
13035 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13036 ScopedVector
<UploadElementReader
> element_readers
;
13037 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13038 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13040 HttpRequestInfo request
;
13041 request
.method
= "POST";
13042 request
.url
= GURL("http://www.foo.com/");
13043 request
.upload_data_stream
= &upload_data_stream
;
13044 request
.load_flags
= 0;
13046 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13047 scoped_ptr
<HttpTransaction
> trans(
13048 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13049 // Send headers successfully, but get an error while sending the body.
13050 MockWrite data_writes
[] = {
13051 MockWrite("POST / HTTP/1.1\r\n"
13052 "Host: www.foo.com\r\n"
13053 "Connection: keep-alive\r\n"
13054 "Content-Length: 3\r\n\r\n"),
13055 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13058 MockRead data_reads
[] = {
13059 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13060 MockRead("hello world"),
13061 MockRead(SYNCHRONOUS
, OK
),
13063 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13064 arraysize(data_writes
));
13065 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13067 TestCompletionCallback callback
;
13069 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13070 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13072 rv
= callback
.WaitForResult();
13073 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13075 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13076 EXPECT_TRUE(response
== NULL
);
13079 TEST_P(HttpNetworkTransactionTest
,
13080 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13081 ScopedVector
<UploadElementReader
> element_readers
;
13082 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13083 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13085 HttpRequestInfo request
;
13086 request
.method
= "POST";
13087 request
.url
= GURL("http://www.foo.com/");
13088 request
.upload_data_stream
= &upload_data_stream
;
13089 request
.load_flags
= 0;
13091 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13092 scoped_ptr
<HttpTransaction
> trans(
13093 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13094 // Send headers successfully, but get an error while sending the body.
13095 MockWrite data_writes
[] = {
13096 MockWrite("POST / HTTP/1.1\r\n"
13097 "Host: www.foo.com\r\n"
13098 "Connection: keep-alive\r\n"
13099 "Content-Length: 3\r\n\r\n"),
13100 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13103 MockRead data_reads
[] = {
13104 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13105 MockRead("HTTP/1.0 302 Redirect\r\n"),
13106 MockRead("Location: http://somewhere-else.com/\r\n"),
13107 MockRead("Content-Length: 0\r\n\r\n"),
13108 MockRead(SYNCHRONOUS
, OK
),
13110 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13111 arraysize(data_writes
));
13112 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13114 TestCompletionCallback callback
;
13116 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13117 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13119 rv
= callback
.WaitForResult();
13120 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13122 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13123 EXPECT_TRUE(response
== NULL
);
13126 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13127 ScopedVector
<UploadElementReader
> element_readers
;
13128 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13129 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13131 HttpRequestInfo request
;
13132 request
.method
= "POST";
13133 request
.url
= GURL("http://www.foo.com/");
13134 request
.upload_data_stream
= &upload_data_stream
;
13135 request
.load_flags
= 0;
13137 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13138 scoped_ptr
<HttpTransaction
> trans(
13139 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13140 // Send headers successfully, but get an error while sending the body.
13141 MockWrite data_writes
[] = {
13142 MockWrite("POST / HTTP/1.1\r\n"
13143 "Host: www.foo.com\r\n"
13144 "Connection: keep-alive\r\n"
13145 "Content-Length: 3\r\n\r\n"),
13146 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13149 MockRead data_reads
[] = {
13150 MockRead("HTTP 0.9 rocks!"),
13151 MockRead(SYNCHRONOUS
, OK
),
13153 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13154 arraysize(data_writes
));
13155 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13157 TestCompletionCallback callback
;
13159 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13160 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13162 rv
= callback
.WaitForResult();
13163 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13165 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13166 EXPECT_TRUE(response
== NULL
);
13169 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13170 ScopedVector
<UploadElementReader
> element_readers
;
13171 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13172 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13174 HttpRequestInfo request
;
13175 request
.method
= "POST";
13176 request
.url
= GURL("http://www.foo.com/");
13177 request
.upload_data_stream
= &upload_data_stream
;
13178 request
.load_flags
= 0;
13180 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13181 scoped_ptr
<HttpTransaction
> trans(
13182 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13183 // Send headers successfully, but get an error while sending the body.
13184 MockWrite data_writes
[] = {
13185 MockWrite("POST / HTTP/1.1\r\n"
13186 "Host: www.foo.com\r\n"
13187 "Connection: keep-alive\r\n"
13188 "Content-Length: 3\r\n\r\n"),
13189 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13192 MockRead data_reads
[] = {
13193 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13194 MockRead(SYNCHRONOUS
, OK
),
13196 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13197 arraysize(data_writes
));
13198 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13200 TestCompletionCallback callback
;
13202 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13205 rv
= callback
.WaitForResult();
13206 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13208 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13209 EXPECT_TRUE(response
== NULL
);