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/files/file_path.h"
15 #include "base/files/file_util.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/chunked_upload_data_stream.h"
26 #include "net/base/completion_callback.h"
27 #include "net/base/elements_upload_data_stream.h"
28 #include "net/base/load_timing_info.h"
29 #include "net/base/load_timing_info_test_util.h"
30 #include "net/base/net_log.h"
31 #include "net/base/net_log_unittest.h"
32 #include "net/base/request_priority.h"
33 #include "net/base/test_completion_callback.h"
34 #include "net/base/test_data_directory.h"
35 #include "net/base/upload_bytes_element_reader.h"
36 #include "net/base/upload_file_element_reader.h"
37 #include "net/cert/mock_cert_verifier.h"
38 #include "net/dns/host_cache.h"
39 #include "net/dns/mock_host_resolver.h"
40 #include "net/http/http_auth_challenge_tokenizer.h"
41 #include "net/http/http_auth_handler_digest.h"
42 #include "net/http/http_auth_handler_mock.h"
43 #include "net/http/http_auth_handler_ntlm.h"
44 #include "net/http/http_basic_stream.h"
45 #include "net/http/http_network_session.h"
46 #include "net/http/http_network_session_peer.h"
47 #include "net/http/http_server_properties_impl.h"
48 #include "net/http/http_stream.h"
49 #include "net/http/http_stream_factory.h"
50 #include "net/http/http_transaction_test_util.h"
51 #include "net/proxy/proxy_config_service_fixed.h"
52 #include "net/proxy/proxy_info.h"
53 #include "net/proxy/proxy_resolver.h"
54 #include "net/proxy/proxy_service.h"
55 #include "net/socket/client_socket_factory.h"
56 #include "net/socket/client_socket_pool_manager.h"
57 #include "net/socket/mock_client_socket_pool_manager.h"
58 #include "net/socket/next_proto.h"
59 #include "net/socket/socket_test_util.h"
60 #include "net/socket/ssl_client_socket.h"
61 #include "net/spdy/spdy_framer.h"
62 #include "net/spdy/spdy_session.h"
63 #include "net/spdy/spdy_session_pool.h"
64 #include "net/spdy/spdy_test_util_common.h"
65 #include "net/ssl/ssl_cert_request_info.h"
66 #include "net/ssl/ssl_config_service.h"
67 #include "net/ssl/ssl_config_service_defaults.h"
68 #include "net/ssl/ssl_info.h"
69 #include "net/test/cert_test_util.h"
70 #include "net/websockets/websocket_handshake_stream_base.h"
71 #include "testing/gtest/include/gtest/gtest.h"
72 #include "testing/platform_test.h"
75 using base::ASCIIToUTF16
;
77 //-----------------------------------------------------------------------------
81 const base::string16
kBar(ASCIIToUTF16("bar"));
82 const base::string16
kBar2(ASCIIToUTF16("bar2"));
83 const base::string16
kBar3(ASCIIToUTF16("bar3"));
84 const base::string16
kBaz(ASCIIToUTF16("baz"));
85 const base::string16
kFirst(ASCIIToUTF16("first"));
86 const base::string16
kFoo(ASCIIToUTF16("foo"));
87 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
88 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
89 const base::string16
kFou(ASCIIToUTF16("fou"));
90 const base::string16
kSecond(ASCIIToUTF16("second"));
91 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
92 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
94 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession
* session
) {
95 return session
->GetTransportSocketPool(
96 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
99 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession
* session
) {
100 return session
->GetSSLSocketPool(
101 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
104 bool IsTransportSocketPoolStalled(net::HttpNetworkSession
* session
) {
105 return session
->GetTransportSocketPool(
106 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IsStalled();
109 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
110 // a JSONified list of headers as a single string. Uses single quotes instead
111 // of double quotes for easier comparison. Returns false on failure.
112 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
115 base::ListValue
* header_list
;
116 if (!params
->GetList("headers", &header_list
))
118 std::string double_quote_headers
;
119 base::JSONWriter::Write(header_list
, &double_quote_headers
);
120 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
124 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
126 void TestLoadTimingReused(const net::LoadTimingInfo
& load_timing_info
) {
127 EXPECT_TRUE(load_timing_info
.socket_reused
);
128 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
130 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
131 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
133 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
134 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
136 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
138 // Set at a higher level.
139 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
140 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
141 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
144 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
146 void TestLoadTimingNotReused(const net::LoadTimingInfo
& load_timing_info
,
147 int connect_timing_flags
) {
148 EXPECT_FALSE(load_timing_info
.socket_reused
);
149 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
151 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
152 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
154 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
155 connect_timing_flags
);
156 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
157 load_timing_info
.send_start
);
159 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
161 // Set at a higher level.
162 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
163 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
164 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
167 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
169 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo
& load_timing_info
) {
170 EXPECT_TRUE(load_timing_info
.socket_reused
);
171 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
173 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
175 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
176 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
177 load_timing_info
.proxy_resolve_end
);
178 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
179 load_timing_info
.send_start
);
180 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
182 // Set at a higher level.
183 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
184 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
185 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
188 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
190 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo
& load_timing_info
,
191 int connect_timing_flags
) {
192 EXPECT_FALSE(load_timing_info
.socket_reused
);
193 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
195 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
196 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
197 load_timing_info
.proxy_resolve_end
);
198 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
199 load_timing_info
.connect_timing
.connect_start
);
200 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
201 connect_timing_flags
);
202 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
203 load_timing_info
.send_start
);
205 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
207 // Set at a higher level.
208 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
209 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
210 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
219 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
220 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
225 class HttpNetworkTransactionTest
226 : public PlatformTest
,
227 public ::testing::WithParamInterface
<NextProto
> {
229 virtual ~HttpNetworkTransactionTest() {
230 // Important to restore the per-pool limit first, since the pool limit must
231 // always be greater than group limit, and the tests reduce both limits.
232 ClientSocketPoolManager::set_max_sockets_per_pool(
233 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
234 ClientSocketPoolManager::set_max_sockets_per_group(
235 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
239 HttpNetworkTransactionTest()
240 : spdy_util_(GetParam()),
241 session_deps_(GetParam()),
242 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
243 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
244 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
245 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
248 struct SimpleGetHelperResult
{
250 std::string status_line
;
251 std::string response_data
;
252 int64 totalReceivedBytes
;
253 LoadTimingInfo load_timing_info
;
256 void SetUp() override
{
257 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
258 base::MessageLoop::current()->RunUntilIdle();
261 void TearDown() override
{
262 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
263 base::MessageLoop::current()->RunUntilIdle();
264 // Empty the current queue.
265 base::MessageLoop::current()->RunUntilIdle();
266 PlatformTest::TearDown();
267 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
268 base::MessageLoop::current()->RunUntilIdle();
271 // This is the expected return from a current server advertising SPDY.
272 std::string
GetAlternateProtocolHttpHeader() {
274 std::string("Alternate-Protocol: 443:") +
275 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
279 // Either |write_failure| specifies a write failure or |read_failure|
280 // specifies a read failure when using a reused socket. In either case, the
281 // failure should cause the network transaction to resend the request, and the
282 // other argument should be NULL.
283 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
284 const MockRead
* read_failure
);
286 // Either |write_failure| specifies a write failure or |read_failure|
287 // specifies a read failure when using a reused socket. In either case, the
288 // failure should cause the network transaction to resend the request, and the
289 // other argument should be NULL.
290 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
291 const MockRead
* read_failure
,
294 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
296 SimpleGetHelperResult out
;
298 HttpRequestInfo request
;
299 request
.method
= "GET";
300 request
.url
= GURL("http://www.google.com/");
301 request
.load_flags
= 0;
303 CapturingBoundNetLog log
;
304 session_deps_
.net_log
= log
.bound().net_log();
305 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
306 scoped_ptr
<HttpTransaction
> trans(
307 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
309 for (size_t i
= 0; i
< data_count
; ++i
) {
310 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
313 TestCompletionCallback callback
;
315 EXPECT_TRUE(log
.bound().IsLogging());
316 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
317 EXPECT_EQ(ERR_IO_PENDING
, rv
);
319 out
.rv
= callback
.WaitForResult();
321 // Even in the failure cases that use this function, connections are always
322 // successfully established before the error.
323 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
324 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
329 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
330 // Can't use ASSERT_* inside helper functions like this, so
332 if (response
== NULL
|| response
->headers
.get() == NULL
) {
333 out
.rv
= ERR_UNEXPECTED
;
336 out
.status_line
= response
->headers
->GetStatusLine();
338 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
339 EXPECT_EQ(80, response
->socket_address
.port());
341 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
344 net::CapturingNetLog::CapturedEntryList entries
;
345 log
.GetEntries(&entries
);
346 size_t pos
= ExpectLogContainsSomewhere(
347 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
349 ExpectLogContainsSomewhere(
351 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
355 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
356 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
358 HttpRequestHeaders request_headers
;
359 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
361 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
362 EXPECT_EQ("www.google.com", value
);
363 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
364 EXPECT_EQ("keep-alive", value
);
366 std::string response_headers
;
367 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
368 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
371 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
375 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
376 size_t reads_count
) {
377 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
378 StaticSocketDataProvider
* data
[] = { &reads
};
379 return SimpleGetHelperForData(data
, 1);
382 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
384 for (size_t i
= 0; i
< reads_count
; ++i
)
385 size
+= data_reads
[i
].data_len
;
389 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
390 int expected_status
);
392 void ConnectStatusHelper(const MockRead
& status
);
394 void BypassHostCacheOnRefreshHelper(int load_flags
);
396 void CheckErrorIsPassedBack(int error
, IoMode mode
);
398 SpdyTestUtil spdy_util_
;
399 SpdySessionDependencies session_deps_
;
401 // Original socket limits. Some tests set these. Safest to always restore
402 // them once each test has been run.
403 int old_max_group_sockets_
;
404 int old_max_pool_sockets_
;
407 INSTANTIATE_TEST_CASE_P(
409 HttpNetworkTransactionTest
,
410 testing::Values(kProtoDeprecatedSPDY2
,
411 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4_14
, kProtoSPDY4_15
));
415 class BeforeNetworkStartHandler
{
417 explicit BeforeNetworkStartHandler(bool defer
)
418 : defer_on_before_network_start_(defer
),
419 observed_before_network_start_(false) {}
421 void OnBeforeNetworkStart(bool* defer
) {
422 *defer
= defer_on_before_network_start_
;
423 observed_before_network_start_
= true;
426 bool observed_before_network_start() const {
427 return observed_before_network_start_
;
431 const bool defer_on_before_network_start_
;
432 bool observed_before_network_start_
;
434 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
437 class BeforeProxyHeadersSentHandler
{
439 BeforeProxyHeadersSentHandler()
440 : observed_before_proxy_headers_sent_(false) {}
442 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
443 HttpRequestHeaders
* request_headers
) {
444 observed_before_proxy_headers_sent_
= true;
445 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
448 bool observed_before_proxy_headers_sent() const {
449 return observed_before_proxy_headers_sent_
;
452 std::string
observed_proxy_server_uri() const {
453 return observed_proxy_server_uri_
;
457 bool observed_before_proxy_headers_sent_
;
458 std::string observed_proxy_server_uri_
;
460 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
463 // Fill |str| with a long header list that consumes >= |size| bytes.
464 void FillLargeHeadersString(std::string
* str
, int size
) {
466 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
467 const int sizeof_row
= strlen(row
);
468 const int num_rows
= static_cast<int>(
469 ceil(static_cast<float>(size
) / sizeof_row
));
470 const int sizeof_data
= num_rows
* sizeof_row
;
471 DCHECK(sizeof_data
>= size
);
472 str
->reserve(sizeof_data
);
474 for (int i
= 0; i
< num_rows
; ++i
)
475 str
->append(row
, sizeof_row
);
478 // Alternative functions that eliminate randomness and dependency on the local
479 // host name so that the generated NTLM messages are reproducible.
480 void MockGenerateRandom1(uint8
* output
, size_t n
) {
481 static const uint8 bytes
[] = {
482 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
484 static size_t current_byte
= 0;
485 for (size_t i
= 0; i
< n
; ++i
) {
486 output
[i
] = bytes
[current_byte
++];
487 current_byte
%= arraysize(bytes
);
491 void MockGenerateRandom2(uint8
* output
, size_t n
) {
492 static const uint8 bytes
[] = {
493 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
494 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
496 static size_t current_byte
= 0;
497 for (size_t i
= 0; i
< n
; ++i
) {
498 output
[i
] = bytes
[current_byte
++];
499 current_byte
%= arraysize(bytes
);
503 std::string
MockGetHostName() {
507 template<typename ParentPool
>
508 class CaptureGroupNameSocketPool
: public ParentPool
{
510 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
511 CertVerifier
* cert_verifier
);
513 const std::string
last_group_name_received() const {
514 return last_group_name_
;
517 virtual int RequestSocket(const std::string
& group_name
,
518 const void* socket_params
,
519 RequestPriority priority
,
520 ClientSocketHandle
* handle
,
521 const CompletionCallback
& callback
,
522 const BoundNetLog
& net_log
) {
523 last_group_name_
= group_name
;
524 return ERR_IO_PENDING
;
526 virtual void CancelRequest(const std::string
& group_name
,
527 ClientSocketHandle
* handle
) {}
528 virtual void ReleaseSocket(const std::string
& group_name
,
529 scoped_ptr
<StreamSocket
> socket
,
531 virtual void CloseIdleSockets() {}
532 virtual int IdleSocketCount() const {
535 virtual int IdleSocketCountInGroup(const std::string
& group_name
) const {
538 virtual LoadState
GetLoadState(const std::string
& group_name
,
539 const ClientSocketHandle
* handle
) const {
540 return LOAD_STATE_IDLE
;
542 virtual base::TimeDelta
ConnectionTimeout() const {
543 return base::TimeDelta();
547 std::string last_group_name_
;
550 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
551 CaptureGroupNameTransportSocketPool
;
552 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
553 CaptureGroupNameHttpProxySocketPool
;
554 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
555 CaptureGroupNameSOCKSSocketPool
;
556 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
557 CaptureGroupNameSSLSocketPool
;
559 template<typename ParentPool
>
560 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
561 HostResolver
* host_resolver
,
562 CertVerifier
* /* cert_verifier */)
563 : ParentPool(0, 0, NULL
, host_resolver
, NULL
, NULL
) {}
566 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
567 HostResolver
* host_resolver
,
568 CertVerifier
* /* cert_verifier */)
569 : HttpProxyClientSocketPool(
570 0, 0, NULL
, host_resolver
, NULL
, NULL
, NULL
, NULL
) {}
573 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
574 HostResolver
* host_resolver
,
575 CertVerifier
* cert_verifier
)
576 : SSLClientSocketPool(0,
594 //-----------------------------------------------------------------------------
596 // Helper functions for validating that AuthChallengeInfo's are correctly
597 // configured for common cases.
598 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
601 EXPECT_FALSE(auth_challenge
->is_proxy
);
602 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
603 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
604 EXPECT_EQ("basic", auth_challenge
->scheme
);
608 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
611 EXPECT_TRUE(auth_challenge
->is_proxy
);
612 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
613 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
614 EXPECT_EQ("basic", auth_challenge
->scheme
);
618 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
621 EXPECT_FALSE(auth_challenge
->is_proxy
);
622 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
623 EXPECT_EQ("digestive", auth_challenge
->realm
);
624 EXPECT_EQ("digest", auth_challenge
->scheme
);
628 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
631 EXPECT_FALSE(auth_challenge
->is_proxy
);
632 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
633 EXPECT_EQ(std::string(), auth_challenge
->realm
);
634 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
640 TEST_P(HttpNetworkTransactionTest
, Basic
) {
641 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
642 scoped_ptr
<HttpTransaction
> trans(
643 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
646 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
647 MockRead data_reads
[] = {
648 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
649 MockRead("hello world"),
650 MockRead(SYNCHRONOUS
, OK
),
652 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
653 arraysize(data_reads
));
654 EXPECT_EQ(OK
, out
.rv
);
655 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
656 EXPECT_EQ("hello world", out
.response_data
);
657 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
658 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
661 // Response with no status line.
662 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
663 MockRead data_reads
[] = {
664 MockRead("hello world"),
665 MockRead(SYNCHRONOUS
, OK
),
667 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
668 arraysize(data_reads
));
669 EXPECT_EQ(OK
, out
.rv
);
670 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
671 EXPECT_EQ("hello world", out
.response_data
);
672 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
673 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
676 // Allow up to 4 bytes of junk to precede status line.
677 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
678 MockRead data_reads
[] = {
679 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
680 MockRead(SYNCHRONOUS
, OK
),
682 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
683 arraysize(data_reads
));
684 EXPECT_EQ(OK
, out
.rv
);
685 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
686 EXPECT_EQ("DATA", out
.response_data
);
687 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
688 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
691 // Allow up to 4 bytes of junk to precede status line.
692 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
693 MockRead data_reads
[] = {
694 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
695 MockRead(SYNCHRONOUS
, OK
),
697 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
698 arraysize(data_reads
));
699 EXPECT_EQ(OK
, out
.rv
);
700 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
701 EXPECT_EQ("DATA", out
.response_data
);
702 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
703 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
706 // Beyond 4 bytes of slop and it should fail to find a status line.
707 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
708 MockRead data_reads
[] = {
709 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
710 MockRead(SYNCHRONOUS
, OK
),
712 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
713 arraysize(data_reads
));
714 EXPECT_EQ(OK
, out
.rv
);
715 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
716 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
717 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
718 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
721 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
722 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
723 MockRead data_reads
[] = {
728 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
729 MockRead(SYNCHRONOUS
, OK
),
731 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
732 arraysize(data_reads
));
733 EXPECT_EQ(OK
, out
.rv
);
734 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
735 EXPECT_EQ("DATA", out
.response_data
);
736 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
737 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
740 // Close the connection before enough bytes to have a status line.
741 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
742 MockRead data_reads
[] = {
744 MockRead(SYNCHRONOUS
, OK
),
746 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
747 arraysize(data_reads
));
748 EXPECT_EQ(OK
, out
.rv
);
749 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
750 EXPECT_EQ("HTT", out
.response_data
);
751 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
752 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
755 // Simulate a 204 response, lacking a Content-Length header, sent over a
756 // persistent connection. The response should still terminate since a 204
757 // cannot have a response body.
758 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
759 char junk
[] = "junk";
760 MockRead data_reads
[] = {
761 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
762 MockRead(junk
), // Should not be read!!
763 MockRead(SYNCHRONOUS
, OK
),
765 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
766 arraysize(data_reads
));
767 EXPECT_EQ(OK
, out
.rv
);
768 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
769 EXPECT_EQ("", out
.response_data
);
770 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
771 int64 response_size
= reads_size
- strlen(junk
);
772 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
775 // A simple request using chunked encoding with some extra data after.
776 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
777 std::string final_chunk
= "0\r\n\r\n";
778 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
779 std::string last_read
= final_chunk
+ extra_data
;
780 MockRead data_reads
[] = {
781 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
782 MockRead("5\r\nHello\r\n"),
785 MockRead("5\r\nworld\r\n"),
786 MockRead(last_read
.data()),
787 MockRead(SYNCHRONOUS
, OK
),
789 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
790 arraysize(data_reads
));
791 EXPECT_EQ(OK
, out
.rv
);
792 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
793 EXPECT_EQ("Hello world", out
.response_data
);
794 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
795 int64 response_size
= reads_size
- extra_data
.size();
796 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
799 // Next tests deal with http://crbug.com/56344.
801 TEST_P(HttpNetworkTransactionTest
,
802 MultipleContentLengthHeadersNoTransferEncoding
) {
803 MockRead data_reads
[] = {
804 MockRead("HTTP/1.1 200 OK\r\n"),
805 MockRead("Content-Length: 10\r\n"),
806 MockRead("Content-Length: 5\r\n\r\n"),
808 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
809 arraysize(data_reads
));
810 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
813 TEST_P(HttpNetworkTransactionTest
,
814 DuplicateContentLengthHeadersNoTransferEncoding
) {
815 MockRead data_reads
[] = {
816 MockRead("HTTP/1.1 200 OK\r\n"),
817 MockRead("Content-Length: 5\r\n"),
818 MockRead("Content-Length: 5\r\n\r\n"),
821 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
822 arraysize(data_reads
));
823 EXPECT_EQ(OK
, out
.rv
);
824 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
825 EXPECT_EQ("Hello", out
.response_data
);
828 TEST_P(HttpNetworkTransactionTest
,
829 ComplexContentLengthHeadersNoTransferEncoding
) {
830 // More than 2 dupes.
832 MockRead data_reads
[] = {
833 MockRead("HTTP/1.1 200 OK\r\n"),
834 MockRead("Content-Length: 5\r\n"),
835 MockRead("Content-Length: 5\r\n"),
836 MockRead("Content-Length: 5\r\n\r\n"),
839 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
840 arraysize(data_reads
));
841 EXPECT_EQ(OK
, out
.rv
);
842 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
843 EXPECT_EQ("Hello", out
.response_data
);
847 MockRead data_reads
[] = {
848 MockRead("HTTP/1.0 200 OK\r\n"),
849 MockRead("Content-Length: 5\r\n"),
850 MockRead("Content-Length: 5\r\n"),
851 MockRead("Content-Length: 5\r\n\r\n"),
854 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
855 arraysize(data_reads
));
856 EXPECT_EQ(OK
, out
.rv
);
857 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
858 EXPECT_EQ("Hello", out
.response_data
);
860 // 2 dupes and one mismatched.
862 MockRead data_reads
[] = {
863 MockRead("HTTP/1.1 200 OK\r\n"),
864 MockRead("Content-Length: 10\r\n"),
865 MockRead("Content-Length: 10\r\n"),
866 MockRead("Content-Length: 5\r\n\r\n"),
868 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
869 arraysize(data_reads
));
870 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
874 TEST_P(HttpNetworkTransactionTest
,
875 MultipleContentLengthHeadersTransferEncoding
) {
876 MockRead data_reads
[] = {
877 MockRead("HTTP/1.1 200 OK\r\n"),
878 MockRead("Content-Length: 666\r\n"),
879 MockRead("Content-Length: 1337\r\n"),
880 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
881 MockRead("5\r\nHello\r\n"),
884 MockRead("5\r\nworld\r\n"),
885 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
886 MockRead(SYNCHRONOUS
, OK
),
888 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
889 arraysize(data_reads
));
890 EXPECT_EQ(OK
, out
.rv
);
891 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
892 EXPECT_EQ("Hello world", out
.response_data
);
895 // Next tests deal with http://crbug.com/98895.
897 // Checks that a single Content-Disposition header results in no error.
898 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
899 MockRead data_reads
[] = {
900 MockRead("HTTP/1.1 200 OK\r\n"),
901 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
902 MockRead("Content-Length: 5\r\n\r\n"),
905 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
906 arraysize(data_reads
));
907 EXPECT_EQ(OK
, out
.rv
);
908 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
909 EXPECT_EQ("Hello", out
.response_data
);
912 // Checks that two identical Content-Disposition headers result in no error.
913 TEST_P(HttpNetworkTransactionTest
,
914 TwoIdenticalContentDispositionHeaders
) {
915 MockRead data_reads
[] = {
916 MockRead("HTTP/1.1 200 OK\r\n"),
917 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
918 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
919 MockRead("Content-Length: 5\r\n\r\n"),
922 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
923 arraysize(data_reads
));
924 EXPECT_EQ(OK
, out
.rv
);
925 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
926 EXPECT_EQ("Hello", out
.response_data
);
929 // Checks that two distinct Content-Disposition headers result in an error.
930 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
931 MockRead data_reads
[] = {
932 MockRead("HTTP/1.1 200 OK\r\n"),
933 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
934 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
935 MockRead("Content-Length: 5\r\n\r\n"),
938 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
939 arraysize(data_reads
));
940 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
943 // Checks that two identical Location headers result in no error.
944 // Also tests Location header behavior.
945 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
946 MockRead data_reads
[] = {
947 MockRead("HTTP/1.1 302 Redirect\r\n"),
948 MockRead("Location: http://good.com/\r\n"),
949 MockRead("Location: http://good.com/\r\n"),
950 MockRead("Content-Length: 0\r\n\r\n"),
951 MockRead(SYNCHRONOUS
, OK
),
954 HttpRequestInfo request
;
955 request
.method
= "GET";
956 request
.url
= GURL("http://redirect.com/");
957 request
.load_flags
= 0;
959 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
960 scoped_ptr
<HttpTransaction
> trans(
961 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
963 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
964 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
966 TestCompletionCallback callback
;
968 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
969 EXPECT_EQ(ERR_IO_PENDING
, rv
);
971 EXPECT_EQ(OK
, callback
.WaitForResult());
973 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
974 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
975 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
977 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
978 EXPECT_EQ("http://good.com/", url
);
979 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
982 // Checks that two distinct Location headers result in an error.
983 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
984 MockRead data_reads
[] = {
985 MockRead("HTTP/1.1 302 Redirect\r\n"),
986 MockRead("Location: http://good.com/\r\n"),
987 MockRead("Location: http://evil.com/\r\n"),
988 MockRead("Content-Length: 0\r\n\r\n"),
989 MockRead(SYNCHRONOUS
, OK
),
991 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
992 arraysize(data_reads
));
993 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
996 // Do a request using the HEAD method. Verify that we don't try to read the
997 // message body (since HEAD has none).
998 TEST_P(HttpNetworkTransactionTest
, Head
) {
999 HttpRequestInfo request
;
1000 request
.method
= "HEAD";
1001 request
.url
= GURL("http://www.google.com/");
1002 request
.load_flags
= 0;
1004 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1005 scoped_ptr
<HttpTransaction
> trans(
1006 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1007 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1008 trans
->SetBeforeProxyHeadersSentCallback(
1009 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1010 base::Unretained(&proxy_headers_handler
)));
1012 MockWrite data_writes1
[] = {
1013 MockWrite("HEAD / HTTP/1.1\r\n"
1014 "Host: www.google.com\r\n"
1015 "Connection: keep-alive\r\n"
1016 "Content-Length: 0\r\n\r\n"),
1018 MockRead data_reads1
[] = {
1019 MockRead("HTTP/1.1 404 Not Found\r\n"),
1020 MockRead("Server: Blah\r\n"),
1021 MockRead("Content-Length: 1234\r\n\r\n"),
1023 // No response body because the test stops reading here.
1024 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1027 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1028 data_writes1
, arraysize(data_writes1
));
1029 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1031 TestCompletionCallback callback1
;
1033 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1034 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1036 rv
= callback1
.WaitForResult();
1039 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1040 ASSERT_TRUE(response
!= NULL
);
1042 // Check that the headers got parsed.
1043 EXPECT_TRUE(response
->headers
.get() != NULL
);
1044 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1045 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1046 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1047 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1049 std::string server_header
;
1051 bool has_server_header
= response
->headers
->EnumerateHeader(
1052 &iter
, "Server", &server_header
);
1053 EXPECT_TRUE(has_server_header
);
1054 EXPECT_EQ("Blah", server_header
);
1056 // Reading should give EOF right away, since there is no message body
1057 // (despite non-zero content-length).
1058 std::string response_data
;
1059 rv
= ReadTransaction(trans
.get(), &response_data
);
1061 EXPECT_EQ("", response_data
);
1064 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1065 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1067 MockRead data_reads
[] = {
1068 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1070 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1072 MockRead(SYNCHRONOUS
, OK
),
1074 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1075 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1077 const char* const kExpectedResponseData
[] = {
1081 for (int i
= 0; i
< 2; ++i
) {
1082 HttpRequestInfo request
;
1083 request
.method
= "GET";
1084 request
.url
= GURL("http://www.google.com/");
1085 request
.load_flags
= 0;
1087 scoped_ptr
<HttpTransaction
> trans(
1088 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1090 TestCompletionCallback callback
;
1092 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1093 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1095 rv
= callback
.WaitForResult();
1098 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1099 ASSERT_TRUE(response
!= NULL
);
1101 EXPECT_TRUE(response
->headers
.get() != NULL
);
1102 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1103 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1105 std::string response_data
;
1106 rv
= ReadTransaction(trans
.get(), &response_data
);
1108 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1112 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1113 ScopedVector
<UploadElementReader
> element_readers
;
1114 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1115 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1117 HttpRequestInfo request
;
1118 request
.method
= "POST";
1119 request
.url
= GURL("http://www.foo.com/");
1120 request
.upload_data_stream
= &upload_data_stream
;
1121 request
.load_flags
= 0;
1123 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1124 scoped_ptr
<HttpTransaction
> trans(
1125 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1127 MockRead data_reads
[] = {
1128 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1129 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1130 MockRead("hello world"),
1131 MockRead(SYNCHRONOUS
, OK
),
1133 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1134 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1136 TestCompletionCallback callback
;
1138 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1139 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1141 rv
= callback
.WaitForResult();
1144 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1145 ASSERT_TRUE(response
!= NULL
);
1147 EXPECT_TRUE(response
->headers
.get() != NULL
);
1148 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1150 std::string response_data
;
1151 rv
= ReadTransaction(trans
.get(), &response_data
);
1153 EXPECT_EQ("hello world", response_data
);
1156 // This test is almost the same as Ignores100 above, but the response contains
1157 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1158 // HTTP/1.1 and the two status headers are read in one read.
1159 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1160 HttpRequestInfo request
;
1161 request
.method
= "GET";
1162 request
.url
= GURL("http://www.foo.com/");
1163 request
.load_flags
= 0;
1165 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1166 scoped_ptr
<HttpTransaction
> trans(
1167 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1169 MockRead data_reads
[] = {
1170 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1171 "HTTP/1.1 200 OK\r\n\r\n"),
1172 MockRead("hello world"),
1173 MockRead(SYNCHRONOUS
, OK
),
1175 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1178 TestCompletionCallback callback
;
1180 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1183 rv
= callback
.WaitForResult();
1186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1187 ASSERT_TRUE(response
!= NULL
);
1189 EXPECT_TRUE(response
->headers
.get() != NULL
);
1190 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1192 std::string response_data
;
1193 rv
= ReadTransaction(trans
.get(), &response_data
);
1195 EXPECT_EQ("hello world", response_data
);
1198 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1199 HttpRequestInfo request
;
1200 request
.method
= "POST";
1201 request
.url
= GURL("http://www.foo.com/");
1202 request
.load_flags
= 0;
1204 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1205 scoped_ptr
<HttpTransaction
> trans(
1206 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1208 MockRead data_reads
[] = {
1209 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1212 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1213 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1215 TestCompletionCallback callback
;
1217 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1218 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1220 rv
= callback
.WaitForResult();
1223 std::string response_data
;
1224 rv
= ReadTransaction(trans
.get(), &response_data
);
1226 EXPECT_EQ("", response_data
);
1229 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1230 HttpRequestInfo request
;
1231 request
.method
= "POST";
1232 request
.url
= GURL("http://www.foo.com/");
1233 request
.load_flags
= 0;
1235 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1236 scoped_ptr
<HttpTransaction
> trans(
1237 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1239 MockRead data_reads
[] = {
1242 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1243 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1245 TestCompletionCallback callback
;
1247 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1248 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1250 rv
= callback
.WaitForResult();
1251 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1254 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1255 const MockWrite
* write_failure
,
1256 const MockRead
* read_failure
) {
1257 HttpRequestInfo request
;
1258 request
.method
= "GET";
1259 request
.url
= GURL("http://www.foo.com/");
1260 request
.load_flags
= 0;
1262 CapturingNetLog net_log
;
1263 session_deps_
.net_log
= &net_log
;
1264 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1266 // Written data for successfully sending both requests.
1267 MockWrite data1_writes
[] = {
1268 MockWrite("GET / HTTP/1.1\r\n"
1269 "Host: www.foo.com\r\n"
1270 "Connection: keep-alive\r\n\r\n"),
1271 MockWrite("GET / HTTP/1.1\r\n"
1272 "Host: www.foo.com\r\n"
1273 "Connection: keep-alive\r\n\r\n")
1276 // Read results for the first request.
1277 MockRead data1_reads
[] = {
1278 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1280 MockRead(ASYNC
, OK
),
1283 if (write_failure
) {
1284 ASSERT_FALSE(read_failure
);
1285 data1_writes
[1] = *write_failure
;
1287 ASSERT_TRUE(read_failure
);
1288 data1_reads
[2] = *read_failure
;
1291 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1292 data1_writes
, arraysize(data1_writes
));
1293 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1295 MockRead data2_reads
[] = {
1296 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1298 MockRead(ASYNC
, OK
),
1300 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1301 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1303 const char* kExpectedResponseData
[] = {
1307 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1308 for (int i
= 0; i
< 2; ++i
) {
1309 TestCompletionCallback callback
;
1311 scoped_ptr
<HttpTransaction
> trans(
1312 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1314 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1315 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1317 rv
= callback
.WaitForResult();
1320 LoadTimingInfo load_timing_info
;
1321 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1322 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1324 first_socket_log_id
= load_timing_info
.socket_log_id
;
1326 // The second request should be using a new socket.
1327 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1330 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1331 ASSERT_TRUE(response
!= NULL
);
1333 EXPECT_TRUE(response
->headers
.get() != NULL
);
1334 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1336 std::string response_data
;
1337 rv
= ReadTransaction(trans
.get(), &response_data
);
1339 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1343 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1344 const MockWrite
* write_failure
,
1345 const MockRead
* read_failure
,
1347 HttpRequestInfo request
;
1348 request
.method
= "GET";
1349 request
.url
= GURL("https://www.foo.com/");
1350 request
.load_flags
= 0;
1352 CapturingNetLog net_log
;
1353 session_deps_
.net_log
= &net_log
;
1354 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1356 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1357 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1359 ssl1
.SetNextProto(GetParam());
1360 ssl2
.SetNextProto(GetParam());
1362 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1363 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1365 // SPDY versions of the request and response.
1366 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1367 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1368 scoped_ptr
<SpdyFrame
> spdy_response(
1369 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1370 scoped_ptr
<SpdyFrame
> spdy_data(
1371 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1373 // HTTP/1.1 versions of the request and response.
1374 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1375 "Host: www.foo.com\r\n"
1376 "Connection: keep-alive\r\n\r\n";
1377 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1378 const char kHttpData
[] = "hello";
1380 std::vector
<MockRead
> data1_reads
;
1381 std::vector
<MockWrite
> data1_writes
;
1382 if (write_failure
) {
1383 ASSERT_FALSE(read_failure
);
1384 data1_writes
.push_back(*write_failure
);
1385 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1387 ASSERT_TRUE(read_failure
);
1389 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1391 data1_writes
.push_back(MockWrite(kHttpRequest
));
1393 data1_reads
.push_back(*read_failure
);
1396 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1397 &data1_writes
[0], data1_writes
.size());
1398 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1400 std::vector
<MockRead
> data2_reads
;
1401 std::vector
<MockWrite
> data2_writes
;
1404 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1406 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1407 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1408 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1410 data2_writes
.push_back(
1411 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1413 data2_reads
.push_back(
1414 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1415 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1416 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1418 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1419 &data2_writes
[0], data2_writes
.size());
1420 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1422 // Preconnect a socket.
1423 net::SSLConfig ssl_config
;
1424 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1425 session
->GetNextProtos(&ssl_config
.next_protos
);
1426 session
->http_stream_factory()->PreconnectStreams(
1427 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1428 // Wait for the preconnect to complete.
1429 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1430 base::RunLoop().RunUntilIdle();
1431 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1433 // Make the request.
1434 TestCompletionCallback callback
;
1436 scoped_ptr
<HttpTransaction
> trans(
1437 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1439 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1442 rv
= callback
.WaitForResult();
1445 LoadTimingInfo load_timing_info
;
1446 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1447 TestLoadTimingNotReused(
1449 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1451 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1452 ASSERT_TRUE(response
!= NULL
);
1454 EXPECT_TRUE(response
->headers
.get() != NULL
);
1455 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1457 std::string response_data
;
1458 rv
= ReadTransaction(trans
.get(), &response_data
);
1460 EXPECT_EQ(kHttpData
, response_data
);
1463 TEST_P(HttpNetworkTransactionTest
,
1464 KeepAliveConnectionNotConnectedOnWrite
) {
1465 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1466 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1469 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1470 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1471 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1474 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1475 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1476 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1479 // Make sure that on a 408 response (Request Timeout), the request is retried,
1480 // if the socket was a reused keep alive socket.
1481 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1482 MockRead
read_failure(SYNCHRONOUS
,
1483 "HTTP/1.1 408 Request Timeout\r\n"
1484 "Connection: Keep-Alive\r\n"
1485 "Content-Length: 6\r\n\r\n"
1487 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1490 TEST_P(HttpNetworkTransactionTest
,
1491 PreconnectErrorNotConnectedOnWrite
) {
1492 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1493 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1496 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1497 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1498 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1501 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1502 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1503 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1506 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1507 MockRead
read_failure(ASYNC
, OK
); // EOF
1508 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1511 // Make sure that on a 408 response (Request Timeout), the request is retried,
1512 // if the socket was a preconnected (UNUSED_IDLE) socket.
1513 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1514 MockRead
read_failure(SYNCHRONOUS
,
1515 "HTTP/1.1 408 Request Timeout\r\n"
1516 "Connection: Keep-Alive\r\n"
1517 "Content-Length: 6\r\n\r\n"
1519 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1520 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1523 TEST_P(HttpNetworkTransactionTest
,
1524 SpdyPreconnectErrorNotConnectedOnWrite
) {
1525 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1526 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1529 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1530 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1531 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1534 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1535 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1536 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1539 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1540 MockRead
read_failure(ASYNC
, OK
); // EOF
1541 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1544 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1545 HttpRequestInfo request
;
1546 request
.method
= "GET";
1547 request
.url
= GURL("http://www.google.com/");
1548 request
.load_flags
= 0;
1550 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1551 scoped_ptr
<HttpTransaction
> trans(
1552 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1554 MockRead data_reads
[] = {
1555 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1556 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1557 MockRead("hello world"),
1558 MockRead(SYNCHRONOUS
, OK
),
1560 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1561 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1563 TestCompletionCallback callback
;
1565 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1566 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1568 rv
= callback
.WaitForResult();
1569 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1571 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1572 EXPECT_TRUE(response
== NULL
);
1575 // What do various browsers do when the server closes a non-keepalive
1576 // connection without sending any response header or body?
1579 // Safari 3.1.2 (Windows): error page
1580 // Firefox 3.0.1: blank page
1581 // Opera 9.52: after five attempts, blank page
1582 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1583 // Us: error page (EMPTY_RESPONSE)
1584 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1585 MockRead data_reads
[] = {
1586 MockRead(SYNCHRONOUS
, OK
), // EOF
1587 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1588 MockRead("hello world"),
1589 MockRead(SYNCHRONOUS
, OK
),
1591 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1592 arraysize(data_reads
));
1593 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1596 // Test that network access can be deferred and resumed.
1597 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1598 HttpRequestInfo request
;
1599 request
.method
= "GET";
1600 request
.url
= GURL("http://www.google.com/");
1601 request
.load_flags
= 0;
1603 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1604 scoped_ptr
<HttpTransaction
> trans(
1605 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1607 // Defer on OnBeforeNetworkStart.
1608 BeforeNetworkStartHandler
net_start_handler(true); // defer
1609 trans
->SetBeforeNetworkStartCallback(
1610 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1611 base::Unretained(&net_start_handler
)));
1613 MockRead data_reads
[] = {
1614 MockRead("HTTP/1.0 200 OK\r\n"),
1615 MockRead("Content-Length: 5\r\n\r\n"),
1617 MockRead(SYNCHRONOUS
, 0),
1619 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1620 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1622 TestCompletionCallback callback
;
1624 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1625 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1626 base::MessageLoop::current()->RunUntilIdle();
1628 // Should have deferred for network start.
1629 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1630 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1631 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1633 trans
->ResumeNetworkStart();
1634 rv
= callback
.WaitForResult();
1636 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1638 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1639 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1640 if (rv
== ERR_IO_PENDING
)
1641 rv
= callback
.WaitForResult();
1646 // Test that network use can be deferred and canceled.
1647 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1648 HttpRequestInfo request
;
1649 request
.method
= "GET";
1650 request
.url
= GURL("http://www.google.com/");
1651 request
.load_flags
= 0;
1653 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1654 scoped_ptr
<HttpTransaction
> trans(
1655 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1657 // Defer on OnBeforeNetworkStart.
1658 BeforeNetworkStartHandler
net_start_handler(true); // defer
1659 trans
->SetBeforeNetworkStartCallback(
1660 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1661 base::Unretained(&net_start_handler
)));
1663 TestCompletionCallback callback
;
1665 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1666 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1667 base::MessageLoop::current()->RunUntilIdle();
1669 // Should have deferred for network start.
1670 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1671 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1672 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1675 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1676 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1677 // destructor in such situations.
1678 // See http://crbug.com/154712 and http://crbug.com/156609.
1679 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1680 HttpRequestInfo request
;
1681 request
.method
= "GET";
1682 request
.url
= GURL("http://www.google.com/");
1683 request
.load_flags
= 0;
1685 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1686 scoped_ptr
<HttpTransaction
> trans(
1687 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1689 MockRead data_reads
[] = {
1690 MockRead("HTTP/1.0 200 OK\r\n"),
1691 MockRead("Connection: keep-alive\r\n"),
1692 MockRead("Content-Length: 100\r\n\r\n"),
1694 MockRead(SYNCHRONOUS
, 0),
1696 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1697 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1699 TestCompletionCallback callback
;
1701 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1702 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1704 rv
= callback
.WaitForResult();
1707 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1708 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1709 if (rv
== ERR_IO_PENDING
)
1710 rv
= callback
.WaitForResult();
1712 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1713 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1716 base::MessageLoop::current()->RunUntilIdle();
1717 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1720 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1721 HttpRequestInfo request
;
1722 request
.method
= "GET";
1723 request
.url
= GURL("http://www.google.com/");
1724 request
.load_flags
= 0;
1726 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1727 scoped_ptr
<HttpTransaction
> trans(
1728 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1730 MockRead data_reads
[] = {
1731 MockRead("HTTP/1.0 200 OK\r\n"),
1732 MockRead("Connection: keep-alive\r\n"),
1733 MockRead("Content-Length: 100\r\n\r\n"),
1734 MockRead(SYNCHRONOUS
, 0),
1736 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1737 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1739 TestCompletionCallback callback
;
1741 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1742 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1744 rv
= callback
.WaitForResult();
1747 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1748 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1749 if (rv
== ERR_IO_PENDING
)
1750 rv
= callback
.WaitForResult();
1751 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1754 base::MessageLoop::current()->RunUntilIdle();
1755 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1758 // Test that we correctly reuse a keep-alive connection after not explicitly
1759 // reading the body.
1760 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1761 HttpRequestInfo request
;
1762 request
.method
= "GET";
1763 request
.url
= GURL("http://www.foo.com/");
1764 request
.load_flags
= 0;
1766 CapturingNetLog net_log
;
1767 session_deps_
.net_log
= &net_log
;
1768 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1770 // Note that because all these reads happen in the same
1771 // StaticSocketDataProvider, it shows that the same socket is being reused for
1772 // all transactions.
1773 MockRead data1_reads
[] = {
1774 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1775 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1776 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1777 MockRead("HTTP/1.1 302 Found\r\n"
1778 "Content-Length: 0\r\n\r\n"),
1779 MockRead("HTTP/1.1 302 Found\r\n"
1780 "Content-Length: 5\r\n\r\n"
1782 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1783 "Content-Length: 0\r\n\r\n"),
1784 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1785 "Content-Length: 5\r\n\r\n"
1787 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1790 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1791 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1793 MockRead data2_reads
[] = {
1794 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1796 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1797 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1799 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1800 std::string response_lines
[kNumUnreadBodies
];
1802 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1803 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1804 TestCompletionCallback callback
;
1806 scoped_ptr
<HttpTransaction
> trans(
1807 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1809 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1810 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1812 rv
= callback
.WaitForResult();
1815 LoadTimingInfo load_timing_info
;
1816 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1818 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1819 first_socket_log_id
= load_timing_info
.socket_log_id
;
1821 TestLoadTimingReused(load_timing_info
);
1822 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1825 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1826 ASSERT_TRUE(response
!= NULL
);
1828 ASSERT_TRUE(response
->headers
.get() != NULL
);
1829 response_lines
[i
] = response
->headers
->GetStatusLine();
1831 // We intentionally don't read the response bodies.
1834 const char* const kStatusLines
[] = {
1835 "HTTP/1.1 204 No Content",
1836 "HTTP/1.1 205 Reset Content",
1837 "HTTP/1.1 304 Not Modified",
1838 "HTTP/1.1 302 Found",
1839 "HTTP/1.1 302 Found",
1840 "HTTP/1.1 301 Moved Permanently",
1841 "HTTP/1.1 301 Moved Permanently",
1844 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1845 forgot_to_update_kStatusLines
);
1847 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1848 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1850 TestCompletionCallback callback
;
1851 scoped_ptr
<HttpTransaction
> trans(
1852 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1853 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1855 rv
= callback
.WaitForResult();
1857 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1858 ASSERT_TRUE(response
!= NULL
);
1859 ASSERT_TRUE(response
->headers
.get() != NULL
);
1860 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1861 std::string response_data
;
1862 rv
= ReadTransaction(trans
.get(), &response_data
);
1864 EXPECT_EQ("hello", response_data
);
1867 // Test the request-challenge-retry sequence for basic auth.
1868 // (basic auth is the easiest to mock, because it has no randomness).
1869 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1870 HttpRequestInfo request
;
1871 request
.method
= "GET";
1872 request
.url
= GURL("http://www.google.com/");
1873 request
.load_flags
= 0;
1875 CapturingNetLog log
;
1876 session_deps_
.net_log
= &log
;
1877 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1878 scoped_ptr
<HttpTransaction
> trans(
1879 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1881 MockWrite data_writes1
[] = {
1882 MockWrite("GET / HTTP/1.1\r\n"
1883 "Host: www.google.com\r\n"
1884 "Connection: keep-alive\r\n\r\n"),
1887 MockRead data_reads1
[] = {
1888 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1889 // Give a couple authenticate options (only the middle one is actually
1891 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1892 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1893 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1894 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1895 // Large content-length -- won't matter, as connection will be reset.
1896 MockRead("Content-Length: 10000\r\n\r\n"),
1897 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1900 // After calling trans->RestartWithAuth(), this is the request we should
1901 // be issuing -- the final header line contains the credentials.
1902 MockWrite data_writes2
[] = {
1903 MockWrite("GET / HTTP/1.1\r\n"
1904 "Host: www.google.com\r\n"
1905 "Connection: keep-alive\r\n"
1906 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1909 // Lastly, the server responds with the actual content.
1910 MockRead data_reads2
[] = {
1911 MockRead("HTTP/1.0 200 OK\r\n"),
1912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1913 MockRead("Content-Length: 100\r\n\r\n"),
1914 MockRead(SYNCHRONOUS
, OK
),
1917 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1918 data_writes1
, arraysize(data_writes1
));
1919 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1920 data_writes2
, arraysize(data_writes2
));
1921 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1922 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1924 TestCompletionCallback callback1
;
1926 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1927 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1929 rv
= callback1
.WaitForResult();
1932 LoadTimingInfo load_timing_info1
;
1933 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1934 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1936 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1937 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1939 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1940 ASSERT_TRUE(response
!= NULL
);
1941 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1943 TestCompletionCallback callback2
;
1945 rv
= trans
->RestartWithAuth(
1946 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1947 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1949 rv
= callback2
.WaitForResult();
1952 LoadTimingInfo load_timing_info2
;
1953 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1954 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1955 // The load timing after restart should have a new socket ID, and times after
1956 // those of the first load timing.
1957 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1958 load_timing_info2
.connect_timing
.connect_start
);
1959 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1961 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1962 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1964 response
= trans
->GetResponseInfo();
1965 ASSERT_TRUE(response
!= NULL
);
1966 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1967 EXPECT_EQ(100, response
->headers
->GetContentLength());
1970 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1971 HttpRequestInfo request
;
1972 request
.method
= "GET";
1973 request
.url
= GURL("http://www.google.com/");
1974 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1976 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1977 scoped_ptr
<HttpTransaction
> trans(
1978 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1980 MockWrite data_writes
[] = {
1981 MockWrite("GET / HTTP/1.1\r\n"
1982 "Host: www.google.com\r\n"
1983 "Connection: keep-alive\r\n\r\n"),
1986 MockRead data_reads
[] = {
1987 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1988 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1989 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1990 // Large content-length -- won't matter, as connection will be reset.
1991 MockRead("Content-Length: 10000\r\n\r\n"),
1992 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1995 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1996 data_writes
, arraysize(data_writes
));
1997 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1998 TestCompletionCallback callback
;
2000 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2001 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2003 rv
= callback
.WaitForResult();
2006 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2007 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2009 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2010 ASSERT_TRUE(response
!= NULL
);
2011 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2014 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2016 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2017 HttpRequestInfo request
;
2018 request
.method
= "GET";
2019 request
.url
= GURL("http://www.google.com/");
2020 request
.load_flags
= 0;
2022 CapturingNetLog log
;
2023 session_deps_
.net_log
= &log
;
2024 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2026 MockWrite data_writes1
[] = {
2027 MockWrite("GET / HTTP/1.1\r\n"
2028 "Host: www.google.com\r\n"
2029 "Connection: keep-alive\r\n\r\n"),
2031 // After calling trans->RestartWithAuth(), this is the request we should
2032 // be issuing -- the final header line contains the credentials.
2033 MockWrite("GET / HTTP/1.1\r\n"
2034 "Host: www.google.com\r\n"
2035 "Connection: keep-alive\r\n"
2036 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2039 MockRead data_reads1
[] = {
2040 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2041 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2042 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2043 MockRead("Content-Length: 14\r\n\r\n"),
2044 MockRead("Unauthorized\r\n"),
2046 // Lastly, the server responds with the actual content.
2047 MockRead("HTTP/1.1 200 OK\r\n"),
2048 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2049 MockRead("Content-Length: 5\r\n\r\n"),
2053 // If there is a regression where we disconnect a Keep-Alive
2054 // connection during an auth roundtrip, we'll end up reading this.
2055 MockRead data_reads2
[] = {
2056 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2059 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2060 data_writes1
, arraysize(data_writes1
));
2061 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2063 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2064 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2066 TestCompletionCallback callback1
;
2068 scoped_ptr
<HttpTransaction
> trans(
2069 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2070 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2071 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2073 rv
= callback1
.WaitForResult();
2076 LoadTimingInfo load_timing_info1
;
2077 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2078 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2080 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2081 ASSERT_TRUE(response
!= NULL
);
2082 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2084 TestCompletionCallback callback2
;
2086 rv
= trans
->RestartWithAuth(
2087 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2088 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2090 rv
= callback2
.WaitForResult();
2093 LoadTimingInfo load_timing_info2
;
2094 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2095 TestLoadTimingReused(load_timing_info2
);
2096 // The load timing after restart should have the same socket ID, and times
2097 // those of the first load timing.
2098 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2099 load_timing_info2
.send_start
);
2100 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2102 response
= trans
->GetResponseInfo();
2103 ASSERT_TRUE(response
!= NULL
);
2104 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2105 EXPECT_EQ(5, response
->headers
->GetContentLength());
2107 std::string response_data
;
2108 rv
= ReadTransaction(trans
.get(), &response_data
);
2110 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2111 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2114 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2115 // connection and with no response body to drain.
2116 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2117 HttpRequestInfo request
;
2118 request
.method
= "GET";
2119 request
.url
= GURL("http://www.google.com/");
2120 request
.load_flags
= 0;
2122 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2124 MockWrite data_writes1
[] = {
2125 MockWrite("GET / HTTP/1.1\r\n"
2126 "Host: www.google.com\r\n"
2127 "Connection: keep-alive\r\n\r\n"),
2129 // After calling trans->RestartWithAuth(), this is the request we should
2130 // be issuing -- the final header line contains the credentials.
2131 MockWrite("GET / HTTP/1.1\r\n"
2132 "Host: www.google.com\r\n"
2133 "Connection: keep-alive\r\n"
2134 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2137 MockRead data_reads1
[] = {
2138 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2139 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2140 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2142 // Lastly, the server responds with the actual content.
2143 MockRead("HTTP/1.1 200 OK\r\n"),
2144 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2145 MockRead("Content-Length: 5\r\n\r\n"),
2149 // An incorrect reconnect would cause this to be read.
2150 MockRead data_reads2
[] = {
2151 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2154 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2155 data_writes1
, arraysize(data_writes1
));
2156 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2158 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2159 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2161 TestCompletionCallback callback1
;
2163 scoped_ptr
<HttpTransaction
> trans(
2164 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2165 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2168 rv
= callback1
.WaitForResult();
2171 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2172 ASSERT_TRUE(response
!= NULL
);
2173 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2175 TestCompletionCallback callback2
;
2177 rv
= trans
->RestartWithAuth(
2178 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2181 rv
= callback2
.WaitForResult();
2184 response
= trans
->GetResponseInfo();
2185 ASSERT_TRUE(response
!= NULL
);
2186 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2187 EXPECT_EQ(5, response
->headers
->GetContentLength());
2190 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2191 // connection and with a large response body to drain.
2192 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2193 HttpRequestInfo request
;
2194 request
.method
= "GET";
2195 request
.url
= GURL("http://www.google.com/");
2196 request
.load_flags
= 0;
2198 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2200 MockWrite data_writes1
[] = {
2201 MockWrite("GET / HTTP/1.1\r\n"
2202 "Host: www.google.com\r\n"
2203 "Connection: keep-alive\r\n\r\n"),
2205 // After calling trans->RestartWithAuth(), this is the request we should
2206 // be issuing -- the final header line contains the credentials.
2207 MockWrite("GET / HTTP/1.1\r\n"
2208 "Host: www.google.com\r\n"
2209 "Connection: keep-alive\r\n"
2210 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2213 // Respond with 5 kb of response body.
2214 std::string
large_body_string("Unauthorized");
2215 large_body_string
.append(5 * 1024, ' ');
2216 large_body_string
.append("\r\n");
2218 MockRead data_reads1
[] = {
2219 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2220 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2221 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2222 // 5134 = 12 + 5 * 1024 + 2
2223 MockRead("Content-Length: 5134\r\n\r\n"),
2224 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2226 // Lastly, the server responds with the actual content.
2227 MockRead("HTTP/1.1 200 OK\r\n"),
2228 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2229 MockRead("Content-Length: 5\r\n\r\n"),
2233 // An incorrect reconnect would cause this to be read.
2234 MockRead data_reads2
[] = {
2235 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2238 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2239 data_writes1
, arraysize(data_writes1
));
2240 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2242 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2243 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2245 TestCompletionCallback callback1
;
2247 scoped_ptr
<HttpTransaction
> trans(
2248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2249 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2252 rv
= callback1
.WaitForResult();
2255 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2256 ASSERT_TRUE(response
!= NULL
);
2257 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2259 TestCompletionCallback callback2
;
2261 rv
= trans
->RestartWithAuth(
2262 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2263 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2265 rv
= callback2
.WaitForResult();
2268 response
= trans
->GetResponseInfo();
2269 ASSERT_TRUE(response
!= NULL
);
2270 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2271 EXPECT_EQ(5, response
->headers
->GetContentLength());
2274 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2275 // connection, but the server gets impatient and closes the connection.
2276 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2277 HttpRequestInfo request
;
2278 request
.method
= "GET";
2279 request
.url
= GURL("http://www.google.com/");
2280 request
.load_flags
= 0;
2282 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2284 MockWrite data_writes1
[] = {
2285 MockWrite("GET / HTTP/1.1\r\n"
2286 "Host: www.google.com\r\n"
2287 "Connection: keep-alive\r\n\r\n"),
2288 // This simulates the seemingly successful write to a closed connection
2289 // if the bug is not fixed.
2290 MockWrite("GET / HTTP/1.1\r\n"
2291 "Host: www.google.com\r\n"
2292 "Connection: keep-alive\r\n"
2293 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2296 MockRead data_reads1
[] = {
2297 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2298 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2299 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2300 MockRead("Content-Length: 14\r\n\r\n"),
2301 // Tell MockTCPClientSocket to simulate the server closing the connection.
2302 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2303 MockRead("Unauthorized\r\n"),
2304 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2307 // After calling trans->RestartWithAuth(), this is the request we should
2308 // be issuing -- the final header line contains the credentials.
2309 MockWrite data_writes2
[] = {
2310 MockWrite("GET / HTTP/1.1\r\n"
2311 "Host: www.google.com\r\n"
2312 "Connection: keep-alive\r\n"
2313 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2316 // Lastly, the server responds with the actual content.
2317 MockRead data_reads2
[] = {
2318 MockRead("HTTP/1.1 200 OK\r\n"),
2319 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2320 MockRead("Content-Length: 5\r\n\r\n"),
2324 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2325 data_writes1
, arraysize(data_writes1
));
2326 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2327 data_writes2
, arraysize(data_writes2
));
2328 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2329 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2331 TestCompletionCallback callback1
;
2333 scoped_ptr
<HttpTransaction
> trans(
2334 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2335 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2336 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2338 rv
= callback1
.WaitForResult();
2341 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2342 ASSERT_TRUE(response
!= NULL
);
2343 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2345 TestCompletionCallback callback2
;
2347 rv
= trans
->RestartWithAuth(
2348 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2349 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2351 rv
= callback2
.WaitForResult();
2354 response
= trans
->GetResponseInfo();
2355 ASSERT_TRUE(response
!= NULL
);
2356 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2357 EXPECT_EQ(5, response
->headers
->GetContentLength());
2360 // Test the request-challenge-retry sequence for basic auth, over a connection
2361 // that requires a restart when setting up an SSL tunnel.
2362 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
2363 HttpRequestInfo request
;
2364 request
.method
= "GET";
2365 request
.url
= GURL("https://www.google.com/");
2366 // when the no authentication data flag is set.
2367 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2369 // Configure against proxy server "myproxy:70".
2370 session_deps_
.proxy_service
.reset(
2371 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2372 CapturingBoundNetLog log
;
2373 session_deps_
.net_log
= log
.bound().net_log();
2374 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2376 // Since we have proxy, should try to establish tunnel.
2377 MockWrite data_writes1
[] = {
2378 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2379 "Host: www.google.com\r\n"
2380 "Proxy-Connection: keep-alive\r\n\r\n"),
2382 // After calling trans->RestartWithAuth(), this is the request we should
2383 // be issuing -- the final header line contains the credentials.
2384 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2385 "Host: www.google.com\r\n"
2386 "Proxy-Connection: keep-alive\r\n"
2387 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2389 MockWrite("GET / HTTP/1.1\r\n"
2390 "Host: www.google.com\r\n"
2391 "Connection: keep-alive\r\n\r\n"),
2394 // The proxy responds to the connect with a 407, using a persistent
2396 MockRead data_reads1
[] = {
2398 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2399 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2400 MockRead("Proxy-Connection: close\r\n\r\n"),
2402 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2404 MockRead("HTTP/1.1 200 OK\r\n"),
2405 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2406 MockRead("Content-Length: 5\r\n\r\n"),
2407 MockRead(SYNCHRONOUS
, "hello"),
2410 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2411 data_writes1
, arraysize(data_writes1
));
2412 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2413 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2414 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2416 TestCompletionCallback callback1
;
2418 scoped_ptr
<HttpTransaction
> trans(
2419 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2421 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2424 rv
= callback1
.WaitForResult();
2426 net::CapturingNetLog::CapturedEntryList entries
;
2427 log
.GetEntries(&entries
);
2428 size_t pos
= ExpectLogContainsSomewhere(
2429 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2430 NetLog::PHASE_NONE
);
2431 ExpectLogContainsSomewhere(
2433 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2434 NetLog::PHASE_NONE
);
2436 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2437 ASSERT_TRUE(response
!= NULL
);
2438 ASSERT_FALSE(response
->headers
.get() == NULL
);
2439 EXPECT_EQ(407, response
->headers
->response_code());
2440 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2441 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2443 LoadTimingInfo load_timing_info
;
2444 // CONNECT requests and responses are handled at the connect job level, so
2445 // the transaction does not yet have a connection.
2446 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2448 TestCompletionCallback callback2
;
2450 rv
= trans
->RestartWithAuth(
2451 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2452 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2454 rv
= callback2
.WaitForResult();
2457 response
= trans
->GetResponseInfo();
2458 ASSERT_TRUE(response
!= NULL
);
2460 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2461 EXPECT_EQ(200, response
->headers
->response_code());
2462 EXPECT_EQ(5, response
->headers
->GetContentLength());
2463 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2465 // The password prompt info should not be set.
2466 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2468 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2469 TestLoadTimingNotReusedWithPac(load_timing_info
,
2470 CONNECT_TIMING_HAS_SSL_TIMES
);
2473 session
->CloseAllConnections();
2476 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2477 // proxy connection, when setting up an SSL tunnel.
2478 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2479 HttpRequestInfo request
;
2480 request
.method
= "GET";
2481 request
.url
= GURL("https://www.google.com/");
2482 // Ensure that proxy authentication is attempted even
2483 // when the no authentication data flag is set.
2484 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2486 // Configure against proxy server "myproxy:70".
2487 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2488 CapturingBoundNetLog log
;
2489 session_deps_
.net_log
= log
.bound().net_log();
2490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2492 scoped_ptr
<HttpTransaction
> trans(
2493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2495 // Since we have proxy, should try to establish tunnel.
2496 MockWrite data_writes1
[] = {
2497 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2498 "Host: www.google.com\r\n"
2499 "Proxy-Connection: keep-alive\r\n\r\n"),
2501 // After calling trans->RestartWithAuth(), this is the request we should
2502 // be issuing -- the final header line contains the credentials.
2503 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2504 "Host: www.google.com\r\n"
2505 "Proxy-Connection: keep-alive\r\n"
2506 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2509 // The proxy responds to the connect with a 407, using a persistent
2511 MockRead data_reads1
[] = {
2513 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2514 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2515 MockRead("Content-Length: 10\r\n\r\n"),
2516 MockRead("0123456789"),
2518 // Wrong credentials (wrong password).
2519 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2520 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2521 MockRead("Content-Length: 10\r\n\r\n"),
2522 // No response body because the test stops reading here.
2523 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2526 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2527 data_writes1
, arraysize(data_writes1
));
2528 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2530 TestCompletionCallback callback1
;
2532 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2533 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2535 rv
= callback1
.WaitForResult();
2537 net::CapturingNetLog::CapturedEntryList entries
;
2538 log
.GetEntries(&entries
);
2539 size_t pos
= ExpectLogContainsSomewhere(
2540 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2541 NetLog::PHASE_NONE
);
2542 ExpectLogContainsSomewhere(
2544 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2545 NetLog::PHASE_NONE
);
2547 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2548 ASSERT_TRUE(response
!= NULL
);
2549 ASSERT_FALSE(response
->headers
.get() == NULL
);
2550 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2551 EXPECT_EQ(407, response
->headers
->response_code());
2552 EXPECT_EQ(10, response
->headers
->GetContentLength());
2553 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2554 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2556 TestCompletionCallback callback2
;
2558 // Wrong password (should be "bar").
2559 rv
= trans
->RestartWithAuth(
2560 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2561 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2563 rv
= callback2
.WaitForResult();
2566 response
= trans
->GetResponseInfo();
2567 ASSERT_TRUE(response
!= NULL
);
2568 ASSERT_FALSE(response
->headers
.get() == NULL
);
2569 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2570 EXPECT_EQ(407, response
->headers
->response_code());
2571 EXPECT_EQ(10, response
->headers
->GetContentLength());
2572 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2573 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2575 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2577 session
->CloseAllConnections();
2580 // Test that we don't read the response body when we fail to establish a tunnel,
2581 // even if the user cancels the proxy's auth attempt.
2582 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2583 HttpRequestInfo request
;
2584 request
.method
= "GET";
2585 request
.url
= GURL("https://www.google.com/");
2586 request
.load_flags
= 0;
2588 // Configure against proxy server "myproxy:70".
2589 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2591 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2593 scoped_ptr
<HttpTransaction
> trans(
2594 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2596 // Since we have proxy, should try to establish tunnel.
2597 MockWrite data_writes
[] = {
2598 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2599 "Host: www.google.com\r\n"
2600 "Proxy-Connection: keep-alive\r\n\r\n"),
2603 // The proxy responds to the connect with a 407.
2604 MockRead data_reads
[] = {
2605 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2606 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2607 MockRead("Content-Length: 10\r\n\r\n"),
2608 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2611 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2612 data_writes
, arraysize(data_writes
));
2613 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2615 TestCompletionCallback callback
;
2617 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2618 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2620 rv
= callback
.WaitForResult();
2623 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2624 ASSERT_TRUE(response
!= NULL
);
2626 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2627 EXPECT_EQ(407, response
->headers
->response_code());
2628 EXPECT_EQ(10, response
->headers
->GetContentLength());
2629 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2631 std::string response_data
;
2632 rv
= ReadTransaction(trans
.get(), &response_data
);
2633 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2635 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2636 session
->CloseAllConnections();
2639 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2640 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2641 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2642 HttpRequestInfo request
;
2643 request
.method
= "GET";
2644 request
.url
= GURL("http://www.google.com/");
2645 request
.load_flags
= 0;
2647 // We are using a DIRECT connection (i.e. no proxy) for this session.
2648 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2649 scoped_ptr
<HttpTransaction
> trans(
2650 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2652 MockWrite data_writes1
[] = {
2653 MockWrite("GET / HTTP/1.1\r\n"
2654 "Host: www.google.com\r\n"
2655 "Connection: keep-alive\r\n\r\n"),
2658 MockRead data_reads1
[] = {
2659 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2660 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2661 // Large content-length -- won't matter, as connection will be reset.
2662 MockRead("Content-Length: 10000\r\n\r\n"),
2663 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2666 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2667 data_writes1
, arraysize(data_writes1
));
2668 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2670 TestCompletionCallback callback
;
2672 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2675 rv
= callback
.WaitForResult();
2676 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2679 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2680 // through a non-authenticating proxy. The request should fail with
2681 // ERR_UNEXPECTED_PROXY_AUTH.
2682 // Note that it is impossible to detect if an HTTP server returns a 407 through
2683 // a non-authenticating proxy - there is nothing to indicate whether the
2684 // response came from the proxy or the server, so it is treated as if the proxy
2685 // issued the challenge.
2686 TEST_P(HttpNetworkTransactionTest
,
2687 HttpsServerRequestsProxyAuthThroughProxy
) {
2688 HttpRequestInfo request
;
2689 request
.method
= "GET";
2690 request
.url
= GURL("https://www.google.com/");
2692 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2693 CapturingBoundNetLog log
;
2694 session_deps_
.net_log
= log
.bound().net_log();
2695 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2697 // Since we have proxy, should try to establish tunnel.
2698 MockWrite data_writes1
[] = {
2699 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2700 "Host: www.google.com\r\n"
2701 "Proxy-Connection: keep-alive\r\n\r\n"),
2703 MockWrite("GET / HTTP/1.1\r\n"
2704 "Host: www.google.com\r\n"
2705 "Connection: keep-alive\r\n\r\n"),
2708 MockRead data_reads1
[] = {
2709 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2711 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2712 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2714 MockRead(SYNCHRONOUS
, OK
),
2717 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2718 data_writes1
, arraysize(data_writes1
));
2719 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2720 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2721 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2723 TestCompletionCallback callback1
;
2725 scoped_ptr
<HttpTransaction
> trans(
2726 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2728 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2731 rv
= callback1
.WaitForResult();
2732 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2733 net::CapturingNetLog::CapturedEntryList entries
;
2734 log
.GetEntries(&entries
);
2735 size_t pos
= ExpectLogContainsSomewhere(
2736 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2737 NetLog::PHASE_NONE
);
2738 ExpectLogContainsSomewhere(
2740 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2741 NetLog::PHASE_NONE
);
2744 // Test the load timing for HTTPS requests with an HTTP proxy.
2745 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2746 HttpRequestInfo request1
;
2747 request1
.method
= "GET";
2748 request1
.url
= GURL("https://www.google.com/1");
2750 HttpRequestInfo request2
;
2751 request2
.method
= "GET";
2752 request2
.url
= GURL("https://www.google.com/2");
2754 // Configure against proxy server "myproxy:70".
2755 session_deps_
.proxy_service
.reset(
2756 ProxyService::CreateFixed("PROXY myproxy:70"));
2757 CapturingBoundNetLog log
;
2758 session_deps_
.net_log
= log
.bound().net_log();
2759 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2761 // Since we have proxy, should try to establish tunnel.
2762 MockWrite data_writes1
[] = {
2763 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2764 "Host: www.google.com\r\n"
2765 "Proxy-Connection: keep-alive\r\n\r\n"),
2767 MockWrite("GET /1 HTTP/1.1\r\n"
2768 "Host: www.google.com\r\n"
2769 "Connection: keep-alive\r\n\r\n"),
2771 MockWrite("GET /2 HTTP/1.1\r\n"
2772 "Host: www.google.com\r\n"
2773 "Connection: keep-alive\r\n\r\n"),
2776 // The proxy responds to the connect with a 407, using a persistent
2778 MockRead data_reads1
[] = {
2779 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2781 MockRead("HTTP/1.1 200 OK\r\n"),
2782 MockRead("Content-Length: 1\r\n\r\n"),
2783 MockRead(SYNCHRONOUS
, "1"),
2785 MockRead("HTTP/1.1 200 OK\r\n"),
2786 MockRead("Content-Length: 2\r\n\r\n"),
2787 MockRead(SYNCHRONOUS
, "22"),
2790 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2791 data_writes1
, arraysize(data_writes1
));
2792 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2793 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2796 TestCompletionCallback callback1
;
2797 scoped_ptr
<HttpTransaction
> trans1(
2798 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2800 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2801 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2803 rv
= callback1
.WaitForResult();
2806 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2807 ASSERT_TRUE(response1
!= NULL
);
2808 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2809 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2811 LoadTimingInfo load_timing_info1
;
2812 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2813 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2817 TestCompletionCallback callback2
;
2818 scoped_ptr
<HttpTransaction
> trans2(
2819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2821 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2822 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2824 rv
= callback2
.WaitForResult();
2827 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2828 ASSERT_TRUE(response2
!= NULL
);
2829 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2830 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2832 LoadTimingInfo load_timing_info2
;
2833 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2834 TestLoadTimingReused(load_timing_info2
);
2836 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2839 session
->CloseAllConnections();
2842 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2843 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2844 HttpRequestInfo request1
;
2845 request1
.method
= "GET";
2846 request1
.url
= GURL("https://www.google.com/1");
2848 HttpRequestInfo request2
;
2849 request2
.method
= "GET";
2850 request2
.url
= GURL("https://www.google.com/2");
2852 // Configure against proxy server "myproxy:70".
2853 session_deps_
.proxy_service
.reset(
2854 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2855 CapturingBoundNetLog log
;
2856 session_deps_
.net_log
= log
.bound().net_log();
2857 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2859 // Since we have proxy, should try to establish tunnel.
2860 MockWrite data_writes1
[] = {
2861 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2862 "Host: www.google.com\r\n"
2863 "Proxy-Connection: keep-alive\r\n\r\n"),
2865 MockWrite("GET /1 HTTP/1.1\r\n"
2866 "Host: www.google.com\r\n"
2867 "Connection: keep-alive\r\n\r\n"),
2869 MockWrite("GET /2 HTTP/1.1\r\n"
2870 "Host: www.google.com\r\n"
2871 "Connection: keep-alive\r\n\r\n"),
2874 // The proxy responds to the connect with a 407, using a persistent
2876 MockRead data_reads1
[] = {
2877 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2879 MockRead("HTTP/1.1 200 OK\r\n"),
2880 MockRead("Content-Length: 1\r\n\r\n"),
2881 MockRead(SYNCHRONOUS
, "1"),
2883 MockRead("HTTP/1.1 200 OK\r\n"),
2884 MockRead("Content-Length: 2\r\n\r\n"),
2885 MockRead(SYNCHRONOUS
, "22"),
2888 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2889 data_writes1
, arraysize(data_writes1
));
2890 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2891 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2892 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2894 TestCompletionCallback callback1
;
2895 scoped_ptr
<HttpTransaction
> trans1(
2896 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2898 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2899 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2901 rv
= callback1
.WaitForResult();
2904 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2905 ASSERT_TRUE(response1
!= NULL
);
2906 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2907 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2909 LoadTimingInfo load_timing_info1
;
2910 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2911 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2912 CONNECT_TIMING_HAS_SSL_TIMES
);
2916 TestCompletionCallback callback2
;
2917 scoped_ptr
<HttpTransaction
> trans2(
2918 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2920 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2923 rv
= callback2
.WaitForResult();
2926 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2927 ASSERT_TRUE(response2
!= NULL
);
2928 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2929 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2931 LoadTimingInfo load_timing_info2
;
2932 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2933 TestLoadTimingReusedWithPac(load_timing_info2
);
2935 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2938 session
->CloseAllConnections();
2941 // Test a simple get through an HTTPS Proxy.
2942 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2943 HttpRequestInfo request
;
2944 request
.method
= "GET";
2945 request
.url
= GURL("http://www.google.com/");
2947 // Configure against https proxy server "proxy:70".
2948 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2949 "https://proxy:70"));
2950 CapturingBoundNetLog log
;
2951 session_deps_
.net_log
= log
.bound().net_log();
2952 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2954 // Since we have proxy, should use full url
2955 MockWrite data_writes1
[] = {
2956 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2957 "Host: www.google.com\r\n"
2958 "Proxy-Connection: keep-alive\r\n\r\n"),
2961 MockRead data_reads1
[] = {
2962 MockRead("HTTP/1.1 200 OK\r\n"),
2963 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2964 MockRead("Content-Length: 100\r\n\r\n"),
2965 MockRead(SYNCHRONOUS
, OK
),
2968 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2969 data_writes1
, arraysize(data_writes1
));
2970 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2971 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2972 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2974 TestCompletionCallback callback1
;
2976 scoped_ptr
<HttpTransaction
> trans(
2977 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2979 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2980 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2982 rv
= callback1
.WaitForResult();
2985 LoadTimingInfo load_timing_info
;
2986 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2987 TestLoadTimingNotReused(load_timing_info
,
2988 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2990 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2991 ASSERT_TRUE(response
!= NULL
);
2993 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2994 EXPECT_EQ(200, response
->headers
->response_code());
2995 EXPECT_EQ(100, response
->headers
->GetContentLength());
2996 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2998 // The password prompt info should not be set.
2999 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3002 // Test a SPDY get through an HTTPS Proxy.
3003 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3004 HttpRequestInfo request
;
3005 request
.method
= "GET";
3006 request
.url
= GURL("http://www.google.com/");
3007 request
.load_flags
= 0;
3009 // Configure against https proxy server "proxy:70".
3010 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3011 "https://proxy:70"));
3012 CapturingBoundNetLog log
;
3013 session_deps_
.net_log
= log
.bound().net_log();
3014 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3016 // fetch http://www.google.com/ via SPDY
3017 scoped_ptr
<SpdyFrame
> req(
3018 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3019 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
3021 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3022 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3023 MockRead spdy_reads
[] = {
3024 CreateMockRead(*resp
),
3025 CreateMockRead(*data
),
3026 MockRead(ASYNC
, 0, 0),
3029 DelayedSocketData
spdy_data(
3030 1, // wait for one write to finish before reading.
3031 spdy_reads
, arraysize(spdy_reads
),
3032 spdy_writes
, arraysize(spdy_writes
));
3033 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3035 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3036 ssl
.SetNextProto(GetParam());
3037 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3039 TestCompletionCallback callback1
;
3041 scoped_ptr
<HttpTransaction
> trans(
3042 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3044 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3047 rv
= callback1
.WaitForResult();
3050 LoadTimingInfo load_timing_info
;
3051 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3052 TestLoadTimingNotReused(load_timing_info
,
3053 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3055 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3056 ASSERT_TRUE(response
!= NULL
);
3057 ASSERT_TRUE(response
->headers
.get() != NULL
);
3058 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3060 std::string response_data
;
3061 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3062 EXPECT_EQ(kUploadData
, response_data
);
3065 // Verifies that a session which races and wins against the owning transaction
3066 // (completing prior to host resolution), doesn't fail the transaction.
3067 // Regression test for crbug.com/334413.
3068 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3069 HttpRequestInfo request
;
3070 request
.method
= "GET";
3071 request
.url
= GURL("http://www.google.com/");
3072 request
.load_flags
= 0;
3074 // Configure SPDY proxy server "proxy:70".
3075 session_deps_
.proxy_service
.reset(
3076 ProxyService::CreateFixed("https://proxy:70"));
3077 CapturingBoundNetLog log
;
3078 session_deps_
.net_log
= log
.bound().net_log();
3079 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3081 // Fetch http://www.google.com/ through the SPDY proxy.
3082 scoped_ptr
<SpdyFrame
> req(
3083 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3084 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3086 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3087 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3088 MockRead spdy_reads
[] = {
3089 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3092 DelayedSocketData
spdy_data(
3093 1, // wait for one write to finish before reading.
3095 arraysize(spdy_reads
),
3097 arraysize(spdy_writes
));
3098 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3100 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3101 ssl
.SetNextProto(GetParam());
3102 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3104 TestCompletionCallback callback1
;
3106 scoped_ptr
<HttpTransaction
> trans(
3107 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3109 // Stall the hostname resolution begun by the transaction.
3110 session_deps_
.host_resolver
->set_synchronous_mode(false);
3111 session_deps_
.host_resolver
->set_ondemand_mode(true);
3113 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3116 // Race a session to the proxy, which completes first.
3117 session_deps_
.host_resolver
->set_ondemand_mode(false);
3119 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3120 base::WeakPtr
<SpdySession
> spdy_session
=
3121 CreateSecureSpdySession(session
, key
, log
.bound());
3123 // Unstall the resolution begun by the transaction.
3124 session_deps_
.host_resolver
->set_ondemand_mode(true);
3125 session_deps_
.host_resolver
->ResolveAllPending();
3127 EXPECT_FALSE(callback1
.have_result());
3128 rv
= callback1
.WaitForResult();
3131 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3132 ASSERT_TRUE(response
!= NULL
);
3133 ASSERT_TRUE(response
->headers
.get() != NULL
);
3134 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3136 std::string response_data
;
3137 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3138 EXPECT_EQ(kUploadData
, response_data
);
3141 // Test a SPDY get through an HTTPS Proxy.
3142 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3143 HttpRequestInfo request
;
3144 request
.method
= "GET";
3145 request
.url
= GURL("http://www.google.com/");
3146 request
.load_flags
= 0;
3148 // Configure against https proxy server "myproxy:70".
3149 session_deps_
.proxy_service
.reset(
3150 ProxyService::CreateFixed("https://myproxy:70"));
3151 CapturingBoundNetLog log
;
3152 session_deps_
.net_log
= log
.bound().net_log();
3153 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3155 // The first request will be a bare GET, the second request will be a
3156 // GET with a Proxy-Authorization header.
3157 scoped_ptr
<SpdyFrame
> req_get(
3158 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3159 const char* const kExtraAuthorizationHeaders
[] = {
3160 "proxy-authorization", "Basic Zm9vOmJhcg=="
3162 scoped_ptr
<SpdyFrame
> req_get_authorization(
3163 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3164 arraysize(kExtraAuthorizationHeaders
) / 2,
3169 MockWrite spdy_writes
[] = {
3170 CreateMockWrite(*req_get
, 1),
3171 CreateMockWrite(*req_get_authorization
, 4),
3174 // The first response is a 407 proxy authentication challenge, and the second
3175 // response will be a 200 response since the second request includes a valid
3176 // Authorization header.
3177 const char* const kExtraAuthenticationHeaders
[] = {
3178 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3180 scoped_ptr
<SpdyFrame
> resp_authentication(
3181 spdy_util_
.ConstructSpdySynReplyError(
3182 "407 Proxy Authentication Required",
3183 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3185 scoped_ptr
<SpdyFrame
> body_authentication(
3186 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3187 scoped_ptr
<SpdyFrame
> resp_data(
3188 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3189 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3190 MockRead spdy_reads
[] = {
3191 CreateMockRead(*resp_authentication
, 2),
3192 CreateMockRead(*body_authentication
, 3),
3193 CreateMockRead(*resp_data
, 5),
3194 CreateMockRead(*body_data
, 6),
3195 MockRead(ASYNC
, 0, 7),
3198 OrderedSocketData
data(
3199 spdy_reads
, arraysize(spdy_reads
),
3200 spdy_writes
, arraysize(spdy_writes
));
3201 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3203 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3204 ssl
.SetNextProto(GetParam());
3205 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3207 TestCompletionCallback callback1
;
3209 scoped_ptr
<HttpTransaction
> trans(
3210 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3212 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3215 rv
= callback1
.WaitForResult();
3218 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3220 ASSERT_TRUE(response
!= NULL
);
3221 ASSERT_TRUE(response
->headers
.get() != NULL
);
3222 EXPECT_EQ(407, response
->headers
->response_code());
3223 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3224 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3226 TestCompletionCallback callback2
;
3228 rv
= trans
->RestartWithAuth(
3229 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3230 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3232 rv
= callback2
.WaitForResult();
3235 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3237 ASSERT_TRUE(response_restart
!= NULL
);
3238 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3239 EXPECT_EQ(200, response_restart
->headers
->response_code());
3240 // The password prompt info should not be set.
3241 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3244 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3245 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3246 HttpRequestInfo request
;
3247 request
.method
= "GET";
3248 request
.url
= GURL("https://www.google.com/");
3249 request
.load_flags
= 0;
3251 // Configure against https proxy server "proxy:70".
3252 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3253 "https://proxy:70"));
3254 CapturingBoundNetLog log
;
3255 session_deps_
.net_log
= log
.bound().net_log();
3256 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3258 scoped_ptr
<HttpTransaction
> trans(
3259 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3261 // CONNECT to www.google.com:443 via SPDY
3262 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3264 // fetch https://www.google.com/ via HTTP
3266 const char get
[] = "GET / HTTP/1.1\r\n"
3267 "Host: www.google.com\r\n"
3268 "Connection: keep-alive\r\n\r\n";
3269 scoped_ptr
<SpdyFrame
> wrapped_get(
3270 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3271 scoped_ptr
<SpdyFrame
> conn_resp(
3272 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3273 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3274 "Content-Length: 10\r\n\r\n";
3275 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3276 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3277 scoped_ptr
<SpdyFrame
> wrapped_body(
3278 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3279 scoped_ptr
<SpdyFrame
> window_update(
3280 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3282 MockWrite spdy_writes
[] = {
3283 CreateMockWrite(*connect
, 1),
3284 CreateMockWrite(*wrapped_get
, 3),
3285 CreateMockWrite(*window_update
, 5),
3288 MockRead spdy_reads
[] = {
3289 CreateMockRead(*conn_resp
, 2, ASYNC
),
3290 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3291 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3292 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3293 MockRead(ASYNC
, 0, 8),
3296 OrderedSocketData
spdy_data(
3297 spdy_reads
, arraysize(spdy_reads
),
3298 spdy_writes
, arraysize(spdy_writes
));
3299 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3301 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3302 ssl
.SetNextProto(GetParam());
3303 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3304 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3305 ssl2
.was_npn_negotiated
= false;
3306 ssl2
.protocol_negotiated
= kProtoUnknown
;
3307 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3309 TestCompletionCallback callback1
;
3311 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3312 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3314 rv
= callback1
.WaitForResult();
3317 LoadTimingInfo load_timing_info
;
3318 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3319 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3321 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3322 ASSERT_TRUE(response
!= NULL
);
3323 ASSERT_TRUE(response
->headers
.get() != NULL
);
3324 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3326 std::string response_data
;
3327 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3328 EXPECT_EQ("1234567890", response_data
);
3331 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3332 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3333 HttpRequestInfo request
;
3334 request
.method
= "GET";
3335 request
.url
= GURL("https://www.google.com/");
3336 request
.load_flags
= 0;
3338 // Configure against https proxy server "proxy:70".
3339 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3340 "https://proxy:70"));
3341 CapturingBoundNetLog log
;
3342 session_deps_
.net_log
= log
.bound().net_log();
3343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3345 scoped_ptr
<HttpTransaction
> trans(
3346 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3348 // CONNECT to www.google.com:443 via SPDY
3349 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3351 // fetch https://www.google.com/ via SPDY
3352 const char* const kMyUrl
= "https://www.google.com/";
3353 scoped_ptr
<SpdyFrame
> get(
3354 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3355 scoped_ptr
<SpdyFrame
> wrapped_get(
3356 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3357 scoped_ptr
<SpdyFrame
> conn_resp(
3358 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3359 scoped_ptr
<SpdyFrame
> get_resp(
3360 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3361 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3362 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3363 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3364 scoped_ptr
<SpdyFrame
> wrapped_body(
3365 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3366 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3367 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3368 scoped_ptr
<SpdyFrame
> window_update_body(
3369 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3371 MockWrite spdy_writes
[] = {
3372 CreateMockWrite(*connect
, 1),
3373 CreateMockWrite(*wrapped_get
, 3),
3374 CreateMockWrite(*window_update_get_resp
, 5),
3375 CreateMockWrite(*window_update_body
, 7),
3378 MockRead spdy_reads
[] = {
3379 CreateMockRead(*conn_resp
, 2, ASYNC
),
3380 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3381 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3382 MockRead(ASYNC
, 0, 8),
3385 OrderedSocketData
spdy_data(
3386 spdy_reads
, arraysize(spdy_reads
),
3387 spdy_writes
, arraysize(spdy_writes
));
3388 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3390 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3391 ssl
.SetNextProto(GetParam());
3392 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3393 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3394 ssl2
.SetNextProto(GetParam());
3395 ssl2
.protocol_negotiated
= GetParam();
3396 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3398 TestCompletionCallback callback1
;
3400 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3401 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3403 rv
= callback1
.WaitForResult();
3406 LoadTimingInfo load_timing_info
;
3407 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3408 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3410 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3411 ASSERT_TRUE(response
!= NULL
);
3412 ASSERT_TRUE(response
->headers
.get() != NULL
);
3413 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3415 std::string response_data
;
3416 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3417 EXPECT_EQ(kUploadData
, response_data
);
3420 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3421 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3422 HttpRequestInfo request
;
3423 request
.method
= "GET";
3424 request
.url
= GURL("https://www.google.com/");
3425 request
.load_flags
= 0;
3427 // Configure against https proxy server "proxy:70".
3428 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3429 "https://proxy:70"));
3430 CapturingBoundNetLog log
;
3431 session_deps_
.net_log
= log
.bound().net_log();
3432 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3434 scoped_ptr
<HttpTransaction
> trans(
3435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3437 // CONNECT to www.google.com:443 via SPDY
3438 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3440 scoped_ptr
<SpdyFrame
> get(
3441 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3443 MockWrite spdy_writes
[] = {
3444 CreateMockWrite(*connect
, 1),
3445 CreateMockWrite(*get
, 3),
3448 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3449 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3450 MockRead spdy_reads
[] = {
3451 CreateMockRead(*resp
, 2, ASYNC
),
3452 MockRead(ASYNC
, 0, 4),
3455 OrderedSocketData
spdy_data(
3456 spdy_reads
, arraysize(spdy_reads
),
3457 spdy_writes
, arraysize(spdy_writes
));
3458 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3460 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3461 ssl
.SetNextProto(GetParam());
3462 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3463 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3464 ssl2
.SetNextProto(GetParam());
3465 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3467 TestCompletionCallback callback1
;
3469 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3470 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3472 rv
= callback1
.WaitForResult();
3473 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3475 // TODO(ttuttle): Anything else to check here?
3478 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3479 // HTTPS Proxy to different servers.
3480 TEST_P(HttpNetworkTransactionTest
,
3481 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3482 // Configure against https proxy server "proxy:70".
3483 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3484 "https://proxy:70"));
3485 CapturingBoundNetLog log
;
3486 session_deps_
.net_log
= log
.bound().net_log();
3487 scoped_refptr
<HttpNetworkSession
> session(
3488 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3490 HttpRequestInfo request1
;
3491 request1
.method
= "GET";
3492 request1
.url
= GURL("https://www.google.com/");
3493 request1
.load_flags
= 0;
3495 HttpRequestInfo request2
;
3496 request2
.method
= "GET";
3497 request2
.url
= GURL("https://news.google.com/");
3498 request2
.load_flags
= 0;
3500 // CONNECT to www.google.com:443 via SPDY.
3501 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3503 scoped_ptr
<SpdyFrame
> conn_resp1(
3504 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3506 // Fetch https://www.google.com/ via HTTP.
3507 const char get1
[] = "GET / HTTP/1.1\r\n"
3508 "Host: www.google.com\r\n"
3509 "Connection: keep-alive\r\n\r\n";
3510 scoped_ptr
<SpdyFrame
> wrapped_get1(
3511 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3512 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3513 "Content-Length: 1\r\n\r\n";
3514 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3515 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3516 scoped_ptr
<SpdyFrame
> wrapped_body1(
3517 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3518 scoped_ptr
<SpdyFrame
> window_update(
3519 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3521 // CONNECT to news.google.com:443 via SPDY.
3522 SpdyHeaderBlock connect2_block
;
3523 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3524 connect2_block
[spdy_util_
.GetPathKey()] = "news.google.com:443";
3525 connect2_block
[spdy_util_
.GetHostKey()] = "news.google.com";
3526 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3527 scoped_ptr
<SpdyFrame
> connect2(
3528 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3530 scoped_ptr
<SpdyFrame
> conn_resp2(
3531 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3533 // Fetch https://news.google.com/ via HTTP.
3534 const char get2
[] = "GET / HTTP/1.1\r\n"
3535 "Host: news.google.com\r\n"
3536 "Connection: keep-alive\r\n\r\n";
3537 scoped_ptr
<SpdyFrame
> wrapped_get2(
3538 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3539 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3540 "Content-Length: 2\r\n\r\n";
3541 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3542 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3543 scoped_ptr
<SpdyFrame
> wrapped_body2(
3544 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3546 MockWrite spdy_writes
[] = {
3547 CreateMockWrite(*connect1
, 0),
3548 CreateMockWrite(*wrapped_get1
, 2),
3549 CreateMockWrite(*connect2
, 5),
3550 CreateMockWrite(*wrapped_get2
, 7),
3553 MockRead spdy_reads
[] = {
3554 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3555 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3556 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3557 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3558 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3559 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3560 MockRead(ASYNC
, 0, 10),
3563 DeterministicSocketData
spdy_data(
3564 spdy_reads
, arraysize(spdy_reads
),
3565 spdy_writes
, arraysize(spdy_writes
));
3566 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3568 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3569 ssl
.SetNextProto(GetParam());
3570 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3571 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3572 ssl2
.was_npn_negotiated
= false;
3573 ssl2
.protocol_negotiated
= kProtoUnknown
;
3574 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3575 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3576 ssl3
.was_npn_negotiated
= false;
3577 ssl3
.protocol_negotiated
= kProtoUnknown
;
3578 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3580 TestCompletionCallback callback
;
3582 scoped_ptr
<HttpTransaction
> trans(
3583 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3584 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3585 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3586 // The first connect and request, each of their responses, and the body.
3587 spdy_data
.RunFor(5);
3589 rv
= callback
.WaitForResult();
3592 LoadTimingInfo load_timing_info
;
3593 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3594 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3596 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3597 ASSERT_TRUE(response
!= NULL
);
3598 ASSERT_TRUE(response
->headers
.get() != NULL
);
3599 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3601 std::string response_data
;
3602 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3603 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3605 scoped_ptr
<HttpTransaction
> trans2(
3606 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3607 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3608 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3610 // The second connect and request, each of their responses, and the body.
3611 spdy_data
.RunFor(5);
3612 rv
= callback
.WaitForResult();
3615 LoadTimingInfo load_timing_info2
;
3616 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3617 // Even though the SPDY connection is reused, a new tunnelled connection has
3618 // to be created, so the socket's load timing looks like a fresh connection.
3619 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3621 // The requests should have different IDs, since they each are using their own
3623 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3625 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3628 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3629 // HTTPS Proxy to the same server.
3630 TEST_P(HttpNetworkTransactionTest
,
3631 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3632 // Configure against https proxy server "proxy:70".
3633 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3634 "https://proxy:70"));
3635 CapturingBoundNetLog log
;
3636 session_deps_
.net_log
= log
.bound().net_log();
3637 scoped_refptr
<HttpNetworkSession
> session(
3638 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3640 HttpRequestInfo request1
;
3641 request1
.method
= "GET";
3642 request1
.url
= GURL("https://www.google.com/");
3643 request1
.load_flags
= 0;
3645 HttpRequestInfo request2
;
3646 request2
.method
= "GET";
3647 request2
.url
= GURL("https://www.google.com/2");
3648 request2
.load_flags
= 0;
3650 // CONNECT to www.google.com:443 via SPDY.
3651 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3653 scoped_ptr
<SpdyFrame
> conn_resp1(
3654 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3656 // Fetch https://www.google.com/ via HTTP.
3657 const char get1
[] = "GET / HTTP/1.1\r\n"
3658 "Host: www.google.com\r\n"
3659 "Connection: keep-alive\r\n\r\n";
3660 scoped_ptr
<SpdyFrame
> wrapped_get1(
3661 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3662 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3663 "Content-Length: 1\r\n\r\n";
3664 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3665 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3666 scoped_ptr
<SpdyFrame
> wrapped_body1(
3667 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3668 scoped_ptr
<SpdyFrame
> window_update(
3669 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3671 // Fetch https://www.google.com/2 via HTTP.
3672 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3673 "Host: www.google.com\r\n"
3674 "Connection: keep-alive\r\n\r\n";
3675 scoped_ptr
<SpdyFrame
> wrapped_get2(
3676 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3677 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3678 "Content-Length: 2\r\n\r\n";
3679 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3680 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3681 scoped_ptr
<SpdyFrame
> wrapped_body2(
3682 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3684 MockWrite spdy_writes
[] = {
3685 CreateMockWrite(*connect1
, 0),
3686 CreateMockWrite(*wrapped_get1
, 2),
3687 CreateMockWrite(*wrapped_get2
, 5),
3690 MockRead spdy_reads
[] = {
3691 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3692 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3693 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3694 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3695 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3696 MockRead(ASYNC
, 0, 8),
3699 DeterministicSocketData
spdy_data(
3700 spdy_reads
, arraysize(spdy_reads
),
3701 spdy_writes
, arraysize(spdy_writes
));
3702 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3704 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3705 ssl
.SetNextProto(GetParam());
3706 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3707 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3708 ssl2
.was_npn_negotiated
= false;
3709 ssl2
.protocol_negotiated
= kProtoUnknown
;
3710 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3712 TestCompletionCallback callback
;
3714 scoped_ptr
<HttpTransaction
> trans(
3715 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3716 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3717 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3718 // The first connect and request, each of their responses, and the body.
3719 spdy_data
.RunFor(5);
3721 rv
= callback
.WaitForResult();
3724 LoadTimingInfo load_timing_info
;
3725 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3726 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3728 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3729 ASSERT_TRUE(response
!= NULL
);
3730 ASSERT_TRUE(response
->headers
.get() != NULL
);
3731 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3733 std::string response_data
;
3734 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3735 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3738 scoped_ptr
<HttpTransaction
> trans2(
3739 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3740 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3741 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3743 // The second request, response, and body. There should not be a second
3745 spdy_data
.RunFor(3);
3746 rv
= callback
.WaitForResult();
3749 LoadTimingInfo load_timing_info2
;
3750 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3751 TestLoadTimingReused(load_timing_info2
);
3753 // The requests should have the same ID.
3754 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3756 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3759 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3760 // Proxy to different servers.
3761 TEST_P(HttpNetworkTransactionTest
,
3762 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3763 // Configure against https proxy server "proxy:70".
3764 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3765 "https://proxy:70"));
3766 CapturingBoundNetLog log
;
3767 session_deps_
.net_log
= log
.bound().net_log();
3768 scoped_refptr
<HttpNetworkSession
> session(
3769 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3771 HttpRequestInfo request1
;
3772 request1
.method
= "GET";
3773 request1
.url
= GURL("http://www.google.com/");
3774 request1
.load_flags
= 0;
3776 HttpRequestInfo request2
;
3777 request2
.method
= "GET";
3778 request2
.url
= GURL("http://news.google.com/");
3779 request2
.load_flags
= 0;
3781 // http://www.google.com/
3782 scoped_ptr
<SpdyHeaderBlock
> headers(
3783 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3784 scoped_ptr
<SpdyFrame
> get1(
3785 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
3786 scoped_ptr
<SpdyFrame
> get_resp1(
3787 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3788 scoped_ptr
<SpdyFrame
> body1(
3789 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3791 // http://news.google.com/
3792 scoped_ptr
<SpdyHeaderBlock
> headers2(
3793 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3794 scoped_ptr
<SpdyFrame
> get2(
3795 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
3796 scoped_ptr
<SpdyFrame
> get_resp2(
3797 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3798 scoped_ptr
<SpdyFrame
> body2(
3799 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3801 MockWrite spdy_writes
[] = {
3802 CreateMockWrite(*get1
, 0),
3803 CreateMockWrite(*get2
, 3),
3806 MockRead spdy_reads
[] = {
3807 CreateMockRead(*get_resp1
, 1, ASYNC
),
3808 CreateMockRead(*body1
, 2, ASYNC
),
3809 CreateMockRead(*get_resp2
, 4, ASYNC
),
3810 CreateMockRead(*body2
, 5, ASYNC
),
3811 MockRead(ASYNC
, 0, 6),
3814 DeterministicSocketData
spdy_data(
3815 spdy_reads
, arraysize(spdy_reads
),
3816 spdy_writes
, arraysize(spdy_writes
));
3817 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3819 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3820 ssl
.SetNextProto(GetParam());
3821 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3823 TestCompletionCallback callback
;
3825 scoped_ptr
<HttpTransaction
> trans(
3826 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3827 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3828 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3829 spdy_data
.RunFor(2);
3831 rv
= callback
.WaitForResult();
3834 LoadTimingInfo load_timing_info
;
3835 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3836 TestLoadTimingNotReused(load_timing_info
,
3837 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3839 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3840 ASSERT_TRUE(response
!= NULL
);
3841 ASSERT_TRUE(response
->headers
.get() != NULL
);
3842 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3844 std::string response_data
;
3845 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3846 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3847 spdy_data
.RunFor(1);
3848 EXPECT_EQ(1, callback
.WaitForResult());
3849 // Delete the first request, so the second one can reuse the socket.
3852 scoped_ptr
<HttpTransaction
> trans2(
3853 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3854 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3855 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3857 spdy_data
.RunFor(2);
3858 rv
= callback
.WaitForResult();
3861 LoadTimingInfo load_timing_info2
;
3862 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3863 TestLoadTimingReused(load_timing_info2
);
3865 // The requests should have the same ID.
3866 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3868 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3869 spdy_data
.RunFor(1);
3870 EXPECT_EQ(2, callback
.WaitForResult());
3873 // Test the challenge-response-retry sequence through an HTTPS Proxy
3874 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3875 HttpRequestInfo request
;
3876 request
.method
= "GET";
3877 request
.url
= GURL("http://www.google.com/");
3878 // when the no authentication data flag is set.
3879 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3881 // Configure against https proxy server "myproxy:70".
3882 session_deps_
.proxy_service
.reset(
3883 ProxyService::CreateFixed("https://myproxy:70"));
3884 CapturingBoundNetLog log
;
3885 session_deps_
.net_log
= log
.bound().net_log();
3886 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3888 // Since we have proxy, should use full url
3889 MockWrite data_writes1
[] = {
3890 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3891 "Host: www.google.com\r\n"
3892 "Proxy-Connection: keep-alive\r\n\r\n"),
3894 // After calling trans->RestartWithAuth(), this is the request we should
3895 // be issuing -- the final header line contains the credentials.
3896 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3897 "Host: www.google.com\r\n"
3898 "Proxy-Connection: keep-alive\r\n"
3899 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3902 // The proxy responds to the GET with a 407, using a persistent
3904 MockRead data_reads1
[] = {
3906 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3907 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3908 MockRead("Proxy-Connection: keep-alive\r\n"),
3909 MockRead("Content-Length: 0\r\n\r\n"),
3911 MockRead("HTTP/1.1 200 OK\r\n"),
3912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3913 MockRead("Content-Length: 100\r\n\r\n"),
3914 MockRead(SYNCHRONOUS
, OK
),
3917 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3918 data_writes1
, arraysize(data_writes1
));
3919 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3920 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3921 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3923 TestCompletionCallback callback1
;
3925 scoped_ptr
<HttpTransaction
> trans(
3926 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3928 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3929 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3931 rv
= callback1
.WaitForResult();
3934 LoadTimingInfo load_timing_info
;
3935 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3936 TestLoadTimingNotReused(load_timing_info
,
3937 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3939 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3940 ASSERT_TRUE(response
!= NULL
);
3941 ASSERT_FALSE(response
->headers
.get() == NULL
);
3942 EXPECT_EQ(407, response
->headers
->response_code());
3943 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3944 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3946 TestCompletionCallback callback2
;
3948 rv
= trans
->RestartWithAuth(
3949 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3952 rv
= callback2
.WaitForResult();
3955 load_timing_info
= LoadTimingInfo();
3956 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3957 // Retrying with HTTP AUTH is considered to be reusing a socket.
3958 TestLoadTimingReused(load_timing_info
);
3960 response
= trans
->GetResponseInfo();
3961 ASSERT_TRUE(response
!= NULL
);
3963 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3964 EXPECT_EQ(200, response
->headers
->response_code());
3965 EXPECT_EQ(100, response
->headers
->GetContentLength());
3966 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3968 // The password prompt info should not be set.
3969 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3972 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3973 const MockRead
& status
, int expected_status
) {
3974 HttpRequestInfo request
;
3975 request
.method
= "GET";
3976 request
.url
= GURL("https://www.google.com/");
3977 request
.load_flags
= 0;
3979 // Configure against proxy server "myproxy:70".
3980 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3981 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3983 // Since we have proxy, should try to establish tunnel.
3984 MockWrite data_writes
[] = {
3985 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3986 "Host: www.google.com\r\n"
3987 "Proxy-Connection: keep-alive\r\n\r\n"),
3990 MockRead data_reads
[] = {
3992 MockRead("Content-Length: 10\r\n\r\n"),
3993 // No response body because the test stops reading here.
3994 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3997 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3998 data_writes
, arraysize(data_writes
));
3999 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4001 TestCompletionCallback callback
;
4003 scoped_ptr
<HttpTransaction
> trans(
4004 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4006 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4007 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4009 rv
= callback
.WaitForResult();
4010 EXPECT_EQ(expected_status
, rv
);
4013 void HttpNetworkTransactionTest::ConnectStatusHelper(
4014 const MockRead
& status
) {
4015 ConnectStatusHelperWithExpectedStatus(
4016 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4019 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4020 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4023 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4024 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4027 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4028 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4031 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4032 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4035 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4036 ConnectStatusHelper(
4037 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4040 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4041 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4044 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4045 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4048 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4049 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4052 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4053 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4056 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4057 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4060 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4061 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4064 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4065 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4068 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4069 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4072 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4073 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4076 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4077 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4080 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4081 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4084 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4085 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4088 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4089 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4092 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4093 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4096 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4097 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4100 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4101 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4104 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4105 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4108 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4109 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4112 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4113 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4116 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4117 ConnectStatusHelperWithExpectedStatus(
4118 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4119 ERR_PROXY_AUTH_UNSUPPORTED
);
4122 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4123 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4126 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4127 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4130 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4131 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4134 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4135 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4138 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4139 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4142 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4143 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4146 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4147 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4150 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4151 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4154 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4155 ConnectStatusHelper(
4156 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4159 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4160 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4163 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4164 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4167 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4168 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4171 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4172 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4175 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4176 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4179 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4180 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4183 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4184 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4187 // Test the flow when both the proxy server AND origin server require
4188 // authentication. Again, this uses basic auth for both since that is
4189 // the simplest to mock.
4190 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4191 HttpRequestInfo request
;
4192 request
.method
= "GET";
4193 request
.url
= GURL("http://www.google.com/");
4194 request
.load_flags
= 0;
4196 // Configure against proxy server "myproxy:70".
4197 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4198 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4200 scoped_ptr
<HttpTransaction
> trans(
4201 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4203 MockWrite data_writes1
[] = {
4204 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4205 "Host: www.google.com\r\n"
4206 "Proxy-Connection: keep-alive\r\n\r\n"),
4209 MockRead data_reads1
[] = {
4210 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4211 // Give a couple authenticate options (only the middle one is actually
4213 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4214 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4215 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4217 // Large content-length -- won't matter, as connection will be reset.
4218 MockRead("Content-Length: 10000\r\n\r\n"),
4219 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4222 // After calling trans->RestartWithAuth() the first time, this is the
4223 // request we should be issuing -- the final header line contains the
4224 // proxy's credentials.
4225 MockWrite data_writes2
[] = {
4226 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4227 "Host: www.google.com\r\n"
4228 "Proxy-Connection: keep-alive\r\n"
4229 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4232 // Now the proxy server lets the request pass through to origin server.
4233 // The origin server responds with a 401.
4234 MockRead data_reads2
[] = {
4235 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4236 // Note: We are using the same realm-name as the proxy server. This is
4237 // completely valid, as realms are unique across hosts.
4238 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4240 MockRead("Content-Length: 2000\r\n\r\n"),
4241 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4244 // After calling trans->RestartWithAuth() the second time, we should send
4245 // the credentials for both the proxy and origin server.
4246 MockWrite data_writes3
[] = {
4247 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4248 "Host: www.google.com\r\n"
4249 "Proxy-Connection: keep-alive\r\n"
4250 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4251 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4254 // Lastly we get the desired content.
4255 MockRead data_reads3
[] = {
4256 MockRead("HTTP/1.0 200 OK\r\n"),
4257 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4258 MockRead("Content-Length: 100\r\n\r\n"),
4259 MockRead(SYNCHRONOUS
, OK
),
4262 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4263 data_writes1
, arraysize(data_writes1
));
4264 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4265 data_writes2
, arraysize(data_writes2
));
4266 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4267 data_writes3
, arraysize(data_writes3
));
4268 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4269 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4270 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4272 TestCompletionCallback callback1
;
4274 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4275 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4277 rv
= callback1
.WaitForResult();
4280 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4281 ASSERT_TRUE(response
!= NULL
);
4282 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4284 TestCompletionCallback callback2
;
4286 rv
= trans
->RestartWithAuth(
4287 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4288 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4290 rv
= callback2
.WaitForResult();
4293 response
= trans
->GetResponseInfo();
4294 ASSERT_TRUE(response
!= NULL
);
4295 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4297 TestCompletionCallback callback3
;
4299 rv
= trans
->RestartWithAuth(
4300 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4301 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4303 rv
= callback3
.WaitForResult();
4306 response
= trans
->GetResponseInfo();
4307 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4308 EXPECT_EQ(100, response
->headers
->GetContentLength());
4311 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4312 // can't hook into its internals to cause it to generate predictable NTLM
4313 // authorization headers.
4314 #if defined(NTLM_PORTABLE)
4315 // The NTLM authentication unit tests were generated by capturing the HTTP
4316 // requests and responses using Fiddler 2 and inspecting the generated random
4317 // bytes in the debugger.
4319 // Enter the correct password and authenticate successfully.
4320 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4321 HttpRequestInfo request
;
4322 request
.method
= "GET";
4323 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4325 // Ensure load is not disrupted by flags which suppress behaviour specific
4326 // to other auth schemes.
4327 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4329 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4331 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4333 MockWrite data_writes1
[] = {
4334 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4335 "Host: 172.22.68.17\r\n"
4336 "Connection: keep-alive\r\n\r\n"),
4339 MockRead data_reads1
[] = {
4340 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4341 // Negotiate and NTLM are often requested together. However, we only want
4342 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4343 // the header that requests Negotiate for this test.
4344 MockRead("WWW-Authenticate: NTLM\r\n"),
4345 MockRead("Connection: close\r\n"),
4346 MockRead("Content-Length: 42\r\n"),
4347 MockRead("Content-Type: text/html\r\n\r\n"),
4348 // Missing content -- won't matter, as connection will be reset.
4349 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4352 MockWrite data_writes2
[] = {
4353 // After restarting with a null identity, this is the
4354 // request we should be issuing -- the final header line contains a Type
4356 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4357 "Host: 172.22.68.17\r\n"
4358 "Connection: keep-alive\r\n"
4359 "Authorization: NTLM "
4360 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4362 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4363 // (the credentials for the origin server). The second request continues
4364 // on the same connection.
4365 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4366 "Host: 172.22.68.17\r\n"
4367 "Connection: keep-alive\r\n"
4368 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4369 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4370 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4371 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4372 "ahlhx5I=\r\n\r\n"),
4375 MockRead data_reads2
[] = {
4376 // The origin server responds with a Type 2 message.
4377 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4378 MockRead("WWW-Authenticate: NTLM "
4379 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4380 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4381 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4382 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4383 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4384 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4386 MockRead("Content-Length: 42\r\n"),
4387 MockRead("Content-Type: text/html\r\n\r\n"),
4388 MockRead("You are not authorized to view this page\r\n"),
4390 // Lastly we get the desired content.
4391 MockRead("HTTP/1.1 200 OK\r\n"),
4392 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4393 MockRead("Content-Length: 13\r\n\r\n"),
4394 MockRead("Please Login\r\n"),
4395 MockRead(SYNCHRONOUS
, OK
),
4398 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4399 data_writes1
, arraysize(data_writes1
));
4400 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4401 data_writes2
, arraysize(data_writes2
));
4402 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4403 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4405 TestCompletionCallback callback1
;
4407 scoped_ptr
<HttpTransaction
> trans(
4408 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4410 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4411 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4413 rv
= callback1
.WaitForResult();
4416 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4418 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4419 ASSERT_FALSE(response
== NULL
);
4420 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4422 TestCompletionCallback callback2
;
4424 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4425 callback2
.callback());
4426 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4428 rv
= callback2
.WaitForResult();
4431 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4433 response
= trans
->GetResponseInfo();
4434 ASSERT_TRUE(response
!= NULL
);
4435 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4437 TestCompletionCallback callback3
;
4439 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4442 rv
= callback3
.WaitForResult();
4445 response
= trans
->GetResponseInfo();
4446 ASSERT_TRUE(response
!= NULL
);
4447 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4448 EXPECT_EQ(13, response
->headers
->GetContentLength());
4451 // Enter a wrong password, and then the correct one.
4452 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4453 HttpRequestInfo request
;
4454 request
.method
= "GET";
4455 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4456 request
.load_flags
= 0;
4458 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4460 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4462 MockWrite data_writes1
[] = {
4463 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4464 "Host: 172.22.68.17\r\n"
4465 "Connection: keep-alive\r\n\r\n"),
4468 MockRead data_reads1
[] = {
4469 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4470 // Negotiate and NTLM are often requested together. However, we only want
4471 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4472 // the header that requests Negotiate for this test.
4473 MockRead("WWW-Authenticate: NTLM\r\n"),
4474 MockRead("Connection: close\r\n"),
4475 MockRead("Content-Length: 42\r\n"),
4476 MockRead("Content-Type: text/html\r\n\r\n"),
4477 // Missing content -- won't matter, as connection will be reset.
4478 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4481 MockWrite data_writes2
[] = {
4482 // After restarting with a null identity, this is the
4483 // request we should be issuing -- the final header line contains a Type
4485 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4486 "Host: 172.22.68.17\r\n"
4487 "Connection: keep-alive\r\n"
4488 "Authorization: NTLM "
4489 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4491 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4492 // (the credentials for the origin server). The second request continues
4493 // on the same connection.
4494 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4495 "Host: 172.22.68.17\r\n"
4496 "Connection: keep-alive\r\n"
4497 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4498 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4499 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4500 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4501 "4Ww7b7E=\r\n\r\n"),
4504 MockRead data_reads2
[] = {
4505 // The origin server responds with a Type 2 message.
4506 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4507 MockRead("WWW-Authenticate: NTLM "
4508 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4509 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4510 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4511 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4512 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4513 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4515 MockRead("Content-Length: 42\r\n"),
4516 MockRead("Content-Type: text/html\r\n\r\n"),
4517 MockRead("You are not authorized to view this page\r\n"),
4520 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4521 MockRead("WWW-Authenticate: NTLM\r\n"),
4522 MockRead("Connection: close\r\n"),
4523 MockRead("Content-Length: 42\r\n"),
4524 MockRead("Content-Type: text/html\r\n\r\n"),
4525 // Missing content -- won't matter, as connection will be reset.
4526 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4529 MockWrite data_writes3
[] = {
4530 // After restarting with a null identity, this is the
4531 // request we should be issuing -- the final header line contains a Type
4533 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4534 "Host: 172.22.68.17\r\n"
4535 "Connection: keep-alive\r\n"
4536 "Authorization: NTLM "
4537 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4539 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4540 // (the credentials for the origin server). The second request continues
4541 // on the same connection.
4542 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4543 "Host: 172.22.68.17\r\n"
4544 "Connection: keep-alive\r\n"
4545 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4546 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4547 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4548 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4549 "+4MUm7c=\r\n\r\n"),
4552 MockRead data_reads3
[] = {
4553 // The origin server responds with a Type 2 message.
4554 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4555 MockRead("WWW-Authenticate: NTLM "
4556 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4557 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4558 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4559 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4560 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4561 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4563 MockRead("Content-Length: 42\r\n"),
4564 MockRead("Content-Type: text/html\r\n\r\n"),
4565 MockRead("You are not authorized to view this page\r\n"),
4567 // Lastly we get the desired content.
4568 MockRead("HTTP/1.1 200 OK\r\n"),
4569 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4570 MockRead("Content-Length: 13\r\n\r\n"),
4571 MockRead("Please Login\r\n"),
4572 MockRead(SYNCHRONOUS
, OK
),
4575 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4576 data_writes1
, arraysize(data_writes1
));
4577 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4578 data_writes2
, arraysize(data_writes2
));
4579 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4580 data_writes3
, arraysize(data_writes3
));
4581 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4582 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4583 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4585 TestCompletionCallback callback1
;
4587 scoped_ptr
<HttpTransaction
> trans(
4588 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4590 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4591 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4593 rv
= callback1
.WaitForResult();
4596 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4598 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4599 ASSERT_TRUE(response
!= NULL
);
4600 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4602 TestCompletionCallback callback2
;
4604 // Enter the wrong password.
4605 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4606 callback2
.callback());
4607 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4609 rv
= callback2
.WaitForResult();
4612 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4613 TestCompletionCallback callback3
;
4614 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4615 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4616 rv
= callback3
.WaitForResult();
4618 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4620 response
= trans
->GetResponseInfo();
4621 ASSERT_FALSE(response
== NULL
);
4622 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4624 TestCompletionCallback callback4
;
4626 // Now enter the right password.
4627 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4628 callback4
.callback());
4629 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4631 rv
= callback4
.WaitForResult();
4634 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4636 TestCompletionCallback callback5
;
4638 // One more roundtrip
4639 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4642 rv
= callback5
.WaitForResult();
4645 response
= trans
->GetResponseInfo();
4646 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4647 EXPECT_EQ(13, response
->headers
->GetContentLength());
4649 #endif // NTLM_PORTABLE
4651 // Test reading a server response which has only headers, and no body.
4652 // After some maximum number of bytes is consumed, the transaction should
4653 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4654 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4655 HttpRequestInfo request
;
4656 request
.method
= "GET";
4657 request
.url
= GURL("http://www.google.com/");
4658 request
.load_flags
= 0;
4660 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4661 scoped_ptr
<HttpTransaction
> trans(
4662 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4664 // Respond with 300 kb of headers (we should fail after 256 kb).
4665 std::string large_headers_string
;
4666 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4668 MockRead data_reads
[] = {
4669 MockRead("HTTP/1.0 200 OK\r\n"),
4670 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4671 MockRead("\r\nBODY"),
4672 MockRead(SYNCHRONOUS
, OK
),
4674 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4675 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4677 TestCompletionCallback callback
;
4679 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4682 rv
= callback
.WaitForResult();
4683 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4685 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4686 EXPECT_TRUE(response
== NULL
);
4689 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4690 // establish tunnel.
4691 // http://code.google.com/p/chromium/issues/detail?id=3772
4692 TEST_P(HttpNetworkTransactionTest
,
4693 DontRecycleTransportSocketForSSLTunnel
) {
4694 HttpRequestInfo request
;
4695 request
.method
= "GET";
4696 request
.url
= GURL("https://www.google.com/");
4697 request
.load_flags
= 0;
4699 // Configure against proxy server "myproxy:70".
4700 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4702 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4704 scoped_ptr
<HttpTransaction
> trans(
4705 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4707 // Since we have proxy, should try to establish tunnel.
4708 MockWrite data_writes1
[] = {
4709 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4710 "Host: www.google.com\r\n"
4711 "Proxy-Connection: keep-alive\r\n\r\n"),
4714 // The proxy responds to the connect with a 404, using a persistent
4715 // connection. Usually a proxy would return 501 (not implemented),
4716 // or 200 (tunnel established).
4717 MockRead data_reads1
[] = {
4718 MockRead("HTTP/1.1 404 Not Found\r\n"),
4719 MockRead("Content-Length: 10\r\n\r\n"),
4720 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4723 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4724 data_writes1
, arraysize(data_writes1
));
4725 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4727 TestCompletionCallback callback1
;
4729 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4730 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4732 rv
= callback1
.WaitForResult();
4733 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4735 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4736 EXPECT_TRUE(response
== NULL
);
4738 // Empty the current queue. This is necessary because idle sockets are
4739 // added to the connection pool asynchronously with a PostTask.
4740 base::MessageLoop::current()->RunUntilIdle();
4742 // We now check to make sure the TCPClientSocket was not added back to
4744 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4746 base::MessageLoop::current()->RunUntilIdle();
4747 // Make sure that the socket didn't get recycled after calling the destructor.
4748 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4751 // Make sure that we recycle a socket after reading all of the response body.
4752 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4753 HttpRequestInfo request
;
4754 request
.method
= "GET";
4755 request
.url
= GURL("http://www.google.com/");
4756 request
.load_flags
= 0;
4758 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4760 scoped_ptr
<HttpTransaction
> trans(
4761 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4763 MockRead data_reads
[] = {
4764 // A part of the response body is received with the response headers.
4765 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4766 // The rest of the response body is received in two parts.
4769 MockRead("junk"), // Should not be read!!
4770 MockRead(SYNCHRONOUS
, OK
),
4773 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4774 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4776 TestCompletionCallback callback
;
4778 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4781 rv
= callback
.WaitForResult();
4784 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4785 ASSERT_TRUE(response
!= NULL
);
4787 EXPECT_TRUE(response
->headers
.get() != NULL
);
4788 std::string status_line
= response
->headers
->GetStatusLine();
4789 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4791 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4793 std::string response_data
;
4794 rv
= ReadTransaction(trans
.get(), &response_data
);
4796 EXPECT_EQ("hello world", response_data
);
4798 // Empty the current queue. This is necessary because idle sockets are
4799 // added to the connection pool asynchronously with a PostTask.
4800 base::MessageLoop::current()->RunUntilIdle();
4802 // We now check to make sure the socket was added back to the pool.
4803 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4806 // Make sure that we recycle a SSL socket after reading all of the response
4808 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4809 HttpRequestInfo request
;
4810 request
.method
= "GET";
4811 request
.url
= GURL("https://www.google.com/");
4812 request
.load_flags
= 0;
4814 MockWrite data_writes
[] = {
4815 MockWrite("GET / HTTP/1.1\r\n"
4816 "Host: www.google.com\r\n"
4817 "Connection: keep-alive\r\n\r\n"),
4820 MockRead data_reads
[] = {
4821 MockRead("HTTP/1.1 200 OK\r\n"),
4822 MockRead("Content-Length: 11\r\n\r\n"),
4823 MockRead("hello world"),
4824 MockRead(SYNCHRONOUS
, OK
),
4827 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4828 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4830 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4831 data_writes
, arraysize(data_writes
));
4832 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4834 TestCompletionCallback callback
;
4836 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4837 scoped_ptr
<HttpTransaction
> trans(
4838 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4840 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4843 EXPECT_EQ(OK
, callback
.WaitForResult());
4845 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4846 ASSERT_TRUE(response
!= NULL
);
4847 ASSERT_TRUE(response
->headers
.get() != NULL
);
4848 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4850 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4852 std::string response_data
;
4853 rv
= ReadTransaction(trans
.get(), &response_data
);
4855 EXPECT_EQ("hello world", response_data
);
4857 // Empty the current queue. This is necessary because idle sockets are
4858 // added to the connection pool asynchronously with a PostTask.
4859 base::MessageLoop::current()->RunUntilIdle();
4861 // We now check to make sure the socket was added back to the pool.
4862 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4865 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4866 // from the pool and make sure that we recover okay.
4867 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4868 HttpRequestInfo request
;
4869 request
.method
= "GET";
4870 request
.url
= GURL("https://www.google.com/");
4871 request
.load_flags
= 0;
4873 MockWrite data_writes
[] = {
4874 MockWrite("GET / HTTP/1.1\r\n"
4875 "Host: www.google.com\r\n"
4876 "Connection: keep-alive\r\n\r\n"),
4877 MockWrite("GET / HTTP/1.1\r\n"
4878 "Host: www.google.com\r\n"
4879 "Connection: keep-alive\r\n\r\n"),
4882 MockRead data_reads
[] = {
4883 MockRead("HTTP/1.1 200 OK\r\n"),
4884 MockRead("Content-Length: 11\r\n\r\n"),
4885 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4886 MockRead("hello world"),
4887 MockRead(ASYNC
, 0, 0) // EOF
4890 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4891 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4892 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4893 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4895 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4896 data_writes
, arraysize(data_writes
));
4897 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4898 data_writes
, arraysize(data_writes
));
4899 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4900 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4902 TestCompletionCallback callback
;
4904 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4905 scoped_ptr
<HttpTransaction
> trans(
4906 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4908 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4911 EXPECT_EQ(OK
, callback
.WaitForResult());
4913 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4914 ASSERT_TRUE(response
!= NULL
);
4915 ASSERT_TRUE(response
->headers
.get() != NULL
);
4916 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4918 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4920 std::string response_data
;
4921 rv
= ReadTransaction(trans
.get(), &response_data
);
4923 EXPECT_EQ("hello world", response_data
);
4925 // Empty the current queue. This is necessary because idle sockets are
4926 // added to the connection pool asynchronously with a PostTask.
4927 base::MessageLoop::current()->RunUntilIdle();
4929 // We now check to make sure the socket was added back to the pool.
4930 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4932 // Now start the second transaction, which should reuse the previous socket.
4934 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4936 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4938 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4939 EXPECT_EQ(OK
, callback
.WaitForResult());
4941 response
= trans
->GetResponseInfo();
4942 ASSERT_TRUE(response
!= NULL
);
4943 ASSERT_TRUE(response
->headers
.get() != NULL
);
4944 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4946 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4948 rv
= ReadTransaction(trans
.get(), &response_data
);
4950 EXPECT_EQ("hello world", response_data
);
4952 // Empty the current queue. This is necessary because idle sockets are
4953 // added to the connection pool asynchronously with a PostTask.
4954 base::MessageLoop::current()->RunUntilIdle();
4956 // We now check to make sure the socket was added back to the pool.
4957 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4960 // Make sure that we recycle a socket after a zero-length response.
4961 // http://crbug.com/9880
4962 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4963 HttpRequestInfo request
;
4964 request
.method
= "GET";
4965 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4966 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4967 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4968 "rt=prt.2642,ol.2649,xjs.2951");
4969 request
.load_flags
= 0;
4971 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4973 scoped_ptr
<HttpTransaction
> trans(
4974 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4976 MockRead data_reads
[] = {
4977 MockRead("HTTP/1.1 204 No Content\r\n"
4978 "Content-Length: 0\r\n"
4979 "Content-Type: text/html\r\n\r\n"),
4980 MockRead("junk"), // Should not be read!!
4981 MockRead(SYNCHRONOUS
, OK
),
4984 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4985 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4987 TestCompletionCallback callback
;
4989 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4990 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4992 rv
= callback
.WaitForResult();
4995 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4996 ASSERT_TRUE(response
!= NULL
);
4998 EXPECT_TRUE(response
->headers
.get() != NULL
);
4999 std::string status_line
= response
->headers
->GetStatusLine();
5000 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5002 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5004 std::string response_data
;
5005 rv
= ReadTransaction(trans
.get(), &response_data
);
5007 EXPECT_EQ("", response_data
);
5009 // Empty the current queue. This is necessary because idle sockets are
5010 // added to the connection pool asynchronously with a PostTask.
5011 base::MessageLoop::current()->RunUntilIdle();
5013 // We now check to make sure the socket was added back to the pool.
5014 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5017 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5018 ScopedVector
<UploadElementReader
> element_readers
;
5019 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5020 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5022 HttpRequestInfo request
[2];
5023 // Transaction 1: a GET request that succeeds. The socket is recycled
5025 request
[0].method
= "GET";
5026 request
[0].url
= GURL("http://www.google.com/");
5027 request
[0].load_flags
= 0;
5028 // Transaction 2: a POST request. Reuses the socket kept alive from
5029 // transaction 1. The first attempts fails when writing the POST data.
5030 // This causes the transaction to retry with a new socket. The second
5031 // attempt succeeds.
5032 request
[1].method
= "POST";
5033 request
[1].url
= GURL("http://www.google.com/login.cgi");
5034 request
[1].upload_data_stream
= &upload_data_stream
;
5035 request
[1].load_flags
= 0;
5037 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5039 // The first socket is used for transaction 1 and the first attempt of
5042 // The response of transaction 1.
5043 MockRead data_reads1
[] = {
5044 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5045 MockRead("hello world"),
5046 MockRead(SYNCHRONOUS
, OK
),
5048 // The mock write results of transaction 1 and the first attempt of
5050 MockWrite data_writes1
[] = {
5051 MockWrite(SYNCHRONOUS
, 64), // GET
5052 MockWrite(SYNCHRONOUS
, 93), // POST
5053 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5055 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5056 data_writes1
, arraysize(data_writes1
));
5058 // The second socket is used for the second attempt of transaction 2.
5060 // The response of transaction 2.
5061 MockRead data_reads2
[] = {
5062 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5063 MockRead("welcome"),
5064 MockRead(SYNCHRONOUS
, OK
),
5066 // The mock write results of the second attempt of transaction 2.
5067 MockWrite data_writes2
[] = {
5068 MockWrite(SYNCHRONOUS
, 93), // POST
5069 MockWrite(SYNCHRONOUS
, 3), // POST data
5071 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5072 data_writes2
, arraysize(data_writes2
));
5074 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5075 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5077 const char* kExpectedResponseData
[] = {
5078 "hello world", "welcome"
5081 for (int i
= 0; i
< 2; ++i
) {
5082 scoped_ptr
<HttpTransaction
> trans(
5083 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5085 TestCompletionCallback callback
;
5087 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5088 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5090 rv
= callback
.WaitForResult();
5093 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5094 ASSERT_TRUE(response
!= NULL
);
5096 EXPECT_TRUE(response
->headers
.get() != NULL
);
5097 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5099 std::string response_data
;
5100 rv
= ReadTransaction(trans
.get(), &response_data
);
5102 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5106 // Test the request-challenge-retry sequence for basic auth when there is
5107 // an identity in the URL. The request should be sent as normal, but when
5108 // it fails the identity from the URL is used to answer the challenge.
5109 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5110 HttpRequestInfo request
;
5111 request
.method
= "GET";
5112 request
.url
= GURL("http://foo:b@r@www.google.com/");
5113 request
.load_flags
= LOAD_NORMAL
;
5115 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5116 scoped_ptr
<HttpTransaction
> trans(
5117 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5119 // The password contains an escaped character -- for this test to pass it
5120 // will need to be unescaped by HttpNetworkTransaction.
5121 EXPECT_EQ("b%40r", request
.url
.password());
5123 MockWrite data_writes1
[] = {
5124 MockWrite("GET / HTTP/1.1\r\n"
5125 "Host: www.google.com\r\n"
5126 "Connection: keep-alive\r\n\r\n"),
5129 MockRead data_reads1
[] = {
5130 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5131 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5132 MockRead("Content-Length: 10\r\n\r\n"),
5133 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5136 // After the challenge above, the transaction will be restarted using the
5137 // identity from the url (foo, b@r) to answer the challenge.
5138 MockWrite data_writes2
[] = {
5139 MockWrite("GET / HTTP/1.1\r\n"
5140 "Host: www.google.com\r\n"
5141 "Connection: keep-alive\r\n"
5142 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5145 MockRead data_reads2
[] = {
5146 MockRead("HTTP/1.0 200 OK\r\n"),
5147 MockRead("Content-Length: 100\r\n\r\n"),
5148 MockRead(SYNCHRONOUS
, OK
),
5151 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5152 data_writes1
, arraysize(data_writes1
));
5153 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5154 data_writes2
, arraysize(data_writes2
));
5155 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5156 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5158 TestCompletionCallback callback1
;
5159 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5160 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5161 rv
= callback1
.WaitForResult();
5163 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5165 TestCompletionCallback callback2
;
5166 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5167 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5168 rv
= callback2
.WaitForResult();
5170 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5172 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5173 ASSERT_TRUE(response
!= NULL
);
5175 // There is no challenge info, since the identity in URL worked.
5176 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5178 EXPECT_EQ(100, response
->headers
->GetContentLength());
5180 // Empty the current queue.
5181 base::MessageLoop::current()->RunUntilIdle();
5184 // Test the request-challenge-retry sequence for basic auth when there is an
5185 // incorrect identity in the URL. The identity from the URL should be used only
5187 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5188 HttpRequestInfo request
;
5189 request
.method
= "GET";
5190 // Note: the URL has a username:password in it. The password "baz" is
5191 // wrong (should be "bar").
5192 request
.url
= GURL("http://foo:baz@www.google.com/");
5194 request
.load_flags
= LOAD_NORMAL
;
5196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5197 scoped_ptr
<HttpTransaction
> trans(
5198 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5200 MockWrite data_writes1
[] = {
5201 MockWrite("GET / HTTP/1.1\r\n"
5202 "Host: www.google.com\r\n"
5203 "Connection: keep-alive\r\n\r\n"),
5206 MockRead data_reads1
[] = {
5207 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5208 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5209 MockRead("Content-Length: 10\r\n\r\n"),
5210 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5213 // After the challenge above, the transaction will be restarted using the
5214 // identity from the url (foo, baz) to answer the challenge.
5215 MockWrite data_writes2
[] = {
5216 MockWrite("GET / HTTP/1.1\r\n"
5217 "Host: www.google.com\r\n"
5218 "Connection: keep-alive\r\n"
5219 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5222 MockRead data_reads2
[] = {
5223 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5224 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5225 MockRead("Content-Length: 10\r\n\r\n"),
5226 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5229 // After the challenge above, the transaction will be restarted using the
5230 // identity supplied by the user (foo, bar) to answer the challenge.
5231 MockWrite data_writes3
[] = {
5232 MockWrite("GET / HTTP/1.1\r\n"
5233 "Host: www.google.com\r\n"
5234 "Connection: keep-alive\r\n"
5235 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5238 MockRead data_reads3
[] = {
5239 MockRead("HTTP/1.0 200 OK\r\n"),
5240 MockRead("Content-Length: 100\r\n\r\n"),
5241 MockRead(SYNCHRONOUS
, OK
),
5244 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5245 data_writes1
, arraysize(data_writes1
));
5246 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5247 data_writes2
, arraysize(data_writes2
));
5248 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5249 data_writes3
, arraysize(data_writes3
));
5250 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5251 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5252 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5254 TestCompletionCallback callback1
;
5256 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5257 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5259 rv
= callback1
.WaitForResult();
5262 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5263 TestCompletionCallback callback2
;
5264 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5265 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5266 rv
= callback2
.WaitForResult();
5268 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5270 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5271 ASSERT_TRUE(response
!= NULL
);
5272 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5274 TestCompletionCallback callback3
;
5275 rv
= trans
->RestartWithAuth(
5276 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5277 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5278 rv
= callback3
.WaitForResult();
5280 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5282 response
= trans
->GetResponseInfo();
5283 ASSERT_TRUE(response
!= NULL
);
5285 // There is no challenge info, since the identity worked.
5286 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5288 EXPECT_EQ(100, response
->headers
->GetContentLength());
5290 // Empty the current queue.
5291 base::MessageLoop::current()->RunUntilIdle();
5295 // Test the request-challenge-retry sequence for basic auth when there is a
5296 // correct identity in the URL, but its use is being suppressed. The identity
5297 // from the URL should never be used.
5298 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5299 HttpRequestInfo request
;
5300 request
.method
= "GET";
5301 request
.url
= GURL("http://foo:bar@www.google.com/");
5302 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5304 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5305 scoped_ptr
<HttpTransaction
> trans(
5306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5308 MockWrite data_writes1
[] = {
5309 MockWrite("GET / HTTP/1.1\r\n"
5310 "Host: www.google.com\r\n"
5311 "Connection: keep-alive\r\n\r\n"),
5314 MockRead data_reads1
[] = {
5315 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5316 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5317 MockRead("Content-Length: 10\r\n\r\n"),
5318 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5321 // After the challenge above, the transaction will be restarted using the
5322 // identity supplied by the user, not the one in the URL, to answer the
5324 MockWrite data_writes3
[] = {
5325 MockWrite("GET / HTTP/1.1\r\n"
5326 "Host: www.google.com\r\n"
5327 "Connection: keep-alive\r\n"
5328 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5331 MockRead data_reads3
[] = {
5332 MockRead("HTTP/1.0 200 OK\r\n"),
5333 MockRead("Content-Length: 100\r\n\r\n"),
5334 MockRead(SYNCHRONOUS
, OK
),
5337 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5338 data_writes1
, arraysize(data_writes1
));
5339 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5340 data_writes3
, arraysize(data_writes3
));
5341 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5342 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5344 TestCompletionCallback callback1
;
5345 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5346 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5347 rv
= callback1
.WaitForResult();
5349 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5351 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5352 ASSERT_TRUE(response
!= NULL
);
5353 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5355 TestCompletionCallback callback3
;
5356 rv
= trans
->RestartWithAuth(
5357 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5358 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5359 rv
= callback3
.WaitForResult();
5361 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5363 response
= trans
->GetResponseInfo();
5364 ASSERT_TRUE(response
!= NULL
);
5366 // There is no challenge info, since the identity worked.
5367 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5368 EXPECT_EQ(100, response
->headers
->GetContentLength());
5370 // Empty the current queue.
5371 base::MessageLoop::current()->RunUntilIdle();
5374 // Test that previously tried username/passwords for a realm get re-used.
5375 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5376 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5378 // Transaction 1: authenticate (foo, bar) on MyRealm1
5380 HttpRequestInfo request
;
5381 request
.method
= "GET";
5382 request
.url
= GURL("http://www.google.com/x/y/z");
5383 request
.load_flags
= 0;
5385 scoped_ptr
<HttpTransaction
> trans(
5386 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5388 MockWrite data_writes1
[] = {
5389 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5390 "Host: www.google.com\r\n"
5391 "Connection: keep-alive\r\n\r\n"),
5394 MockRead data_reads1
[] = {
5395 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5396 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5397 MockRead("Content-Length: 10000\r\n\r\n"),
5398 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5401 // Resend with authorization (username=foo, password=bar)
5402 MockWrite data_writes2
[] = {
5403 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5404 "Host: www.google.com\r\n"
5405 "Connection: keep-alive\r\n"
5406 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5409 // Sever accepts the authorization.
5410 MockRead data_reads2
[] = {
5411 MockRead("HTTP/1.0 200 OK\r\n"),
5412 MockRead("Content-Length: 100\r\n\r\n"),
5413 MockRead(SYNCHRONOUS
, OK
),
5416 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5417 data_writes1
, arraysize(data_writes1
));
5418 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5419 data_writes2
, arraysize(data_writes2
));
5420 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5421 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5423 TestCompletionCallback callback1
;
5425 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5426 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5428 rv
= callback1
.WaitForResult();
5431 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5432 ASSERT_TRUE(response
!= NULL
);
5433 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5435 TestCompletionCallback callback2
;
5437 rv
= trans
->RestartWithAuth(
5438 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5439 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5441 rv
= callback2
.WaitForResult();
5444 response
= trans
->GetResponseInfo();
5445 ASSERT_TRUE(response
!= NULL
);
5446 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5447 EXPECT_EQ(100, response
->headers
->GetContentLength());
5450 // ------------------------------------------------------------------------
5452 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5454 HttpRequestInfo request
;
5455 request
.method
= "GET";
5456 // Note that Transaction 1 was at /x/y/z, so this is in the same
5457 // protection space as MyRealm1.
5458 request
.url
= GURL("http://www.google.com/x/y/a/b");
5459 request
.load_flags
= 0;
5461 scoped_ptr
<HttpTransaction
> trans(
5462 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5464 MockWrite data_writes1
[] = {
5465 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5466 "Host: www.google.com\r\n"
5467 "Connection: keep-alive\r\n"
5468 // Send preemptive authorization for MyRealm1
5469 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5472 // The server didn't like the preemptive authorization, and
5473 // challenges us for a different realm (MyRealm2).
5474 MockRead data_reads1
[] = {
5475 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5476 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5477 MockRead("Content-Length: 10000\r\n\r\n"),
5478 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5481 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5482 MockWrite data_writes2
[] = {
5483 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5484 "Host: www.google.com\r\n"
5485 "Connection: keep-alive\r\n"
5486 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5489 // Sever accepts the authorization.
5490 MockRead data_reads2
[] = {
5491 MockRead("HTTP/1.0 200 OK\r\n"),
5492 MockRead("Content-Length: 100\r\n\r\n"),
5493 MockRead(SYNCHRONOUS
, OK
),
5496 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5497 data_writes1
, arraysize(data_writes1
));
5498 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5499 data_writes2
, arraysize(data_writes2
));
5500 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5501 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5503 TestCompletionCallback callback1
;
5505 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5506 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5508 rv
= callback1
.WaitForResult();
5511 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5512 ASSERT_TRUE(response
!= NULL
);
5513 ASSERT_TRUE(response
->auth_challenge
.get());
5514 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5515 EXPECT_EQ("www.google.com:80",
5516 response
->auth_challenge
->challenger
.ToString());
5517 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5518 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5520 TestCompletionCallback callback2
;
5522 rv
= trans
->RestartWithAuth(
5523 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5524 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5526 rv
= callback2
.WaitForResult();
5529 response
= trans
->GetResponseInfo();
5530 ASSERT_TRUE(response
!= NULL
);
5531 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5532 EXPECT_EQ(100, response
->headers
->GetContentLength());
5535 // ------------------------------------------------------------------------
5537 // Transaction 3: Resend a request in MyRealm's protection space --
5538 // succeed with preemptive authorization.
5540 HttpRequestInfo request
;
5541 request
.method
= "GET";
5542 request
.url
= GURL("http://www.google.com/x/y/z2");
5543 request
.load_flags
= 0;
5545 scoped_ptr
<HttpTransaction
> trans(
5546 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5548 MockWrite data_writes1
[] = {
5549 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5550 "Host: www.google.com\r\n"
5551 "Connection: keep-alive\r\n"
5552 // The authorization for MyRealm1 gets sent preemptively
5553 // (since the url is in the same protection space)
5554 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5557 // Sever accepts the preemptive authorization
5558 MockRead data_reads1
[] = {
5559 MockRead("HTTP/1.0 200 OK\r\n"),
5560 MockRead("Content-Length: 100\r\n\r\n"),
5561 MockRead(SYNCHRONOUS
, OK
),
5564 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5565 data_writes1
, arraysize(data_writes1
));
5566 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5568 TestCompletionCallback callback1
;
5570 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5571 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5573 rv
= callback1
.WaitForResult();
5576 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5577 ASSERT_TRUE(response
!= NULL
);
5579 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5580 EXPECT_EQ(100, response
->headers
->GetContentLength());
5583 // ------------------------------------------------------------------------
5585 // Transaction 4: request another URL in MyRealm (however the
5586 // url is not known to belong to the protection space, so no pre-auth).
5588 HttpRequestInfo request
;
5589 request
.method
= "GET";
5590 request
.url
= GURL("http://www.google.com/x/1");
5591 request
.load_flags
= 0;
5593 scoped_ptr
<HttpTransaction
> trans(
5594 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5596 MockWrite data_writes1
[] = {
5597 MockWrite("GET /x/1 HTTP/1.1\r\n"
5598 "Host: www.google.com\r\n"
5599 "Connection: keep-alive\r\n\r\n"),
5602 MockRead data_reads1
[] = {
5603 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5604 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5605 MockRead("Content-Length: 10000\r\n\r\n"),
5606 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5609 // Resend with authorization from MyRealm's cache.
5610 MockWrite data_writes2
[] = {
5611 MockWrite("GET /x/1 HTTP/1.1\r\n"
5612 "Host: www.google.com\r\n"
5613 "Connection: keep-alive\r\n"
5614 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5617 // Sever accepts the authorization.
5618 MockRead data_reads2
[] = {
5619 MockRead("HTTP/1.0 200 OK\r\n"),
5620 MockRead("Content-Length: 100\r\n\r\n"),
5621 MockRead(SYNCHRONOUS
, OK
),
5624 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5625 data_writes1
, arraysize(data_writes1
));
5626 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5627 data_writes2
, arraysize(data_writes2
));
5628 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5629 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5631 TestCompletionCallback callback1
;
5633 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5634 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5636 rv
= callback1
.WaitForResult();
5639 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5640 TestCompletionCallback callback2
;
5641 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5642 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5643 rv
= callback2
.WaitForResult();
5645 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5647 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5648 ASSERT_TRUE(response
!= NULL
);
5649 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5650 EXPECT_EQ(100, response
->headers
->GetContentLength());
5653 // ------------------------------------------------------------------------
5655 // Transaction 5: request a URL in MyRealm, but the server rejects the
5656 // cached identity. Should invalidate and re-prompt.
5658 HttpRequestInfo request
;
5659 request
.method
= "GET";
5660 request
.url
= GURL("http://www.google.com/p/q/t");
5661 request
.load_flags
= 0;
5663 scoped_ptr
<HttpTransaction
> trans(
5664 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5666 MockWrite data_writes1
[] = {
5667 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5668 "Host: www.google.com\r\n"
5669 "Connection: keep-alive\r\n\r\n"),
5672 MockRead data_reads1
[] = {
5673 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5674 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5675 MockRead("Content-Length: 10000\r\n\r\n"),
5676 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5679 // Resend with authorization from cache for MyRealm.
5680 MockWrite data_writes2
[] = {
5681 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5682 "Host: www.google.com\r\n"
5683 "Connection: keep-alive\r\n"
5684 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5687 // Sever rejects the authorization.
5688 MockRead data_reads2
[] = {
5689 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5690 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5691 MockRead("Content-Length: 10000\r\n\r\n"),
5692 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5695 // At this point we should prompt for new credentials for MyRealm.
5696 // Restart with username=foo3, password=foo4.
5697 MockWrite data_writes3
[] = {
5698 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5699 "Host: www.google.com\r\n"
5700 "Connection: keep-alive\r\n"
5701 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5704 // Sever accepts the authorization.
5705 MockRead data_reads3
[] = {
5706 MockRead("HTTP/1.0 200 OK\r\n"),
5707 MockRead("Content-Length: 100\r\n\r\n"),
5708 MockRead(SYNCHRONOUS
, OK
),
5711 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5712 data_writes1
, arraysize(data_writes1
));
5713 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5714 data_writes2
, arraysize(data_writes2
));
5715 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5716 data_writes3
, arraysize(data_writes3
));
5717 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5718 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5719 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5721 TestCompletionCallback callback1
;
5723 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5724 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5726 rv
= callback1
.WaitForResult();
5729 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5730 TestCompletionCallback callback2
;
5731 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5733 rv
= callback2
.WaitForResult();
5735 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5737 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5738 ASSERT_TRUE(response
!= NULL
);
5739 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5741 TestCompletionCallback callback3
;
5743 rv
= trans
->RestartWithAuth(
5744 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5745 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5747 rv
= callback3
.WaitForResult();
5750 response
= trans
->GetResponseInfo();
5751 ASSERT_TRUE(response
!= NULL
);
5752 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5753 EXPECT_EQ(100, response
->headers
->GetContentLength());
5757 // Tests that nonce count increments when multiple auth attempts
5758 // are started with the same nonce.
5759 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5760 HttpAuthHandlerDigest::Factory
* digest_factory
=
5761 new HttpAuthHandlerDigest::Factory();
5762 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5763 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5764 digest_factory
->set_nonce_generator(nonce_generator
);
5765 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5766 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5768 // Transaction 1: authenticate (foo, bar) on MyRealm1
5770 HttpRequestInfo request
;
5771 request
.method
= "GET";
5772 request
.url
= GURL("http://www.google.com/x/y/z");
5773 request
.load_flags
= 0;
5775 scoped_ptr
<HttpTransaction
> trans(
5776 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5778 MockWrite data_writes1
[] = {
5779 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5780 "Host: www.google.com\r\n"
5781 "Connection: keep-alive\r\n\r\n"),
5784 MockRead data_reads1
[] = {
5785 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5786 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5787 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5788 MockRead(SYNCHRONOUS
, OK
),
5791 // Resend with authorization (username=foo, password=bar)
5792 MockWrite data_writes2
[] = {
5793 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5794 "Host: www.google.com\r\n"
5795 "Connection: keep-alive\r\n"
5796 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5797 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5798 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5799 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5802 // Sever accepts the authorization.
5803 MockRead data_reads2
[] = {
5804 MockRead("HTTP/1.0 200 OK\r\n"),
5805 MockRead(SYNCHRONOUS
, OK
),
5808 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5809 data_writes1
, arraysize(data_writes1
));
5810 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5811 data_writes2
, arraysize(data_writes2
));
5812 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5813 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5815 TestCompletionCallback callback1
;
5817 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5820 rv
= callback1
.WaitForResult();
5823 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5824 ASSERT_TRUE(response
!= NULL
);
5825 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5827 TestCompletionCallback callback2
;
5829 rv
= trans
->RestartWithAuth(
5830 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5831 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5833 rv
= callback2
.WaitForResult();
5836 response
= trans
->GetResponseInfo();
5837 ASSERT_TRUE(response
!= NULL
);
5838 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5841 // ------------------------------------------------------------------------
5843 // Transaction 2: Request another resource in digestive's protection space.
5844 // This will preemptively add an Authorization header which should have an
5845 // "nc" value of 2 (as compared to 1 in the first use.
5847 HttpRequestInfo request
;
5848 request
.method
= "GET";
5849 // Note that Transaction 1 was at /x/y/z, so this is in the same
5850 // protection space as digest.
5851 request
.url
= GURL("http://www.google.com/x/y/a/b");
5852 request
.load_flags
= 0;
5854 scoped_ptr
<HttpTransaction
> trans(
5855 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5857 MockWrite data_writes1
[] = {
5858 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5859 "Host: www.google.com\r\n"
5860 "Connection: keep-alive\r\n"
5861 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5862 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5863 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5864 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5867 // Sever accepts the authorization.
5868 MockRead data_reads1
[] = {
5869 MockRead("HTTP/1.0 200 OK\r\n"),
5870 MockRead("Content-Length: 100\r\n\r\n"),
5871 MockRead(SYNCHRONOUS
, OK
),
5874 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5875 data_writes1
, arraysize(data_writes1
));
5876 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5878 TestCompletionCallback callback1
;
5880 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5883 rv
= callback1
.WaitForResult();
5886 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5887 ASSERT_TRUE(response
!= NULL
);
5888 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5892 // Test the ResetStateForRestart() private method.
5893 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5894 // Create a transaction (the dependencies aren't important).
5895 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5896 scoped_ptr
<HttpNetworkTransaction
> trans(
5897 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5899 // Setup some state (which we expect ResetStateForRestart() will clear).
5900 trans
->read_buf_
= new IOBuffer(15);
5901 trans
->read_buf_len_
= 15;
5902 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5904 // Setup state in response_
5905 HttpResponseInfo
* response
= &trans
->response_
;
5906 response
->auth_challenge
= new AuthChallengeInfo();
5907 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5908 response
->response_time
= base::Time::Now();
5909 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5911 { // Setup state for response_.vary_data
5912 HttpRequestInfo request
;
5913 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5914 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5915 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5916 request
.extra_headers
.SetHeader("Foo", "1");
5917 request
.extra_headers
.SetHeader("bar", "23");
5918 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5921 // Cause the above state to be reset.
5922 trans
->ResetStateForRestart();
5924 // Verify that the state that needed to be reset, has been reset.
5925 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5926 EXPECT_EQ(0, trans
->read_buf_len_
);
5927 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5928 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5929 EXPECT_TRUE(response
->headers
.get() == NULL
);
5930 EXPECT_FALSE(response
->was_cached
);
5931 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5932 EXPECT_FALSE(response
->vary_data
.is_valid());
5935 // Test HTTPS connections to a site with a bad certificate
5936 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5937 HttpRequestInfo request
;
5938 request
.method
= "GET";
5939 request
.url
= GURL("https://www.google.com/");
5940 request
.load_flags
= 0;
5942 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5943 scoped_ptr
<HttpTransaction
> trans(
5944 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5946 MockWrite data_writes
[] = {
5947 MockWrite("GET / HTTP/1.1\r\n"
5948 "Host: www.google.com\r\n"
5949 "Connection: keep-alive\r\n\r\n"),
5952 MockRead data_reads
[] = {
5953 MockRead("HTTP/1.0 200 OK\r\n"),
5954 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5955 MockRead("Content-Length: 100\r\n\r\n"),
5956 MockRead(SYNCHRONOUS
, OK
),
5959 StaticSocketDataProvider ssl_bad_certificate
;
5960 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5961 data_writes
, arraysize(data_writes
));
5962 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5963 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5965 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5966 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5967 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5968 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5970 TestCompletionCallback callback
;
5972 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5973 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5975 rv
= callback
.WaitForResult();
5976 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5978 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5981 rv
= callback
.WaitForResult();
5984 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5986 ASSERT_TRUE(response
!= NULL
);
5987 EXPECT_EQ(100, response
->headers
->GetContentLength());
5990 // Test HTTPS connections to a site with a bad certificate, going through a
5992 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5993 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5995 HttpRequestInfo request
;
5996 request
.method
= "GET";
5997 request
.url
= GURL("https://www.google.com/");
5998 request
.load_flags
= 0;
6000 MockWrite proxy_writes
[] = {
6001 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6002 "Host: www.google.com\r\n"
6003 "Proxy-Connection: keep-alive\r\n\r\n"),
6006 MockRead proxy_reads
[] = {
6007 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6008 MockRead(SYNCHRONOUS
, OK
)
6011 MockWrite data_writes
[] = {
6012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6013 "Host: www.google.com\r\n"
6014 "Proxy-Connection: keep-alive\r\n\r\n"),
6015 MockWrite("GET / HTTP/1.1\r\n"
6016 "Host: www.google.com\r\n"
6017 "Connection: keep-alive\r\n\r\n"),
6020 MockRead data_reads
[] = {
6021 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6022 MockRead("HTTP/1.0 200 OK\r\n"),
6023 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6024 MockRead("Content-Length: 100\r\n\r\n"),
6025 MockRead(SYNCHRONOUS
, OK
),
6028 StaticSocketDataProvider
ssl_bad_certificate(
6029 proxy_reads
, arraysize(proxy_reads
),
6030 proxy_writes
, arraysize(proxy_writes
));
6031 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6032 data_writes
, arraysize(data_writes
));
6033 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6034 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6036 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6037 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6038 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6039 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6041 TestCompletionCallback callback
;
6043 for (int i
= 0; i
< 2; i
++) {
6044 session_deps_
.socket_factory
->ResetNextMockIndexes();
6046 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6047 scoped_ptr
<HttpTransaction
> trans(
6048 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6050 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6051 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6053 rv
= callback
.WaitForResult();
6054 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6056 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6057 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6059 rv
= callback
.WaitForResult();
6062 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6064 ASSERT_TRUE(response
!= NULL
);
6065 EXPECT_EQ(100, response
->headers
->GetContentLength());
6070 // Test HTTPS connections to a site, going through an HTTPS proxy
6071 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6072 session_deps_
.proxy_service
.reset(
6073 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6074 CapturingNetLog net_log
;
6075 session_deps_
.net_log
= &net_log
;
6077 HttpRequestInfo request
;
6078 request
.method
= "GET";
6079 request
.url
= GURL("https://www.google.com/");
6080 request
.load_flags
= 0;
6082 MockWrite data_writes
[] = {
6083 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6084 "Host: www.google.com\r\n"
6085 "Proxy-Connection: keep-alive\r\n\r\n"),
6086 MockWrite("GET / HTTP/1.1\r\n"
6087 "Host: www.google.com\r\n"
6088 "Connection: keep-alive\r\n\r\n"),
6091 MockRead data_reads
[] = {
6092 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6093 MockRead("HTTP/1.1 200 OK\r\n"),
6094 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6095 MockRead("Content-Length: 100\r\n\r\n"),
6096 MockRead(SYNCHRONOUS
, OK
),
6099 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6100 data_writes
, arraysize(data_writes
));
6101 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6102 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6104 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6105 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6106 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6108 TestCompletionCallback callback
;
6110 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6111 scoped_ptr
<HttpTransaction
> trans(
6112 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6114 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6115 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6117 rv
= callback
.WaitForResult();
6119 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6121 ASSERT_TRUE(response
!= NULL
);
6123 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6124 EXPECT_EQ(200, response
->headers
->response_code());
6125 EXPECT_EQ(100, response
->headers
->GetContentLength());
6126 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6128 LoadTimingInfo load_timing_info
;
6129 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6130 TestLoadTimingNotReusedWithPac(load_timing_info
,
6131 CONNECT_TIMING_HAS_SSL_TIMES
);
6134 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6135 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6136 session_deps_
.proxy_service
.reset(
6137 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6138 CapturingNetLog net_log
;
6139 session_deps_
.net_log
= &net_log
;
6141 HttpRequestInfo request
;
6142 request
.method
= "GET";
6143 request
.url
= GURL("https://www.google.com/");
6144 request
.load_flags
= 0;
6146 MockWrite data_writes
[] = {
6147 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6148 "Host: www.google.com\r\n"
6149 "Proxy-Connection: keep-alive\r\n\r\n"),
6152 MockRead data_reads
[] = {
6153 MockRead("HTTP/1.1 302 Redirect\r\n"),
6154 MockRead("Location: http://login.example.com/\r\n"),
6155 MockRead("Content-Length: 0\r\n\r\n"),
6156 MockRead(SYNCHRONOUS
, OK
),
6159 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6160 data_writes
, arraysize(data_writes
));
6161 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6163 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6164 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6166 TestCompletionCallback callback
;
6168 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6169 scoped_ptr
<HttpTransaction
> trans(
6170 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6172 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6173 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6175 rv
= callback
.WaitForResult();
6177 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6179 ASSERT_TRUE(response
!= NULL
);
6181 EXPECT_EQ(302, response
->headers
->response_code());
6183 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6184 EXPECT_EQ("http://login.example.com/", url
);
6186 // In the case of redirects from proxies, HttpNetworkTransaction returns
6187 // timing for the proxy connection instead of the connection to the host,
6188 // and no send / receive times.
6189 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6190 LoadTimingInfo load_timing_info
;
6191 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6193 EXPECT_FALSE(load_timing_info
.socket_reused
);
6194 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6196 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6197 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6198 load_timing_info
.proxy_resolve_end
);
6199 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6200 load_timing_info
.connect_timing
.connect_start
);
6201 ExpectConnectTimingHasTimes(
6202 load_timing_info
.connect_timing
,
6203 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6205 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6206 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6207 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6210 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6211 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6212 session_deps_
.proxy_service
.reset(
6213 ProxyService::CreateFixed("https://proxy:70"));
6215 HttpRequestInfo request
;
6216 request
.method
= "GET";
6217 request
.url
= GURL("https://www.google.com/");
6218 request
.load_flags
= 0;
6220 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6222 scoped_ptr
<SpdyFrame
> goaway(
6223 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6224 MockWrite data_writes
[] = {
6225 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6226 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6229 static const char* const kExtraHeaders
[] = {
6231 "http://login.example.com/",
6233 scoped_ptr
<SpdyFrame
> resp(
6234 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6235 arraysize(kExtraHeaders
)/2, 1));
6236 MockRead data_reads
[] = {
6237 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6238 MockRead(ASYNC
, 0, 2), // EOF
6241 DelayedSocketData
data(
6242 1, // wait for one write to finish before reading.
6243 data_reads
, arraysize(data_reads
),
6244 data_writes
, arraysize(data_writes
));
6245 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6246 proxy_ssl
.SetNextProto(GetParam());
6248 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6249 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6251 TestCompletionCallback callback
;
6253 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6254 scoped_ptr
<HttpTransaction
> trans(
6255 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6257 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6258 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6260 rv
= callback
.WaitForResult();
6262 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6264 ASSERT_TRUE(response
!= NULL
);
6266 EXPECT_EQ(302, response
->headers
->response_code());
6268 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6269 EXPECT_EQ("http://login.example.com/", url
);
6272 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6273 TEST_P(HttpNetworkTransactionTest
,
6274 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6275 session_deps_
.proxy_service
.reset(
6276 ProxyService::CreateFixed("https://proxy:70"));
6278 HttpRequestInfo request
;
6279 request
.method
= "GET";
6280 request
.url
= GURL("https://www.google.com/");
6281 request
.load_flags
= 0;
6283 MockWrite data_writes
[] = {
6284 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6285 "Host: www.google.com\r\n"
6286 "Proxy-Connection: keep-alive\r\n\r\n"),
6289 MockRead data_reads
[] = {
6290 MockRead("HTTP/1.1 404 Not Found\r\n"),
6291 MockRead("Content-Length: 23\r\n\r\n"),
6292 MockRead("The host does not exist"),
6293 MockRead(SYNCHRONOUS
, OK
),
6296 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6297 data_writes
, arraysize(data_writes
));
6298 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6300 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6301 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6303 TestCompletionCallback callback
;
6305 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6306 scoped_ptr
<HttpTransaction
> trans(
6307 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6309 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6312 rv
= callback
.WaitForResult();
6313 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6315 // TODO(ttuttle): Anything else to check here?
6318 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6319 TEST_P(HttpNetworkTransactionTest
,
6320 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6321 session_deps_
.proxy_service
.reset(
6322 ProxyService::CreateFixed("https://proxy:70"));
6324 HttpRequestInfo request
;
6325 request
.method
= "GET";
6326 request
.url
= GURL("https://www.google.com/");
6327 request
.load_flags
= 0;
6329 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6331 scoped_ptr
<SpdyFrame
> rst(
6332 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6333 MockWrite data_writes
[] = {
6334 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6335 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6338 static const char* const kExtraHeaders
[] = {
6340 "http://login.example.com/",
6342 scoped_ptr
<SpdyFrame
> resp(
6343 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6344 arraysize(kExtraHeaders
)/2, 1));
6345 scoped_ptr
<SpdyFrame
> body(
6346 spdy_util_
.ConstructSpdyBodyFrame(
6347 1, "The host does not exist", 23, true));
6348 MockRead data_reads
[] = {
6349 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6350 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6351 MockRead(ASYNC
, 0, 4), // EOF
6354 DelayedSocketData
data(
6355 1, // wait for one write to finish before reading.
6356 data_reads
, arraysize(data_reads
),
6357 data_writes
, arraysize(data_writes
));
6358 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6359 proxy_ssl
.SetNextProto(GetParam());
6361 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6362 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6364 TestCompletionCallback callback
;
6366 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6367 scoped_ptr
<HttpTransaction
> trans(
6368 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6370 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6371 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6373 rv
= callback
.WaitForResult();
6374 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6376 // TODO(ttuttle): Anything else to check here?
6379 // Test the request-challenge-retry sequence for basic auth, through
6380 // a SPDY proxy over a single SPDY session.
6381 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6382 HttpRequestInfo request
;
6383 request
.method
= "GET";
6384 request
.url
= GURL("https://www.google.com/");
6385 // when the no authentication data flag is set.
6386 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6388 // Configure against https proxy server "myproxy:70".
6389 session_deps_
.proxy_service
.reset(
6390 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6391 CapturingBoundNetLog log
;
6392 session_deps_
.net_log
= log
.bound().net_log();
6393 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6395 // Since we have proxy, should try to establish tunnel.
6396 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6398 scoped_ptr
<SpdyFrame
> rst(
6399 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6401 // After calling trans->RestartWithAuth(), this is the request we should
6402 // be issuing -- the final header line contains the credentials.
6403 const char* const kAuthCredentials
[] = {
6404 "proxy-authorization", "Basic Zm9vOmJhcg==",
6406 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6407 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
));
6408 // fetch https://www.google.com/ via HTTP
6409 const char get
[] = "GET / HTTP/1.1\r\n"
6410 "Host: www.google.com\r\n"
6411 "Connection: keep-alive\r\n\r\n";
6412 scoped_ptr
<SpdyFrame
> wrapped_get(
6413 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6415 MockWrite spdy_writes
[] = {
6416 CreateMockWrite(*req
, 1, ASYNC
),
6417 CreateMockWrite(*rst
, 4, ASYNC
),
6418 CreateMockWrite(*connect2
, 5),
6419 CreateMockWrite(*wrapped_get
, 8),
6422 // The proxy responds to the connect with a 407, using a persistent
6424 const char* const kAuthStatus
= "407";
6425 const char* const kAuthChallenge
[] = {
6426 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6428 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6429 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6431 scoped_ptr
<SpdyFrame
> conn_resp(
6432 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6433 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6434 "Content-Length: 5\r\n\r\n";
6436 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6437 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6438 scoped_ptr
<SpdyFrame
> wrapped_body(
6439 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6440 MockRead spdy_reads
[] = {
6441 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6442 CreateMockRead(*conn_resp
, 6, ASYNC
),
6443 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6444 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6445 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6448 OrderedSocketData
spdy_data(
6449 spdy_reads
, arraysize(spdy_reads
),
6450 spdy_writes
, arraysize(spdy_writes
));
6451 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6452 // Negotiate SPDY to the proxy
6453 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6454 proxy
.SetNextProto(GetParam());
6455 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6456 // Vanilla SSL to the server
6457 SSLSocketDataProvider
server(ASYNC
, OK
);
6458 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6460 TestCompletionCallback callback1
;
6462 scoped_ptr
<HttpTransaction
> trans(
6463 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6465 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6466 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6468 rv
= callback1
.WaitForResult();
6470 net::CapturingNetLog::CapturedEntryList entries
;
6471 log
.GetEntries(&entries
);
6472 size_t pos
= ExpectLogContainsSomewhere(
6473 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6474 NetLog::PHASE_NONE
);
6475 ExpectLogContainsSomewhere(
6477 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6478 NetLog::PHASE_NONE
);
6480 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6481 ASSERT_TRUE(response
!= NULL
);
6482 ASSERT_FALSE(response
->headers
.get() == NULL
);
6483 EXPECT_EQ(407, response
->headers
->response_code());
6484 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6485 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6486 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6488 TestCompletionCallback callback2
;
6490 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6491 callback2
.callback());
6492 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6494 rv
= callback2
.WaitForResult();
6497 response
= trans
->GetResponseInfo();
6498 ASSERT_TRUE(response
!= NULL
);
6500 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6501 EXPECT_EQ(200, response
->headers
->response_code());
6502 EXPECT_EQ(5, response
->headers
->GetContentLength());
6503 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6505 // The password prompt info should not be set.
6506 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6508 LoadTimingInfo load_timing_info
;
6509 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6510 TestLoadTimingNotReusedWithPac(load_timing_info
,
6511 CONNECT_TIMING_HAS_SSL_TIMES
);
6514 session
->CloseAllConnections();
6517 // Test that an explicitly trusted SPDY proxy can push a resource from an
6518 // origin that is different from that of its associated resource.
6519 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6520 HttpRequestInfo request
;
6521 HttpRequestInfo push_request
;
6523 request
.method
= "GET";
6524 request
.url
= GURL("http://www.google.com/");
6525 push_request
.method
= "GET";
6526 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6528 // Configure against https proxy server "myproxy:70".
6529 session_deps_
.proxy_service
.reset(
6530 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6531 CapturingBoundNetLog log
;
6532 session_deps_
.net_log
= log
.bound().net_log();
6534 // Enable cross-origin push.
6535 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6537 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6539 scoped_ptr
<SpdyFrame
> stream1_syn(
6540 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6542 MockWrite spdy_writes
[] = {
6543 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6546 scoped_ptr
<SpdyFrame
>
6547 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6549 scoped_ptr
<SpdyFrame
>
6550 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6552 scoped_ptr
<SpdyFrame
>
6553 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6557 "http://www.another-origin.com/foo.dat"));
6558 const char kPushedData
[] = "pushed";
6559 scoped_ptr
<SpdyFrame
> stream2_body(
6560 spdy_util_
.ConstructSpdyBodyFrame(
6561 2, kPushedData
, strlen(kPushedData
), true));
6563 MockRead spdy_reads
[] = {
6564 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6565 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6566 CreateMockRead(*stream1_body
, 4, ASYNC
),
6567 CreateMockRead(*stream2_body
, 5, ASYNC
),
6568 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6571 OrderedSocketData
spdy_data(
6572 spdy_reads
, arraysize(spdy_reads
),
6573 spdy_writes
, arraysize(spdy_writes
));
6574 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6575 // Negotiate SPDY to the proxy
6576 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6577 proxy
.SetNextProto(GetParam());
6578 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6580 scoped_ptr
<HttpTransaction
> trans(
6581 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6582 TestCompletionCallback callback
;
6583 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6584 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6586 rv
= callback
.WaitForResult();
6588 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6590 scoped_ptr
<HttpTransaction
> push_trans(
6591 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6592 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6593 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6595 rv
= callback
.WaitForResult();
6597 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6599 ASSERT_TRUE(response
!= NULL
);
6600 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6602 EXPECT_EQ(200, response
->headers
->response_code());
6603 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6605 std::string response_data
;
6606 rv
= ReadTransaction(trans
.get(), &response_data
);
6608 EXPECT_EQ("hello!", response_data
);
6610 LoadTimingInfo load_timing_info
;
6611 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6612 TestLoadTimingNotReusedWithPac(load_timing_info
,
6613 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6615 // Verify the pushed stream.
6616 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6617 EXPECT_EQ(200, push_response
->headers
->response_code());
6619 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6621 EXPECT_EQ("pushed", response_data
);
6623 LoadTimingInfo push_load_timing_info
;
6624 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6625 TestLoadTimingReusedWithPac(push_load_timing_info
);
6626 // The transactions should share a socket ID, despite being for different
6628 EXPECT_EQ(load_timing_info
.socket_log_id
,
6629 push_load_timing_info
.socket_log_id
);
6633 session
->CloseAllConnections();
6636 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6637 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6638 HttpRequestInfo request
;
6640 request
.method
= "GET";
6641 request
.url
= GURL("http://www.google.com/");
6643 // Configure against https proxy server "myproxy:70".
6644 session_deps_
.proxy_service
.reset(
6645 ProxyService::CreateFixed("https://myproxy:70"));
6646 CapturingBoundNetLog log
;
6647 session_deps_
.net_log
= log
.bound().net_log();
6649 // Enable cross-origin push.
6650 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6652 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6654 scoped_ptr
<SpdyFrame
> stream1_syn(
6655 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6657 scoped_ptr
<SpdyFrame
> push_rst(
6658 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6660 MockWrite spdy_writes
[] = {
6661 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6662 CreateMockWrite(*push_rst
, 4),
6665 scoped_ptr
<SpdyFrame
>
6666 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6668 scoped_ptr
<SpdyFrame
>
6669 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6671 scoped_ptr
<SpdyFrame
>
6672 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6676 "https://www.another-origin.com/foo.dat"));
6678 MockRead spdy_reads
[] = {
6679 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6680 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6681 CreateMockRead(*stream1_body
, 5, ASYNC
),
6682 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6685 OrderedSocketData
spdy_data(
6686 spdy_reads
, arraysize(spdy_reads
),
6687 spdy_writes
, arraysize(spdy_writes
));
6688 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6689 // Negotiate SPDY to the proxy
6690 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6691 proxy
.SetNextProto(GetParam());
6692 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6694 scoped_ptr
<HttpTransaction
> trans(
6695 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6696 TestCompletionCallback callback
;
6697 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6698 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6700 rv
= callback
.WaitForResult();
6702 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6704 ASSERT_TRUE(response
!= NULL
);
6705 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6707 EXPECT_EQ(200, response
->headers
->response_code());
6708 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6710 std::string response_data
;
6711 rv
= ReadTransaction(trans
.get(), &response_data
);
6713 EXPECT_EQ("hello!", response_data
);
6716 session
->CloseAllConnections();
6719 // Test HTTPS connections to a site with a bad certificate, going through an
6721 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6722 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6723 "https://proxy:70"));
6725 HttpRequestInfo request
;
6726 request
.method
= "GET";
6727 request
.url
= GURL("https://www.google.com/");
6728 request
.load_flags
= 0;
6730 // Attempt to fetch the URL from a server with a bad cert
6731 MockWrite bad_cert_writes
[] = {
6732 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6733 "Host: www.google.com\r\n"
6734 "Proxy-Connection: keep-alive\r\n\r\n"),
6737 MockRead bad_cert_reads
[] = {
6738 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6739 MockRead(SYNCHRONOUS
, OK
)
6742 // Attempt to fetch the URL with a good cert
6743 MockWrite good_data_writes
[] = {
6744 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6745 "Host: www.google.com\r\n"
6746 "Proxy-Connection: keep-alive\r\n\r\n"),
6747 MockWrite("GET / HTTP/1.1\r\n"
6748 "Host: www.google.com\r\n"
6749 "Connection: keep-alive\r\n\r\n"),
6752 MockRead good_cert_reads
[] = {
6753 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6754 MockRead("HTTP/1.0 200 OK\r\n"),
6755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6756 MockRead("Content-Length: 100\r\n\r\n"),
6757 MockRead(SYNCHRONOUS
, OK
),
6760 StaticSocketDataProvider
ssl_bad_certificate(
6761 bad_cert_reads
, arraysize(bad_cert_reads
),
6762 bad_cert_writes
, arraysize(bad_cert_writes
));
6763 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6764 good_data_writes
, arraysize(good_data_writes
));
6765 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6766 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6768 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6769 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6770 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6771 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6773 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6774 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6775 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6776 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6778 TestCompletionCallback callback
;
6780 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6781 scoped_ptr
<HttpTransaction
> trans(
6782 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6784 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6785 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6787 rv
= callback
.WaitForResult();
6788 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6790 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6791 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6793 rv
= callback
.WaitForResult();
6796 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6798 ASSERT_TRUE(response
!= NULL
);
6799 EXPECT_EQ(100, response
->headers
->GetContentLength());
6802 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6803 HttpRequestInfo request
;
6804 request
.method
= "GET";
6805 request
.url
= GURL("http://www.google.com/");
6806 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6807 "Chromium Ultra Awesome X Edition");
6809 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6810 scoped_ptr
<HttpTransaction
> trans(
6811 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6813 MockWrite data_writes
[] = {
6814 MockWrite("GET / HTTP/1.1\r\n"
6815 "Host: www.google.com\r\n"
6816 "Connection: keep-alive\r\n"
6817 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6820 // Lastly, the server responds with the actual content.
6821 MockRead data_reads
[] = {
6822 MockRead("HTTP/1.0 200 OK\r\n"),
6823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6824 MockRead("Content-Length: 100\r\n\r\n"),
6825 MockRead(SYNCHRONOUS
, OK
),
6828 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6829 data_writes
, arraysize(data_writes
));
6830 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6832 TestCompletionCallback callback
;
6834 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6835 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6837 rv
= callback
.WaitForResult();
6841 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6842 HttpRequestInfo request
;
6843 request
.method
= "GET";
6844 request
.url
= GURL("https://www.google.com/");
6845 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6846 "Chromium Ultra Awesome X Edition");
6848 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6849 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6850 scoped_ptr
<HttpTransaction
> trans(
6851 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6853 MockWrite data_writes
[] = {
6854 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6855 "Host: www.google.com\r\n"
6856 "Proxy-Connection: keep-alive\r\n"
6857 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6859 MockRead data_reads
[] = {
6860 // Return an error, so the transaction stops here (this test isn't
6861 // interested in the rest).
6862 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6863 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6864 MockRead("Proxy-Connection: close\r\n\r\n"),
6867 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6868 data_writes
, arraysize(data_writes
));
6869 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6871 TestCompletionCallback callback
;
6873 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6874 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6876 rv
= callback
.WaitForResult();
6880 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6881 HttpRequestInfo request
;
6882 request
.method
= "GET";
6883 request
.url
= GURL("http://www.google.com/");
6884 request
.load_flags
= 0;
6885 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6886 "http://the.previous.site.com/");
6888 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6889 scoped_ptr
<HttpTransaction
> trans(
6890 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6892 MockWrite data_writes
[] = {
6893 MockWrite("GET / HTTP/1.1\r\n"
6894 "Host: www.google.com\r\n"
6895 "Connection: keep-alive\r\n"
6896 "Referer: http://the.previous.site.com/\r\n\r\n"),
6899 // Lastly, the server responds with the actual content.
6900 MockRead data_reads
[] = {
6901 MockRead("HTTP/1.0 200 OK\r\n"),
6902 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6903 MockRead("Content-Length: 100\r\n\r\n"),
6904 MockRead(SYNCHRONOUS
, OK
),
6907 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6908 data_writes
, arraysize(data_writes
));
6909 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6911 TestCompletionCallback callback
;
6913 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6914 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6916 rv
= callback
.WaitForResult();
6920 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6921 HttpRequestInfo request
;
6922 request
.method
= "POST";
6923 request
.url
= GURL("http://www.google.com/");
6925 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6926 scoped_ptr
<HttpTransaction
> trans(
6927 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6929 MockWrite data_writes
[] = {
6930 MockWrite("POST / HTTP/1.1\r\n"
6931 "Host: www.google.com\r\n"
6932 "Connection: keep-alive\r\n"
6933 "Content-Length: 0\r\n\r\n"),
6936 // Lastly, the server responds with the actual content.
6937 MockRead data_reads
[] = {
6938 MockRead("HTTP/1.0 200 OK\r\n"),
6939 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6940 MockRead("Content-Length: 100\r\n\r\n"),
6941 MockRead(SYNCHRONOUS
, OK
),
6944 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6945 data_writes
, arraysize(data_writes
));
6946 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6948 TestCompletionCallback callback
;
6950 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6951 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6953 rv
= callback
.WaitForResult();
6957 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6958 HttpRequestInfo request
;
6959 request
.method
= "PUT";
6960 request
.url
= GURL("http://www.google.com/");
6962 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6963 scoped_ptr
<HttpTransaction
> trans(
6964 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6966 MockWrite data_writes
[] = {
6967 MockWrite("PUT / HTTP/1.1\r\n"
6968 "Host: www.google.com\r\n"
6969 "Connection: keep-alive\r\n"
6970 "Content-Length: 0\r\n\r\n"),
6973 // Lastly, the server responds with the actual content.
6974 MockRead data_reads
[] = {
6975 MockRead("HTTP/1.0 200 OK\r\n"),
6976 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6977 MockRead("Content-Length: 100\r\n\r\n"),
6978 MockRead(SYNCHRONOUS
, OK
),
6981 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6982 data_writes
, arraysize(data_writes
));
6983 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6985 TestCompletionCallback callback
;
6987 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6988 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6990 rv
= callback
.WaitForResult();
6994 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6995 HttpRequestInfo request
;
6996 request
.method
= "HEAD";
6997 request
.url
= GURL("http://www.google.com/");
6999 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7000 scoped_ptr
<HttpTransaction
> trans(
7001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7003 MockWrite data_writes
[] = {
7004 MockWrite("HEAD / HTTP/1.1\r\n"
7005 "Host: www.google.com\r\n"
7006 "Connection: keep-alive\r\n"
7007 "Content-Length: 0\r\n\r\n"),
7010 // Lastly, the server responds with the actual content.
7011 MockRead data_reads
[] = {
7012 MockRead("HTTP/1.0 200 OK\r\n"),
7013 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7014 MockRead("Content-Length: 100\r\n\r\n"),
7015 MockRead(SYNCHRONOUS
, OK
),
7018 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7019 data_writes
, arraysize(data_writes
));
7020 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7022 TestCompletionCallback callback
;
7024 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7025 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7027 rv
= callback
.WaitForResult();
7031 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7032 HttpRequestInfo request
;
7033 request
.method
= "GET";
7034 request
.url
= GURL("http://www.google.com/");
7035 request
.load_flags
= LOAD_BYPASS_CACHE
;
7037 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7038 scoped_ptr
<HttpTransaction
> trans(
7039 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7041 MockWrite data_writes
[] = {
7042 MockWrite("GET / HTTP/1.1\r\n"
7043 "Host: www.google.com\r\n"
7044 "Connection: keep-alive\r\n"
7045 "Pragma: no-cache\r\n"
7046 "Cache-Control: no-cache\r\n\r\n"),
7049 // Lastly, the server responds with the actual content.
7050 MockRead data_reads
[] = {
7051 MockRead("HTTP/1.0 200 OK\r\n"),
7052 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7053 MockRead("Content-Length: 100\r\n\r\n"),
7054 MockRead(SYNCHRONOUS
, OK
),
7057 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7058 data_writes
, arraysize(data_writes
));
7059 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7061 TestCompletionCallback callback
;
7063 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7064 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7066 rv
= callback
.WaitForResult();
7070 TEST_P(HttpNetworkTransactionTest
,
7071 BuildRequest_CacheControlValidateCache
) {
7072 HttpRequestInfo request
;
7073 request
.method
= "GET";
7074 request
.url
= GURL("http://www.google.com/");
7075 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7077 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7078 scoped_ptr
<HttpTransaction
> trans(
7079 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7081 MockWrite data_writes
[] = {
7082 MockWrite("GET / HTTP/1.1\r\n"
7083 "Host: www.google.com\r\n"
7084 "Connection: keep-alive\r\n"
7085 "Cache-Control: max-age=0\r\n\r\n"),
7088 // Lastly, the server responds with the actual content.
7089 MockRead data_reads
[] = {
7090 MockRead("HTTP/1.0 200 OK\r\n"),
7091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7092 MockRead("Content-Length: 100\r\n\r\n"),
7093 MockRead(SYNCHRONOUS
, OK
),
7096 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7097 data_writes
, arraysize(data_writes
));
7098 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7100 TestCompletionCallback callback
;
7102 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7103 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7105 rv
= callback
.WaitForResult();
7109 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7110 HttpRequestInfo request
;
7111 request
.method
= "GET";
7112 request
.url
= GURL("http://www.google.com/");
7113 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7115 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7116 scoped_ptr
<HttpTransaction
> trans(
7117 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7119 MockWrite data_writes
[] = {
7120 MockWrite("GET / HTTP/1.1\r\n"
7121 "Host: www.google.com\r\n"
7122 "Connection: keep-alive\r\n"
7123 "FooHeader: Bar\r\n\r\n"),
7126 // Lastly, the server responds with the actual content.
7127 MockRead data_reads
[] = {
7128 MockRead("HTTP/1.0 200 OK\r\n"),
7129 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7130 MockRead("Content-Length: 100\r\n\r\n"),
7131 MockRead(SYNCHRONOUS
, OK
),
7134 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7135 data_writes
, arraysize(data_writes
));
7136 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7138 TestCompletionCallback callback
;
7140 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7141 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7143 rv
= callback
.WaitForResult();
7147 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7148 HttpRequestInfo request
;
7149 request
.method
= "GET";
7150 request
.url
= GURL("http://www.google.com/");
7151 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7152 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7153 request
.extra_headers
.SetHeader("FoO", "bar");
7155 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7156 scoped_ptr
<HttpTransaction
> trans(
7157 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7159 MockWrite data_writes
[] = {
7160 MockWrite("GET / HTTP/1.1\r\n"
7161 "Host: www.google.com\r\n"
7162 "Connection: keep-alive\r\n"
7163 "referer: www.foo.com\r\n"
7165 "FoO: bar\r\n\r\n"),
7168 // Lastly, the server responds with the actual content.
7169 MockRead data_reads
[] = {
7170 MockRead("HTTP/1.0 200 OK\r\n"),
7171 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7172 MockRead("Content-Length: 100\r\n\r\n"),
7173 MockRead(SYNCHRONOUS
, OK
),
7176 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7177 data_writes
, arraysize(data_writes
));
7178 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7180 TestCompletionCallback callback
;
7182 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7185 rv
= callback
.WaitForResult();
7189 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7190 HttpRequestInfo request
;
7191 request
.method
= "GET";
7192 request
.url
= GURL("http://www.google.com/");
7193 request
.load_flags
= 0;
7195 session_deps_
.proxy_service
.reset(
7196 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7197 CapturingNetLog net_log
;
7198 session_deps_
.net_log
= &net_log
;
7200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7201 scoped_ptr
<HttpTransaction
> trans(
7202 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7204 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7205 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7207 MockWrite data_writes
[] = {
7208 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7209 MockWrite("GET / HTTP/1.1\r\n"
7210 "Host: www.google.com\r\n"
7211 "Connection: keep-alive\r\n\r\n")
7214 MockRead data_reads
[] = {
7215 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7216 MockRead("HTTP/1.0 200 OK\r\n"),
7217 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7218 MockRead("Payload"),
7219 MockRead(SYNCHRONOUS
, OK
)
7222 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7223 data_writes
, arraysize(data_writes
));
7224 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7226 TestCompletionCallback callback
;
7228 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7229 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7231 rv
= callback
.WaitForResult();
7234 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7235 ASSERT_TRUE(response
!= NULL
);
7237 LoadTimingInfo load_timing_info
;
7238 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7239 TestLoadTimingNotReusedWithPac(load_timing_info
,
7240 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7242 std::string response_text
;
7243 rv
= ReadTransaction(trans
.get(), &response_text
);
7245 EXPECT_EQ("Payload", response_text
);
7248 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7249 HttpRequestInfo request
;
7250 request
.method
= "GET";
7251 request
.url
= GURL("https://www.google.com/");
7252 request
.load_flags
= 0;
7254 session_deps_
.proxy_service
.reset(
7255 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7256 CapturingNetLog net_log
;
7257 session_deps_
.net_log
= &net_log
;
7259 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7260 scoped_ptr
<HttpTransaction
> trans(
7261 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7263 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7264 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7266 MockWrite data_writes
[] = {
7267 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7268 arraysize(write_buffer
)),
7269 MockWrite("GET / HTTP/1.1\r\n"
7270 "Host: www.google.com\r\n"
7271 "Connection: keep-alive\r\n\r\n")
7274 MockRead data_reads
[] = {
7275 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7276 arraysize(read_buffer
)),
7277 MockRead("HTTP/1.0 200 OK\r\n"),
7278 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7279 MockRead("Payload"),
7280 MockRead(SYNCHRONOUS
, OK
)
7283 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7284 data_writes
, arraysize(data_writes
));
7285 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7287 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7288 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7290 TestCompletionCallback callback
;
7292 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7295 rv
= callback
.WaitForResult();
7298 LoadTimingInfo load_timing_info
;
7299 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7300 TestLoadTimingNotReusedWithPac(load_timing_info
,
7301 CONNECT_TIMING_HAS_SSL_TIMES
);
7303 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7304 ASSERT_TRUE(response
!= NULL
);
7306 std::string response_text
;
7307 rv
= ReadTransaction(trans
.get(), &response_text
);
7309 EXPECT_EQ("Payload", response_text
);
7312 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7313 HttpRequestInfo request
;
7314 request
.method
= "GET";
7315 request
.url
= GURL("http://www.google.com/");
7316 request
.load_flags
= 0;
7318 session_deps_
.proxy_service
.reset(
7319 ProxyService::CreateFixed("socks4://myproxy:1080"));
7320 CapturingNetLog net_log
;
7321 session_deps_
.net_log
= &net_log
;
7323 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7324 scoped_ptr
<HttpTransaction
> trans(
7325 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7327 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7328 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7330 MockWrite data_writes
[] = {
7331 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7332 MockWrite("GET / HTTP/1.1\r\n"
7333 "Host: www.google.com\r\n"
7334 "Connection: keep-alive\r\n\r\n")
7337 MockRead data_reads
[] = {
7338 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7339 MockRead("HTTP/1.0 200 OK\r\n"),
7340 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7341 MockRead("Payload"),
7342 MockRead(SYNCHRONOUS
, OK
)
7345 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7346 data_writes
, arraysize(data_writes
));
7347 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7349 TestCompletionCallback callback
;
7351 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7352 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7354 rv
= callback
.WaitForResult();
7357 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7358 ASSERT_TRUE(response
!= NULL
);
7360 LoadTimingInfo load_timing_info
;
7361 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7362 TestLoadTimingNotReused(load_timing_info
,
7363 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7365 std::string response_text
;
7366 rv
= ReadTransaction(trans
.get(), &response_text
);
7368 EXPECT_EQ("Payload", response_text
);
7371 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7372 HttpRequestInfo request
;
7373 request
.method
= "GET";
7374 request
.url
= GURL("http://www.google.com/");
7375 request
.load_flags
= 0;
7377 session_deps_
.proxy_service
.reset(
7378 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7379 CapturingNetLog net_log
;
7380 session_deps_
.net_log
= &net_log
;
7382 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7383 scoped_ptr
<HttpTransaction
> trans(
7384 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7386 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7387 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7388 const char kSOCKS5OkRequest
[] = {
7390 0x01, // Command (CONNECT)
7392 0x03, // Address type (DOMAINNAME).
7393 0x0E, // Length of domain (14)
7395 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7396 0x00, 0x50, // 16-bit port (80)
7398 const char kSOCKS5OkResponse
[] =
7399 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7401 MockWrite data_writes
[] = {
7402 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7403 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7404 MockWrite("GET / HTTP/1.1\r\n"
7405 "Host: www.google.com\r\n"
7406 "Connection: keep-alive\r\n\r\n")
7409 MockRead data_reads
[] = {
7410 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7411 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7412 MockRead("HTTP/1.0 200 OK\r\n"),
7413 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7414 MockRead("Payload"),
7415 MockRead(SYNCHRONOUS
, OK
)
7418 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7419 data_writes
, arraysize(data_writes
));
7420 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7422 TestCompletionCallback callback
;
7424 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7425 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7427 rv
= callback
.WaitForResult();
7430 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7431 ASSERT_TRUE(response
!= NULL
);
7433 LoadTimingInfo load_timing_info
;
7434 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7435 TestLoadTimingNotReusedWithPac(load_timing_info
,
7436 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7438 std::string response_text
;
7439 rv
= ReadTransaction(trans
.get(), &response_text
);
7441 EXPECT_EQ("Payload", response_text
);
7444 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7445 HttpRequestInfo request
;
7446 request
.method
= "GET";
7447 request
.url
= GURL("https://www.google.com/");
7448 request
.load_flags
= 0;
7450 session_deps_
.proxy_service
.reset(
7451 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7452 CapturingNetLog net_log
;
7453 session_deps_
.net_log
= &net_log
;
7455 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7456 scoped_ptr
<HttpTransaction
> trans(
7457 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7459 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7460 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7461 const unsigned char kSOCKS5OkRequest
[] = {
7463 0x01, // Command (CONNECT)
7465 0x03, // Address type (DOMAINNAME).
7466 0x0E, // Length of domain (14)
7468 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7469 0x01, 0xBB, // 16-bit port (443)
7472 const char kSOCKS5OkResponse
[] =
7473 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7475 MockWrite data_writes
[] = {
7476 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7477 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7478 arraysize(kSOCKS5OkRequest
)),
7479 MockWrite("GET / HTTP/1.1\r\n"
7480 "Host: www.google.com\r\n"
7481 "Connection: keep-alive\r\n\r\n")
7484 MockRead data_reads
[] = {
7485 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7486 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7487 MockRead("HTTP/1.0 200 OK\r\n"),
7488 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7489 MockRead("Payload"),
7490 MockRead(SYNCHRONOUS
, OK
)
7493 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7494 data_writes
, arraysize(data_writes
));
7495 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7497 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7498 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7500 TestCompletionCallback callback
;
7502 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7505 rv
= callback
.WaitForResult();
7508 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7509 ASSERT_TRUE(response
!= NULL
);
7511 LoadTimingInfo load_timing_info
;
7512 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7513 TestLoadTimingNotReusedWithPac(load_timing_info
,
7514 CONNECT_TIMING_HAS_SSL_TIMES
);
7516 std::string response_text
;
7517 rv
= ReadTransaction(trans
.get(), &response_text
);
7519 EXPECT_EQ("Payload", response_text
);
7524 // Tests that for connection endpoints the group names are correctly set.
7526 struct GroupNameTest
{
7527 std::string proxy_server
;
7529 std::string expected_group_name
;
7533 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7534 NextProto next_proto
,
7535 SpdySessionDependencies
* session_deps_
) {
7536 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7538 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7539 session
->http_server_properties();
7540 http_server_properties
->SetAlternateProtocol(
7541 HostPortPair("host.with.alternate", 80), 443,
7542 AlternateProtocolFromNextProto(next_proto
), 1);
7547 int GroupNameTransactionHelper(
7548 const std::string
& url
,
7549 const scoped_refptr
<HttpNetworkSession
>& session
) {
7550 HttpRequestInfo request
;
7551 request
.method
= "GET";
7552 request
.url
= GURL(url
);
7553 request
.load_flags
= 0;
7555 scoped_ptr
<HttpTransaction
> trans(
7556 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7558 TestCompletionCallback callback
;
7560 // We do not complete this request, the dtor will clean the transaction up.
7561 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7566 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7567 const GroupNameTest tests
[] = {
7570 "http://www.google.com/direct",
7571 "www.google.com:80",
7576 "http://[2001:1418:13:1::25]/direct",
7577 "[2001:1418:13:1::25]:80",
7584 "https://www.google.com/direct_ssl",
7585 "ssl/www.google.com:443",
7590 "https://[2001:1418:13:1::25]/direct",
7591 "ssl/[2001:1418:13:1::25]:443",
7596 "http://host.with.alternate/direct",
7597 "ssl/host.with.alternate:443",
7602 session_deps_
.use_alternate_protocols
= true;
7604 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7605 session_deps_
.proxy_service
.reset(
7606 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7607 scoped_refptr
<HttpNetworkSession
> session(
7608 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7610 HttpNetworkSessionPeer
peer(session
);
7611 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7612 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7613 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7614 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7615 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7616 new MockClientSocketPoolManager
);
7617 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7618 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7619 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7621 EXPECT_EQ(ERR_IO_PENDING
,
7622 GroupNameTransactionHelper(tests
[i
].url
, session
));
7624 EXPECT_EQ(tests
[i
].expected_group_name
,
7625 ssl_conn_pool
->last_group_name_received());
7627 EXPECT_EQ(tests
[i
].expected_group_name
,
7628 transport_conn_pool
->last_group_name_received());
7633 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7634 const GroupNameTest tests
[] = {
7637 "http://www.google.com/http_proxy_normal",
7638 "www.google.com:80",
7645 "https://www.google.com/http_connect_ssl",
7646 "ssl/www.google.com:443",
7652 "http://host.with.alternate/direct",
7653 "ssl/host.with.alternate:443",
7659 "ftp://ftp.google.com/http_proxy_normal",
7660 "ftp/ftp.google.com:21",
7665 session_deps_
.use_alternate_protocols
= true;
7667 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7668 session_deps_
.proxy_service
.reset(
7669 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7670 scoped_refptr
<HttpNetworkSession
> session(
7671 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7673 HttpNetworkSessionPeer
peer(session
);
7675 HostPortPair
proxy_host("http_proxy", 80);
7676 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7677 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7678 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7679 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7681 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7682 new MockClientSocketPoolManager
);
7683 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7684 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7685 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7687 EXPECT_EQ(ERR_IO_PENDING
,
7688 GroupNameTransactionHelper(tests
[i
].url
, session
));
7690 EXPECT_EQ(tests
[i
].expected_group_name
,
7691 ssl_conn_pool
->last_group_name_received());
7693 EXPECT_EQ(tests
[i
].expected_group_name
,
7694 http_proxy_pool
->last_group_name_received());
7698 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7699 const GroupNameTest tests
[] = {
7701 "socks4://socks_proxy:1080",
7702 "http://www.google.com/socks4_direct",
7703 "socks4/www.google.com:80",
7707 "socks5://socks_proxy:1080",
7708 "http://www.google.com/socks5_direct",
7709 "socks5/www.google.com:80",
7715 "socks4://socks_proxy:1080",
7716 "https://www.google.com/socks4_ssl",
7717 "socks4/ssl/www.google.com:443",
7721 "socks5://socks_proxy:1080",
7722 "https://www.google.com/socks5_ssl",
7723 "socks5/ssl/www.google.com:443",
7728 "socks4://socks_proxy:1080",
7729 "http://host.with.alternate/direct",
7730 "socks4/ssl/host.with.alternate:443",
7735 session_deps_
.use_alternate_protocols
= true;
7737 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7738 session_deps_
.proxy_service
.reset(
7739 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7740 scoped_refptr
<HttpNetworkSession
> session(
7741 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7743 HttpNetworkSessionPeer
peer(session
);
7745 HostPortPair
proxy_host("socks_proxy", 1080);
7746 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7747 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7748 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7749 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7751 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7752 new MockClientSocketPoolManager
);
7753 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7754 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7755 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
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
.get()));
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
.get()));
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
.get()));
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
.get()));
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
.get()));
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
.get()));
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 ElementsUploadDataStream
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
.get()));
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(base::MakeFileUnreadable(temp_file
));
8153 ScopedVector
<UploadElementReader
> element_readers
;
8154 element_readers
.push_back(
8155 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8160 ElementsUploadDataStream
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
.get()));
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 ~FakeUploadElementReader() override
{}
8196 const CompletionCallback
& callback() const { return callback_
; }
8198 // UploadElementReader overrides:
8199 int Init(const CompletionCallback
& callback
) override
{
8200 callback_
= callback
;
8201 return ERR_IO_PENDING
;
8203 uint64
GetContentLength() const override
{ return 0; }
8204 uint64
BytesRemaining() const override
{ return 0; }
8205 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 ElementsUploadDataStream
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
.get()));
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
.get()));
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_TRUE(alternate
.is_broken
);
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 ~CapturingProxyResolver() override
{}
9102 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 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9116 LoadState
GetLoadState(RequestHandle request
) const override
{
9118 return LOAD_STATE_IDLE
;
9121 void CancelSetPacScript() override
{ NOTREACHED(); }
9123 int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9124 const CompletionCallback
& /*callback*/) override
{
9128 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9131 std::vector
<GURL
> resolved_
;
9133 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9136 TEST_P(HttpNetworkTransactionTest
,
9137 UseAlternateProtocolForTunneledNpnSpdy
) {
9138 session_deps_
.use_alternate_protocols
= true;
9139 session_deps_
.next_protos
= SpdyNextProtos();
9141 ProxyConfig proxy_config
;
9142 proxy_config
.set_auto_detect(true);
9143 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9145 CapturingProxyResolver
* capturing_proxy_resolver
=
9146 new CapturingProxyResolver();
9147 session_deps_
.proxy_service
.reset(new ProxyService(
9148 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
9150 CapturingNetLog net_log
;
9151 session_deps_
.net_log
= &net_log
;
9153 HttpRequestInfo request
;
9154 request
.method
= "GET";
9155 request
.url
= GURL("http://www.google.com/");
9156 request
.load_flags
= 0;
9158 std::string alternate_protocol_http_header
=
9159 GetAlternateProtocolHttpHeader();
9161 MockRead data_reads
[] = {
9162 MockRead("HTTP/1.1 200 OK\r\n"),
9163 MockRead(alternate_protocol_http_header
.c_str()),
9164 MockRead("hello world"),
9165 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9166 MockRead(ASYNC
, OK
),
9169 StaticSocketDataProvider
first_transaction(
9170 data_reads
, arraysize(data_reads
), NULL
, 0);
9171 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9173 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9174 ssl
.SetNextProto(GetParam());
9175 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9177 scoped_ptr
<SpdyFrame
> req(
9178 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9179 MockWrite spdy_writes
[] = {
9180 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9181 "Host: www.google.com\r\n"
9182 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9183 CreateMockWrite(*req
), // 3
9186 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9188 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9189 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9190 MockRead spdy_reads
[] = {
9191 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9192 CreateMockRead(*resp
.get(), 4), // 2, 4
9193 CreateMockRead(*data
.get(), 4), // 5
9194 MockRead(ASYNC
, 0, 0, 4), // 6
9197 OrderedSocketData
spdy_data(
9198 spdy_reads
, arraysize(spdy_reads
),
9199 spdy_writes
, arraysize(spdy_writes
));
9200 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9202 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9203 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9205 hanging_non_alternate_protocol_socket
.set_connect_data(
9206 never_finishing_connect
);
9207 session_deps_
.socket_factory
->AddSocketDataProvider(
9208 &hanging_non_alternate_protocol_socket
);
9210 TestCompletionCallback callback
;
9212 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9213 scoped_ptr
<HttpTransaction
> trans(
9214 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9216 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9217 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9218 EXPECT_EQ(OK
, callback
.WaitForResult());
9220 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9221 ASSERT_TRUE(response
!= NULL
);
9222 ASSERT_TRUE(response
->headers
.get() != NULL
);
9223 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9224 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9225 EXPECT_FALSE(response
->was_npn_negotiated
);
9227 std::string response_data
;
9228 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9229 EXPECT_EQ("hello world", response_data
);
9231 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9233 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9234 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9235 EXPECT_EQ(OK
, callback
.WaitForResult());
9237 response
= trans
->GetResponseInfo();
9238 ASSERT_TRUE(response
!= NULL
);
9239 ASSERT_TRUE(response
->headers
.get() != NULL
);
9240 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9241 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9242 EXPECT_TRUE(response
->was_npn_negotiated
);
9244 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9245 EXPECT_EQ("hello!", response_data
);
9246 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
9247 EXPECT_EQ("http://www.google.com/",
9248 capturing_proxy_resolver
->resolved()[0].spec());
9249 EXPECT_EQ("https://www.google.com/",
9250 capturing_proxy_resolver
->resolved()[1].spec());
9252 LoadTimingInfo load_timing_info
;
9253 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9254 TestLoadTimingNotReusedWithPac(load_timing_info
,
9255 CONNECT_TIMING_HAS_SSL_TIMES
);
9258 TEST_P(HttpNetworkTransactionTest
,
9259 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9260 session_deps_
.use_alternate_protocols
= true;
9261 session_deps_
.next_protos
= SpdyNextProtos();
9263 HttpRequestInfo request
;
9264 request
.method
= "GET";
9265 request
.url
= GURL("http://www.google.com/");
9266 request
.load_flags
= 0;
9268 std::string alternate_protocol_http_header
=
9269 GetAlternateProtocolHttpHeader();
9271 MockRead data_reads
[] = {
9272 MockRead("HTTP/1.1 200 OK\r\n"),
9273 MockRead(alternate_protocol_http_header
.c_str()),
9274 MockRead("hello world"),
9275 MockRead(ASYNC
, OK
),
9278 StaticSocketDataProvider
first_transaction(
9279 data_reads
, arraysize(data_reads
), NULL
, 0);
9280 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9282 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9283 ssl
.SetNextProto(GetParam());
9284 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9286 scoped_ptr
<SpdyFrame
> req(
9287 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9288 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9290 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9291 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9292 MockRead spdy_reads
[] = {
9293 CreateMockRead(*resp
),
9294 CreateMockRead(*data
),
9295 MockRead(ASYNC
, 0, 0),
9298 DelayedSocketData
spdy_data(
9299 1, // wait for one write to finish before reading.
9300 spdy_reads
, arraysize(spdy_reads
),
9301 spdy_writes
, arraysize(spdy_writes
));
9302 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9304 TestCompletionCallback callback
;
9306 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9308 scoped_ptr
<HttpTransaction
> trans(
9309 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9311 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9312 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9313 EXPECT_EQ(OK
, callback
.WaitForResult());
9315 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9316 ASSERT_TRUE(response
!= NULL
);
9317 ASSERT_TRUE(response
->headers
.get() != NULL
);
9318 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9320 std::string response_data
;
9321 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9322 EXPECT_EQ("hello world", response_data
);
9324 // Set up an initial SpdySession in the pool to reuse.
9325 HostPortPair
host_port_pair("www.google.com", 443);
9326 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9327 PRIVACY_MODE_DISABLED
);
9328 base::WeakPtr
<SpdySession
> spdy_session
=
9329 CreateSecureSpdySession(session
, key
, BoundNetLog());
9331 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9333 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9335 EXPECT_EQ(OK
, callback
.WaitForResult());
9337 response
= trans
->GetResponseInfo();
9338 ASSERT_TRUE(response
!= NULL
);
9339 ASSERT_TRUE(response
->headers
.get() != NULL
);
9340 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9341 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9342 EXPECT_TRUE(response
->was_npn_negotiated
);
9344 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9345 EXPECT_EQ("hello!", response_data
);
9348 // GenerateAuthToken is a mighty big test.
9349 // It tests all permutation of GenerateAuthToken behavior:
9350 // - Synchronous and Asynchronous completion.
9351 // - OK or error on completion.
9352 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9353 // - HTTP or HTTPS backend (to include proxy tunneling).
9354 // - Non-authenticating and authenticating backend.
9356 // In all, there are 44 reasonable permuations (for example, if there are
9357 // problems generating an auth token for an authenticating proxy, we don't
9358 // need to test all permutations of the backend server).
9360 // The test proceeds by going over each of the configuration cases, and
9361 // potentially running up to three rounds in each of the tests. The TestConfig
9362 // specifies both the configuration for the test as well as the expectations
9364 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9365 static const char kServer
[] = "http://www.example.com";
9366 static const char kSecureServer
[] = "https://www.example.com";
9367 static const char kProxy
[] = "myproxy:70";
9368 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9376 const MockWrite
kGet(
9377 "GET / HTTP/1.1\r\n"
9378 "Host: www.example.com\r\n"
9379 "Connection: keep-alive\r\n\r\n");
9380 const MockWrite
kGetProxy(
9381 "GET http://www.example.com/ HTTP/1.1\r\n"
9382 "Host: www.example.com\r\n"
9383 "Proxy-Connection: keep-alive\r\n\r\n");
9384 const MockWrite
kGetAuth(
9385 "GET / HTTP/1.1\r\n"
9386 "Host: www.example.com\r\n"
9387 "Connection: keep-alive\r\n"
9388 "Authorization: auth_token\r\n\r\n");
9389 const MockWrite
kGetProxyAuth(
9390 "GET http://www.example.com/ HTTP/1.1\r\n"
9391 "Host: www.example.com\r\n"
9392 "Proxy-Connection: keep-alive\r\n"
9393 "Proxy-Authorization: auth_token\r\n\r\n");
9394 const MockWrite
kGetAuthThroughProxy(
9395 "GET http://www.example.com/ HTTP/1.1\r\n"
9396 "Host: www.example.com\r\n"
9397 "Proxy-Connection: keep-alive\r\n"
9398 "Authorization: auth_token\r\n\r\n");
9399 const MockWrite
kGetAuthWithProxyAuth(
9400 "GET http://www.example.com/ HTTP/1.1\r\n"
9401 "Host: www.example.com\r\n"
9402 "Proxy-Connection: keep-alive\r\n"
9403 "Proxy-Authorization: auth_token\r\n"
9404 "Authorization: auth_token\r\n\r\n");
9405 const MockWrite
kConnect(
9406 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9407 "Host: www.example.com\r\n"
9408 "Proxy-Connection: keep-alive\r\n\r\n");
9409 const MockWrite
kConnectProxyAuth(
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"
9413 "Proxy-Authorization: auth_token\r\n\r\n");
9415 const MockRead
kSuccess(
9416 "HTTP/1.1 200 OK\r\n"
9417 "Content-Type: text/html; charset=iso-8859-1\r\n"
9418 "Content-Length: 3\r\n\r\n"
9420 const MockRead
kFailure(
9421 "Should not be called.");
9422 const MockRead
kServerChallenge(
9423 "HTTP/1.1 401 Unauthorized\r\n"
9424 "WWW-Authenticate: Mock realm=server\r\n"
9425 "Content-Type: text/html; charset=iso-8859-1\r\n"
9426 "Content-Length: 14\r\n\r\n"
9427 "Unauthorized\r\n");
9428 const MockRead
kProxyChallenge(
9429 "HTTP/1.1 407 Unauthorized\r\n"
9430 "Proxy-Authenticate: Mock realm=proxy\r\n"
9431 "Proxy-Connection: close\r\n"
9432 "Content-Type: text/html; charset=iso-8859-1\r\n"
9433 "Content-Length: 14\r\n\r\n"
9434 "Unauthorized\r\n");
9435 const MockRead
kProxyConnected(
9436 "HTTP/1.1 200 Connection Established\r\n\r\n");
9438 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9439 // no constructors, but the C++ compiler on Windows warns about
9440 // unspecified data in compound literals. So, moved to using constructors,
9441 // and TestRound's created with the default constructor should not be used.
9444 : expected_rv(ERR_UNEXPECTED
),
9448 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9449 int expected_rv_arg
)
9452 expected_rv(expected_rv_arg
),
9456 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9457 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9458 const MockRead
* extra_read_arg
)
9461 expected_rv(expected_rv_arg
),
9462 extra_write(extra_write_arg
),
9463 extra_read(extra_read_arg
) {
9468 const MockWrite
* extra_write
;
9469 const MockRead
* extra_read
;
9472 static const int kNoSSL
= 500;
9475 const char* proxy_url
;
9476 AuthTiming proxy_auth_timing
;
9478 const char* server_url
;
9479 AuthTiming server_auth_timing
;
9481 int num_auth_rounds
;
9482 int first_ssl_round
;
9483 TestRound rounds
[3];
9484 } test_configs
[] = {
9485 // Non-authenticating HTTP server with a direct connection.
9486 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9487 { TestRound(kGet
, kSuccess
, OK
)}},
9488 // Authenticating HTTP server with a direct connection.
9489 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9490 { TestRound(kGet
, kServerChallenge
, OK
),
9491 TestRound(kGetAuth
, kSuccess
, OK
)}},
9492 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9493 { TestRound(kGet
, kServerChallenge
, OK
),
9494 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9495 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9496 { TestRound(kGet
, kServerChallenge
, OK
),
9497 TestRound(kGetAuth
, kSuccess
, OK
)}},
9498 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9499 { TestRound(kGet
, kServerChallenge
, OK
),
9500 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9501 // Non-authenticating HTTP server through a non-authenticating proxy.
9502 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9503 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9504 // Authenticating HTTP server through a non-authenticating proxy.
9505 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9506 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9507 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9508 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9509 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9510 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9511 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9512 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9513 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9514 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9515 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9516 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9517 // Non-authenticating HTTP server through an authenticating proxy.
9518 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9519 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9520 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9521 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9522 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9523 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9524 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9525 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9526 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9527 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9528 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9529 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9530 // Authenticating HTTP server through an authenticating proxy.
9531 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9532 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9533 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9534 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9535 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9536 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9537 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9538 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9539 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9540 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9541 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9542 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9543 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9544 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9545 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9546 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9547 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9548 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9549 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9550 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9551 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9552 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9553 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9554 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9555 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9556 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9557 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9558 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9559 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9560 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9561 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9562 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9563 // Non-authenticating HTTPS server with a direct connection.
9564 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9565 { TestRound(kGet
, kSuccess
, OK
)}},
9566 // Authenticating HTTPS server with a direct connection.
9567 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9568 { TestRound(kGet
, kServerChallenge
, OK
),
9569 TestRound(kGetAuth
, kSuccess
, OK
)}},
9570 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9571 { TestRound(kGet
, kServerChallenge
, OK
),
9572 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9573 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9574 { TestRound(kGet
, kServerChallenge
, OK
),
9575 TestRound(kGetAuth
, kSuccess
, OK
)}},
9576 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9577 { TestRound(kGet
, kServerChallenge
, OK
),
9578 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9579 // Non-authenticating HTTPS server with a non-authenticating proxy.
9580 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9581 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9582 // Authenticating HTTPS server through a non-authenticating proxy.
9583 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9584 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9585 TestRound(kGetAuth
, kSuccess
, OK
)}},
9586 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9587 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9588 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9589 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9590 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9591 TestRound(kGetAuth
, kSuccess
, OK
)}},
9592 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9593 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9594 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9595 // Non-Authenticating HTTPS server through an authenticating proxy.
9596 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9597 { TestRound(kConnect
, kProxyChallenge
, OK
),
9598 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9599 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9600 { TestRound(kConnect
, kProxyChallenge
, OK
),
9601 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9602 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9603 { TestRound(kConnect
, kProxyChallenge
, OK
),
9604 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9605 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9606 { TestRound(kConnect
, kProxyChallenge
, OK
),
9607 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9608 // Authenticating HTTPS server through an authenticating proxy.
9609 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9610 { TestRound(kConnect
, kProxyChallenge
, OK
),
9611 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9612 &kGet
, &kServerChallenge
),
9613 TestRound(kGetAuth
, kSuccess
, OK
)}},
9614 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9615 { TestRound(kConnect
, kProxyChallenge
, OK
),
9616 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9617 &kGet
, &kServerChallenge
),
9618 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9619 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9620 { TestRound(kConnect
, kProxyChallenge
, OK
),
9621 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9622 &kGet
, &kServerChallenge
),
9623 TestRound(kGetAuth
, kSuccess
, OK
)}},
9624 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9625 { TestRound(kConnect
, kProxyChallenge
, OK
),
9626 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9627 &kGet
, &kServerChallenge
),
9628 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9629 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9630 { TestRound(kConnect
, kProxyChallenge
, OK
),
9631 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9632 &kGet
, &kServerChallenge
),
9633 TestRound(kGetAuth
, kSuccess
, OK
)}},
9634 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9635 { TestRound(kConnect
, kProxyChallenge
, OK
),
9636 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9637 &kGet
, &kServerChallenge
),
9638 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9639 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9640 { TestRound(kConnect
, kProxyChallenge
, OK
),
9641 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9642 &kGet
, &kServerChallenge
),
9643 TestRound(kGetAuth
, kSuccess
, OK
)}},
9644 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9645 { TestRound(kConnect
, kProxyChallenge
, OK
),
9646 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9647 &kGet
, &kServerChallenge
),
9648 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9651 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
9652 HttpAuthHandlerMock::Factory
* auth_factory(
9653 new HttpAuthHandlerMock::Factory());
9654 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9655 const TestConfig
& test_config
= test_configs
[i
];
9657 // Set up authentication handlers as necessary.
9658 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9659 for (int n
= 0; n
< 2; n
++) {
9660 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9661 std::string auth_challenge
= "Mock realm=proxy";
9662 GURL
origin(test_config
.proxy_url
);
9663 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9664 auth_challenge
.end());
9665 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9666 origin
, BoundNetLog());
9667 auth_handler
->SetGenerateExpectation(
9668 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9669 test_config
.proxy_auth_rv
);
9670 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9673 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9674 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9675 std::string auth_challenge
= "Mock realm=server";
9676 GURL
origin(test_config
.server_url
);
9677 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9678 auth_challenge
.end());
9679 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9680 origin
, BoundNetLog());
9681 auth_handler
->SetGenerateExpectation(
9682 test_config
.server_auth_timing
== AUTH_ASYNC
,
9683 test_config
.server_auth_rv
);
9684 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9686 if (test_config
.proxy_url
) {
9687 session_deps_
.proxy_service
.reset(
9688 ProxyService::CreateFixed(test_config
.proxy_url
));
9690 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9693 HttpRequestInfo request
;
9694 request
.method
= "GET";
9695 request
.url
= GURL(test_config
.server_url
);
9696 request
.load_flags
= 0;
9698 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9699 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
9701 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9702 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9704 // Set up expected reads and writes.
9706 reads
[0] = read_write_round
.read
;
9707 size_t length_reads
= 1;
9708 if (read_write_round
.extra_read
) {
9709 reads
[1] = *read_write_round
.extra_read
;
9713 MockWrite writes
[2];
9714 writes
[0] = read_write_round
.write
;
9715 size_t length_writes
= 1;
9716 if (read_write_round
.extra_write
) {
9717 writes
[1] = *read_write_round
.extra_write
;
9720 StaticSocketDataProvider
data_provider(
9721 reads
, length_reads
, writes
, length_writes
);
9722 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9724 // Add an SSL sequence if necessary.
9725 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9726 if (round
>= test_config
.first_ssl_round
)
9727 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9728 &ssl_socket_data_provider
);
9730 // Start or restart the transaction.
9731 TestCompletionCallback callback
;
9734 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9736 rv
= trans
.RestartWithAuth(
9737 AuthCredentials(kFoo
, kBar
), callback
.callback());
9739 if (rv
== ERR_IO_PENDING
)
9740 rv
= callback
.WaitForResult();
9742 // Compare results with expected data.
9743 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9744 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9745 if (read_write_round
.expected_rv
== OK
) {
9746 ASSERT_TRUE(response
!= NULL
);
9748 EXPECT_TRUE(response
== NULL
);
9749 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9752 if (round
+ 1 < test_config
.num_auth_rounds
) {
9753 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9755 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9761 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9762 // Do multi-round authentication and make sure it works correctly.
9763 HttpAuthHandlerMock::Factory
* auth_factory(
9764 new HttpAuthHandlerMock::Factory());
9765 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9766 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9767 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9768 session_deps_
.host_resolver
->set_synchronous_mode(true);
9770 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9771 auth_handler
->set_connection_based(true);
9772 std::string auth_challenge
= "Mock realm=server";
9773 GURL
origin("http://www.example.com");
9774 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9775 auth_challenge
.end());
9776 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9777 origin
, BoundNetLog());
9778 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9781 const HttpResponseInfo
* response
= NULL
;
9782 HttpRequestInfo request
;
9783 request
.method
= "GET";
9784 request
.url
= origin
;
9785 request
.load_flags
= 0;
9787 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9789 // Use a TCP Socket Pool with only one connection per group. This is used
9790 // to validate that the TCP socket is not released to the pool between
9791 // each round of multi-round authentication.
9792 HttpNetworkSessionPeer
session_peer(session
);
9793 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9794 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9795 50, // Max sockets for pool
9796 1, // Max sockets per group
9797 &transport_pool_histograms
,
9798 session_deps_
.host_resolver
.get(),
9799 session_deps_
.socket_factory
.get(),
9800 session_deps_
.net_log
);
9801 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
9802 new MockClientSocketPoolManager
);
9803 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9804 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
9806 scoped_ptr
<HttpTransaction
> trans(
9807 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9808 TestCompletionCallback callback
;
9810 const MockWrite
kGet(
9811 "GET / HTTP/1.1\r\n"
9812 "Host: www.example.com\r\n"
9813 "Connection: keep-alive\r\n\r\n");
9814 const MockWrite
kGetAuth(
9815 "GET / HTTP/1.1\r\n"
9816 "Host: www.example.com\r\n"
9817 "Connection: keep-alive\r\n"
9818 "Authorization: auth_token\r\n\r\n");
9820 const MockRead
kServerChallenge(
9821 "HTTP/1.1 401 Unauthorized\r\n"
9822 "WWW-Authenticate: Mock realm=server\r\n"
9823 "Content-Type: text/html; charset=iso-8859-1\r\n"
9824 "Content-Length: 14\r\n\r\n"
9825 "Unauthorized\r\n");
9826 const MockRead
kSuccess(
9827 "HTTP/1.1 200 OK\r\n"
9828 "Content-Type: text/html; charset=iso-8859-1\r\n"
9829 "Content-Length: 3\r\n\r\n"
9832 MockWrite writes
[] = {
9841 // Competing request
9844 MockRead reads
[] = {
9853 // Competing response
9856 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9857 writes
, arraysize(writes
));
9858 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9860 const char* const kSocketGroup
= "www.example.com:80";
9862 // First round of authentication.
9863 auth_handler
->SetGenerateExpectation(false, OK
);
9864 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9865 if (rv
== ERR_IO_PENDING
)
9866 rv
= callback
.WaitForResult();
9868 response
= trans
->GetResponseInfo();
9869 ASSERT_TRUE(response
!= NULL
);
9870 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9871 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9873 // In between rounds, another request comes in for the same domain.
9874 // It should not be able to grab the TCP socket that trans has already
9876 scoped_ptr
<HttpTransaction
> trans_compete(
9877 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9878 TestCompletionCallback callback_compete
;
9879 rv
= trans_compete
->Start(
9880 &request
, callback_compete
.callback(), BoundNetLog());
9881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9882 // callback_compete.WaitForResult at this point would stall forever,
9883 // since the HttpNetworkTransaction does not release the request back to
9884 // the pool until after authentication completes.
9886 // Second round of authentication.
9887 auth_handler
->SetGenerateExpectation(false, OK
);
9888 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9889 if (rv
== ERR_IO_PENDING
)
9890 rv
= callback
.WaitForResult();
9892 response
= trans
->GetResponseInfo();
9893 ASSERT_TRUE(response
!= NULL
);
9894 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9895 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9897 // Third round of authentication.
9898 auth_handler
->SetGenerateExpectation(false, OK
);
9899 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9900 if (rv
== ERR_IO_PENDING
)
9901 rv
= callback
.WaitForResult();
9903 response
= trans
->GetResponseInfo();
9904 ASSERT_TRUE(response
!= NULL
);
9905 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9906 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9908 // Fourth round of authentication, which completes successfully.
9909 auth_handler
->SetGenerateExpectation(false, OK
);
9910 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9911 if (rv
== ERR_IO_PENDING
)
9912 rv
= callback
.WaitForResult();
9914 response
= trans
->GetResponseInfo();
9915 ASSERT_TRUE(response
!= NULL
);
9916 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9917 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9919 // Read the body since the fourth round was successful. This will also
9920 // release the socket back to the pool.
9921 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9922 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9923 if (rv
== ERR_IO_PENDING
)
9924 rv
= callback
.WaitForResult();
9926 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9928 // There are still 0 idle sockets, since the trans_compete transaction
9929 // will be handed it immediately after trans releases it to the group.
9930 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9932 // The competing request can now finish. Wait for the headers and then
9934 rv
= callback_compete
.WaitForResult();
9936 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9937 if (rv
== ERR_IO_PENDING
)
9938 rv
= callback
.WaitForResult();
9940 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9943 // Finally, the socket is released to the group.
9944 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9947 // This tests the case that a request is issued via http instead of spdy after
9948 // npn is negotiated.
9949 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9950 session_deps_
.use_alternate_protocols
= true;
9951 NextProtoVector next_protos
;
9952 next_protos
.push_back(kProtoHTTP11
);
9953 session_deps_
.next_protos
= next_protos
;
9955 HttpRequestInfo request
;
9956 request
.method
= "GET";
9957 request
.url
= GURL("https://www.google.com/");
9958 request
.load_flags
= 0;
9960 MockWrite data_writes
[] = {
9961 MockWrite("GET / HTTP/1.1\r\n"
9962 "Host: www.google.com\r\n"
9963 "Connection: keep-alive\r\n\r\n"),
9966 std::string alternate_protocol_http_header
=
9967 GetAlternateProtocolHttpHeader();
9969 MockRead data_reads
[] = {
9970 MockRead("HTTP/1.1 200 OK\r\n"),
9971 MockRead(alternate_protocol_http_header
.c_str()),
9972 MockRead("hello world"),
9973 MockRead(SYNCHRONOUS
, OK
),
9976 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9977 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9978 ssl
.next_proto
= "http/1.1";
9979 ssl
.protocol_negotiated
= kProtoHTTP11
;
9981 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9983 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9984 data_writes
, arraysize(data_writes
));
9985 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9987 TestCompletionCallback callback
;
9989 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9990 scoped_ptr
<HttpTransaction
> trans(
9991 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9993 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9995 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9996 EXPECT_EQ(OK
, callback
.WaitForResult());
9998 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9999 ASSERT_TRUE(response
!= NULL
);
10000 ASSERT_TRUE(response
->headers
.get() != NULL
);
10001 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10003 std::string response_data
;
10004 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10005 EXPECT_EQ("hello world", response_data
);
10007 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10008 EXPECT_TRUE(response
->was_npn_negotiated
);
10011 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10012 // Simulate the SSL handshake completing with an NPN negotiation
10013 // followed by an immediate server closing of the socket.
10014 // Fix crash: http://crbug.com/46369
10015 session_deps_
.use_alternate_protocols
= true;
10016 session_deps_
.next_protos
= SpdyNextProtos();
10018 HttpRequestInfo request
;
10019 request
.method
= "GET";
10020 request
.url
= GURL("https://www.google.com/");
10021 request
.load_flags
= 0;
10023 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10024 ssl
.SetNextProto(GetParam());
10025 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10027 scoped_ptr
<SpdyFrame
> req(
10028 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10029 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10031 MockRead spdy_reads
[] = {
10032 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10035 DelayedSocketData
spdy_data(
10036 0, // don't wait in this case, immediate hangup.
10037 spdy_reads
, arraysize(spdy_reads
),
10038 spdy_writes
, arraysize(spdy_writes
));
10039 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10041 TestCompletionCallback callback
;
10043 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10044 scoped_ptr
<HttpTransaction
> trans(
10045 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10047 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10048 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10049 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10052 // A subclass of HttpAuthHandlerMock that records the request URL when
10053 // it gets it. This is needed since the auth handler may get destroyed
10054 // before we get a chance to query it.
10055 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10057 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10059 ~UrlRecordingHttpAuthHandlerMock() override
{}
10062 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10063 const HttpRequestInfo
* request
,
10064 const CompletionCallback
& callback
,
10065 std::string
* auth_token
) override
{
10066 *url_
= request
->url
;
10067 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10068 credentials
, request
, callback
, auth_token
);
10075 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10076 // This test ensures that the URL passed into the proxy is upgraded
10077 // to https when doing an Alternate Protocol upgrade.
10078 session_deps_
.use_alternate_protocols
= true;
10079 session_deps_
.next_protos
= SpdyNextProtos();
10081 session_deps_
.proxy_service
.reset(
10082 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10083 CapturingNetLog net_log
;
10084 session_deps_
.net_log
= &net_log
;
10087 HttpAuthHandlerMock::Factory
* auth_factory
=
10088 new HttpAuthHandlerMock::Factory();
10089 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10090 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10091 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10092 auth_factory
->set_do_init_from_challenge(true);
10093 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10096 HttpRequestInfo request
;
10097 request
.method
= "GET";
10098 request
.url
= GURL("http://www.google.com");
10099 request
.load_flags
= 0;
10101 // First round goes unauthenticated through the proxy.
10102 MockWrite data_writes_1
[] = {
10103 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10104 "Host: www.google.com\r\n"
10105 "Proxy-Connection: keep-alive\r\n"
10108 MockRead data_reads_1
[] = {
10109 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10110 MockRead("HTTP/1.1 200 OK\r\n"
10111 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10112 "Proxy-Connection: close\r\n"
10115 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10116 data_writes_1
, arraysize(data_writes_1
));
10118 // Second round tries to tunnel to www.google.com due to the
10119 // Alternate-Protocol announcement in the first round. It fails due
10120 // to a proxy authentication challenge.
10121 // After the failure, a tunnel is established to www.google.com using
10122 // Proxy-Authorization headers. There is then a SPDY request round.
10124 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10125 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10126 // does a Disconnect and Connect on the same socket, rather than trying
10127 // to obtain a new one.
10129 // NOTE: Originally, the proxy response to the second CONNECT request
10130 // simply returned another 407 so the unit test could skip the SSL connection
10131 // establishment and SPDY framing issues. Alas, the
10132 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10133 // complicated to set up expectations for than the SPDY session.
10135 scoped_ptr
<SpdyFrame
> req(
10136 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10137 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10138 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10140 MockWrite data_writes_2
[] = {
10141 // First connection attempt without Proxy-Authorization.
10142 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10143 "Host: www.google.com\r\n"
10144 "Proxy-Connection: keep-alive\r\n"
10147 // Second connection attempt with Proxy-Authorization.
10148 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10149 "Host: www.google.com\r\n"
10150 "Proxy-Connection: keep-alive\r\n"
10151 "Proxy-Authorization: auth_token\r\n"
10155 CreateMockWrite(*req
),
10157 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10158 "Proxy-Authenticate: Mock\r\n"
10159 "Proxy-Connection: close\r\n"
10161 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10162 MockRead data_reads_2
[] = {
10163 // First connection attempt fails
10164 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10165 MockRead(ASYNC
, kRejectConnectResponse
,
10166 arraysize(kRejectConnectResponse
) - 1, 1),
10168 // Second connection attempt passes
10169 MockRead(ASYNC
, kAcceptConnectResponse
,
10170 arraysize(kAcceptConnectResponse
) -1, 4),
10173 CreateMockRead(*resp
.get(), 6),
10174 CreateMockRead(*data
.get(), 6),
10175 MockRead(ASYNC
, 0, 0, 6),
10177 OrderedSocketData
data_2(
10178 data_reads_2
, arraysize(data_reads_2
),
10179 data_writes_2
, arraysize(data_writes_2
));
10181 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10182 ssl
.SetNextProto(GetParam());
10184 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10185 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10187 hanging_non_alternate_protocol_socket
.set_connect_data(
10188 never_finishing_connect
);
10190 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10191 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10192 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10193 session_deps_
.socket_factory
->AddSocketDataProvider(
10194 &hanging_non_alternate_protocol_socket
);
10195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10197 // First round should work and provide the Alternate-Protocol state.
10198 TestCompletionCallback callback_1
;
10199 scoped_ptr
<HttpTransaction
> trans_1(
10200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10201 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10202 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10203 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10205 // Second round should attempt a tunnel connect and get an auth challenge.
10206 TestCompletionCallback callback_2
;
10207 scoped_ptr
<HttpTransaction
> trans_2(
10208 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10209 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10211 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10212 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10213 ASSERT_TRUE(response
!= NULL
);
10214 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10216 // Restart with auth. Tunnel should work and response received.
10217 TestCompletionCallback callback_3
;
10218 rv
= trans_2
->RestartWithAuth(
10219 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10220 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10221 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10223 // After all that work, these two lines (or actually, just the scheme) are
10224 // what this test is all about. Make sure it happens correctly.
10225 EXPECT_EQ("https", request_url
.scheme());
10226 EXPECT_EQ("www.google.com", request_url
.host());
10228 LoadTimingInfo load_timing_info
;
10229 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10230 TestLoadTimingNotReusedWithPac(load_timing_info
,
10231 CONNECT_TIMING_HAS_SSL_TIMES
);
10234 // Test that if we cancel the transaction as the connection is completing, that
10235 // everything tears down correctly.
10236 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10237 // Setup everything about the connection to complete synchronously, so that
10238 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10239 // for is the callback from the HttpStreamRequest.
10240 // Then cancel the transaction.
10241 // Verify that we don't crash.
10242 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10243 MockRead data_reads
[] = {
10244 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10245 MockRead(SYNCHRONOUS
, "hello world"),
10246 MockRead(SYNCHRONOUS
, OK
),
10249 HttpRequestInfo request
;
10250 request
.method
= "GET";
10251 request
.url
= GURL("http://www.google.com/");
10252 request
.load_flags
= 0;
10254 session_deps_
.host_resolver
->set_synchronous_mode(true);
10255 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10256 scoped_ptr
<HttpTransaction
> trans(
10257 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10259 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10260 data
.set_connect_data(mock_connect
);
10261 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10263 TestCompletionCallback callback
;
10265 CapturingBoundNetLog log
;
10266 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10268 trans
.reset(); // Cancel the transaction here.
10270 base::MessageLoop::current()->RunUntilIdle();
10273 // Test that if a transaction is cancelled after receiving the headers, the
10274 // stream is drained properly and added back to the socket pool. The main
10275 // purpose of this test is to make sure that an HttpStreamParser can be read
10276 // from after the HttpNetworkTransaction and the objects it owns have been
10278 // See http://crbug.com/368418
10279 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10280 MockRead data_reads
[] = {
10281 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10282 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10283 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10284 MockRead(ASYNC
, "1"),
10285 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10286 // HttpNetworkTransaction has been deleted.
10287 MockRead(ASYNC
, "2"),
10288 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10290 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10291 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10293 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10296 HttpRequestInfo request
;
10297 request
.method
= "GET";
10298 request
.url
= GURL("http://www.google.com/");
10299 request
.load_flags
= 0;
10301 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10302 TestCompletionCallback callback
;
10304 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10306 callback
.WaitForResult();
10308 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10309 ASSERT_TRUE(response
!= NULL
);
10310 EXPECT_TRUE(response
->headers
.get() != NULL
);
10311 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10313 // The transaction and HttpRequestInfo are deleted.
10316 // Let the HttpResponseBodyDrainer drain the socket.
10317 base::MessageLoop::current()->RunUntilIdle();
10319 // Socket should now be idle, waiting to be reused.
10320 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10323 // Test a basic GET request through a proxy.
10324 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10325 session_deps_
.proxy_service
.reset(
10326 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10327 CapturingBoundNetLog log
;
10328 session_deps_
.net_log
= log
.bound().net_log();
10329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10331 HttpRequestInfo request
;
10332 request
.method
= "GET";
10333 request
.url
= GURL("http://www.google.com/");
10335 MockWrite data_writes1
[] = {
10336 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10337 "Host: www.google.com\r\n"
10338 "Proxy-Connection: keep-alive\r\n\r\n"),
10341 MockRead data_reads1
[] = {
10342 MockRead("HTTP/1.1 200 OK\r\n"),
10343 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10344 MockRead("Content-Length: 100\r\n\r\n"),
10345 MockRead(SYNCHRONOUS
, OK
),
10348 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10349 data_writes1
, arraysize(data_writes1
));
10350 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10352 TestCompletionCallback callback1
;
10354 scoped_ptr
<HttpTransaction
> trans(
10355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10356 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10357 trans
->SetBeforeProxyHeadersSentCallback(
10358 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10359 base::Unretained(&proxy_headers_handler
)));
10361 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10362 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10364 rv
= callback1
.WaitForResult();
10367 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10368 ASSERT_TRUE(response
!= NULL
);
10370 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10371 EXPECT_EQ(200, response
->headers
->response_code());
10372 EXPECT_EQ(100, response
->headers
->GetContentLength());
10373 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10375 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10376 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10377 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10378 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10380 LoadTimingInfo load_timing_info
;
10381 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10382 TestLoadTimingNotReusedWithPac(load_timing_info
,
10383 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10386 // Test a basic HTTPS GET request through a proxy.
10387 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10388 session_deps_
.proxy_service
.reset(
10389 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10390 CapturingBoundNetLog log
;
10391 session_deps_
.net_log
= log
.bound().net_log();
10392 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10394 HttpRequestInfo request
;
10395 request
.method
= "GET";
10396 request
.url
= GURL("https://www.google.com/");
10398 // Since we have proxy, should try to establish tunnel.
10399 MockWrite data_writes1
[] = {
10400 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10401 "Host: www.google.com\r\n"
10402 "Proxy-Connection: keep-alive\r\n\r\n"),
10404 MockWrite("GET / HTTP/1.1\r\n"
10405 "Host: www.google.com\r\n"
10406 "Connection: keep-alive\r\n\r\n"),
10409 MockRead data_reads1
[] = {
10410 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10412 MockRead("HTTP/1.1 200 OK\r\n"),
10413 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10414 MockRead("Content-Length: 100\r\n\r\n"),
10415 MockRead(SYNCHRONOUS
, OK
),
10418 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10419 data_writes1
, arraysize(data_writes1
));
10420 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10421 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10422 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10424 TestCompletionCallback callback1
;
10426 scoped_ptr
<HttpTransaction
> trans(
10427 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10429 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10430 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10432 rv
= callback1
.WaitForResult();
10434 net::CapturingNetLog::CapturedEntryList entries
;
10435 log
.GetEntries(&entries
);
10436 size_t pos
= ExpectLogContainsSomewhere(
10437 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10438 NetLog::PHASE_NONE
);
10439 ExpectLogContainsSomewhere(
10441 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10442 NetLog::PHASE_NONE
);
10444 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10445 ASSERT_TRUE(response
!= NULL
);
10447 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10448 EXPECT_EQ(200, response
->headers
->response_code());
10449 EXPECT_EQ(100, response
->headers
->GetContentLength());
10450 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10451 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10453 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10455 LoadTimingInfo load_timing_info
;
10456 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10457 TestLoadTimingNotReusedWithPac(load_timing_info
,
10458 CONNECT_TIMING_HAS_SSL_TIMES
);
10461 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10462 // while establishing the tunnel.
10463 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10464 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10465 CapturingBoundNetLog log
;
10466 session_deps_
.net_log
= log
.bound().net_log();
10467 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10469 HttpRequestInfo request
;
10470 request
.method
= "GET";
10471 request
.url
= GURL("https://www.google.com/");
10473 // Since we have proxy, should try to establish tunnel.
10474 MockWrite data_writes1
[] = {
10475 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10476 "Host: www.google.com\r\n"
10477 "Proxy-Connection: keep-alive\r\n\r\n"),
10479 MockWrite("GET / HTTP/1.1\r\n"
10480 "Host: www.google.com\r\n"
10481 "Connection: keep-alive\r\n\r\n"),
10484 MockRead data_reads1
[] = {
10485 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10486 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10487 MockRead(ASYNC
, 0, 0), // EOF
10490 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10491 data_writes1
, arraysize(data_writes1
));
10492 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10493 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10494 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10496 TestCompletionCallback callback1
;
10498 scoped_ptr
<HttpTransaction
> trans(
10499 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10501 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10502 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10504 rv
= callback1
.WaitForResult();
10505 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10506 net::CapturingNetLog::CapturedEntryList entries
;
10507 log
.GetEntries(&entries
);
10508 size_t pos
= ExpectLogContainsSomewhere(
10509 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10510 NetLog::PHASE_NONE
);
10511 ExpectLogContainsSomewhere(
10513 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10514 NetLog::PHASE_NONE
);
10517 // Test for crbug.com/55424.
10518 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10519 scoped_ptr
<SpdyFrame
> req(
10520 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10521 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10523 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10524 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10525 MockRead spdy_reads
[] = {
10526 CreateMockRead(*resp
),
10527 CreateMockRead(*data
),
10528 MockRead(ASYNC
, 0, 0),
10531 DelayedSocketData
spdy_data(
10532 1, // wait for one write to finish before reading.
10533 spdy_reads
, arraysize(spdy_reads
),
10534 spdy_writes
, arraysize(spdy_writes
));
10535 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10537 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10538 ssl
.SetNextProto(GetParam());
10539 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10541 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10543 // Set up an initial SpdySession in the pool to reuse.
10544 HostPortPair
host_port_pair("www.google.com", 443);
10545 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10546 PRIVACY_MODE_DISABLED
);
10547 base::WeakPtr
<SpdySession
> spdy_session
=
10548 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10550 HttpRequestInfo request
;
10551 request
.method
= "GET";
10552 request
.url
= GURL("https://www.google.com/");
10553 request
.load_flags
= 0;
10555 // This is the important line that marks this as a preconnect.
10556 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10558 scoped_ptr
<HttpTransaction
> trans(
10559 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10561 TestCompletionCallback callback
;
10562 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10563 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10564 EXPECT_EQ(OK
, callback
.WaitForResult());
10567 // Given a net error, cause that error to be returned from the first Write()
10568 // call and verify that the HttpTransaction fails with that error.
10569 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10570 int error
, IoMode mode
) {
10571 net::HttpRequestInfo request_info
;
10572 request_info
.url
= GURL("https://www.example.com/");
10573 request_info
.method
= "GET";
10574 request_info
.load_flags
= net::LOAD_NORMAL
;
10576 SSLSocketDataProvider
ssl_data(mode
, OK
);
10577 net::MockWrite data_writes
[] = {
10578 net::MockWrite(mode
, error
),
10580 net::StaticSocketDataProvider
data(NULL
, 0,
10581 data_writes
, arraysize(data_writes
));
10582 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10583 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10585 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10586 scoped_ptr
<HttpTransaction
> trans(
10587 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10589 TestCompletionCallback callback
;
10590 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10591 if (rv
== net::ERR_IO_PENDING
)
10592 rv
= callback
.WaitForResult();
10593 ASSERT_EQ(error
, rv
);
10596 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10597 // Just check a grab bag of cert errors.
10598 static const int kErrors
[] = {
10599 ERR_CERT_COMMON_NAME_INVALID
,
10600 ERR_CERT_AUTHORITY_INVALID
,
10601 ERR_CERT_DATE_INVALID
,
10603 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10604 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10605 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10609 // Ensure that a client certificate is removed from the SSL client auth
10611 // 1) No proxy is involved.
10612 // 2) TLS False Start is disabled.
10613 // 3) The initial TLS handshake requests a client certificate.
10614 // 4) The client supplies an invalid/unacceptable certificate.
10615 TEST_P(HttpNetworkTransactionTest
,
10616 ClientAuthCertCache_Direct_NoFalseStart
) {
10617 net::HttpRequestInfo request_info
;
10618 request_info
.url
= GURL("https://www.example.com/");
10619 request_info
.method
= "GET";
10620 request_info
.load_flags
= net::LOAD_NORMAL
;
10622 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10623 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10625 // [ssl_]data1 contains the data for the first SSL handshake. When a
10626 // CertificateRequest is received for the first time, the handshake will
10627 // be aborted to allow the caller to provide a certificate.
10628 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10629 ssl_data1
.cert_request_info
= cert_request
.get();
10630 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10631 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10632 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10634 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10635 // False Start is not being used, the result of the SSL handshake will be
10636 // returned as part of the SSLClientSocket::Connect() call. This test
10637 // matches the result of a server sending a handshake_failure alert,
10638 // rather than a Finished message, because it requires a client
10639 // certificate and none was supplied.
10640 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10641 ssl_data2
.cert_request_info
= cert_request
.get();
10642 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10643 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10644 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10646 // [ssl_]data3 contains the data for the third SSL handshake. When a
10647 // connection to a server fails during an SSL handshake,
10648 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10649 // connection was attempted with TLSv1.1. This is transparent to the caller
10650 // of the HttpNetworkTransaction. Because this test failure is due to
10651 // requiring a client certificate, this fallback handshake should also
10653 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10654 ssl_data3
.cert_request_info
= cert_request
.get();
10655 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10656 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10657 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10659 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10660 // connection to a server fails during an SSL handshake,
10661 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10662 // connection was attempted with TLSv1. This is transparent to the caller
10663 // of the HttpNetworkTransaction. Because this test failure is due to
10664 // requiring a client certificate, this fallback handshake should also
10666 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10667 ssl_data4
.cert_request_info
= cert_request
.get();
10668 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10669 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10670 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10672 // Need one more if TLSv1.2 is enabled.
10673 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10674 ssl_data5
.cert_request_info
= cert_request
.get();
10675 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10676 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10677 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10679 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10680 scoped_ptr
<HttpTransaction
> trans(
10681 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10683 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10684 TestCompletionCallback callback
;
10685 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10686 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10688 // Complete the SSL handshake, which should abort due to requiring a
10689 // client certificate.
10690 rv
= callback
.WaitForResult();
10691 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10693 // Indicate that no certificate should be supplied. From the perspective
10694 // of SSLClientCertCache, NULL is just as meaningful as a real
10695 // certificate, so this is the same as supply a
10696 // legitimate-but-unacceptable certificate.
10697 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10698 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10700 // Ensure the certificate was added to the client auth cache before
10701 // allowing the connection to continue restarting.
10702 scoped_refptr
<X509Certificate
> client_cert
;
10703 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10704 HostPortPair("www.example.com", 443), &client_cert
));
10705 ASSERT_EQ(NULL
, client_cert
.get());
10707 // Restart the handshake. This will consume ssl_data2, which fails, and
10708 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10709 // The result code is checked against what ssl_data4 should return.
10710 rv
= callback
.WaitForResult();
10711 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10713 // Ensure that the client certificate is removed from the cache on a
10714 // handshake failure.
10715 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10716 HostPortPair("www.example.com", 443), &client_cert
));
10719 // Ensure that a client certificate is removed from the SSL client auth
10721 // 1) No proxy is involved.
10722 // 2) TLS False Start is enabled.
10723 // 3) The initial TLS handshake requests a client certificate.
10724 // 4) The client supplies an invalid/unacceptable certificate.
10725 TEST_P(HttpNetworkTransactionTest
,
10726 ClientAuthCertCache_Direct_FalseStart
) {
10727 net::HttpRequestInfo request_info
;
10728 request_info
.url
= GURL("https://www.example.com/");
10729 request_info
.method
= "GET";
10730 request_info
.load_flags
= net::LOAD_NORMAL
;
10732 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10733 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10735 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10736 // return successfully after reading up to the peer's Certificate message.
10737 // This is to allow the caller to call SSLClientSocket::Write(), which can
10738 // enqueue application data to be sent in the same packet as the
10739 // ChangeCipherSpec and Finished messages.
10740 // The actual handshake will be finished when SSLClientSocket::Read() is
10741 // called, which expects to process the peer's ChangeCipherSpec and
10742 // Finished messages. If there was an error negotiating with the peer,
10743 // such as due to the peer requiring a client certificate when none was
10744 // supplied, the alert sent by the peer won't be processed until Read() is
10747 // Like the non-False Start case, when a client certificate is requested by
10748 // the peer, the handshake is aborted during the Connect() call.
10749 // [ssl_]data1 represents the initial SSL handshake with the peer.
10750 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10751 ssl_data1
.cert_request_info
= cert_request
.get();
10752 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10753 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10754 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10756 // When a client certificate is supplied, Connect() will not be aborted
10757 // when the peer requests the certificate. Instead, the handshake will
10758 // artificially succeed, allowing the caller to write the HTTP request to
10759 // the socket. The handshake messages are not processed until Read() is
10760 // called, which then detects that the handshake was aborted, due to the
10761 // peer sending a handshake_failure because it requires a client
10763 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10764 ssl_data2
.cert_request_info
= cert_request
.get();
10765 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10766 net::MockRead data2_reads
[] = {
10767 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10769 net::StaticSocketDataProvider
data2(
10770 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10771 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10773 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10774 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10775 // TLSv1. It has the same behaviour as [ssl_]data2.
10776 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10777 ssl_data3
.cert_request_info
= cert_request
.get();
10778 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10779 net::StaticSocketDataProvider
data3(
10780 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10781 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10783 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10784 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10785 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10786 ssl_data4
.cert_request_info
= cert_request
.get();
10787 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10788 net::StaticSocketDataProvider
data4(
10789 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10790 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10792 // Need one more if TLSv1.2 is enabled.
10793 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10794 ssl_data5
.cert_request_info
= cert_request
.get();
10795 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10796 net::StaticSocketDataProvider
data5(
10797 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10798 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10800 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10801 scoped_ptr
<HttpTransaction
> trans(
10802 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10804 // Begin the initial SSL handshake.
10805 TestCompletionCallback callback
;
10806 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10807 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10809 // Complete the SSL handshake, which should abort due to requiring a
10810 // client certificate.
10811 rv
= callback
.WaitForResult();
10812 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10814 // Indicate that no certificate should be supplied. From the perspective
10815 // of SSLClientCertCache, NULL is just as meaningful as a real
10816 // certificate, so this is the same as supply a
10817 // legitimate-but-unacceptable certificate.
10818 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10819 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10821 // Ensure the certificate was added to the client auth cache before
10822 // allowing the connection to continue restarting.
10823 scoped_refptr
<X509Certificate
> client_cert
;
10824 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10825 HostPortPair("www.example.com", 443), &client_cert
));
10826 ASSERT_EQ(NULL
, client_cert
.get());
10828 // Restart the handshake. This will consume ssl_data2, which fails, and
10829 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10830 // The result code is checked against what ssl_data4 should return.
10831 rv
= callback
.WaitForResult();
10832 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10834 // Ensure that the client certificate is removed from the cache on a
10835 // handshake failure.
10836 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10837 HostPortPair("www.example.com", 443), &client_cert
));
10840 // Ensure that a client certificate is removed from the SSL client auth
10842 // 1) An HTTPS proxy is involved.
10843 // 3) The HTTPS proxy requests a client certificate.
10844 // 4) The client supplies an invalid/unacceptable certificate for the
10846 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10847 // then for connecting to an HTTP endpoint.
10848 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10849 session_deps_
.proxy_service
.reset(
10850 ProxyService::CreateFixed("https://proxy:70"));
10851 CapturingBoundNetLog log
;
10852 session_deps_
.net_log
= log
.bound().net_log();
10854 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10855 cert_request
->host_and_port
= HostPortPair("proxy", 70);
10857 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10858 // [ssl_]data[1-3]. Rather than represending the endpoint
10859 // (www.example.com:443), they represent failures with the HTTPS proxy
10861 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10862 ssl_data1
.cert_request_info
= cert_request
.get();
10863 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10864 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10865 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10867 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10868 ssl_data2
.cert_request_info
= cert_request
.get();
10869 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10870 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10871 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10873 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10875 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10876 ssl_data3
.cert_request_info
= cert_request
.get();
10877 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10878 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10879 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10882 net::HttpRequestInfo requests
[2];
10883 requests
[0].url
= GURL("https://www.example.com/");
10884 requests
[0].method
= "GET";
10885 requests
[0].load_flags
= net::LOAD_NORMAL
;
10887 requests
[1].url
= GURL("http://www.example.com/");
10888 requests
[1].method
= "GET";
10889 requests
[1].load_flags
= net::LOAD_NORMAL
;
10891 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10892 session_deps_
.socket_factory
->ResetNextMockIndexes();
10893 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10894 scoped_ptr
<HttpNetworkTransaction
> trans(
10895 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10897 // Begin the SSL handshake with the proxy.
10898 TestCompletionCallback callback
;
10899 int rv
= trans
->Start(
10900 &requests
[i
], callback
.callback(), net::BoundNetLog());
10901 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10903 // Complete the SSL handshake, which should abort due to requiring a
10904 // client certificate.
10905 rv
= callback
.WaitForResult();
10906 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10908 // Indicate that no certificate should be supplied. From the perspective
10909 // of SSLClientCertCache, NULL is just as meaningful as a real
10910 // certificate, so this is the same as supply a
10911 // legitimate-but-unacceptable certificate.
10912 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10913 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10915 // Ensure the certificate was added to the client auth cache before
10916 // allowing the connection to continue restarting.
10917 scoped_refptr
<X509Certificate
> client_cert
;
10918 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10919 HostPortPair("proxy", 70), &client_cert
));
10920 ASSERT_EQ(NULL
, client_cert
.get());
10921 // Ensure the certificate was NOT cached for the endpoint. This only
10922 // applies to HTTPS requests, but is fine to check for HTTP requests.
10923 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10924 HostPortPair("www.example.com", 443), &client_cert
));
10926 // Restart the handshake. This will consume ssl_data2, which fails, and
10927 // then consume ssl_data3, which should also fail. The result code is
10928 // checked against what ssl_data3 should return.
10929 rv
= callback
.WaitForResult();
10930 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10932 // Now that the new handshake has failed, ensure that the client
10933 // certificate was removed from the client auth cache.
10934 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10935 HostPortPair("proxy", 70), &client_cert
));
10936 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10937 HostPortPair("www.example.com", 443), &client_cert
));
10941 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10942 // TEST_P is a macro that expands directly to code that stringizes the
10943 // arguments. As a result, macros passed as parameters (such as prefix
10944 // or test_case_name) will not be expanded by the preprocessor. To
10945 // work around this, indirect the macro for TEST_P, so that the
10946 // pre-processor will expand macros such as MAYBE_test_name before
10947 // instantiating the test.
10948 #define WRAPPED_TEST_P(test_case_name, test_name) \
10949 TEST_P(test_case_name, test_name)
10951 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10952 #if defined(OS_WIN)
10953 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10955 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10957 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10958 session_deps_
.use_alternate_protocols
= true;
10959 session_deps_
.next_protos
= SpdyNextProtos();
10961 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10962 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10963 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10964 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10965 pool_peer
.DisableDomainAuthenticationVerification();
10967 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10968 ssl
.SetNextProto(GetParam());
10969 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10971 scoped_ptr
<SpdyFrame
> host1_req(
10972 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10973 scoped_ptr
<SpdyFrame
> host2_req(
10974 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10975 MockWrite spdy_writes
[] = {
10976 CreateMockWrite(*host1_req
, 1),
10977 CreateMockWrite(*host2_req
, 4),
10979 scoped_ptr
<SpdyFrame
> host1_resp(
10980 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10981 scoped_ptr
<SpdyFrame
> host1_resp_body(
10982 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10983 scoped_ptr
<SpdyFrame
> host2_resp(
10984 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10985 scoped_ptr
<SpdyFrame
> host2_resp_body(
10986 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10987 MockRead spdy_reads
[] = {
10988 CreateMockRead(*host1_resp
, 2),
10989 CreateMockRead(*host1_resp_body
, 3),
10990 CreateMockRead(*host2_resp
, 5),
10991 CreateMockRead(*host2_resp_body
, 6),
10992 MockRead(ASYNC
, 0, 7),
10995 IPAddressNumber ip
;
10996 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10997 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10998 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10999 OrderedSocketData
spdy_data(
11001 spdy_reads
, arraysize(spdy_reads
),
11002 spdy_writes
, arraysize(spdy_writes
));
11003 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11005 TestCompletionCallback callback
;
11006 HttpRequestInfo request1
;
11007 request1
.method
= "GET";
11008 request1
.url
= GURL("https://www.google.com/");
11009 request1
.load_flags
= 0;
11010 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11012 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11013 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11014 EXPECT_EQ(OK
, callback
.WaitForResult());
11016 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11017 ASSERT_TRUE(response
!= NULL
);
11018 ASSERT_TRUE(response
->headers
.get() != NULL
);
11019 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11021 std::string response_data
;
11022 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11023 EXPECT_EQ("hello!", response_data
);
11025 // Preload www.gmail.com into HostCache.
11026 HostPortPair
host_port("www.gmail.com", 443);
11027 HostResolver::RequestInfo
resolve_info(host_port
);
11028 AddressList ignored
;
11029 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11032 callback
.callback(),
11035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11036 rv
= callback
.WaitForResult();
11039 HttpRequestInfo request2
;
11040 request2
.method
= "GET";
11041 request2
.url
= GURL("https://www.gmail.com/");
11042 request2
.load_flags
= 0;
11043 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11045 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11046 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11047 EXPECT_EQ(OK
, callback
.WaitForResult());
11049 response
= trans2
.GetResponseInfo();
11050 ASSERT_TRUE(response
!= NULL
);
11051 ASSERT_TRUE(response
->headers
.get() != NULL
);
11052 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11053 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11054 EXPECT_TRUE(response
->was_npn_negotiated
);
11055 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11056 EXPECT_EQ("hello!", response_data
);
11058 #undef MAYBE_UseIPConnectionPooling
11060 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11061 session_deps_
.use_alternate_protocols
= true;
11062 session_deps_
.next_protos
= SpdyNextProtos();
11064 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11065 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11066 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11067 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11068 pool_peer
.DisableDomainAuthenticationVerification();
11070 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11071 ssl
.SetNextProto(GetParam());
11072 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11074 scoped_ptr
<SpdyFrame
> host1_req(
11075 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11076 scoped_ptr
<SpdyFrame
> host2_req(
11077 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11078 MockWrite spdy_writes
[] = {
11079 CreateMockWrite(*host1_req
, 1),
11080 CreateMockWrite(*host2_req
, 4),
11082 scoped_ptr
<SpdyFrame
> host1_resp(
11083 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11084 scoped_ptr
<SpdyFrame
> host1_resp_body(
11085 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11086 scoped_ptr
<SpdyFrame
> host2_resp(
11087 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11088 scoped_ptr
<SpdyFrame
> host2_resp_body(
11089 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11090 MockRead spdy_reads
[] = {
11091 CreateMockRead(*host1_resp
, 2),
11092 CreateMockRead(*host1_resp_body
, 3),
11093 CreateMockRead(*host2_resp
, 5),
11094 CreateMockRead(*host2_resp_body
, 6),
11095 MockRead(ASYNC
, 0, 7),
11098 IPAddressNumber ip
;
11099 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11100 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11101 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11102 OrderedSocketData
spdy_data(
11104 spdy_reads
, arraysize(spdy_reads
),
11105 spdy_writes
, arraysize(spdy_writes
));
11106 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11108 TestCompletionCallback callback
;
11109 HttpRequestInfo request1
;
11110 request1
.method
= "GET";
11111 request1
.url
= GURL("https://www.google.com/");
11112 request1
.load_flags
= 0;
11113 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11115 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11117 EXPECT_EQ(OK
, callback
.WaitForResult());
11119 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11120 ASSERT_TRUE(response
!= NULL
);
11121 ASSERT_TRUE(response
->headers
.get() != NULL
);
11122 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11124 std::string response_data
;
11125 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11126 EXPECT_EQ("hello!", response_data
);
11128 HttpRequestInfo request2
;
11129 request2
.method
= "GET";
11130 request2
.url
= GURL("https://www.gmail.com/");
11131 request2
.load_flags
= 0;
11132 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11134 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11136 EXPECT_EQ(OK
, callback
.WaitForResult());
11138 response
= trans2
.GetResponseInfo();
11139 ASSERT_TRUE(response
!= NULL
);
11140 ASSERT_TRUE(response
->headers
.get() != NULL
);
11141 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11142 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11143 EXPECT_TRUE(response
->was_npn_negotiated
);
11144 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11145 EXPECT_EQ("hello!", response_data
);
11148 class OneTimeCachingHostResolver
: public net::HostResolver
{
11150 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11151 : host_port_(host_port
) {}
11152 ~OneTimeCachingHostResolver() override
{}
11154 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11156 // HostResolver methods:
11157 int Resolve(const RequestInfo
& info
,
11158 RequestPriority priority
,
11159 AddressList
* addresses
,
11160 const CompletionCallback
& callback
,
11161 RequestHandle
* out_req
,
11162 const BoundNetLog
& net_log
) override
{
11163 return host_resolver_
.Resolve(
11164 info
, priority
, addresses
, callback
, out_req
, net_log
);
11167 int ResolveFromCache(const RequestInfo
& info
,
11168 AddressList
* addresses
,
11169 const BoundNetLog
& net_log
) override
{
11170 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11171 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11172 host_resolver_
.GetHostCache()->clear();
11176 void CancelRequest(RequestHandle req
) override
{
11177 host_resolver_
.CancelRequest(req
);
11180 MockCachingHostResolver
* GetMockHostResolver() {
11181 return &host_resolver_
;
11185 MockCachingHostResolver host_resolver_
;
11186 const HostPortPair host_port_
;
11189 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11190 #if defined(OS_WIN)
11191 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11192 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11194 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11195 UseIPConnectionPoolingWithHostCacheExpiration
11197 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11198 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11199 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11200 // prefix doesn't work with parametrized tests).
11201 #if defined(OS_WIN)
11204 session_deps_
.use_alternate_protocols
= true;
11205 session_deps_
.next_protos
= SpdyNextProtos();
11207 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11208 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11209 HttpNetworkSession::Params params
=
11210 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11211 params
.host_resolver
= &host_resolver
;
11212 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11213 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11214 pool_peer
.DisableDomainAuthenticationVerification();
11216 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11217 ssl
.SetNextProto(GetParam());
11218 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11220 scoped_ptr
<SpdyFrame
> host1_req(
11221 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11222 scoped_ptr
<SpdyFrame
> host2_req(
11223 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11224 MockWrite spdy_writes
[] = {
11225 CreateMockWrite(*host1_req
, 1),
11226 CreateMockWrite(*host2_req
, 4),
11228 scoped_ptr
<SpdyFrame
> host1_resp(
11229 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11230 scoped_ptr
<SpdyFrame
> host1_resp_body(
11231 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11232 scoped_ptr
<SpdyFrame
> host2_resp(
11233 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11234 scoped_ptr
<SpdyFrame
> host2_resp_body(
11235 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11236 MockRead spdy_reads
[] = {
11237 CreateMockRead(*host1_resp
, 2),
11238 CreateMockRead(*host1_resp_body
, 3),
11239 CreateMockRead(*host2_resp
, 5),
11240 CreateMockRead(*host2_resp_body
, 6),
11241 MockRead(ASYNC
, 0, 7),
11244 IPAddressNumber ip
;
11245 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11246 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11247 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11248 OrderedSocketData
spdy_data(
11250 spdy_reads
, arraysize(spdy_reads
),
11251 spdy_writes
, arraysize(spdy_writes
));
11252 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11254 TestCompletionCallback callback
;
11255 HttpRequestInfo request1
;
11256 request1
.method
= "GET";
11257 request1
.url
= GURL("https://www.google.com/");
11258 request1
.load_flags
= 0;
11259 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11261 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11262 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11263 EXPECT_EQ(OK
, callback
.WaitForResult());
11265 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11266 ASSERT_TRUE(response
!= NULL
);
11267 ASSERT_TRUE(response
->headers
.get() != NULL
);
11268 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11270 std::string response_data
;
11271 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11272 EXPECT_EQ("hello!", response_data
);
11274 // Preload cache entries into HostCache.
11275 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11276 AddressList ignored
;
11277 rv
= host_resolver
.Resolve(resolve_info
,
11280 callback
.callback(),
11283 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11284 rv
= callback
.WaitForResult();
11287 HttpRequestInfo request2
;
11288 request2
.method
= "GET";
11289 request2
.url
= GURL("https://www.gmail.com/");
11290 request2
.load_flags
= 0;
11291 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11293 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11294 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11295 EXPECT_EQ(OK
, callback
.WaitForResult());
11297 response
= trans2
.GetResponseInfo();
11298 ASSERT_TRUE(response
!= NULL
);
11299 ASSERT_TRUE(response
->headers
.get() != NULL
);
11300 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11301 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11302 EXPECT_TRUE(response
->was_npn_negotiated
);
11303 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11304 EXPECT_EQ("hello!", response_data
);
11307 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11309 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11310 const std::string https_url
= "https://www.google.com/";
11311 const std::string http_url
= "http://www.google.com:443/";
11313 // SPDY GET for HTTPS URL
11314 scoped_ptr
<SpdyFrame
> req1(
11315 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11317 MockWrite writes1
[] = {
11318 CreateMockWrite(*req1
, 0),
11321 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11322 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11323 MockRead reads1
[] = {
11324 CreateMockRead(*resp1
, 1),
11325 CreateMockRead(*body1
, 2),
11326 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11329 DelayedSocketData
data1(
11330 1, reads1
, arraysize(reads1
),
11331 writes1
, arraysize(writes1
));
11332 MockConnect
connect_data1(ASYNC
, OK
);
11333 data1
.set_connect_data(connect_data1
);
11335 // HTTP GET for the HTTP URL
11336 MockWrite writes2
[] = {
11337 MockWrite(ASYNC
, 4,
11338 "GET / HTTP/1.1\r\n"
11339 "Host: www.google.com:443\r\n"
11340 "Connection: keep-alive\r\n\r\n"),
11343 MockRead reads2
[] = {
11344 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11345 MockRead(ASYNC
, 6, "hello"),
11346 MockRead(ASYNC
, 7, OK
),
11349 DelayedSocketData
data2(
11350 1, reads2
, arraysize(reads2
),
11351 writes2
, arraysize(writes2
));
11353 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11354 ssl
.SetNextProto(GetParam());
11355 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11356 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11357 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11359 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11361 // Start the first transaction to set up the SpdySession
11362 HttpRequestInfo request1
;
11363 request1
.method
= "GET";
11364 request1
.url
= GURL(https_url
);
11365 request1
.load_flags
= 0;
11366 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11367 TestCompletionCallback callback1
;
11368 EXPECT_EQ(ERR_IO_PENDING
,
11369 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11370 base::MessageLoop::current()->RunUntilIdle();
11372 EXPECT_EQ(OK
, callback1
.WaitForResult());
11373 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11375 // Now, start the HTTP request
11376 HttpRequestInfo request2
;
11377 request2
.method
= "GET";
11378 request2
.url
= GURL(http_url
);
11379 request2
.load_flags
= 0;
11380 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11381 TestCompletionCallback callback2
;
11382 EXPECT_EQ(ERR_IO_PENDING
,
11383 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11384 base::MessageLoop::current()->RunUntilIdle();
11386 EXPECT_EQ(OK
, callback2
.WaitForResult());
11387 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11390 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11391 const std::string https_url
= "https://www.google.com/";
11392 const std::string http_url
= "http://www.google.com:443/";
11394 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11395 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
11397 scoped_ptr
<SpdyFrame
> req1(
11398 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11399 scoped_ptr
<SpdyFrame
> wrapped_req1(
11400 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11402 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11403 SpdyHeaderBlock req2_block
;
11404 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11405 req2_block
[spdy_util_
.GetPathKey()] =
11406 spdy_util_
.is_spdy2() ? http_url
.c_str() : "/";
11407 req2_block
[spdy_util_
.GetHostKey()] = "www.google.com:443";
11408 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11409 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11410 scoped_ptr
<SpdyFrame
> req2(
11411 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11413 MockWrite writes1
[] = {
11414 CreateMockWrite(*connect
, 0),
11415 CreateMockWrite(*wrapped_req1
, 2),
11416 CreateMockWrite(*req2
, 5),
11419 scoped_ptr
<SpdyFrame
> conn_resp(
11420 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11421 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11422 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11423 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11424 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11425 scoped_ptr
<SpdyFrame
> wrapped_body1(
11426 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11427 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11428 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11429 MockRead reads1
[] = {
11430 CreateMockRead(*conn_resp
, 1),
11431 CreateMockRead(*wrapped_resp1
, 3),
11432 CreateMockRead(*wrapped_body1
, 4),
11433 CreateMockRead(*resp2
, 6),
11434 CreateMockRead(*body2
, 7),
11435 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11438 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11439 writes1
, arraysize(writes1
));
11440 MockConnect
connect_data1(ASYNC
, OK
);
11441 data1
.set_connect_data(connect_data1
);
11443 session_deps_
.proxy_service
.reset(
11444 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11445 CapturingNetLog log
;
11446 session_deps_
.net_log
= &log
;
11447 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11448 ssl1
.SetNextProto(GetParam());
11449 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11450 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11451 ssl2
.SetNextProto(GetParam());
11452 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11453 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11455 scoped_refptr
<HttpNetworkSession
> session(
11456 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11458 // Start the first transaction to set up the SpdySession
11459 HttpRequestInfo request1
;
11460 request1
.method
= "GET";
11461 request1
.url
= GURL(https_url
);
11462 request1
.load_flags
= 0;
11463 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11464 TestCompletionCallback callback1
;
11465 EXPECT_EQ(ERR_IO_PENDING
,
11466 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11467 base::MessageLoop::current()->RunUntilIdle();
11470 EXPECT_EQ(OK
, callback1
.WaitForResult());
11471 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11473 LoadTimingInfo load_timing_info1
;
11474 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11475 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11476 CONNECT_TIMING_HAS_SSL_TIMES
);
11478 // Now, start the HTTP request
11479 HttpRequestInfo request2
;
11480 request2
.method
= "GET";
11481 request2
.url
= GURL(http_url
);
11482 request2
.load_flags
= 0;
11483 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11484 TestCompletionCallback callback2
;
11485 EXPECT_EQ(ERR_IO_PENDING
,
11486 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11487 base::MessageLoop::current()->RunUntilIdle();
11490 EXPECT_EQ(OK
, callback2
.WaitForResult());
11491 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11493 LoadTimingInfo load_timing_info2
;
11494 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11495 // The established SPDY sessions is considered reused by the HTTP request.
11496 TestLoadTimingReusedWithPac(load_timing_info2
);
11497 // HTTP requests over a SPDY session should have a different connection
11498 // socket_log_id than requests over a tunnel.
11499 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11502 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11503 session_deps_
.force_spdy_always
= true;
11504 const std::string https_url
= "https://www.google.com/";
11505 const std::string http_url
= "http://www.google.com:443/";
11507 // SPDY GET for HTTPS URL
11508 scoped_ptr
<SpdyFrame
> req1(
11509 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11510 // SPDY GET for the HTTP URL
11511 scoped_ptr
<SpdyFrame
> req2(
11512 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11514 MockWrite writes
[] = {
11515 CreateMockWrite(*req1
, 1),
11516 CreateMockWrite(*req2
, 4),
11519 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11520 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11521 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11522 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11523 MockRead reads
[] = {
11524 CreateMockRead(*resp1
, 2),
11525 CreateMockRead(*body1
, 3),
11526 CreateMockRead(*resp2
, 5),
11527 CreateMockRead(*body2
, 6),
11528 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11531 OrderedSocketData
data(reads
, arraysize(reads
),
11532 writes
, arraysize(writes
));
11534 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11535 ssl
.SetNextProto(GetParam());
11536 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11537 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11541 // Start the first transaction to set up the SpdySession
11542 HttpRequestInfo request1
;
11543 request1
.method
= "GET";
11544 request1
.url
= GURL(https_url
);
11545 request1
.load_flags
= 0;
11546 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11547 TestCompletionCallback callback1
;
11548 EXPECT_EQ(ERR_IO_PENDING
,
11549 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11550 base::MessageLoop::current()->RunUntilIdle();
11552 EXPECT_EQ(OK
, callback1
.WaitForResult());
11553 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11555 // Now, start the HTTP request
11556 HttpRequestInfo request2
;
11557 request2
.method
= "GET";
11558 request2
.url
= GURL(http_url
);
11559 request2
.load_flags
= 0;
11560 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11561 TestCompletionCallback callback2
;
11562 EXPECT_EQ(ERR_IO_PENDING
,
11563 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11564 base::MessageLoop::current()->RunUntilIdle();
11566 EXPECT_EQ(OK
, callback2
.WaitForResult());
11567 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11570 // Test that in the case where we have a SPDY session to a SPDY proxy
11571 // that we do not pool other origins that resolve to the same IP when
11572 // the certificate does not match the new origin.
11573 // http://crbug.com/134690
11574 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11575 const std::string url1
= "http://www.google.com/";
11576 const std::string url2
= "https://mail.google.com/";
11577 const std::string ip_addr
= "1.2.3.4";
11579 // SPDY GET for HTTP URL (through SPDY proxy)
11580 scoped_ptr
<SpdyHeaderBlock
> headers(
11581 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11582 scoped_ptr
<SpdyFrame
> req1(
11583 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
11585 MockWrite writes1
[] = {
11586 CreateMockWrite(*req1
, 0),
11589 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11590 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11591 MockRead reads1
[] = {
11592 CreateMockRead(*resp1
, 1),
11593 CreateMockRead(*body1
, 2),
11594 MockRead(ASYNC
, OK
, 3) // EOF
11597 scoped_ptr
<DeterministicSocketData
> data1(
11598 new DeterministicSocketData(reads1
, arraysize(reads1
),
11599 writes1
, arraysize(writes1
)));
11600 IPAddressNumber ip
;
11601 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11602 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11603 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11604 data1
->set_connect_data(connect_data1
);
11606 // SPDY GET for HTTPS URL (direct)
11607 scoped_ptr
<SpdyFrame
> req2(
11608 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11610 MockWrite writes2
[] = {
11611 CreateMockWrite(*req2
, 0),
11614 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11615 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11616 MockRead reads2
[] = {
11617 CreateMockRead(*resp2
, 1),
11618 CreateMockRead(*body2
, 2),
11619 MockRead(ASYNC
, OK
, 3) // EOF
11622 scoped_ptr
<DeterministicSocketData
> data2(
11623 new DeterministicSocketData(reads2
, arraysize(reads2
),
11624 writes2
, arraysize(writes2
)));
11625 MockConnect
connect_data2(ASYNC
, OK
);
11626 data2
->set_connect_data(connect_data2
);
11628 // Set up a proxy config that sends HTTP requests to a proxy, and
11629 // all others direct.
11630 ProxyConfig proxy_config
;
11631 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11632 CapturingProxyResolver
* capturing_proxy_resolver
=
11633 new CapturingProxyResolver();
11634 session_deps_
.proxy_service
.reset(new ProxyService(
11635 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11638 // Load a valid cert. Note, that this does not need to
11639 // be valid for proxy because the MockSSLClientSocket does
11640 // not actually verify it. But SpdySession will use this
11641 // to see if it is valid for the new origin
11642 base::FilePath certs_dir
= GetTestCertsDirectory();
11643 scoped_refptr
<X509Certificate
> server_cert(
11644 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11645 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
.get());
11647 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11648 ssl1
.SetNextProto(GetParam());
11649 ssl1
.cert
= server_cert
;
11650 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11651 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11654 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11655 ssl2
.SetNextProto(GetParam());
11656 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11657 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11660 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11661 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11662 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11664 scoped_refptr
<HttpNetworkSession
> session(
11665 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11667 // Start the first transaction to set up the SpdySession
11668 HttpRequestInfo request1
;
11669 request1
.method
= "GET";
11670 request1
.url
= GURL(url1
);
11671 request1
.load_flags
= 0;
11672 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11673 TestCompletionCallback callback1
;
11674 ASSERT_EQ(ERR_IO_PENDING
,
11675 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11678 ASSERT_TRUE(callback1
.have_result());
11679 EXPECT_EQ(OK
, callback1
.WaitForResult());
11680 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11682 // Now, start the HTTP request
11683 HttpRequestInfo request2
;
11684 request2
.method
= "GET";
11685 request2
.url
= GURL(url2
);
11686 request2
.load_flags
= 0;
11687 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11688 TestCompletionCallback callback2
;
11689 EXPECT_EQ(ERR_IO_PENDING
,
11690 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11691 base::MessageLoop::current()->RunUntilIdle();
11694 ASSERT_TRUE(callback2
.have_result());
11695 EXPECT_EQ(OK
, callback2
.WaitForResult());
11696 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11699 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11700 // error) in SPDY session, removes the socket from pool and closes the SPDY
11701 // session. Verify that new url's from the same HttpNetworkSession (and a new
11702 // SpdySession) do work. http://crbug.com/224701
11703 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11704 const std::string https_url
= "https://www.google.com/";
11706 MockRead reads1
[] = {
11707 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11710 scoped_ptr
<DeterministicSocketData
> data1(
11711 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11714 scoped_ptr
<SpdyFrame
> req2(
11715 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11716 MockWrite writes2
[] = {
11717 CreateMockWrite(*req2
, 0),
11720 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11721 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11722 MockRead reads2
[] = {
11723 CreateMockRead(*resp2
, 1),
11724 CreateMockRead(*body2
, 2),
11725 MockRead(ASYNC
, OK
, 3) // EOF
11728 scoped_ptr
<DeterministicSocketData
> data2(
11729 new DeterministicSocketData(reads2
, arraysize(reads2
),
11730 writes2
, arraysize(writes2
)));
11732 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11733 ssl1
.SetNextProto(GetParam());
11734 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11735 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11738 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11739 ssl2
.SetNextProto(GetParam());
11740 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11741 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11744 scoped_refptr
<HttpNetworkSession
> session(
11745 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11747 // Start the first transaction to set up the SpdySession and verify that
11748 // connection was closed.
11749 HttpRequestInfo request1
;
11750 request1
.method
= "GET";
11751 request1
.url
= GURL(https_url
);
11752 request1
.load_flags
= 0;
11753 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11754 TestCompletionCallback callback1
;
11755 EXPECT_EQ(ERR_IO_PENDING
,
11756 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11757 base::MessageLoop::current()->RunUntilIdle();
11758 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11760 // Now, start the second request and make sure it succeeds.
11761 HttpRequestInfo request2
;
11762 request2
.method
= "GET";
11763 request2
.url
= GURL(https_url
);
11764 request2
.load_flags
= 0;
11765 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11766 TestCompletionCallback callback2
;
11767 EXPECT_EQ(ERR_IO_PENDING
,
11768 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11769 base::MessageLoop::current()->RunUntilIdle();
11772 ASSERT_TRUE(callback2
.have_result());
11773 EXPECT_EQ(OK
, callback2
.WaitForResult());
11774 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11777 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11778 session_deps_
.next_protos
= SpdyNextProtos();
11779 ClientSocketPoolManager::set_max_sockets_per_group(
11780 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11781 ClientSocketPoolManager::set_max_sockets_per_pool(
11782 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11784 // Use two different hosts with different IPs so they don't get pooled.
11785 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11786 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11787 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11789 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11790 ssl1
.SetNextProto(GetParam());
11791 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11792 ssl2
.SetNextProto(GetParam());
11793 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11796 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11797 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11798 MockWrite spdy1_writes
[] = {
11799 CreateMockWrite(*host1_req
, 1),
11801 scoped_ptr
<SpdyFrame
> host1_resp(
11802 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11803 scoped_ptr
<SpdyFrame
> host1_resp_body(
11804 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11805 MockRead spdy1_reads
[] = {
11806 CreateMockRead(*host1_resp
, 2),
11807 CreateMockRead(*host1_resp_body
, 3),
11808 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11811 scoped_ptr
<OrderedSocketData
> spdy1_data(
11812 new OrderedSocketData(
11813 spdy1_reads
, arraysize(spdy1_reads
),
11814 spdy1_writes
, arraysize(spdy1_writes
)));
11815 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11817 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11818 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11819 MockWrite spdy2_writes
[] = {
11820 CreateMockWrite(*host2_req
, 1),
11822 scoped_ptr
<SpdyFrame
> host2_resp(
11823 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11824 scoped_ptr
<SpdyFrame
> host2_resp_body(
11825 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11826 MockRead spdy2_reads
[] = {
11827 CreateMockRead(*host2_resp
, 2),
11828 CreateMockRead(*host2_resp_body
, 3),
11829 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11832 scoped_ptr
<OrderedSocketData
> spdy2_data(
11833 new OrderedSocketData(
11834 spdy2_reads
, arraysize(spdy2_reads
),
11835 spdy2_writes
, arraysize(spdy2_writes
)));
11836 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11838 MockWrite http_write
[] = {
11839 MockWrite("GET / HTTP/1.1\r\n"
11840 "Host: www.a.com\r\n"
11841 "Connection: keep-alive\r\n\r\n"),
11844 MockRead http_read
[] = {
11845 MockRead("HTTP/1.1 200 OK\r\n"),
11846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11847 MockRead("Content-Length: 6\r\n\r\n"),
11848 MockRead("hello!"),
11850 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11851 http_write
, arraysize(http_write
));
11852 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11854 HostPortPair
host_port_pair_a("www.a.com", 443);
11855 SpdySessionKey
spdy_session_key_a(
11856 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11858 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11860 TestCompletionCallback callback
;
11861 HttpRequestInfo request1
;
11862 request1
.method
= "GET";
11863 request1
.url
= GURL("https://www.a.com/");
11864 request1
.load_flags
= 0;
11865 scoped_ptr
<HttpNetworkTransaction
> trans(
11866 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11868 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11869 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11870 EXPECT_EQ(OK
, callback
.WaitForResult());
11872 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11873 ASSERT_TRUE(response
!= NULL
);
11874 ASSERT_TRUE(response
->headers
.get() != NULL
);
11875 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11876 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11877 EXPECT_TRUE(response
->was_npn_negotiated
);
11879 std::string response_data
;
11880 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11881 EXPECT_EQ("hello!", response_data
);
11884 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11886 HostPortPair
host_port_pair_b("www.b.com", 443);
11887 SpdySessionKey
spdy_session_key_b(
11888 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11890 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11891 HttpRequestInfo request2
;
11892 request2
.method
= "GET";
11893 request2
.url
= GURL("https://www.b.com/");
11894 request2
.load_flags
= 0;
11895 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11897 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11898 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11899 EXPECT_EQ(OK
, callback
.WaitForResult());
11901 response
= trans
->GetResponseInfo();
11902 ASSERT_TRUE(response
!= NULL
);
11903 ASSERT_TRUE(response
->headers
.get() != NULL
);
11904 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11905 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11906 EXPECT_TRUE(response
->was_npn_negotiated
);
11907 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11908 EXPECT_EQ("hello!", response_data
);
11910 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11912 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11914 HostPortPair
host_port_pair_a1("www.a.com", 80);
11915 SpdySessionKey
spdy_session_key_a1(
11916 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11918 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11919 HttpRequestInfo request3
;
11920 request3
.method
= "GET";
11921 request3
.url
= GURL("http://www.a.com/");
11922 request3
.load_flags
= 0;
11923 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11925 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11927 EXPECT_EQ(OK
, callback
.WaitForResult());
11929 response
= trans
->GetResponseInfo();
11930 ASSERT_TRUE(response
!= NULL
);
11931 ASSERT_TRUE(response
->headers
.get() != NULL
);
11932 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11933 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11934 EXPECT_FALSE(response
->was_npn_negotiated
);
11935 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11936 EXPECT_EQ("hello!", response_data
);
11938 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11940 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11943 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11944 HttpRequestInfo request
;
11945 request
.method
= "GET";
11946 request
.url
= GURL("http://www.google.com/");
11947 request
.load_flags
= 0;
11949 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11950 scoped_ptr
<HttpTransaction
> trans(
11951 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11953 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11954 StaticSocketDataProvider data
;
11955 data
.set_connect_data(mock_connect
);
11956 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11958 TestCompletionCallback callback
;
11960 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11961 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11963 rv
= callback
.WaitForResult();
11964 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11966 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11968 // We don't care whether this succeeds or fails, but it shouldn't crash.
11969 HttpRequestHeaders request_headers
;
11970 trans
->GetFullRequestHeaders(&request_headers
);
11973 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11974 HttpRequestInfo request
;
11975 request
.method
= "GET";
11976 request
.url
= GURL("http://www.google.com/");
11977 request
.load_flags
= 0;
11979 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11980 scoped_ptr
<HttpTransaction
> trans(
11981 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11983 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11984 StaticSocketDataProvider data
;
11985 data
.set_connect_data(mock_connect
);
11986 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11988 TestCompletionCallback callback
;
11990 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11991 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11993 rv
= callback
.WaitForResult();
11994 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11996 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11998 // We don't care whether this succeeds or fails, but it shouldn't crash.
11999 HttpRequestHeaders request_headers
;
12000 trans
->GetFullRequestHeaders(&request_headers
);
12003 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12004 HttpRequestInfo request
;
12005 request
.method
= "GET";
12006 request
.url
= GURL("http://www.google.com/");
12007 request
.load_flags
= 0;
12009 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12010 scoped_ptr
<HttpTransaction
> trans(
12011 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12013 MockWrite data_writes
[] = {
12014 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12016 MockRead data_reads
[] = {
12017 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12020 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12021 data_writes
, arraysize(data_writes
));
12022 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12024 TestCompletionCallback callback
;
12026 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12027 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12029 rv
= callback
.WaitForResult();
12030 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12032 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12034 HttpRequestHeaders request_headers
;
12035 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12036 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12039 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12040 HttpRequestInfo request
;
12041 request
.method
= "GET";
12042 request
.url
= GURL("http://www.google.com/");
12043 request
.load_flags
= 0;
12045 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12046 scoped_ptr
<HttpTransaction
> trans(
12047 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12049 MockWrite data_writes
[] = {
12050 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12052 MockRead data_reads
[] = {
12053 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12056 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12057 data_writes
, arraysize(data_writes
));
12058 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12060 TestCompletionCallback callback
;
12062 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12063 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12065 rv
= callback
.WaitForResult();
12066 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12068 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12070 HttpRequestHeaders request_headers
;
12071 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12072 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12075 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12076 HttpRequestInfo request
;
12077 request
.method
= "GET";
12078 request
.url
= GURL("http://www.google.com/");
12079 request
.load_flags
= 0;
12081 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12082 scoped_ptr
<HttpTransaction
> trans(
12083 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12085 MockWrite data_writes
[] = {
12086 MockWrite("GET / HTTP/1.1\r\n"
12087 "Host: www.google.com\r\n"
12088 "Connection: keep-alive\r\n\r\n"),
12090 MockRead data_reads
[] = {
12091 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12094 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12095 data_writes
, arraysize(data_writes
));
12096 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12098 TestCompletionCallback callback
;
12100 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12101 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12103 rv
= callback
.WaitForResult();
12104 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12106 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12108 HttpRequestHeaders request_headers
;
12109 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12110 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12113 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12114 HttpRequestInfo request
;
12115 request
.method
= "GET";
12116 request
.url
= GURL("http://www.google.com/");
12117 request
.load_flags
= 0;
12119 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12120 scoped_ptr
<HttpTransaction
> trans(
12121 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12123 MockWrite data_writes
[] = {
12124 MockWrite("GET / HTTP/1.1\r\n"
12125 "Host: www.google.com\r\n"
12126 "Connection: keep-alive\r\n\r\n"),
12128 MockRead data_reads
[] = {
12129 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12132 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12133 data_writes
, arraysize(data_writes
));
12134 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12136 TestCompletionCallback callback
;
12138 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12139 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12141 rv
= callback
.WaitForResult();
12142 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12144 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12146 HttpRequestHeaders request_headers
;
12147 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12148 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12151 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12152 HttpRequestInfo request
;
12153 request
.method
= "GET";
12154 request
.url
= GURL("http://www.google.com/");
12155 request
.load_flags
= 0;
12156 request
.extra_headers
.SetHeader("X-Foo", "bar");
12158 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12159 scoped_ptr
<HttpTransaction
> trans(
12160 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12162 MockWrite data_writes
[] = {
12163 MockWrite("GET / HTTP/1.1\r\n"
12164 "Host: www.google.com\r\n"
12165 "Connection: keep-alive\r\n"
12166 "X-Foo: bar\r\n\r\n"),
12168 MockRead data_reads
[] = {
12169 MockRead("HTTP/1.1 200 OK\r\n"
12170 "Content-Length: 5\r\n\r\n"
12172 MockRead(ASYNC
, ERR_UNEXPECTED
),
12175 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12176 data_writes
, arraysize(data_writes
));
12177 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12179 TestCompletionCallback callback
;
12181 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12182 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12184 rv
= callback
.WaitForResult();
12187 HttpRequestHeaders request_headers
;
12188 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12190 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12191 EXPECT_EQ("bar", foo
);
12196 // Fake HttpStream that simply records calls to SetPriority().
12197 class FakeStream
: public HttpStream
,
12198 public base::SupportsWeakPtr
<FakeStream
> {
12200 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12201 ~FakeStream() override
{}
12203 RequestPriority
priority() const { return priority_
; }
12205 int InitializeStream(const HttpRequestInfo
* request_info
,
12206 RequestPriority priority
,
12207 const BoundNetLog
& net_log
,
12208 const CompletionCallback
& callback
) override
{
12209 return ERR_IO_PENDING
;
12212 int SendRequest(const HttpRequestHeaders
& request_headers
,
12213 HttpResponseInfo
* response
,
12214 const CompletionCallback
& callback
) override
{
12216 return ERR_UNEXPECTED
;
12219 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12221 return ERR_UNEXPECTED
;
12224 int ReadResponseBody(IOBuffer
* buf
,
12226 const CompletionCallback
& callback
) override
{
12228 return ERR_UNEXPECTED
;
12231 void Close(bool not_reusable
) override
{}
12233 bool IsResponseBodyComplete() const override
{
12238 bool CanFindEndOfResponse() const override
{ return false; }
12240 bool IsConnectionReused() const override
{
12245 void SetConnectionReused() override
{ ADD_FAILURE(); }
12247 bool IsConnectionReusable() const override
{
12252 int64
GetTotalReceivedBytes() const override
{
12257 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12262 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
12264 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12268 bool IsSpdyHttpStream() const override
{
12273 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
12275 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12277 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
12279 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
12282 RequestPriority priority_
;
12284 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12287 // Fake HttpStreamRequest that simply records calls to SetPriority()
12288 // and vends FakeStreams with its current priority.
12289 class FakeStreamRequest
: public HttpStreamRequest
,
12290 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12292 FakeStreamRequest(RequestPriority priority
,
12293 HttpStreamRequest::Delegate
* delegate
)
12294 : priority_(priority
),
12295 delegate_(delegate
),
12296 websocket_stream_create_helper_(NULL
) {}
12298 FakeStreamRequest(RequestPriority priority
,
12299 HttpStreamRequest::Delegate
* delegate
,
12300 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12301 : priority_(priority
),
12302 delegate_(delegate
),
12303 websocket_stream_create_helper_(create_helper
) {}
12305 ~FakeStreamRequest() override
{}
12307 RequestPriority
priority() const { return priority_
; }
12309 const WebSocketHandshakeStreamBase::CreateHelper
*
12310 websocket_stream_create_helper() const {
12311 return websocket_stream_create_helper_
;
12314 // Create a new FakeStream and pass it to the request's
12315 // delegate. Returns a weak pointer to the FakeStream.
12316 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12317 FakeStream
* fake_stream
= new FakeStream(priority_
);
12318 // Do this before calling OnStreamReady() as OnStreamReady() may
12319 // immediately delete |fake_stream|.
12320 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12321 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12322 return weak_stream
;
12325 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
12327 return ERR_UNEXPECTED
;
12330 LoadState
GetLoadState() const override
{
12332 return LoadState();
12335 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12337 bool was_npn_negotiated() const override
{ return false; }
12339 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
12341 bool using_spdy() const override
{ return false; }
12344 RequestPriority priority_
;
12345 HttpStreamRequest::Delegate
* const delegate_
;
12346 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12348 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12351 // Fake HttpStreamFactory that vends FakeStreamRequests.
12352 class FakeStreamFactory
: public HttpStreamFactory
{
12354 FakeStreamFactory() {}
12355 ~FakeStreamFactory() override
{}
12357 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12358 // RequestStream() (which may be NULL if it was destroyed already).
12359 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12360 return last_stream_request_
;
12363 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
12364 RequestPriority priority
,
12365 const SSLConfig
& server_ssl_config
,
12366 const SSLConfig
& proxy_ssl_config
,
12367 HttpStreamRequest::Delegate
* delegate
,
12368 const BoundNetLog
& net_log
) override
{
12369 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12370 last_stream_request_
= fake_request
->AsWeakPtr();
12371 return fake_request
;
12374 HttpStreamRequest
* RequestWebSocketHandshakeStream(
12375 const HttpRequestInfo
& info
,
12376 RequestPriority priority
,
12377 const SSLConfig
& server_ssl_config
,
12378 const SSLConfig
& proxy_ssl_config
,
12379 HttpStreamRequest::Delegate
* delegate
,
12380 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12381 const BoundNetLog
& net_log
) override
{
12382 FakeStreamRequest
* fake_request
=
12383 new FakeStreamRequest(priority
, delegate
, create_helper
);
12384 last_stream_request_
= fake_request
->AsWeakPtr();
12385 return fake_request
;
12388 void PreconnectStreams(int num_streams
,
12389 const HttpRequestInfo
& info
,
12390 RequestPriority priority
,
12391 const SSLConfig
& server_ssl_config
,
12392 const SSLConfig
& proxy_ssl_config
) override
{
12396 const HostMappingRules
* GetHostMappingRules() const override
{
12402 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12404 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12407 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12409 class FakeWebSocketStreamCreateHelper
:
12410 public WebSocketHandshakeStreamBase::CreateHelper
{
12412 WebSocketHandshakeStreamBase
* CreateBasicStream(
12413 scoped_ptr
<ClientSocketHandle
> connection
,
12414 bool using_proxy
) override
{
12419 WebSocketHandshakeStreamBase
* CreateSpdyStream(
12420 const base::WeakPtr
<SpdySession
>& session
,
12421 bool use_relative_url
) override
{
12426 ~FakeWebSocketStreamCreateHelper() override
{}
12428 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12430 return scoped_ptr
<WebSocketStream
>();
12436 // Make sure that HttpNetworkTransaction passes on its priority to its
12437 // stream request on start.
12438 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12439 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12440 HttpNetworkSessionPeer
peer(session
);
12441 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12442 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12444 HttpNetworkTransaction
trans(LOW
, session
.get());
12446 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12448 HttpRequestInfo request
;
12449 TestCompletionCallback callback
;
12450 EXPECT_EQ(ERR_IO_PENDING
,
12451 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12453 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12454 fake_factory
->last_stream_request();
12455 ASSERT_TRUE(fake_request
!= NULL
);
12456 EXPECT_EQ(LOW
, fake_request
->priority());
12459 // Make sure that HttpNetworkTransaction passes on its priority
12460 // updates to its stream request.
12461 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12462 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12463 HttpNetworkSessionPeer
peer(session
);
12464 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12465 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12467 HttpNetworkTransaction
trans(LOW
, session
.get());
12469 HttpRequestInfo request
;
12470 TestCompletionCallback callback
;
12471 EXPECT_EQ(ERR_IO_PENDING
,
12472 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12474 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12475 fake_factory
->last_stream_request();
12476 ASSERT_TRUE(fake_request
!= NULL
);
12477 EXPECT_EQ(LOW
, fake_request
->priority());
12479 trans
.SetPriority(LOWEST
);
12480 ASSERT_TRUE(fake_request
!= NULL
);
12481 EXPECT_EQ(LOWEST
, fake_request
->priority());
12484 // Make sure that HttpNetworkTransaction passes on its priority
12485 // updates to its stream.
12486 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12487 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12488 HttpNetworkSessionPeer
peer(session
);
12489 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12490 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12492 HttpNetworkTransaction
trans(LOW
, session
.get());
12494 HttpRequestInfo request
;
12495 TestCompletionCallback callback
;
12496 EXPECT_EQ(ERR_IO_PENDING
,
12497 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12499 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12500 fake_factory
->last_stream_request();
12501 ASSERT_TRUE(fake_request
!= NULL
);
12502 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12503 ASSERT_TRUE(fake_stream
!= NULL
);
12504 EXPECT_EQ(LOW
, fake_stream
->priority());
12506 trans
.SetPriority(LOWEST
);
12507 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12510 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12511 // The same logic needs to be tested for both ws: and wss: schemes, but this
12512 // test is already parameterised on NextProto, so it uses a loop to verify
12513 // that the different schemes work.
12514 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
12515 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
12516 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12517 HttpNetworkSessionPeer
peer(session
);
12518 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12519 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
12520 peer
.SetHttpStreamFactoryForWebSocket(
12521 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12523 HttpNetworkTransaction
trans(LOW
, session
.get());
12524 trans
.SetWebSocketHandshakeStreamCreateHelper(
12525 &websocket_stream_create_helper
);
12527 HttpRequestInfo request
;
12528 TestCompletionCallback callback
;
12529 request
.method
= "GET";
12530 request
.url
= GURL(test_cases
[i
]);
12532 EXPECT_EQ(ERR_IO_PENDING
,
12533 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12535 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12536 fake_factory
->last_stream_request();
12537 ASSERT_TRUE(fake_request
!= NULL
);
12538 EXPECT_EQ(&websocket_stream_create_helper
,
12539 fake_request
->websocket_stream_create_helper());
12543 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12544 // if the transport socket pool is stalled on the global socket limit.
12545 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
12546 ClientSocketPoolManager::set_max_sockets_per_group(
12547 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12548 ClientSocketPoolManager::set_max_sockets_per_pool(
12549 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12551 // Set up SSL request.
12553 HttpRequestInfo ssl_request
;
12554 ssl_request
.method
= "GET";
12555 ssl_request
.url
= GURL("https://www.google.com/");
12557 MockWrite ssl_writes
[] = {
12558 MockWrite("GET / HTTP/1.1\r\n"
12559 "Host: www.google.com\r\n"
12560 "Connection: keep-alive\r\n\r\n"),
12562 MockRead ssl_reads
[] = {
12563 MockRead("HTTP/1.1 200 OK\r\n"),
12564 MockRead("Content-Length: 11\r\n\r\n"),
12565 MockRead("hello world"),
12566 MockRead(SYNCHRONOUS
, OK
),
12568 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
12569 ssl_writes
, arraysize(ssl_writes
));
12570 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12572 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12573 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12575 // Set up HTTP request.
12577 HttpRequestInfo http_request
;
12578 http_request
.method
= "GET";
12579 http_request
.url
= GURL("http://www.google.com/");
12581 MockWrite http_writes
[] = {
12582 MockWrite("GET / HTTP/1.1\r\n"
12583 "Host: www.google.com\r\n"
12584 "Connection: keep-alive\r\n\r\n"),
12586 MockRead http_reads
[] = {
12587 MockRead("HTTP/1.1 200 OK\r\n"),
12588 MockRead("Content-Length: 7\r\n\r\n"),
12589 MockRead("falafel"),
12590 MockRead(SYNCHRONOUS
, OK
),
12592 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12593 http_writes
, arraysize(http_writes
));
12594 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12596 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12598 // Start the SSL request.
12599 TestCompletionCallback ssl_callback
;
12600 scoped_ptr
<HttpTransaction
> ssl_trans(
12601 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12602 ASSERT_EQ(ERR_IO_PENDING
,
12603 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
12606 // Start the HTTP request. Pool should stall.
12607 TestCompletionCallback http_callback
;
12608 scoped_ptr
<HttpTransaction
> http_trans(
12609 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12610 ASSERT_EQ(ERR_IO_PENDING
,
12611 http_trans
->Start(&http_request
, http_callback
.callback(),
12613 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
12615 // Wait for response from SSL request.
12616 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
12617 std::string response_data
;
12618 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
12619 EXPECT_EQ("hello world", response_data
);
12621 // The SSL socket should automatically be closed, so the HTTP request can
12623 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
12624 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
12626 // The HTTP request can now complete.
12627 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12628 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12629 EXPECT_EQ("falafel", response_data
);
12631 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
12634 // Tests that when a SSL connection is established but there's no corresponding
12635 // request that needs it, the new socket is closed if the transport socket pool
12636 // is stalled on the global socket limit.
12637 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
12638 ClientSocketPoolManager::set_max_sockets_per_group(
12639 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12640 ClientSocketPoolManager::set_max_sockets_per_pool(
12641 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12643 // Set up an ssl request.
12645 HttpRequestInfo ssl_request
;
12646 ssl_request
.method
= "GET";
12647 ssl_request
.url
= GURL("https://www.foopy.com/");
12649 // No data will be sent on the SSL socket.
12650 StaticSocketDataProvider ssl_data
;
12651 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12653 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12654 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12656 // Set up HTTP request.
12658 HttpRequestInfo http_request
;
12659 http_request
.method
= "GET";
12660 http_request
.url
= GURL("http://www.google.com/");
12662 MockWrite http_writes
[] = {
12663 MockWrite("GET / HTTP/1.1\r\n"
12664 "Host: www.google.com\r\n"
12665 "Connection: keep-alive\r\n\r\n"),
12667 MockRead http_reads
[] = {
12668 MockRead("HTTP/1.1 200 OK\r\n"),
12669 MockRead("Content-Length: 7\r\n\r\n"),
12670 MockRead("falafel"),
12671 MockRead(SYNCHRONOUS
, OK
),
12673 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12674 http_writes
, arraysize(http_writes
));
12675 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12677 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12679 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12680 // cancelled when a normal transaction is cancelled.
12681 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
12682 net::SSLConfig ssl_config
;
12683 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
12684 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
12685 ssl_config
, ssl_config
);
12686 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
12688 // Start the HTTP request. Pool should stall.
12689 TestCompletionCallback http_callback
;
12690 scoped_ptr
<HttpTransaction
> http_trans(
12691 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12692 ASSERT_EQ(ERR_IO_PENDING
,
12693 http_trans
->Start(&http_request
, http_callback
.callback(),
12695 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
12697 // The SSL connection will automatically be closed once the connection is
12698 // established, to let the HTTP request start.
12699 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12700 std::string response_data
;
12701 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12702 EXPECT_EQ("falafel", response_data
);
12704 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
12707 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
12708 ScopedVector
<UploadElementReader
> element_readers
;
12709 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12710 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12712 HttpRequestInfo request
;
12713 request
.method
= "POST";
12714 request
.url
= GURL("http://www.foo.com/");
12715 request
.upload_data_stream
= &upload_data_stream
;
12716 request
.load_flags
= 0;
12718 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12719 scoped_ptr
<HttpTransaction
> trans(
12720 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12721 // Send headers successfully, but get an error while sending the body.
12722 MockWrite data_writes
[] = {
12723 MockWrite("POST / HTTP/1.1\r\n"
12724 "Host: www.foo.com\r\n"
12725 "Connection: keep-alive\r\n"
12726 "Content-Length: 3\r\n\r\n"),
12727 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12730 MockRead data_reads
[] = {
12731 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12732 MockRead("hello world"),
12733 MockRead(SYNCHRONOUS
, OK
),
12735 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12736 arraysize(data_writes
));
12737 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12739 TestCompletionCallback callback
;
12741 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12742 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12744 rv
= callback
.WaitForResult();
12747 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12748 ASSERT_TRUE(response
!= NULL
);
12750 EXPECT_TRUE(response
->headers
.get() != NULL
);
12751 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12753 std::string response_data
;
12754 rv
= ReadTransaction(trans
.get(), &response_data
);
12756 EXPECT_EQ("hello world", response_data
);
12759 // This test makes sure the retry logic doesn't trigger when reading an error
12760 // response from a server that rejected a POST with a CONNECTION_RESET.
12761 TEST_P(HttpNetworkTransactionTest
,
12762 PostReadsErrorResponseAfterResetOnReusedSocket
) {
12763 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12764 MockWrite data_writes
[] = {
12765 MockWrite("GET / HTTP/1.1\r\n"
12766 "Host: www.foo.com\r\n"
12767 "Connection: keep-alive\r\n\r\n"),
12768 MockWrite("POST / HTTP/1.1\r\n"
12769 "Host: www.foo.com\r\n"
12770 "Connection: keep-alive\r\n"
12771 "Content-Length: 3\r\n\r\n"),
12772 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12775 MockRead data_reads
[] = {
12776 MockRead("HTTP/1.1 200 Peachy\r\n"
12777 "Content-Length: 14\r\n\r\n"),
12778 MockRead("first response"),
12779 MockRead("HTTP/1.1 400 Not OK\r\n"
12780 "Content-Length: 15\r\n\r\n"),
12781 MockRead("second response"),
12782 MockRead(SYNCHRONOUS
, OK
),
12784 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12785 arraysize(data_writes
));
12786 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12788 TestCompletionCallback callback
;
12789 HttpRequestInfo request1
;
12790 request1
.method
= "GET";
12791 request1
.url
= GURL("http://www.foo.com/");
12792 request1
.load_flags
= 0;
12794 scoped_ptr
<HttpTransaction
> trans1(
12795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12796 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
12797 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12799 rv
= callback
.WaitForResult();
12802 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12803 ASSERT_TRUE(response1
!= NULL
);
12805 EXPECT_TRUE(response1
->headers
.get() != NULL
);
12806 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
12808 std::string response_data1
;
12809 rv
= ReadTransaction(trans1
.get(), &response_data1
);
12811 EXPECT_EQ("first response", response_data1
);
12812 // Delete the transaction to release the socket back into the socket pool.
12815 ScopedVector
<UploadElementReader
> element_readers
;
12816 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12817 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12819 HttpRequestInfo request2
;
12820 request2
.method
= "POST";
12821 request2
.url
= GURL("http://www.foo.com/");
12822 request2
.upload_data_stream
= &upload_data_stream
;
12823 request2
.load_flags
= 0;
12825 scoped_ptr
<HttpTransaction
> trans2(
12826 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12827 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
12828 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12830 rv
= callback
.WaitForResult();
12833 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
12834 ASSERT_TRUE(response2
!= NULL
);
12836 EXPECT_TRUE(response2
->headers
.get() != NULL
);
12837 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
12839 std::string response_data2
;
12840 rv
= ReadTransaction(trans2
.get(), &response_data2
);
12842 EXPECT_EQ("second response", response_data2
);
12845 TEST_P(HttpNetworkTransactionTest
,
12846 PostReadsErrorResponseAfterResetPartialBodySent
) {
12847 ScopedVector
<UploadElementReader
> element_readers
;
12848 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12849 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12851 HttpRequestInfo request
;
12852 request
.method
= "POST";
12853 request
.url
= GURL("http://www.foo.com/");
12854 request
.upload_data_stream
= &upload_data_stream
;
12855 request
.load_flags
= 0;
12857 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12858 scoped_ptr
<HttpTransaction
> trans(
12859 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12860 // Send headers successfully, but get an error while sending the body.
12861 MockWrite data_writes
[] = {
12862 MockWrite("POST / HTTP/1.1\r\n"
12863 "Host: www.foo.com\r\n"
12864 "Connection: keep-alive\r\n"
12865 "Content-Length: 3\r\n\r\n"
12867 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12870 MockRead data_reads
[] = {
12871 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12872 MockRead("hello world"),
12873 MockRead(SYNCHRONOUS
, OK
),
12875 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12876 arraysize(data_writes
));
12877 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12879 TestCompletionCallback callback
;
12881 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12882 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12884 rv
= callback
.WaitForResult();
12887 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12888 ASSERT_TRUE(response
!= NULL
);
12890 EXPECT_TRUE(response
->headers
.get() != NULL
);
12891 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12893 std::string response_data
;
12894 rv
= ReadTransaction(trans
.get(), &response_data
);
12896 EXPECT_EQ("hello world", response_data
);
12899 // This tests the more common case than the previous test, where headers and
12900 // body are not merged into a single request.
12901 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
12902 ScopedVector
<UploadElementReader
> element_readers
;
12903 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12904 ChunkedUploadDataStream
upload_data_stream(0);
12906 HttpRequestInfo request
;
12907 request
.method
= "POST";
12908 request
.url
= GURL("http://www.foo.com/");
12909 request
.upload_data_stream
= &upload_data_stream
;
12910 request
.load_flags
= 0;
12912 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12913 scoped_ptr
<HttpTransaction
> trans(
12914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12915 // Send headers successfully, but get an error while sending the body.
12916 MockWrite data_writes
[] = {
12917 MockWrite("POST / HTTP/1.1\r\n"
12918 "Host: www.foo.com\r\n"
12919 "Connection: keep-alive\r\n"
12920 "Transfer-Encoding: chunked\r\n\r\n"),
12921 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12924 MockRead data_reads
[] = {
12925 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12926 MockRead("hello world"),
12927 MockRead(SYNCHRONOUS
, OK
),
12929 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12930 arraysize(data_writes
));
12931 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12933 TestCompletionCallback callback
;
12935 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12937 // Make sure the headers are sent before adding a chunk. This ensures that
12938 // they can't be merged with the body in a single send. Not currently
12939 // necessary since a chunked body is never merged with headers, but this makes
12940 // the test more future proof.
12941 base::RunLoop().RunUntilIdle();
12943 upload_data_stream
.AppendData("last chunk", 10, true);
12945 rv
= callback
.WaitForResult();
12948 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12949 ASSERT_TRUE(response
!= NULL
);
12951 EXPECT_TRUE(response
->headers
.get() != NULL
);
12952 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12954 std::string response_data
;
12955 rv
= ReadTransaction(trans
.get(), &response_data
);
12957 EXPECT_EQ("hello world", response_data
);
12960 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
12961 ScopedVector
<UploadElementReader
> element_readers
;
12962 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12963 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12965 HttpRequestInfo request
;
12966 request
.method
= "POST";
12967 request
.url
= GURL("http://www.foo.com/");
12968 request
.upload_data_stream
= &upload_data_stream
;
12969 request
.load_flags
= 0;
12971 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12972 scoped_ptr
<HttpTransaction
> trans(
12973 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12975 MockWrite data_writes
[] = {
12976 MockWrite("POST / HTTP/1.1\r\n"
12977 "Host: www.foo.com\r\n"
12978 "Connection: keep-alive\r\n"
12979 "Content-Length: 3\r\n\r\n"),
12980 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12983 MockRead data_reads
[] = {
12984 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12985 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12986 MockRead("hello world"),
12987 MockRead(SYNCHRONOUS
, OK
),
12989 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12990 arraysize(data_writes
));
12991 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12993 TestCompletionCallback callback
;
12995 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12996 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12998 rv
= callback
.WaitForResult();
13001 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13002 ASSERT_TRUE(response
!= NULL
);
13004 EXPECT_TRUE(response
->headers
.get() != NULL
);
13005 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13007 std::string response_data
;
13008 rv
= ReadTransaction(trans
.get(), &response_data
);
13010 EXPECT_EQ("hello world", response_data
);
13013 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13014 ScopedVector
<UploadElementReader
> element_readers
;
13015 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13016 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13018 HttpRequestInfo request
;
13019 request
.method
= "POST";
13020 request
.url
= GURL("http://www.foo.com/");
13021 request
.upload_data_stream
= &upload_data_stream
;
13022 request
.load_flags
= 0;
13024 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13025 scoped_ptr
<HttpTransaction
> trans(
13026 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13027 // Send headers successfully, but get an error while sending the body.
13028 MockWrite data_writes
[] = {
13029 MockWrite("POST / HTTP/1.1\r\n"
13030 "Host: www.foo.com\r\n"
13031 "Connection: keep-alive\r\n"
13032 "Content-Length: 3\r\n\r\n"),
13033 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13036 MockRead data_reads
[] = {
13037 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13038 MockRead("hello world"),
13039 MockRead(SYNCHRONOUS
, OK
),
13041 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13042 arraysize(data_writes
));
13043 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13045 TestCompletionCallback callback
;
13047 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13048 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13050 rv
= callback
.WaitForResult();
13051 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13053 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13054 EXPECT_TRUE(response
== NULL
);
13057 TEST_P(HttpNetworkTransactionTest
,
13058 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13059 ScopedVector
<UploadElementReader
> element_readers
;
13060 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13061 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13063 HttpRequestInfo request
;
13064 request
.method
= "POST";
13065 request
.url
= GURL("http://www.foo.com/");
13066 request
.upload_data_stream
= &upload_data_stream
;
13067 request
.load_flags
= 0;
13069 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13070 scoped_ptr
<HttpTransaction
> trans(
13071 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13072 // Send headers successfully, but get an error while sending the body.
13073 MockWrite data_writes
[] = {
13074 MockWrite("POST / HTTP/1.1\r\n"
13075 "Host: www.foo.com\r\n"
13076 "Connection: keep-alive\r\n"
13077 "Content-Length: 3\r\n\r\n"),
13078 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13081 MockRead data_reads
[] = {
13082 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13083 MockRead("HTTP/1.0 302 Redirect\r\n"),
13084 MockRead("Location: http://somewhere-else.com/\r\n"),
13085 MockRead("Content-Length: 0\r\n\r\n"),
13086 MockRead(SYNCHRONOUS
, OK
),
13088 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13089 arraysize(data_writes
));
13090 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13092 TestCompletionCallback callback
;
13094 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13097 rv
= callback
.WaitForResult();
13098 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13100 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13101 EXPECT_TRUE(response
== NULL
);
13104 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13105 ScopedVector
<UploadElementReader
> element_readers
;
13106 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13107 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13109 HttpRequestInfo request
;
13110 request
.method
= "POST";
13111 request
.url
= GURL("http://www.foo.com/");
13112 request
.upload_data_stream
= &upload_data_stream
;
13113 request
.load_flags
= 0;
13115 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13116 scoped_ptr
<HttpTransaction
> trans(
13117 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13118 // Send headers successfully, but get an error while sending the body.
13119 MockWrite data_writes
[] = {
13120 MockWrite("POST / HTTP/1.1\r\n"
13121 "Host: www.foo.com\r\n"
13122 "Connection: keep-alive\r\n"
13123 "Content-Length: 3\r\n\r\n"),
13124 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13127 MockRead data_reads
[] = {
13128 MockRead("HTTP 0.9 rocks!"),
13129 MockRead(SYNCHRONOUS
, OK
),
13131 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13132 arraysize(data_writes
));
13133 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13135 TestCompletionCallback callback
;
13137 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13138 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13140 rv
= callback
.WaitForResult();
13141 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13143 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13144 EXPECT_TRUE(response
== NULL
);
13147 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13148 ScopedVector
<UploadElementReader
> element_readers
;
13149 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13150 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13152 HttpRequestInfo request
;
13153 request
.method
= "POST";
13154 request
.url
= GURL("http://www.foo.com/");
13155 request
.upload_data_stream
= &upload_data_stream
;
13156 request
.load_flags
= 0;
13158 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13159 scoped_ptr
<HttpTransaction
> trans(
13160 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13161 // Send headers successfully, but get an error while sending the body.
13162 MockWrite data_writes
[] = {
13163 MockWrite("POST / HTTP/1.1\r\n"
13164 "Host: www.foo.com\r\n"
13165 "Connection: keep-alive\r\n"
13166 "Content-Length: 3\r\n\r\n"),
13167 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13170 MockRead data_reads
[] = {
13171 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13172 MockRead(SYNCHRONOUS
, OK
),
13174 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13175 arraysize(data_writes
));
13176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13178 TestCompletionCallback callback
;
13180 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13183 rv
= callback
.WaitForResult();
13184 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13187 EXPECT_TRUE(response
== NULL
);