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/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/test/test_file_util.h"
24 #include "net/base/auth.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_errors.h"
31 #include "net/base/request_priority.h"
32 #include "net/base/test_completion_callback.h"
33 #include "net/base/test_data_directory.h"
34 #include "net/base/upload_bytes_element_reader.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_state.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_request_headers.h"
48 #include "net/http/http_server_properties_impl.h"
49 #include "net/http/http_stream.h"
50 #include "net/http/http_stream_factory.h"
51 #include "net/http/http_stream_parser.h"
52 #include "net/http/http_transaction_test_util.h"
53 #include "net/log/capturing_net_log.h"
54 #include "net/log/net_log.h"
55 #include "net/log/net_log_unittest.h"
56 #include "net/proxy/mock_proxy_resolver.h"
57 #include "net/proxy/proxy_config_service_fixed.h"
58 #include "net/proxy/proxy_info.h"
59 #include "net/proxy/proxy_resolver.h"
60 #include "net/proxy/proxy_service.h"
61 #include "net/socket/client_socket_factory.h"
62 #include "net/socket/client_socket_pool_manager.h"
63 #include "net/socket/mock_client_socket_pool_manager.h"
64 #include "net/socket/next_proto.h"
65 #include "net/socket/socket_test_util.h"
66 #include "net/socket/ssl_client_socket.h"
67 #include "net/spdy/spdy_framer.h"
68 #include "net/spdy/spdy_session.h"
69 #include "net/spdy/spdy_session_pool.h"
70 #include "net/spdy/spdy_test_util_common.h"
71 #include "net/ssl/ssl_cert_request_info.h"
72 #include "net/ssl/ssl_config_service.h"
73 #include "net/ssl/ssl_config_service_defaults.h"
74 #include "net/ssl/ssl_info.h"
75 #include "net/test/cert_test_util.h"
76 #include "net/websockets/websocket_handshake_stream_base.h"
77 #include "testing/gtest/include/gtest/gtest.h"
78 #include "testing/platform_test.h"
81 using base::ASCIIToUTF16
;
83 //-----------------------------------------------------------------------------
87 const base::string16
kBar(ASCIIToUTF16("bar"));
88 const base::string16
kBar2(ASCIIToUTF16("bar2"));
89 const base::string16
kBar3(ASCIIToUTF16("bar3"));
90 const base::string16
kBaz(ASCIIToUTF16("baz"));
91 const base::string16
kFirst(ASCIIToUTF16("first"));
92 const base::string16
kFoo(ASCIIToUTF16("foo"));
93 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
94 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
95 const base::string16
kFou(ASCIIToUTF16("fou"));
96 const base::string16
kSecond(ASCIIToUTF16("second"));
97 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
98 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
100 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession
* session
) {
101 return session
->GetTransportSocketPool(
102 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
105 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession
* session
) {
106 return session
->GetSSLSocketPool(
107 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
110 bool IsTransportSocketPoolStalled(net::HttpNetworkSession
* session
) {
111 return session
->GetTransportSocketPool(
112 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IsStalled();
115 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
116 // a JSONified list of headers as a single string. Uses single quotes instead
117 // of double quotes for easier comparison. Returns false on failure.
118 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
121 base::ListValue
* header_list
;
122 if (!params
->GetList("headers", &header_list
))
124 std::string double_quote_headers
;
125 base::JSONWriter::Write(header_list
, &double_quote_headers
);
126 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
130 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
132 void TestLoadTimingReused(const net::LoadTimingInfo
& load_timing_info
) {
133 EXPECT_TRUE(load_timing_info
.socket_reused
);
134 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
136 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
137 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
139 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
140 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
142 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
144 // Set at a higher level.
145 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
146 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
147 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
150 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
152 void TestLoadTimingNotReused(const net::LoadTimingInfo
& load_timing_info
,
153 int connect_timing_flags
) {
154 EXPECT_FALSE(load_timing_info
.socket_reused
);
155 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
157 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
158 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
160 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
161 connect_timing_flags
);
162 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
163 load_timing_info
.send_start
);
165 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
167 // Set at a higher level.
168 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
169 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
170 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
173 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
175 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo
& load_timing_info
) {
176 EXPECT_TRUE(load_timing_info
.socket_reused
);
177 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
179 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
181 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
182 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
183 load_timing_info
.proxy_resolve_end
);
184 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
185 load_timing_info
.send_start
);
186 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
188 // Set at a higher level.
189 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
190 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
191 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
194 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
196 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo
& load_timing_info
,
197 int connect_timing_flags
) {
198 EXPECT_FALSE(load_timing_info
.socket_reused
);
199 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
201 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
202 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
203 load_timing_info
.proxy_resolve_end
);
204 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
205 load_timing_info
.connect_timing
.connect_start
);
206 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
207 connect_timing_flags
);
208 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
209 load_timing_info
.send_start
);
211 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
213 // Set at a higher level.
214 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
215 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
216 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
219 void AddWebSocketHeaders(net::HttpRequestHeaders
* headers
) {
220 headers
->SetHeader("Connection", "Upgrade");
221 headers
->SetHeader("Upgrade", "websocket");
222 headers
->SetHeader("Origin", "http://www.google.com");
223 headers
->SetHeader("Sec-WebSocket-Version", "13");
224 headers
->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
233 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
234 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
239 class HttpNetworkTransactionTest
240 : public PlatformTest
,
241 public ::testing::WithParamInterface
<NextProto
> {
243 virtual ~HttpNetworkTransactionTest() {
244 // Important to restore the per-pool limit first, since the pool limit must
245 // always be greater than group limit, and the tests reduce both limits.
246 ClientSocketPoolManager::set_max_sockets_per_pool(
247 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
248 ClientSocketPoolManager::set_max_sockets_per_group(
249 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
253 HttpNetworkTransactionTest()
254 : spdy_util_(GetParam()),
255 session_deps_(GetParam()),
256 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
257 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
258 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
259 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
262 struct SimpleGetHelperResult
{
264 std::string status_line
;
265 std::string response_data
;
266 int64 totalReceivedBytes
;
267 LoadTimingInfo load_timing_info
;
270 void SetUp() override
{
271 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
272 base::MessageLoop::current()->RunUntilIdle();
275 void TearDown() override
{
276 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
277 base::MessageLoop::current()->RunUntilIdle();
278 // Empty the current queue.
279 base::MessageLoop::current()->RunUntilIdle();
280 PlatformTest::TearDown();
281 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
282 base::MessageLoop::current()->RunUntilIdle();
285 const char* GetAlternateProtocolFromParam() {
287 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
290 // This is the expected return from a current server advertising SPDY.
291 std::string
GetAlternateProtocolHttpHeader() {
292 return std::string("Alternate-Protocol: 443:") +
293 GetAlternateProtocolFromParam() + "\r\n\r\n";
296 // Either |write_failure| specifies a write failure or |read_failure|
297 // specifies a read failure when using a reused socket. In either case, the
298 // failure should cause the network transaction to resend the request, and the
299 // other argument should be NULL.
300 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
301 const MockRead
* read_failure
);
303 // Either |write_failure| specifies a write failure or |read_failure|
304 // specifies a read failure when using a reused socket. In either case, the
305 // failure should cause the network transaction to resend the request, and the
306 // other argument should be NULL.
307 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
308 const MockRead
* read_failure
,
311 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
313 SimpleGetHelperResult out
;
315 HttpRequestInfo request
;
316 request
.method
= "GET";
317 request
.url
= GURL("http://www.google.com/");
318 request
.load_flags
= 0;
320 CapturingBoundNetLog log
;
321 session_deps_
.net_log
= log
.bound().net_log();
322 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
323 scoped_ptr
<HttpTransaction
> trans(
324 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
326 for (size_t i
= 0; i
< data_count
; ++i
) {
327 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
330 TestCompletionCallback callback
;
332 EXPECT_TRUE(log
.bound().IsLogging());
333 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
336 out
.rv
= callback
.WaitForResult();
338 // Even in the failure cases that use this function, connections are always
339 // successfully established before the error.
340 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
341 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
346 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
347 // Can't use ASSERT_* inside helper functions like this, so
349 if (response
== NULL
|| response
->headers
.get() == NULL
) {
350 out
.rv
= ERR_UNEXPECTED
;
353 out
.status_line
= response
->headers
->GetStatusLine();
355 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
356 EXPECT_EQ(80, response
->socket_address
.port());
358 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
361 net::CapturingNetLog::CapturedEntryList entries
;
362 log
.GetEntries(&entries
);
363 size_t pos
= ExpectLogContainsSomewhere(
364 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
366 ExpectLogContainsSomewhere(
368 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
372 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
373 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
375 HttpRequestHeaders request_headers
;
376 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
378 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
379 EXPECT_EQ("www.google.com", value
);
380 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
381 EXPECT_EQ("keep-alive", value
);
383 std::string response_headers
;
384 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
385 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
388 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
392 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
393 size_t reads_count
) {
394 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
395 StaticSocketDataProvider
* data
[] = { &reads
};
396 return SimpleGetHelperForData(data
, 1);
399 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
401 for (size_t i
= 0; i
< reads_count
; ++i
)
402 size
+= data_reads
[i
].data_len
;
406 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
407 int expected_status
);
409 void ConnectStatusHelper(const MockRead
& status
);
411 void BypassHostCacheOnRefreshHelper(int load_flags
);
413 void CheckErrorIsPassedBack(int error
, IoMode mode
);
415 SpdyTestUtil spdy_util_
;
416 SpdySessionDependencies session_deps_
;
418 // Original socket limits. Some tests set these. Safest to always restore
419 // them once each test has been run.
420 int old_max_group_sockets_
;
421 int old_max_pool_sockets_
;
424 INSTANTIATE_TEST_CASE_P(NextProto
,
425 HttpNetworkTransactionTest
,
426 testing::Values(kProtoSPDY31
,
432 class BeforeNetworkStartHandler
{
434 explicit BeforeNetworkStartHandler(bool defer
)
435 : defer_on_before_network_start_(defer
),
436 observed_before_network_start_(false) {}
438 void OnBeforeNetworkStart(bool* defer
) {
439 *defer
= defer_on_before_network_start_
;
440 observed_before_network_start_
= true;
443 bool observed_before_network_start() const {
444 return observed_before_network_start_
;
448 const bool defer_on_before_network_start_
;
449 bool observed_before_network_start_
;
451 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
454 class BeforeProxyHeadersSentHandler
{
456 BeforeProxyHeadersSentHandler()
457 : observed_before_proxy_headers_sent_(false) {}
459 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
460 HttpRequestHeaders
* request_headers
) {
461 observed_before_proxy_headers_sent_
= true;
462 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
465 bool observed_before_proxy_headers_sent() const {
466 return observed_before_proxy_headers_sent_
;
469 std::string
observed_proxy_server_uri() const {
470 return observed_proxy_server_uri_
;
474 bool observed_before_proxy_headers_sent_
;
475 std::string observed_proxy_server_uri_
;
477 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
480 // Fill |str| with a long header list that consumes >= |size| bytes.
481 void FillLargeHeadersString(std::string
* str
, int size
) {
483 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
484 const int sizeof_row
= strlen(row
);
485 const int num_rows
= static_cast<int>(
486 ceil(static_cast<float>(size
) / sizeof_row
));
487 const int sizeof_data
= num_rows
* sizeof_row
;
488 DCHECK(sizeof_data
>= size
);
489 str
->reserve(sizeof_data
);
491 for (int i
= 0; i
< num_rows
; ++i
)
492 str
->append(row
, sizeof_row
);
495 // Alternative functions that eliminate randomness and dependency on the local
496 // host name so that the generated NTLM messages are reproducible.
497 void MockGenerateRandom1(uint8
* output
, size_t n
) {
498 static const uint8 bytes
[] = {
499 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
501 static size_t current_byte
= 0;
502 for (size_t i
= 0; i
< n
; ++i
) {
503 output
[i
] = bytes
[current_byte
++];
504 current_byte
%= arraysize(bytes
);
508 void MockGenerateRandom2(uint8
* output
, size_t n
) {
509 static const uint8 bytes
[] = {
510 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
511 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
513 static size_t current_byte
= 0;
514 for (size_t i
= 0; i
< n
; ++i
) {
515 output
[i
] = bytes
[current_byte
++];
516 current_byte
%= arraysize(bytes
);
520 std::string
MockGetHostName() {
524 template<typename ParentPool
>
525 class CaptureGroupNameSocketPool
: public ParentPool
{
527 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
528 CertVerifier
* cert_verifier
);
530 const std::string
last_group_name_received() const {
531 return last_group_name_
;
534 int RequestSocket(const std::string
& group_name
,
535 const void* socket_params
,
536 RequestPriority priority
,
537 ClientSocketHandle
* handle
,
538 const CompletionCallback
& callback
,
539 const BoundNetLog
& net_log
) override
{
540 last_group_name_
= group_name
;
541 return ERR_IO_PENDING
;
543 void CancelRequest(const std::string
& group_name
,
544 ClientSocketHandle
* handle
) override
{}
545 void ReleaseSocket(const std::string
& group_name
,
546 scoped_ptr
<StreamSocket
> socket
,
548 void CloseIdleSockets() override
{}
549 int IdleSocketCount() const override
{ return 0; }
550 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
553 LoadState
GetLoadState(const std::string
& group_name
,
554 const ClientSocketHandle
* handle
) const override
{
555 return LOAD_STATE_IDLE
;
557 base::TimeDelta
ConnectionTimeout() const override
{
558 return base::TimeDelta();
562 std::string last_group_name_
;
565 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
566 CaptureGroupNameTransportSocketPool
;
567 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
568 CaptureGroupNameHttpProxySocketPool
;
569 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
570 CaptureGroupNameSOCKSSocketPool
;
571 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
572 CaptureGroupNameSSLSocketPool
;
574 template <typename ParentPool
>
575 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
576 HostResolver
* host_resolver
,
577 CertVerifier
* /* cert_verifier */)
578 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
582 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
583 HostResolver
* /* host_resolver */,
584 CertVerifier
* /* cert_verifier */)
585 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
589 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
590 HostResolver
* /* host_resolver */,
591 CertVerifier
* cert_verifier
)
592 : SSLClientSocketPool(0,
608 //-----------------------------------------------------------------------------
610 // Helper functions for validating that AuthChallengeInfo's are correctly
611 // configured for common cases.
612 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
615 EXPECT_FALSE(auth_challenge
->is_proxy
);
616 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
617 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
618 EXPECT_EQ("basic", auth_challenge
->scheme
);
622 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
625 EXPECT_TRUE(auth_challenge
->is_proxy
);
626 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
627 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
628 EXPECT_EQ("basic", auth_challenge
->scheme
);
632 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
635 EXPECT_FALSE(auth_challenge
->is_proxy
);
636 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
637 EXPECT_EQ("digestive", auth_challenge
->realm
);
638 EXPECT_EQ("digest", auth_challenge
->scheme
);
642 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
645 EXPECT_FALSE(auth_challenge
->is_proxy
);
646 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
647 EXPECT_EQ(std::string(), auth_challenge
->realm
);
648 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
654 TEST_P(HttpNetworkTransactionTest
, Basic
) {
655 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
656 scoped_ptr
<HttpTransaction
> trans(
657 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
660 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
661 MockRead data_reads
[] = {
662 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
663 MockRead("hello world"),
664 MockRead(SYNCHRONOUS
, OK
),
666 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
667 arraysize(data_reads
));
668 EXPECT_EQ(OK
, out
.rv
);
669 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
670 EXPECT_EQ("hello world", out
.response_data
);
671 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
672 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
675 // Response with no status line.
676 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
677 MockRead data_reads
[] = {
678 MockRead("hello world"),
679 MockRead(SYNCHRONOUS
, OK
),
681 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
682 arraysize(data_reads
));
683 EXPECT_EQ(OK
, out
.rv
);
684 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
685 EXPECT_EQ("hello world", out
.response_data
);
686 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
687 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
690 // Allow up to 4 bytes of junk to precede status line.
691 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
692 MockRead data_reads
[] = {
693 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
694 MockRead(SYNCHRONOUS
, OK
),
696 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
697 arraysize(data_reads
));
698 EXPECT_EQ(OK
, out
.rv
);
699 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
700 EXPECT_EQ("DATA", out
.response_data
);
701 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
702 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
705 // Allow up to 4 bytes of junk to precede status line.
706 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
707 MockRead data_reads
[] = {
708 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
709 MockRead(SYNCHRONOUS
, OK
),
711 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
712 arraysize(data_reads
));
713 EXPECT_EQ(OK
, out
.rv
);
714 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
715 EXPECT_EQ("DATA", out
.response_data
);
716 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
717 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
720 // Beyond 4 bytes of slop and it should fail to find a status line.
721 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
722 MockRead data_reads
[] = {
723 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
724 MockRead(SYNCHRONOUS
, OK
),
726 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
727 arraysize(data_reads
));
728 EXPECT_EQ(OK
, out
.rv
);
729 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
730 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
731 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
732 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
735 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
736 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
737 MockRead data_reads
[] = {
742 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
743 MockRead(SYNCHRONOUS
, OK
),
745 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
746 arraysize(data_reads
));
747 EXPECT_EQ(OK
, out
.rv
);
748 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
749 EXPECT_EQ("DATA", out
.response_data
);
750 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
751 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
754 // Close the connection before enough bytes to have a status line.
755 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
756 MockRead data_reads
[] = {
758 MockRead(SYNCHRONOUS
, OK
),
760 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
761 arraysize(data_reads
));
762 EXPECT_EQ(OK
, out
.rv
);
763 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
764 EXPECT_EQ("HTT", out
.response_data
);
765 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
766 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
769 // Simulate a 204 response, lacking a Content-Length header, sent over a
770 // persistent connection. The response should still terminate since a 204
771 // cannot have a response body.
772 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
773 char junk
[] = "junk";
774 MockRead data_reads
[] = {
775 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
776 MockRead(junk
), // Should not be read!!
777 MockRead(SYNCHRONOUS
, OK
),
779 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
780 arraysize(data_reads
));
781 EXPECT_EQ(OK
, out
.rv
);
782 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
783 EXPECT_EQ("", out
.response_data
);
784 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
785 int64 response_size
= reads_size
- strlen(junk
);
786 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
789 // A simple request using chunked encoding with some extra data after.
790 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
791 std::string final_chunk
= "0\r\n\r\n";
792 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
793 std::string last_read
= final_chunk
+ extra_data
;
794 MockRead data_reads
[] = {
795 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
796 MockRead("5\r\nHello\r\n"),
799 MockRead("5\r\nworld\r\n"),
800 MockRead(last_read
.data()),
801 MockRead(SYNCHRONOUS
, OK
),
803 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
804 arraysize(data_reads
));
805 EXPECT_EQ(OK
, out
.rv
);
806 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
807 EXPECT_EQ("Hello world", out
.response_data
);
808 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
809 int64 response_size
= reads_size
- extra_data
.size();
810 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
813 // Next tests deal with http://crbug.com/56344.
815 TEST_P(HttpNetworkTransactionTest
,
816 MultipleContentLengthHeadersNoTransferEncoding
) {
817 MockRead data_reads
[] = {
818 MockRead("HTTP/1.1 200 OK\r\n"),
819 MockRead("Content-Length: 10\r\n"),
820 MockRead("Content-Length: 5\r\n\r\n"),
822 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
823 arraysize(data_reads
));
824 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
827 TEST_P(HttpNetworkTransactionTest
,
828 DuplicateContentLengthHeadersNoTransferEncoding
) {
829 MockRead data_reads
[] = {
830 MockRead("HTTP/1.1 200 OK\r\n"),
831 MockRead("Content-Length: 5\r\n"),
832 MockRead("Content-Length: 5\r\n\r\n"),
835 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
836 arraysize(data_reads
));
837 EXPECT_EQ(OK
, out
.rv
);
838 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
839 EXPECT_EQ("Hello", out
.response_data
);
842 TEST_P(HttpNetworkTransactionTest
,
843 ComplexContentLengthHeadersNoTransferEncoding
) {
844 // More than 2 dupes.
846 MockRead data_reads
[] = {
847 MockRead("HTTP/1.1 200 OK\r\n"),
848 MockRead("Content-Length: 5\r\n"),
849 MockRead("Content-Length: 5\r\n"),
850 MockRead("Content-Length: 5\r\n\r\n"),
853 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
854 arraysize(data_reads
));
855 EXPECT_EQ(OK
, out
.rv
);
856 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
857 EXPECT_EQ("Hello", out
.response_data
);
861 MockRead data_reads
[] = {
862 MockRead("HTTP/1.0 200 OK\r\n"),
863 MockRead("Content-Length: 5\r\n"),
864 MockRead("Content-Length: 5\r\n"),
865 MockRead("Content-Length: 5\r\n\r\n"),
868 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
869 arraysize(data_reads
));
870 EXPECT_EQ(OK
, out
.rv
);
871 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
872 EXPECT_EQ("Hello", out
.response_data
);
874 // 2 dupes and one mismatched.
876 MockRead data_reads
[] = {
877 MockRead("HTTP/1.1 200 OK\r\n"),
878 MockRead("Content-Length: 10\r\n"),
879 MockRead("Content-Length: 10\r\n"),
880 MockRead("Content-Length: 5\r\n\r\n"),
882 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
883 arraysize(data_reads
));
884 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
888 TEST_P(HttpNetworkTransactionTest
,
889 MultipleContentLengthHeadersTransferEncoding
) {
890 MockRead data_reads
[] = {
891 MockRead("HTTP/1.1 200 OK\r\n"),
892 MockRead("Content-Length: 666\r\n"),
893 MockRead("Content-Length: 1337\r\n"),
894 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
895 MockRead("5\r\nHello\r\n"),
898 MockRead("5\r\nworld\r\n"),
899 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
900 MockRead(SYNCHRONOUS
, OK
),
902 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
903 arraysize(data_reads
));
904 EXPECT_EQ(OK
, out
.rv
);
905 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
906 EXPECT_EQ("Hello world", out
.response_data
);
909 // Next tests deal with http://crbug.com/98895.
911 // Checks that a single Content-Disposition header results in no error.
912 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
913 MockRead data_reads
[] = {
914 MockRead("HTTP/1.1 200 OK\r\n"),
915 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
916 MockRead("Content-Length: 5\r\n\r\n"),
919 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
920 arraysize(data_reads
));
921 EXPECT_EQ(OK
, out
.rv
);
922 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
923 EXPECT_EQ("Hello", out
.response_data
);
926 // Checks that two identical Content-Disposition headers result in no error.
927 TEST_P(HttpNetworkTransactionTest
,
928 TwoIdenticalContentDispositionHeaders
) {
929 MockRead data_reads
[] = {
930 MockRead("HTTP/1.1 200 OK\r\n"),
931 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
932 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
933 MockRead("Content-Length: 5\r\n\r\n"),
936 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
937 arraysize(data_reads
));
938 EXPECT_EQ(OK
, out
.rv
);
939 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
940 EXPECT_EQ("Hello", out
.response_data
);
943 // Checks that two distinct Content-Disposition headers result in an error.
944 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
945 MockRead data_reads
[] = {
946 MockRead("HTTP/1.1 200 OK\r\n"),
947 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
948 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
949 MockRead("Content-Length: 5\r\n\r\n"),
952 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
953 arraysize(data_reads
));
954 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
957 // Checks that two identical Location headers result in no error.
958 // Also tests Location header behavior.
959 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
960 MockRead data_reads
[] = {
961 MockRead("HTTP/1.1 302 Redirect\r\n"),
962 MockRead("Location: http://good.com/\r\n"),
963 MockRead("Location: http://good.com/\r\n"),
964 MockRead("Content-Length: 0\r\n\r\n"),
965 MockRead(SYNCHRONOUS
, OK
),
968 HttpRequestInfo request
;
969 request
.method
= "GET";
970 request
.url
= GURL("http://redirect.com/");
971 request
.load_flags
= 0;
973 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
974 scoped_ptr
<HttpTransaction
> trans(
975 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
977 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
978 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
980 TestCompletionCallback callback
;
982 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
983 EXPECT_EQ(ERR_IO_PENDING
, rv
);
985 EXPECT_EQ(OK
, callback
.WaitForResult());
987 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
988 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
989 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
991 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
992 EXPECT_EQ("http://good.com/", url
);
993 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
996 // Checks that two distinct Location headers result in an error.
997 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
998 MockRead data_reads
[] = {
999 MockRead("HTTP/1.1 302 Redirect\r\n"),
1000 MockRead("Location: http://good.com/\r\n"),
1001 MockRead("Location: http://evil.com/\r\n"),
1002 MockRead("Content-Length: 0\r\n\r\n"),
1003 MockRead(SYNCHRONOUS
, OK
),
1005 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1006 arraysize(data_reads
));
1007 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1010 // Do a request using the HEAD method. Verify that we don't try to read the
1011 // message body (since HEAD has none).
1012 TEST_P(HttpNetworkTransactionTest
, Head
) {
1013 HttpRequestInfo request
;
1014 request
.method
= "HEAD";
1015 request
.url
= GURL("http://www.google.com/");
1016 request
.load_flags
= 0;
1018 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1019 scoped_ptr
<HttpTransaction
> trans(
1020 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1021 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1022 trans
->SetBeforeProxyHeadersSentCallback(
1023 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1024 base::Unretained(&proxy_headers_handler
)));
1026 MockWrite data_writes1
[] = {
1027 MockWrite("HEAD / HTTP/1.1\r\n"
1028 "Host: www.google.com\r\n"
1029 "Connection: keep-alive\r\n"
1030 "Content-Length: 0\r\n\r\n"),
1032 MockRead data_reads1
[] = {
1033 MockRead("HTTP/1.1 404 Not Found\r\n"),
1034 MockRead("Server: Blah\r\n"),
1035 MockRead("Content-Length: 1234\r\n\r\n"),
1037 // No response body because the test stops reading here.
1038 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1041 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1042 data_writes1
, arraysize(data_writes1
));
1043 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1045 TestCompletionCallback callback1
;
1047 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1048 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1050 rv
= callback1
.WaitForResult();
1053 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1054 ASSERT_TRUE(response
!= NULL
);
1056 // Check that the headers got parsed.
1057 EXPECT_TRUE(response
->headers
.get() != NULL
);
1058 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1059 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1060 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1061 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1063 std::string server_header
;
1065 bool has_server_header
= response
->headers
->EnumerateHeader(
1066 &iter
, "Server", &server_header
);
1067 EXPECT_TRUE(has_server_header
);
1068 EXPECT_EQ("Blah", server_header
);
1070 // Reading should give EOF right away, since there is no message body
1071 // (despite non-zero content-length).
1072 std::string response_data
;
1073 rv
= ReadTransaction(trans
.get(), &response_data
);
1075 EXPECT_EQ("", response_data
);
1078 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1079 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1081 MockRead data_reads
[] = {
1082 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1084 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1086 MockRead(SYNCHRONOUS
, OK
),
1088 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1089 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1091 const char* const kExpectedResponseData
[] = {
1095 for (int i
= 0; i
< 2; ++i
) {
1096 HttpRequestInfo request
;
1097 request
.method
= "GET";
1098 request
.url
= GURL("http://www.google.com/");
1099 request
.load_flags
= 0;
1101 scoped_ptr
<HttpTransaction
> trans(
1102 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1104 TestCompletionCallback callback
;
1106 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1107 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1109 rv
= callback
.WaitForResult();
1112 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1113 ASSERT_TRUE(response
!= NULL
);
1115 EXPECT_TRUE(response
->headers
.get() != NULL
);
1116 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1117 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1119 std::string response_data
;
1120 rv
= ReadTransaction(trans
.get(), &response_data
);
1122 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1126 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1127 ScopedVector
<UploadElementReader
> element_readers
;
1128 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1129 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1131 HttpRequestInfo request
;
1132 request
.method
= "POST";
1133 request
.url
= GURL("http://www.foo.com/");
1134 request
.upload_data_stream
= &upload_data_stream
;
1135 request
.load_flags
= 0;
1137 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1138 scoped_ptr
<HttpTransaction
> trans(
1139 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1141 MockRead data_reads
[] = {
1142 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1143 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1144 MockRead("hello world"),
1145 MockRead(SYNCHRONOUS
, OK
),
1147 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1148 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1150 TestCompletionCallback callback
;
1152 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1153 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1155 rv
= callback
.WaitForResult();
1158 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1159 ASSERT_TRUE(response
!= NULL
);
1161 EXPECT_TRUE(response
->headers
.get() != NULL
);
1162 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1164 std::string response_data
;
1165 rv
= ReadTransaction(trans
.get(), &response_data
);
1167 EXPECT_EQ("hello world", response_data
);
1170 // This test is almost the same as Ignores100 above, but the response contains
1171 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1172 // HTTP/1.1 and the two status headers are read in one read.
1173 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1174 HttpRequestInfo request
;
1175 request
.method
= "GET";
1176 request
.url
= GURL("http://www.foo.com/");
1177 request
.load_flags
= 0;
1179 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1180 scoped_ptr
<HttpTransaction
> trans(
1181 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1183 MockRead data_reads
[] = {
1184 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1185 "HTTP/1.1 200 OK\r\n\r\n"),
1186 MockRead("hello world"),
1187 MockRead(SYNCHRONOUS
, OK
),
1189 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1190 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1192 TestCompletionCallback callback
;
1194 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1195 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1197 rv
= callback
.WaitForResult();
1200 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1201 ASSERT_TRUE(response
!= NULL
);
1203 EXPECT_TRUE(response
->headers
.get() != NULL
);
1204 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1206 std::string response_data
;
1207 rv
= ReadTransaction(trans
.get(), &response_data
);
1209 EXPECT_EQ("hello world", response_data
);
1212 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1213 HttpRequestInfo request
;
1214 request
.method
= "POST";
1215 request
.url
= GURL("http://www.foo.com/");
1216 request
.load_flags
= 0;
1218 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1219 scoped_ptr
<HttpTransaction
> trans(
1220 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1222 MockRead data_reads
[] = {
1223 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1226 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1227 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1229 TestCompletionCallback callback
;
1231 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1232 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1234 rv
= callback
.WaitForResult();
1237 std::string response_data
;
1238 rv
= ReadTransaction(trans
.get(), &response_data
);
1240 EXPECT_EQ("", response_data
);
1243 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1244 HttpRequestInfo request
;
1245 request
.method
= "POST";
1246 request
.url
= GURL("http://www.foo.com/");
1247 request
.load_flags
= 0;
1249 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1250 scoped_ptr
<HttpTransaction
> trans(
1251 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1253 MockRead data_reads
[] = {
1256 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1257 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1259 TestCompletionCallback callback
;
1261 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1262 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1264 rv
= callback
.WaitForResult();
1265 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1268 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1269 const MockWrite
* write_failure
,
1270 const MockRead
* read_failure
) {
1271 HttpRequestInfo request
;
1272 request
.method
= "GET";
1273 request
.url
= GURL("http://www.foo.com/");
1274 request
.load_flags
= 0;
1276 CapturingNetLog net_log
;
1277 session_deps_
.net_log
= &net_log
;
1278 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1280 // Written data for successfully sending both requests.
1281 MockWrite data1_writes
[] = {
1282 MockWrite("GET / HTTP/1.1\r\n"
1283 "Host: www.foo.com\r\n"
1284 "Connection: keep-alive\r\n\r\n"),
1285 MockWrite("GET / HTTP/1.1\r\n"
1286 "Host: www.foo.com\r\n"
1287 "Connection: keep-alive\r\n\r\n")
1290 // Read results for the first request.
1291 MockRead data1_reads
[] = {
1292 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1294 MockRead(ASYNC
, OK
),
1297 if (write_failure
) {
1298 ASSERT_FALSE(read_failure
);
1299 data1_writes
[1] = *write_failure
;
1301 ASSERT_TRUE(read_failure
);
1302 data1_reads
[2] = *read_failure
;
1305 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1306 data1_writes
, arraysize(data1_writes
));
1307 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1309 MockRead data2_reads
[] = {
1310 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1312 MockRead(ASYNC
, OK
),
1314 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1315 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1317 const char* const kExpectedResponseData
[] = {
1321 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1322 for (int i
= 0; i
< 2; ++i
) {
1323 TestCompletionCallback callback
;
1325 scoped_ptr
<HttpTransaction
> trans(
1326 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1328 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1329 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1331 rv
= callback
.WaitForResult();
1334 LoadTimingInfo load_timing_info
;
1335 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1336 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1338 first_socket_log_id
= load_timing_info
.socket_log_id
;
1340 // The second request should be using a new socket.
1341 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1344 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1345 ASSERT_TRUE(response
!= NULL
);
1347 EXPECT_TRUE(response
->headers
.get() != NULL
);
1348 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1350 std::string response_data
;
1351 rv
= ReadTransaction(trans
.get(), &response_data
);
1353 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1357 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1358 const MockWrite
* write_failure
,
1359 const MockRead
* read_failure
,
1361 HttpRequestInfo request
;
1362 request
.method
= "GET";
1363 request
.url
= GURL("https://www.foo.com/");
1364 request
.load_flags
= 0;
1366 CapturingNetLog net_log
;
1367 session_deps_
.net_log
= &net_log
;
1368 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1370 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1371 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1373 ssl1
.SetNextProto(GetParam());
1374 ssl2
.SetNextProto(GetParam());
1376 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1377 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1379 // SPDY versions of the request and response.
1380 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1381 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1382 scoped_ptr
<SpdyFrame
> spdy_response(
1383 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1384 scoped_ptr
<SpdyFrame
> spdy_data(
1385 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1387 // HTTP/1.1 versions of the request and response.
1388 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1389 "Host: www.foo.com\r\n"
1390 "Connection: keep-alive\r\n\r\n";
1391 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1392 const char kHttpData
[] = "hello";
1394 std::vector
<MockRead
> data1_reads
;
1395 std::vector
<MockWrite
> data1_writes
;
1396 if (write_failure
) {
1397 ASSERT_FALSE(read_failure
);
1398 data1_writes
.push_back(*write_failure
);
1399 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1401 ASSERT_TRUE(read_failure
);
1403 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1405 data1_writes
.push_back(MockWrite(kHttpRequest
));
1407 data1_reads
.push_back(*read_failure
);
1410 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1411 &data1_writes
[0], data1_writes
.size());
1412 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1414 std::vector
<MockRead
> data2_reads
;
1415 std::vector
<MockWrite
> data2_writes
;
1418 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1420 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1421 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1422 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1424 data2_writes
.push_back(
1425 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1427 data2_reads
.push_back(
1428 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1429 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1430 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1432 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1433 &data2_writes
[0], data2_writes
.size());
1434 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1436 // Preconnect a socket.
1437 net::SSLConfig ssl_config
;
1438 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1439 session
->GetNextProtos(&ssl_config
.next_protos
);
1440 session
->http_stream_factory()->PreconnectStreams(
1441 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1442 // Wait for the preconnect to complete.
1443 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1444 base::RunLoop().RunUntilIdle();
1445 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1447 // Make the request.
1448 TestCompletionCallback callback
;
1450 scoped_ptr
<HttpTransaction
> trans(
1451 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1453 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1456 rv
= callback
.WaitForResult();
1459 LoadTimingInfo load_timing_info
;
1460 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1461 TestLoadTimingNotReused(
1463 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1465 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1466 ASSERT_TRUE(response
!= NULL
);
1468 EXPECT_TRUE(response
->headers
.get() != NULL
);
1469 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1471 std::string response_data
;
1472 rv
= ReadTransaction(trans
.get(), &response_data
);
1474 EXPECT_EQ(kHttpData
, response_data
);
1477 TEST_P(HttpNetworkTransactionTest
,
1478 KeepAliveConnectionNotConnectedOnWrite
) {
1479 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1480 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1483 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1484 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1485 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1488 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1489 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1490 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1493 // Make sure that on a 408 response (Request Timeout), the request is retried,
1494 // if the socket was a reused keep alive socket.
1495 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1496 MockRead
read_failure(SYNCHRONOUS
,
1497 "HTTP/1.1 408 Request Timeout\r\n"
1498 "Connection: Keep-Alive\r\n"
1499 "Content-Length: 6\r\n\r\n"
1501 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1504 TEST_P(HttpNetworkTransactionTest
,
1505 PreconnectErrorNotConnectedOnWrite
) {
1506 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1507 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1510 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1511 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1512 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1515 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1516 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1517 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1520 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1521 MockRead
read_failure(ASYNC
, OK
); // EOF
1522 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1525 // Make sure that on a 408 response (Request Timeout), the request is retried,
1526 // if the socket was a preconnected (UNUSED_IDLE) socket.
1527 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1528 MockRead
read_failure(SYNCHRONOUS
,
1529 "HTTP/1.1 408 Request Timeout\r\n"
1530 "Connection: Keep-Alive\r\n"
1531 "Content-Length: 6\r\n\r\n"
1533 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1534 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1537 TEST_P(HttpNetworkTransactionTest
,
1538 SpdyPreconnectErrorNotConnectedOnWrite
) {
1539 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1540 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1543 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1544 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1545 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1548 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1549 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1550 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1553 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1554 MockRead
read_failure(ASYNC
, OK
); // EOF
1555 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1558 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1559 HttpRequestInfo request
;
1560 request
.method
= "GET";
1561 request
.url
= GURL("http://www.google.com/");
1562 request
.load_flags
= 0;
1564 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1565 scoped_ptr
<HttpTransaction
> trans(
1566 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1568 MockRead data_reads
[] = {
1569 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1570 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1571 MockRead("hello world"),
1572 MockRead(SYNCHRONOUS
, OK
),
1574 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1575 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1577 TestCompletionCallback callback
;
1579 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1582 rv
= callback
.WaitForResult();
1583 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1585 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1586 EXPECT_TRUE(response
== NULL
);
1589 // What do various browsers do when the server closes a non-keepalive
1590 // connection without sending any response header or body?
1593 // Safari 3.1.2 (Windows): error page
1594 // Firefox 3.0.1: blank page
1595 // Opera 9.52: after five attempts, blank page
1596 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1597 // Us: error page (EMPTY_RESPONSE)
1598 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1599 MockRead data_reads
[] = {
1600 MockRead(SYNCHRONOUS
, OK
), // EOF
1601 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1602 MockRead("hello world"),
1603 MockRead(SYNCHRONOUS
, OK
),
1605 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1606 arraysize(data_reads
));
1607 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1610 // Test that network access can be deferred and resumed.
1611 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1612 HttpRequestInfo request
;
1613 request
.method
= "GET";
1614 request
.url
= GURL("http://www.google.com/");
1615 request
.load_flags
= 0;
1617 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1618 scoped_ptr
<HttpTransaction
> trans(
1619 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1621 // Defer on OnBeforeNetworkStart.
1622 BeforeNetworkStartHandler
net_start_handler(true); // defer
1623 trans
->SetBeforeNetworkStartCallback(
1624 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1625 base::Unretained(&net_start_handler
)));
1627 MockRead data_reads
[] = {
1628 MockRead("HTTP/1.0 200 OK\r\n"),
1629 MockRead("Content-Length: 5\r\n\r\n"),
1631 MockRead(SYNCHRONOUS
, 0),
1633 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1634 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1636 TestCompletionCallback callback
;
1638 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1640 base::MessageLoop::current()->RunUntilIdle();
1642 // Should have deferred for network start.
1643 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1644 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1645 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1647 trans
->ResumeNetworkStart();
1648 rv
= callback
.WaitForResult();
1650 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1652 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1653 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1654 if (rv
== ERR_IO_PENDING
)
1655 rv
= callback
.WaitForResult();
1660 // Test that network use can be deferred and canceled.
1661 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1662 HttpRequestInfo request
;
1663 request
.method
= "GET";
1664 request
.url
= GURL("http://www.google.com/");
1665 request
.load_flags
= 0;
1667 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1668 scoped_ptr
<HttpTransaction
> trans(
1669 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1671 // Defer on OnBeforeNetworkStart.
1672 BeforeNetworkStartHandler
net_start_handler(true); // defer
1673 trans
->SetBeforeNetworkStartCallback(
1674 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1675 base::Unretained(&net_start_handler
)));
1677 TestCompletionCallback callback
;
1679 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1681 base::MessageLoop::current()->RunUntilIdle();
1683 // Should have deferred for network start.
1684 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1685 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1686 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1689 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1690 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1691 // destructor in such situations.
1692 // See http://crbug.com/154712 and http://crbug.com/156609.
1693 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1694 HttpRequestInfo request
;
1695 request
.method
= "GET";
1696 request
.url
= GURL("http://www.google.com/");
1697 request
.load_flags
= 0;
1699 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1700 scoped_ptr
<HttpTransaction
> trans(
1701 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1703 MockRead data_reads
[] = {
1704 MockRead("HTTP/1.0 200 OK\r\n"),
1705 MockRead("Connection: keep-alive\r\n"),
1706 MockRead("Content-Length: 100\r\n\r\n"),
1708 MockRead(SYNCHRONOUS
, 0),
1710 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1711 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1713 TestCompletionCallback callback
;
1715 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1716 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1718 rv
= callback
.WaitForResult();
1721 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1722 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1723 if (rv
== ERR_IO_PENDING
)
1724 rv
= callback
.WaitForResult();
1726 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1727 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1730 base::MessageLoop::current()->RunUntilIdle();
1731 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1734 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1735 HttpRequestInfo request
;
1736 request
.method
= "GET";
1737 request
.url
= GURL("http://www.google.com/");
1738 request
.load_flags
= 0;
1740 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1741 scoped_ptr
<HttpTransaction
> trans(
1742 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1744 MockRead data_reads
[] = {
1745 MockRead("HTTP/1.0 200 OK\r\n"),
1746 MockRead("Connection: keep-alive\r\n"),
1747 MockRead("Content-Length: 100\r\n\r\n"),
1748 MockRead(SYNCHRONOUS
, 0),
1750 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1751 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1753 TestCompletionCallback callback
;
1755 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1758 rv
= callback
.WaitForResult();
1761 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1762 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1763 if (rv
== ERR_IO_PENDING
)
1764 rv
= callback
.WaitForResult();
1765 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1768 base::MessageLoop::current()->RunUntilIdle();
1769 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1772 // Test that we correctly reuse a keep-alive connection after not explicitly
1773 // reading the body.
1774 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1775 HttpRequestInfo request
;
1776 request
.method
= "GET";
1777 request
.url
= GURL("http://www.foo.com/");
1778 request
.load_flags
= 0;
1780 CapturingNetLog net_log
;
1781 session_deps_
.net_log
= &net_log
;
1782 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1784 // Note that because all these reads happen in the same
1785 // StaticSocketDataProvider, it shows that the same socket is being reused for
1786 // all transactions.
1787 MockRead data1_reads
[] = {
1788 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1789 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1790 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1791 MockRead("HTTP/1.1 302 Found\r\n"
1792 "Content-Length: 0\r\n\r\n"),
1793 MockRead("HTTP/1.1 302 Found\r\n"
1794 "Content-Length: 5\r\n\r\n"
1796 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1797 "Content-Length: 0\r\n\r\n"),
1798 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1799 "Content-Length: 5\r\n\r\n"
1801 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1804 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1805 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1807 MockRead data2_reads
[] = {
1808 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1810 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1811 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1813 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1814 std::string response_lines
[kNumUnreadBodies
];
1816 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1817 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1818 TestCompletionCallback callback
;
1820 scoped_ptr
<HttpTransaction
> trans(
1821 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1823 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1824 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1826 rv
= callback
.WaitForResult();
1829 LoadTimingInfo load_timing_info
;
1830 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1832 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1833 first_socket_log_id
= load_timing_info
.socket_log_id
;
1835 TestLoadTimingReused(load_timing_info
);
1836 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1839 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1840 ASSERT_TRUE(response
!= NULL
);
1842 ASSERT_TRUE(response
->headers
.get() != NULL
);
1843 response_lines
[i
] = response
->headers
->GetStatusLine();
1845 // We intentionally don't read the response bodies.
1848 const char* const kStatusLines
[] = {
1849 "HTTP/1.1 204 No Content",
1850 "HTTP/1.1 205 Reset Content",
1851 "HTTP/1.1 304 Not Modified",
1852 "HTTP/1.1 302 Found",
1853 "HTTP/1.1 302 Found",
1854 "HTTP/1.1 301 Moved Permanently",
1855 "HTTP/1.1 301 Moved Permanently",
1858 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1859 "forgot to update kStatusLines");
1861 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1862 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1864 TestCompletionCallback callback
;
1865 scoped_ptr
<HttpTransaction
> trans(
1866 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1867 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1868 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1869 rv
= callback
.WaitForResult();
1871 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1872 ASSERT_TRUE(response
!= NULL
);
1873 ASSERT_TRUE(response
->headers
.get() != NULL
);
1874 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1875 std::string response_data
;
1876 rv
= ReadTransaction(trans
.get(), &response_data
);
1878 EXPECT_EQ("hello", response_data
);
1881 // Test the request-challenge-retry sequence for basic auth.
1882 // (basic auth is the easiest to mock, because it has no randomness).
1883 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1884 HttpRequestInfo request
;
1885 request
.method
= "GET";
1886 request
.url
= GURL("http://www.google.com/");
1887 request
.load_flags
= 0;
1889 CapturingNetLog log
;
1890 session_deps_
.net_log
= &log
;
1891 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1892 scoped_ptr
<HttpTransaction
> trans(
1893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1895 MockWrite data_writes1
[] = {
1896 MockWrite("GET / HTTP/1.1\r\n"
1897 "Host: www.google.com\r\n"
1898 "Connection: keep-alive\r\n\r\n"),
1901 MockRead data_reads1
[] = {
1902 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1903 // Give a couple authenticate options (only the middle one is actually
1905 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1906 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1907 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909 // Large content-length -- won't matter, as connection will be reset.
1910 MockRead("Content-Length: 10000\r\n\r\n"),
1911 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1914 // After calling trans->RestartWithAuth(), this is the request we should
1915 // be issuing -- the final header line contains the credentials.
1916 MockWrite data_writes2
[] = {
1917 MockWrite("GET / HTTP/1.1\r\n"
1918 "Host: www.google.com\r\n"
1919 "Connection: keep-alive\r\n"
1920 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1923 // Lastly, the server responds with the actual content.
1924 MockRead data_reads2
[] = {
1925 MockRead("HTTP/1.0 200 OK\r\n"),
1926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1927 MockRead("Content-Length: 100\r\n\r\n"),
1928 MockRead(SYNCHRONOUS
, OK
),
1931 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1932 data_writes1
, arraysize(data_writes1
));
1933 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1934 data_writes2
, arraysize(data_writes2
));
1935 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1936 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1938 TestCompletionCallback callback1
;
1940 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1943 rv
= callback1
.WaitForResult();
1946 LoadTimingInfo load_timing_info1
;
1947 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1948 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1950 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1951 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1953 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1954 ASSERT_TRUE(response
!= NULL
);
1955 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1957 TestCompletionCallback callback2
;
1959 rv
= trans
->RestartWithAuth(
1960 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1961 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1963 rv
= callback2
.WaitForResult();
1966 LoadTimingInfo load_timing_info2
;
1967 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1968 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1969 // The load timing after restart should have a new socket ID, and times after
1970 // those of the first load timing.
1971 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1972 load_timing_info2
.connect_timing
.connect_start
);
1973 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1975 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1976 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1978 response
= trans
->GetResponseInfo();
1979 ASSERT_TRUE(response
!= NULL
);
1980 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1981 EXPECT_EQ(100, response
->headers
->GetContentLength());
1984 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1985 HttpRequestInfo request
;
1986 request
.method
= "GET";
1987 request
.url
= GURL("http://www.google.com/");
1988 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1990 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1991 scoped_ptr
<HttpTransaction
> trans(
1992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1994 MockWrite data_writes
[] = {
1995 MockWrite("GET / HTTP/1.1\r\n"
1996 "Host: www.google.com\r\n"
1997 "Connection: keep-alive\r\n\r\n"),
2000 MockRead data_reads
[] = {
2001 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2002 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2004 // Large content-length -- won't matter, as connection will be reset.
2005 MockRead("Content-Length: 10000\r\n\r\n"),
2006 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2009 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2010 data_writes
, arraysize(data_writes
));
2011 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2012 TestCompletionCallback callback
;
2014 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2015 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2017 rv
= callback
.WaitForResult();
2020 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2021 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2023 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2024 ASSERT_TRUE(response
!= NULL
);
2025 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2028 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2030 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2031 HttpRequestInfo request
;
2032 request
.method
= "GET";
2033 request
.url
= GURL("http://www.google.com/");
2034 request
.load_flags
= 0;
2036 CapturingNetLog log
;
2037 session_deps_
.net_log
= &log
;
2038 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2040 MockWrite data_writes1
[] = {
2041 MockWrite("GET / HTTP/1.1\r\n"
2042 "Host: www.google.com\r\n"
2043 "Connection: keep-alive\r\n\r\n"),
2045 // After calling trans->RestartWithAuth(), this is the request we should
2046 // be issuing -- the final header line contains the credentials.
2047 MockWrite("GET / HTTP/1.1\r\n"
2048 "Host: www.google.com\r\n"
2049 "Connection: keep-alive\r\n"
2050 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2053 MockRead data_reads1
[] = {
2054 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2055 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2057 MockRead("Content-Length: 14\r\n\r\n"),
2058 MockRead("Unauthorized\r\n"),
2060 // Lastly, the server responds with the actual content.
2061 MockRead("HTTP/1.1 200 OK\r\n"),
2062 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2063 MockRead("Content-Length: 5\r\n\r\n"),
2067 // If there is a regression where we disconnect a Keep-Alive
2068 // connection during an auth roundtrip, we'll end up reading this.
2069 MockRead data_reads2
[] = {
2070 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2073 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2074 data_writes1
, arraysize(data_writes1
));
2075 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2077 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2078 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2080 TestCompletionCallback callback1
;
2082 scoped_ptr
<HttpTransaction
> trans(
2083 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2084 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2087 rv
= callback1
.WaitForResult();
2090 LoadTimingInfo load_timing_info1
;
2091 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2092 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2094 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2095 ASSERT_TRUE(response
!= NULL
);
2096 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2098 TestCompletionCallback callback2
;
2100 rv
= trans
->RestartWithAuth(
2101 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2102 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2104 rv
= callback2
.WaitForResult();
2107 LoadTimingInfo load_timing_info2
;
2108 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2109 TestLoadTimingReused(load_timing_info2
);
2110 // The load timing after restart should have the same socket ID, and times
2111 // those of the first load timing.
2112 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2113 load_timing_info2
.send_start
);
2114 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2116 response
= trans
->GetResponseInfo();
2117 ASSERT_TRUE(response
!= NULL
);
2118 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2119 EXPECT_EQ(5, response
->headers
->GetContentLength());
2121 std::string response_data
;
2122 rv
= ReadTransaction(trans
.get(), &response_data
);
2124 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2125 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2128 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2129 // connection and with no response body to drain.
2130 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2131 HttpRequestInfo request
;
2132 request
.method
= "GET";
2133 request
.url
= GURL("http://www.google.com/");
2134 request
.load_flags
= 0;
2136 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2138 MockWrite data_writes1
[] = {
2139 MockWrite("GET / HTTP/1.1\r\n"
2140 "Host: www.google.com\r\n"
2141 "Connection: keep-alive\r\n\r\n"),
2143 // After calling trans->RestartWithAuth(), this is the request we should
2144 // be issuing -- the final header line contains the credentials.
2145 MockWrite("GET / HTTP/1.1\r\n"
2146 "Host: www.google.com\r\n"
2147 "Connection: keep-alive\r\n"
2148 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2151 MockRead data_reads1
[] = {
2152 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2153 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2154 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2156 // Lastly, the server responds with the actual content.
2157 MockRead("HTTP/1.1 200 OK\r\n"),
2158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2159 MockRead("Content-Length: 5\r\n\r\n"),
2163 // An incorrect reconnect would cause this to be read.
2164 MockRead data_reads2
[] = {
2165 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2168 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2169 data_writes1
, arraysize(data_writes1
));
2170 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2172 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2173 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2175 TestCompletionCallback callback1
;
2177 scoped_ptr
<HttpTransaction
> trans(
2178 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2179 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2182 rv
= callback1
.WaitForResult();
2185 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2186 ASSERT_TRUE(response
!= NULL
);
2187 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2189 TestCompletionCallback callback2
;
2191 rv
= trans
->RestartWithAuth(
2192 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2193 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2195 rv
= callback2
.WaitForResult();
2198 response
= trans
->GetResponseInfo();
2199 ASSERT_TRUE(response
!= NULL
);
2200 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2201 EXPECT_EQ(5, response
->headers
->GetContentLength());
2204 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2205 // connection and with a large response body to drain.
2206 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2207 HttpRequestInfo request
;
2208 request
.method
= "GET";
2209 request
.url
= GURL("http://www.google.com/");
2210 request
.load_flags
= 0;
2212 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2214 MockWrite data_writes1
[] = {
2215 MockWrite("GET / HTTP/1.1\r\n"
2216 "Host: www.google.com\r\n"
2217 "Connection: keep-alive\r\n\r\n"),
2219 // After calling trans->RestartWithAuth(), this is the request we should
2220 // be issuing -- the final header line contains the credentials.
2221 MockWrite("GET / HTTP/1.1\r\n"
2222 "Host: www.google.com\r\n"
2223 "Connection: keep-alive\r\n"
2224 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2227 // Respond with 5 kb of response body.
2228 std::string
large_body_string("Unauthorized");
2229 large_body_string
.append(5 * 1024, ' ');
2230 large_body_string
.append("\r\n");
2232 MockRead data_reads1
[] = {
2233 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2234 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2235 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2236 // 5134 = 12 + 5 * 1024 + 2
2237 MockRead("Content-Length: 5134\r\n\r\n"),
2238 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2240 // Lastly, the server responds with the actual content.
2241 MockRead("HTTP/1.1 200 OK\r\n"),
2242 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2243 MockRead("Content-Length: 5\r\n\r\n"),
2247 // An incorrect reconnect would cause this to be read.
2248 MockRead data_reads2
[] = {
2249 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2252 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2253 data_writes1
, arraysize(data_writes1
));
2254 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2256 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2257 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2259 TestCompletionCallback callback1
;
2261 scoped_ptr
<HttpTransaction
> trans(
2262 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2263 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2264 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2266 rv
= callback1
.WaitForResult();
2269 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2270 ASSERT_TRUE(response
!= NULL
);
2271 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2273 TestCompletionCallback callback2
;
2275 rv
= trans
->RestartWithAuth(
2276 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2277 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2279 rv
= callback2
.WaitForResult();
2282 response
= trans
->GetResponseInfo();
2283 ASSERT_TRUE(response
!= NULL
);
2284 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2285 EXPECT_EQ(5, response
->headers
->GetContentLength());
2288 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2289 // connection, but the server gets impatient and closes the connection.
2290 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2291 HttpRequestInfo request
;
2292 request
.method
= "GET";
2293 request
.url
= GURL("http://www.google.com/");
2294 request
.load_flags
= 0;
2296 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2298 MockWrite data_writes1
[] = {
2299 MockWrite("GET / HTTP/1.1\r\n"
2300 "Host: www.google.com\r\n"
2301 "Connection: keep-alive\r\n\r\n"),
2302 // This simulates the seemingly successful write to a closed connection
2303 // if the bug is not fixed.
2304 MockWrite("GET / HTTP/1.1\r\n"
2305 "Host: www.google.com\r\n"
2306 "Connection: keep-alive\r\n"
2307 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2310 MockRead data_reads1
[] = {
2311 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2312 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2313 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2314 MockRead("Content-Length: 14\r\n\r\n"),
2315 // Tell MockTCPClientSocket to simulate the server closing the connection.
2316 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2317 MockRead("Unauthorized\r\n"),
2318 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2321 // After calling trans->RestartWithAuth(), this is the request we should
2322 // be issuing -- the final header line contains the credentials.
2323 MockWrite data_writes2
[] = {
2324 MockWrite("GET / HTTP/1.1\r\n"
2325 "Host: www.google.com\r\n"
2326 "Connection: keep-alive\r\n"
2327 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2330 // Lastly, the server responds with the actual content.
2331 MockRead data_reads2
[] = {
2332 MockRead("HTTP/1.1 200 OK\r\n"),
2333 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2334 MockRead("Content-Length: 5\r\n\r\n"),
2338 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2339 data_writes1
, arraysize(data_writes1
));
2340 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2341 data_writes2
, arraysize(data_writes2
));
2342 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2343 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2345 TestCompletionCallback callback1
;
2347 scoped_ptr
<HttpTransaction
> trans(
2348 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2349 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2350 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2352 rv
= callback1
.WaitForResult();
2355 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2356 ASSERT_TRUE(response
!= NULL
);
2357 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2359 TestCompletionCallback callback2
;
2361 rv
= trans
->RestartWithAuth(
2362 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2363 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2365 rv
= callback2
.WaitForResult();
2368 response
= trans
->GetResponseInfo();
2369 ASSERT_TRUE(response
!= NULL
);
2370 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2371 EXPECT_EQ(5, response
->headers
->GetContentLength());
2374 // Test the request-challenge-retry sequence for basic auth, over a connection
2375 // that requires a restart when setting up an SSL tunnel.
2376 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2377 HttpRequestInfo request
;
2378 request
.method
= "GET";
2379 request
.url
= GURL("https://www.google.com/");
2380 // when the no authentication data flag is set.
2381 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2383 // Configure against proxy server "myproxy:70".
2384 session_deps_
.proxy_service
.reset(
2385 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2386 CapturingBoundNetLog log
;
2387 session_deps_
.net_log
= log
.bound().net_log();
2388 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2390 // Since we have proxy, should try to establish tunnel.
2391 MockWrite data_writes1
[] = {
2393 "CONNECT www.google.com:443 HTTP/1.1\r\n"
2394 "Host: www.google.com\r\n"
2395 "Proxy-Connection: keep-alive\r\n\r\n"),
2397 // After calling trans->RestartWithAuth(), this is the request we should
2398 // be issuing -- the final header line contains the credentials.
2400 "CONNECT www.google.com:443 HTTP/1.1\r\n"
2401 "Host: www.google.com\r\n"
2402 "Proxy-Connection: keep-alive\r\n"
2403 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2406 "GET / HTTP/1.1\r\n"
2407 "Host: www.google.com\r\n"
2408 "Connection: keep-alive\r\n\r\n"),
2411 // The proxy responds to the connect with a 407, using a persistent
2413 MockRead data_reads1
[] = {
2415 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2416 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2418 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2420 MockRead("HTTP/1.1 200 OK\r\n"),
2421 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2422 MockRead("Content-Length: 5\r\n\r\n"),
2423 MockRead(SYNCHRONOUS
, "hello"),
2426 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2427 data_writes1
, arraysize(data_writes1
));
2428 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2429 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2430 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2432 TestCompletionCallback callback1
;
2434 scoped_ptr
<HttpTransaction
> trans(
2435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2437 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2440 rv
= callback1
.WaitForResult();
2442 net::CapturingNetLog::CapturedEntryList entries
;
2443 log
.GetEntries(&entries
);
2444 size_t pos
= ExpectLogContainsSomewhere(
2445 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2446 NetLog::PHASE_NONE
);
2447 ExpectLogContainsSomewhere(
2448 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2449 NetLog::PHASE_NONE
);
2451 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2452 ASSERT_TRUE(response
!= NULL
);
2453 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2454 ASSERT_FALSE(response
->headers
.get() == NULL
);
2455 EXPECT_EQ(407, response
->headers
->response_code());
2456 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2457 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2459 LoadTimingInfo load_timing_info
;
2460 // CONNECT requests and responses are handled at the connect job level, so
2461 // the transaction does not yet have a connection.
2462 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2464 TestCompletionCallback callback2
;
2467 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2470 rv
= callback2
.WaitForResult();
2473 response
= trans
->GetResponseInfo();
2474 ASSERT_TRUE(response
!= NULL
);
2476 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2477 EXPECT_EQ(200, response
->headers
->response_code());
2478 EXPECT_EQ(5, response
->headers
->GetContentLength());
2479 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2481 // The password prompt info should not be set.
2482 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2484 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2485 TestLoadTimingNotReusedWithPac(load_timing_info
,
2486 CONNECT_TIMING_HAS_SSL_TIMES
);
2489 session
->CloseAllConnections();
2492 // Test the request-challenge-retry sequence for basic auth, over a connection
2493 // that requires a restart when setting up an SSL tunnel.
2494 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2495 HttpRequestInfo request
;
2496 request
.method
= "GET";
2497 request
.url
= GURL("https://www.google.com/");
2498 // when the no authentication data flag is set.
2499 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2501 // Configure against proxy server "myproxy:70".
2502 session_deps_
.proxy_service
.reset(
2503 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2504 CapturingBoundNetLog log
;
2505 session_deps_
.net_log
= log
.bound().net_log();
2506 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2508 // Since we have proxy, should try to establish tunnel.
2509 MockWrite data_writes1
[] = {
2510 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2511 "Host: www.google.com\r\n"
2512 "Proxy-Connection: keep-alive\r\n\r\n"),
2514 // After calling trans->RestartWithAuth(), this is the request we should
2515 // be issuing -- the final header line contains the credentials.
2516 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2517 "Host: www.google.com\r\n"
2518 "Proxy-Connection: keep-alive\r\n"
2519 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2521 MockWrite("GET / HTTP/1.1\r\n"
2522 "Host: www.google.com\r\n"
2523 "Connection: keep-alive\r\n\r\n"),
2526 // The proxy responds to the connect with a 407, using a persistent
2528 MockRead data_reads1
[] = {
2530 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2531 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2532 MockRead("Proxy-Connection: close\r\n\r\n"),
2534 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2536 MockRead("HTTP/1.1 200 OK\r\n"),
2537 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2538 MockRead("Content-Length: 5\r\n\r\n"),
2539 MockRead(SYNCHRONOUS
, "hello"),
2542 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2543 data_writes1
, arraysize(data_writes1
));
2544 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2545 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2546 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2548 TestCompletionCallback callback1
;
2550 scoped_ptr
<HttpTransaction
> trans(
2551 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2553 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2554 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2556 rv
= callback1
.WaitForResult();
2558 net::CapturingNetLog::CapturedEntryList entries
;
2559 log
.GetEntries(&entries
);
2560 size_t pos
= ExpectLogContainsSomewhere(
2561 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2562 NetLog::PHASE_NONE
);
2563 ExpectLogContainsSomewhere(
2565 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2566 NetLog::PHASE_NONE
);
2568 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2569 ASSERT_TRUE(response
!= NULL
);
2570 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2571 ASSERT_FALSE(response
->headers
.get() == NULL
);
2572 EXPECT_EQ(407, response
->headers
->response_code());
2573 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2574 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2576 LoadTimingInfo load_timing_info
;
2577 // CONNECT requests and responses are handled at the connect job level, so
2578 // the transaction does not yet have a connection.
2579 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2581 TestCompletionCallback callback2
;
2583 rv
= trans
->RestartWithAuth(
2584 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2585 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2587 rv
= callback2
.WaitForResult();
2590 response
= trans
->GetResponseInfo();
2591 ASSERT_TRUE(response
!= NULL
);
2593 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2594 EXPECT_EQ(200, response
->headers
->response_code());
2595 EXPECT_EQ(5, response
->headers
->GetContentLength());
2596 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2598 // The password prompt info should not be set.
2599 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2601 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2602 TestLoadTimingNotReusedWithPac(load_timing_info
,
2603 CONNECT_TIMING_HAS_SSL_TIMES
);
2606 session
->CloseAllConnections();
2609 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2610 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2611 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2612 HttpRequestInfo request
;
2613 request
.method
= "GET";
2614 request
.url
= GURL("https://www.google.com/");
2615 // Ensure that proxy authentication is attempted even
2616 // when the no authentication data flag is set.
2617 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2619 // Configure against proxy server "myproxy:70".
2620 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2621 CapturingBoundNetLog log
;
2622 session_deps_
.net_log
= log
.bound().net_log();
2623 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2625 scoped_ptr
<HttpTransaction
> trans(
2626 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2628 // Since we have proxy, should try to establish tunnel.
2629 MockWrite data_writes1
[] = {
2631 "CONNECT www.google.com:443 HTTP/1.1\r\n"
2632 "Host: www.google.com\r\n"
2633 "Proxy-Connection: keep-alive\r\n\r\n"),
2635 // After calling trans->RestartWithAuth(), this is the request we should
2636 // be issuing -- the final header line contains the credentials.
2638 "CONNECT www.google.com:443 HTTP/1.1\r\n"
2639 "Host: www.google.com\r\n"
2640 "Proxy-Connection: keep-alive\r\n"
2641 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2644 // The proxy responds to the connect with a 407, using a persistent
2645 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2646 MockRead data_reads1
[] = {
2648 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2649 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2650 MockRead("Proxy-Connection: keep-alive\r\n"),
2651 MockRead("Content-Length: 10\r\n\r\n"),
2652 MockRead("0123456789"),
2654 // Wrong credentials (wrong password).
2655 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2656 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2657 MockRead("Proxy-Connection: keep-alive\r\n"),
2658 MockRead("Content-Length: 10\r\n\r\n"),
2659 // No response body because the test stops reading here.
2660 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2663 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2664 data_writes1
, arraysize(data_writes1
));
2665 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2667 TestCompletionCallback callback1
;
2669 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2670 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2672 rv
= callback1
.WaitForResult();
2674 net::CapturingNetLog::CapturedEntryList entries
;
2675 log
.GetEntries(&entries
);
2676 size_t pos
= ExpectLogContainsSomewhere(
2677 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2678 NetLog::PHASE_NONE
);
2679 ExpectLogContainsSomewhere(
2680 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2681 NetLog::PHASE_NONE
);
2683 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2684 ASSERT_TRUE(response
);
2685 ASSERT_TRUE(response
->headers
);
2686 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2687 EXPECT_EQ(407, response
->headers
->response_code());
2688 EXPECT_EQ(10, response
->headers
->GetContentLength());
2689 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2690 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2692 TestCompletionCallback callback2
;
2694 // Wrong password (should be "bar").
2696 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2699 rv
= callback2
.WaitForResult();
2702 response
= trans
->GetResponseInfo();
2703 ASSERT_TRUE(response
);
2704 ASSERT_TRUE(response
->headers
);
2705 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2706 EXPECT_EQ(407, response
->headers
->response_code());
2707 EXPECT_EQ(10, response
->headers
->GetContentLength());
2708 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2709 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2711 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2713 session
->CloseAllConnections();
2716 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2717 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2718 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2719 HttpRequestInfo request
;
2720 request
.method
= "GET";
2721 request
.url
= GURL("https://www.google.com/");
2722 // Ensure that proxy authentication is attempted even
2723 // when the no authentication data flag is set.
2724 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2726 // Configure against proxy server "myproxy:70".
2727 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2728 CapturingBoundNetLog log
;
2729 session_deps_
.net_log
= log
.bound().net_log();
2730 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2732 scoped_ptr
<HttpTransaction
> trans(
2733 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2735 // Since we have proxy, should try to establish tunnel.
2736 MockWrite data_writes1
[] = {
2737 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2738 "Host: www.google.com\r\n"
2739 "Proxy-Connection: keep-alive\r\n\r\n"),
2741 // After calling trans->RestartWithAuth(), this is the request we should
2742 // be issuing -- the final header line contains the credentials.
2743 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2744 "Host: www.google.com\r\n"
2745 "Proxy-Connection: keep-alive\r\n"
2746 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2749 // The proxy responds to the connect with a 407, using a persistent
2751 MockRead data_reads1
[] = {
2753 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2754 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2755 MockRead("Content-Length: 10\r\n\r\n"),
2756 MockRead("0123456789"),
2758 // Wrong credentials (wrong password).
2759 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2760 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2761 MockRead("Content-Length: 10\r\n\r\n"),
2762 // No response body because the test stops reading here.
2763 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2766 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2767 data_writes1
, arraysize(data_writes1
));
2768 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2770 TestCompletionCallback callback1
;
2772 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2773 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2775 rv
= callback1
.WaitForResult();
2777 net::CapturingNetLog::CapturedEntryList entries
;
2778 log
.GetEntries(&entries
);
2779 size_t pos
= ExpectLogContainsSomewhere(
2780 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2781 NetLog::PHASE_NONE
);
2782 ExpectLogContainsSomewhere(
2784 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2785 NetLog::PHASE_NONE
);
2787 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2788 ASSERT_TRUE(response
);
2789 ASSERT_TRUE(response
->headers
);
2790 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2791 EXPECT_EQ(407, response
->headers
->response_code());
2792 EXPECT_EQ(10, response
->headers
->GetContentLength());
2793 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2794 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2796 TestCompletionCallback callback2
;
2798 // Wrong password (should be "bar").
2799 rv
= trans
->RestartWithAuth(
2800 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2801 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2803 rv
= callback2
.WaitForResult();
2806 response
= trans
->GetResponseInfo();
2807 ASSERT_TRUE(response
);
2808 ASSERT_TRUE(response
->headers
);
2809 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2810 EXPECT_EQ(407, response
->headers
->response_code());
2811 EXPECT_EQ(10, response
->headers
->GetContentLength());
2812 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2813 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2815 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2817 session
->CloseAllConnections();
2820 // Test that we don't read the response body when we fail to establish a tunnel,
2821 // even if the user cancels the proxy's auth attempt.
2822 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2823 HttpRequestInfo request
;
2824 request
.method
= "GET";
2825 request
.url
= GURL("https://www.google.com/");
2826 request
.load_flags
= 0;
2828 // Configure against proxy server "myproxy:70".
2829 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2831 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2833 scoped_ptr
<HttpTransaction
> trans(
2834 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2836 // Since we have proxy, should try to establish tunnel.
2837 MockWrite data_writes
[] = {
2838 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2839 "Host: www.google.com\r\n"
2840 "Proxy-Connection: keep-alive\r\n\r\n"),
2843 // The proxy responds to the connect with a 407.
2844 MockRead data_reads
[] = {
2845 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2846 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2847 MockRead("Content-Length: 10\r\n\r\n"),
2848 MockRead("0123456789"), // Should not be reached.
2849 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2852 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2853 data_writes
, arraysize(data_writes
));
2854 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2856 TestCompletionCallback callback
;
2858 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2861 rv
= callback
.WaitForResult();
2864 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2865 ASSERT_TRUE(response
);
2866 ASSERT_TRUE(response
->headers
);
2867 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2868 EXPECT_EQ(407, response
->headers
->response_code());
2869 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2871 std::string response_data
;
2872 rv
= ReadTransaction(trans
.get(), &response_data
);
2873 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2875 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2876 session
->CloseAllConnections();
2879 // Test that we don't pass extraneous headers from the proxy's response to the
2880 // caller when the proxy responds to CONNECT with 407.
2881 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2882 HttpRequestInfo request
;
2883 request
.method
= "GET";
2884 request
.url
= GURL("https://www.google.com/");
2885 request
.load_flags
= 0;
2887 // Configure against proxy server "myproxy:70".
2888 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2890 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2892 scoped_ptr
<HttpTransaction
> trans(
2893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2895 // Since we have proxy, should try to establish tunnel.
2896 MockWrite data_writes
[] = {
2898 "CONNECT www.google.com:443 HTTP/1.1\r\n"
2899 "Host: www.google.com\r\n"
2900 "Proxy-Connection: keep-alive\r\n\r\n"),
2903 // The proxy responds to the connect with a 407.
2904 MockRead data_reads
[] = {
2905 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2906 MockRead("X-Foo: bar\r\n"),
2907 MockRead("Set-Cookie: foo=bar\r\n"),
2908 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2909 MockRead("Content-Length: 10\r\n\r\n"),
2910 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2913 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2914 arraysize(data_writes
));
2915 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2917 TestCompletionCallback callback
;
2919 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2920 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2922 rv
= callback
.WaitForResult();
2925 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2926 ASSERT_TRUE(response
);
2927 ASSERT_TRUE(response
->headers
);
2928 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2929 EXPECT_EQ(407, response
->headers
->response_code());
2930 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2931 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2932 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2934 std::string response_data
;
2935 rv
= ReadTransaction(trans
.get(), &response_data
);
2936 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2938 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2939 session
->CloseAllConnections();
2942 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2943 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2944 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2945 HttpRequestInfo request
;
2946 request
.method
= "GET";
2947 request
.url
= GURL("http://www.google.com/");
2948 request
.load_flags
= 0;
2950 // We are using a DIRECT connection (i.e. no proxy) for this session.
2951 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2952 scoped_ptr
<HttpTransaction
> trans(
2953 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2955 MockWrite data_writes1
[] = {
2956 MockWrite("GET / HTTP/1.1\r\n"
2957 "Host: www.google.com\r\n"
2958 "Connection: keep-alive\r\n\r\n"),
2961 MockRead data_reads1
[] = {
2962 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2963 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2964 // Large content-length -- won't matter, as connection will be reset.
2965 MockRead("Content-Length: 10000\r\n\r\n"),
2966 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2969 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2970 data_writes1
, arraysize(data_writes1
));
2971 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2973 TestCompletionCallback callback
;
2975 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2978 rv
= callback
.WaitForResult();
2979 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2982 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2983 // through a non-authenticating proxy. The request should fail with
2984 // ERR_UNEXPECTED_PROXY_AUTH.
2985 // Note that it is impossible to detect if an HTTP server returns a 407 through
2986 // a non-authenticating proxy - there is nothing to indicate whether the
2987 // response came from the proxy or the server, so it is treated as if the proxy
2988 // issued the challenge.
2989 TEST_P(HttpNetworkTransactionTest
,
2990 HttpsServerRequestsProxyAuthThroughProxy
) {
2991 HttpRequestInfo request
;
2992 request
.method
= "GET";
2993 request
.url
= GURL("https://www.google.com/");
2995 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2996 CapturingBoundNetLog log
;
2997 session_deps_
.net_log
= log
.bound().net_log();
2998 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3000 // Since we have proxy, should try to establish tunnel.
3001 MockWrite data_writes1
[] = {
3002 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3003 "Host: www.google.com\r\n"
3004 "Proxy-Connection: keep-alive\r\n\r\n"),
3006 MockWrite("GET / HTTP/1.1\r\n"
3007 "Host: www.google.com\r\n"
3008 "Connection: keep-alive\r\n\r\n"),
3011 MockRead data_reads1
[] = {
3012 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3014 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3015 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3017 MockRead(SYNCHRONOUS
, OK
),
3020 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3021 data_writes1
, arraysize(data_writes1
));
3022 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3023 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3024 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3026 TestCompletionCallback callback1
;
3028 scoped_ptr
<HttpTransaction
> trans(
3029 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3031 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3034 rv
= callback1
.WaitForResult();
3035 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3036 net::CapturingNetLog::CapturedEntryList entries
;
3037 log
.GetEntries(&entries
);
3038 size_t pos
= ExpectLogContainsSomewhere(
3039 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3040 NetLog::PHASE_NONE
);
3041 ExpectLogContainsSomewhere(
3043 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3044 NetLog::PHASE_NONE
);
3047 // Test the load timing for HTTPS requests with an HTTP proxy.
3048 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3049 HttpRequestInfo request1
;
3050 request1
.method
= "GET";
3051 request1
.url
= GURL("https://www.google.com/1");
3053 HttpRequestInfo request2
;
3054 request2
.method
= "GET";
3055 request2
.url
= GURL("https://www.google.com/2");
3057 // Configure against proxy server "myproxy:70".
3058 session_deps_
.proxy_service
.reset(
3059 ProxyService::CreateFixed("PROXY myproxy:70"));
3060 CapturingBoundNetLog log
;
3061 session_deps_
.net_log
= log
.bound().net_log();
3062 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3064 // Since we have proxy, should try to establish tunnel.
3065 MockWrite data_writes1
[] = {
3066 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3067 "Host: www.google.com\r\n"
3068 "Proxy-Connection: keep-alive\r\n\r\n"),
3070 MockWrite("GET /1 HTTP/1.1\r\n"
3071 "Host: www.google.com\r\n"
3072 "Connection: keep-alive\r\n\r\n"),
3074 MockWrite("GET /2 HTTP/1.1\r\n"
3075 "Host: www.google.com\r\n"
3076 "Connection: keep-alive\r\n\r\n"),
3079 // The proxy responds to the connect with a 407, using a persistent
3081 MockRead data_reads1
[] = {
3082 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3084 MockRead("HTTP/1.1 200 OK\r\n"),
3085 MockRead("Content-Length: 1\r\n\r\n"),
3086 MockRead(SYNCHRONOUS
, "1"),
3088 MockRead("HTTP/1.1 200 OK\r\n"),
3089 MockRead("Content-Length: 2\r\n\r\n"),
3090 MockRead(SYNCHRONOUS
, "22"),
3093 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3094 data_writes1
, arraysize(data_writes1
));
3095 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3096 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3097 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3099 TestCompletionCallback callback1
;
3100 scoped_ptr
<HttpTransaction
> trans1(
3101 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3103 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3104 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3106 rv
= callback1
.WaitForResult();
3109 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3110 ASSERT_TRUE(response1
!= NULL
);
3111 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3112 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3114 LoadTimingInfo load_timing_info1
;
3115 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3116 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3120 TestCompletionCallback callback2
;
3121 scoped_ptr
<HttpTransaction
> trans2(
3122 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3124 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3125 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3127 rv
= callback2
.WaitForResult();
3130 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3131 ASSERT_TRUE(response2
!= NULL
);
3132 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3133 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3135 LoadTimingInfo load_timing_info2
;
3136 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3137 TestLoadTimingReused(load_timing_info2
);
3139 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3142 session
->CloseAllConnections();
3145 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3146 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3147 HttpRequestInfo request1
;
3148 request1
.method
= "GET";
3149 request1
.url
= GURL("https://www.google.com/1");
3151 HttpRequestInfo request2
;
3152 request2
.method
= "GET";
3153 request2
.url
= GURL("https://www.google.com/2");
3155 // Configure against proxy server "myproxy:70".
3156 session_deps_
.proxy_service
.reset(
3157 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3158 CapturingBoundNetLog log
;
3159 session_deps_
.net_log
= log
.bound().net_log();
3160 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3162 // Since we have proxy, should try to establish tunnel.
3163 MockWrite data_writes1
[] = {
3164 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3165 "Host: www.google.com\r\n"
3166 "Proxy-Connection: keep-alive\r\n\r\n"),
3168 MockWrite("GET /1 HTTP/1.1\r\n"
3169 "Host: www.google.com\r\n"
3170 "Connection: keep-alive\r\n\r\n"),
3172 MockWrite("GET /2 HTTP/1.1\r\n"
3173 "Host: www.google.com\r\n"
3174 "Connection: keep-alive\r\n\r\n"),
3177 // The proxy responds to the connect with a 407, using a persistent
3179 MockRead data_reads1
[] = {
3180 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3182 MockRead("HTTP/1.1 200 OK\r\n"),
3183 MockRead("Content-Length: 1\r\n\r\n"),
3184 MockRead(SYNCHRONOUS
, "1"),
3186 MockRead("HTTP/1.1 200 OK\r\n"),
3187 MockRead("Content-Length: 2\r\n\r\n"),
3188 MockRead(SYNCHRONOUS
, "22"),
3191 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3192 data_writes1
, arraysize(data_writes1
));
3193 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3194 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3195 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3197 TestCompletionCallback callback1
;
3198 scoped_ptr
<HttpTransaction
> trans1(
3199 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3201 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3202 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3204 rv
= callback1
.WaitForResult();
3207 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3208 ASSERT_TRUE(response1
!= NULL
);
3209 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3210 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3212 LoadTimingInfo load_timing_info1
;
3213 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3214 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3215 CONNECT_TIMING_HAS_SSL_TIMES
);
3219 TestCompletionCallback callback2
;
3220 scoped_ptr
<HttpTransaction
> trans2(
3221 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3223 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3224 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3226 rv
= callback2
.WaitForResult();
3229 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3230 ASSERT_TRUE(response2
!= NULL
);
3231 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3232 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3234 LoadTimingInfo load_timing_info2
;
3235 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3236 TestLoadTimingReusedWithPac(load_timing_info2
);
3238 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3241 session
->CloseAllConnections();
3244 // Test a simple get through an HTTPS Proxy.
3245 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3246 HttpRequestInfo request
;
3247 request
.method
= "GET";
3248 request
.url
= GURL("http://www.google.com/");
3250 // Configure against https proxy server "proxy:70".
3251 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3252 "https://proxy:70"));
3253 CapturingBoundNetLog log
;
3254 session_deps_
.net_log
= log
.bound().net_log();
3255 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3257 // Since we have proxy, should use full url
3258 MockWrite data_writes1
[] = {
3259 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3260 "Host: www.google.com\r\n"
3261 "Proxy-Connection: keep-alive\r\n\r\n"),
3264 MockRead data_reads1
[] = {
3265 MockRead("HTTP/1.1 200 OK\r\n"),
3266 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3267 MockRead("Content-Length: 100\r\n\r\n"),
3268 MockRead(SYNCHRONOUS
, OK
),
3271 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3272 data_writes1
, arraysize(data_writes1
));
3273 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3274 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3275 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3277 TestCompletionCallback callback1
;
3279 scoped_ptr
<HttpTransaction
> trans(
3280 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3282 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3283 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3285 rv
= callback1
.WaitForResult();
3288 LoadTimingInfo load_timing_info
;
3289 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3290 TestLoadTimingNotReused(load_timing_info
,
3291 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3293 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3294 ASSERT_TRUE(response
!= NULL
);
3296 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3297 EXPECT_EQ(200, response
->headers
->response_code());
3298 EXPECT_EQ(100, response
->headers
->GetContentLength());
3299 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3301 // The password prompt info should not be set.
3302 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3305 // Test a SPDY get through an HTTPS Proxy.
3306 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3307 HttpRequestInfo request
;
3308 request
.method
= "GET";
3309 request
.url
= GURL("http://www.google.com/");
3310 request
.load_flags
= 0;
3312 // Configure against https proxy server "proxy:70".
3313 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3314 "https://proxy:70"));
3315 CapturingBoundNetLog log
;
3316 session_deps_
.net_log
= log
.bound().net_log();
3317 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3319 // fetch http://www.google.com/ via SPDY
3320 scoped_ptr
<SpdyFrame
> req(
3321 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3322 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
3324 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3325 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3326 MockRead spdy_reads
[] = {
3327 CreateMockRead(*resp
),
3328 CreateMockRead(*data
),
3329 MockRead(ASYNC
, 0, 0),
3332 DelayedSocketData
spdy_data(
3333 1, // wait for one write to finish before reading.
3334 spdy_reads
, arraysize(spdy_reads
),
3335 spdy_writes
, arraysize(spdy_writes
));
3336 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3338 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3339 ssl
.SetNextProto(GetParam());
3340 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3342 TestCompletionCallback callback1
;
3344 scoped_ptr
<HttpTransaction
> trans(
3345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3347 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3350 rv
= callback1
.WaitForResult();
3353 LoadTimingInfo load_timing_info
;
3354 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3355 TestLoadTimingNotReused(load_timing_info
,
3356 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3358 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3359 ASSERT_TRUE(response
!= NULL
);
3360 ASSERT_TRUE(response
->headers
.get() != NULL
);
3361 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3363 std::string response_data
;
3364 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3365 EXPECT_EQ(kUploadData
, response_data
);
3368 // Verifies that a session which races and wins against the owning transaction
3369 // (completing prior to host resolution), doesn't fail the transaction.
3370 // Regression test for crbug.com/334413.
3371 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3372 HttpRequestInfo request
;
3373 request
.method
= "GET";
3374 request
.url
= GURL("http://www.google.com/");
3375 request
.load_flags
= 0;
3377 // Configure SPDY proxy server "proxy:70".
3378 session_deps_
.proxy_service
.reset(
3379 ProxyService::CreateFixed("https://proxy:70"));
3380 CapturingBoundNetLog log
;
3381 session_deps_
.net_log
= log
.bound().net_log();
3382 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3384 // Fetch http://www.google.com/ through the SPDY proxy.
3385 scoped_ptr
<SpdyFrame
> req(
3386 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3387 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3389 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3390 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3391 MockRead spdy_reads
[] = {
3392 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3395 DelayedSocketData
spdy_data(
3396 1, // wait for one write to finish before reading.
3398 arraysize(spdy_reads
),
3400 arraysize(spdy_writes
));
3401 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3403 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3404 ssl
.SetNextProto(GetParam());
3405 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3407 TestCompletionCallback callback1
;
3409 scoped_ptr
<HttpTransaction
> trans(
3410 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3412 // Stall the hostname resolution begun by the transaction.
3413 session_deps_
.host_resolver
->set_synchronous_mode(false);
3414 session_deps_
.host_resolver
->set_ondemand_mode(true);
3416 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3417 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3419 // Race a session to the proxy, which completes first.
3420 session_deps_
.host_resolver
->set_ondemand_mode(false);
3422 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3423 base::WeakPtr
<SpdySession
> spdy_session
=
3424 CreateSecureSpdySession(session
, key
, log
.bound());
3426 // Unstall the resolution begun by the transaction.
3427 session_deps_
.host_resolver
->set_ondemand_mode(true);
3428 session_deps_
.host_resolver
->ResolveAllPending();
3430 EXPECT_FALSE(callback1
.have_result());
3431 rv
= callback1
.WaitForResult();
3434 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3435 ASSERT_TRUE(response
!= NULL
);
3436 ASSERT_TRUE(response
->headers
.get() != NULL
);
3437 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3439 std::string response_data
;
3440 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3441 EXPECT_EQ(kUploadData
, response_data
);
3444 // Test a SPDY get through an HTTPS Proxy.
3445 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3446 HttpRequestInfo request
;
3447 request
.method
= "GET";
3448 request
.url
= GURL("http://www.google.com/");
3449 request
.load_flags
= 0;
3451 // Configure against https proxy server "myproxy:70".
3452 session_deps_
.proxy_service
.reset(
3453 ProxyService::CreateFixed("https://myproxy:70"));
3454 CapturingBoundNetLog log
;
3455 session_deps_
.net_log
= log
.bound().net_log();
3456 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3458 // The first request will be a bare GET, the second request will be a
3459 // GET with a Proxy-Authorization header.
3460 scoped_ptr
<SpdyFrame
> req_get(
3461 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3462 const char* const kExtraAuthorizationHeaders
[] = {
3463 "proxy-authorization", "Basic Zm9vOmJhcg=="
3465 scoped_ptr
<SpdyFrame
> req_get_authorization(
3466 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3467 arraysize(kExtraAuthorizationHeaders
) / 2,
3472 MockWrite spdy_writes
[] = {
3473 CreateMockWrite(*req_get
, 1),
3474 CreateMockWrite(*req_get_authorization
, 4),
3477 // The first response is a 407 proxy authentication challenge, and the second
3478 // response will be a 200 response since the second request includes a valid
3479 // Authorization header.
3480 const char* const kExtraAuthenticationHeaders
[] = {
3481 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3483 scoped_ptr
<SpdyFrame
> resp_authentication(
3484 spdy_util_
.ConstructSpdySynReplyError(
3485 "407 Proxy Authentication Required",
3486 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3488 scoped_ptr
<SpdyFrame
> body_authentication(
3489 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3490 scoped_ptr
<SpdyFrame
> resp_data(
3491 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3492 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3493 MockRead spdy_reads
[] = {
3494 CreateMockRead(*resp_authentication
, 2),
3495 CreateMockRead(*body_authentication
, 3),
3496 CreateMockRead(*resp_data
, 5),
3497 CreateMockRead(*body_data
, 6),
3498 MockRead(ASYNC
, 0, 7),
3501 OrderedSocketData
data(
3502 spdy_reads
, arraysize(spdy_reads
),
3503 spdy_writes
, arraysize(spdy_writes
));
3504 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3506 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3507 ssl
.SetNextProto(GetParam());
3508 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3510 TestCompletionCallback callback1
;
3512 scoped_ptr
<HttpTransaction
> trans(
3513 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3515 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3516 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3518 rv
= callback1
.WaitForResult();
3521 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3523 ASSERT_TRUE(response
!= NULL
);
3524 ASSERT_TRUE(response
->headers
.get() != NULL
);
3525 EXPECT_EQ(407, response
->headers
->response_code());
3526 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3527 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3529 TestCompletionCallback callback2
;
3531 rv
= trans
->RestartWithAuth(
3532 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3533 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3535 rv
= callback2
.WaitForResult();
3538 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3540 ASSERT_TRUE(response_restart
!= NULL
);
3541 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3542 EXPECT_EQ(200, response_restart
->headers
->response_code());
3543 // The password prompt info should not be set.
3544 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3547 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3548 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3549 HttpRequestInfo request
;
3550 request
.method
= "GET";
3551 request
.url
= GURL("https://www.google.com/");
3552 request
.load_flags
= 0;
3554 // Configure against https proxy server "proxy:70".
3555 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3556 "https://proxy:70"));
3557 CapturingBoundNetLog log
;
3558 session_deps_
.net_log
= log
.bound().net_log();
3559 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3561 scoped_ptr
<HttpTransaction
> trans(
3562 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3564 // CONNECT to www.google.com:443 via SPDY
3565 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3566 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
3567 // fetch https://www.google.com/ via HTTP
3569 const char get
[] = "GET / HTTP/1.1\r\n"
3570 "Host: www.google.com\r\n"
3571 "Connection: keep-alive\r\n\r\n";
3572 scoped_ptr
<SpdyFrame
> wrapped_get(
3573 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3574 scoped_ptr
<SpdyFrame
> conn_resp(
3575 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3576 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3577 "Content-Length: 10\r\n\r\n";
3578 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3579 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3580 scoped_ptr
<SpdyFrame
> wrapped_body(
3581 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3582 scoped_ptr
<SpdyFrame
> window_update(
3583 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3585 MockWrite spdy_writes
[] = {
3586 CreateMockWrite(*connect
, 1),
3587 CreateMockWrite(*wrapped_get
, 3),
3588 CreateMockWrite(*window_update
, 5),
3591 MockRead spdy_reads
[] = {
3592 CreateMockRead(*conn_resp
, 2, ASYNC
),
3593 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3594 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3595 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3596 MockRead(ASYNC
, 0, 8),
3599 OrderedSocketData
spdy_data(
3600 spdy_reads
, arraysize(spdy_reads
),
3601 spdy_writes
, arraysize(spdy_writes
));
3602 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3604 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3605 ssl
.SetNextProto(GetParam());
3606 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3607 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3608 ssl2
.was_npn_negotiated
= false;
3609 ssl2
.protocol_negotiated
= kProtoUnknown
;
3610 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3612 TestCompletionCallback callback1
;
3614 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3615 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3617 rv
= callback1
.WaitForResult();
3620 LoadTimingInfo load_timing_info
;
3621 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3622 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3624 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3625 ASSERT_TRUE(response
!= NULL
);
3626 ASSERT_TRUE(response
->headers
.get() != NULL
);
3627 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3629 std::string response_data
;
3630 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3631 EXPECT_EQ("1234567890", response_data
);
3634 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3635 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3636 HttpRequestInfo request
;
3637 request
.method
= "GET";
3638 request
.url
= GURL("https://www.google.com/");
3639 request
.load_flags
= 0;
3641 // Configure against https proxy server "proxy:70".
3642 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3643 "https://proxy:70"));
3644 CapturingBoundNetLog log
;
3645 session_deps_
.net_log
= log
.bound().net_log();
3646 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3648 scoped_ptr
<HttpTransaction
> trans(
3649 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3651 // CONNECT to www.google.com:443 via SPDY
3652 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3653 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
3654 // fetch https://www.google.com/ via SPDY
3655 const char kMyUrl
[] = "https://www.google.com/";
3656 scoped_ptr
<SpdyFrame
> get(
3657 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3658 scoped_ptr
<SpdyFrame
> wrapped_get(
3659 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3660 scoped_ptr
<SpdyFrame
> conn_resp(
3661 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3662 scoped_ptr
<SpdyFrame
> get_resp(
3663 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3664 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3665 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3666 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3667 scoped_ptr
<SpdyFrame
> wrapped_body(
3668 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3669 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3670 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3671 scoped_ptr
<SpdyFrame
> window_update_body(
3672 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3674 MockWrite spdy_writes
[] = {
3675 CreateMockWrite(*connect
, 1),
3676 CreateMockWrite(*wrapped_get
, 3),
3677 CreateMockWrite(*window_update_get_resp
, 5),
3678 CreateMockWrite(*window_update_body
, 7),
3681 MockRead spdy_reads
[] = {
3682 CreateMockRead(*conn_resp
, 2, ASYNC
),
3683 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3684 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3685 MockRead(ASYNC
, 0, 8),
3688 OrderedSocketData
spdy_data(
3689 spdy_reads
, arraysize(spdy_reads
),
3690 spdy_writes
, arraysize(spdy_writes
));
3691 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3693 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3694 ssl
.SetNextProto(GetParam());
3695 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3696 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3697 ssl2
.SetNextProto(GetParam());
3698 ssl2
.protocol_negotiated
= GetParam();
3699 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3701 TestCompletionCallback callback1
;
3703 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3706 rv
= callback1
.WaitForResult();
3709 LoadTimingInfo load_timing_info
;
3710 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3711 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3713 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3714 ASSERT_TRUE(response
!= NULL
);
3715 ASSERT_TRUE(response
->headers
.get() != NULL
);
3716 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3718 std::string response_data
;
3719 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3720 EXPECT_EQ(kUploadData
, response_data
);
3723 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3724 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3725 HttpRequestInfo request
;
3726 request
.method
= "GET";
3727 request
.url
= GURL("https://www.google.com/");
3728 request
.load_flags
= 0;
3730 // Configure against https proxy server "proxy:70".
3731 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3732 "https://proxy:70"));
3733 CapturingBoundNetLog log
;
3734 session_deps_
.net_log
= log
.bound().net_log();
3735 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3737 scoped_ptr
<HttpTransaction
> trans(
3738 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3740 // CONNECT to www.google.com:443 via SPDY
3741 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3742 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
3743 scoped_ptr
<SpdyFrame
> get(
3744 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3746 MockWrite spdy_writes
[] = {
3747 CreateMockWrite(*connect
, 1),
3748 CreateMockWrite(*get
, 3),
3751 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3752 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3753 MockRead spdy_reads
[] = {
3754 CreateMockRead(*resp
, 2, ASYNC
),
3755 MockRead(ASYNC
, 0, 4),
3758 OrderedSocketData
spdy_data(
3759 spdy_reads
, arraysize(spdy_reads
),
3760 spdy_writes
, arraysize(spdy_writes
));
3761 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3763 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3764 ssl
.SetNextProto(GetParam());
3765 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3766 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3767 ssl2
.SetNextProto(GetParam());
3768 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3770 TestCompletionCallback callback1
;
3772 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3773 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3775 rv
= callback1
.WaitForResult();
3776 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3778 // TODO(ttuttle): Anything else to check here?
3781 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3782 // HTTPS Proxy to different servers.
3783 TEST_P(HttpNetworkTransactionTest
,
3784 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3785 // Configure against https proxy server "proxy:70".
3786 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3787 "https://proxy:70"));
3788 CapturingBoundNetLog log
;
3789 session_deps_
.net_log
= log
.bound().net_log();
3790 scoped_refptr
<HttpNetworkSession
> session(
3791 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3793 HttpRequestInfo request1
;
3794 request1
.method
= "GET";
3795 request1
.url
= GURL("https://www.google.com/");
3796 request1
.load_flags
= 0;
3798 HttpRequestInfo request2
;
3799 request2
.method
= "GET";
3800 request2
.url
= GURL("https://news.google.com/");
3801 request2
.load_flags
= 0;
3803 // CONNECT to www.google.com:443 via SPDY.
3804 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3805 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
3806 scoped_ptr
<SpdyFrame
> conn_resp1(
3807 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3809 // Fetch https://www.google.com/ via HTTP.
3810 const char get1
[] = "GET / HTTP/1.1\r\n"
3811 "Host: www.google.com\r\n"
3812 "Connection: keep-alive\r\n\r\n";
3813 scoped_ptr
<SpdyFrame
> wrapped_get1(
3814 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3815 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3816 "Content-Length: 1\r\n\r\n";
3817 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3818 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3819 scoped_ptr
<SpdyFrame
> wrapped_body1(
3820 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3821 scoped_ptr
<SpdyFrame
> window_update(
3822 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3824 // CONNECT to news.google.com:443 via SPDY.
3825 SpdyHeaderBlock connect2_block
;
3826 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3827 connect2_block
[spdy_util_
.GetPathKey()] = "news.google.com:443";
3828 connect2_block
[spdy_util_
.GetHostKey()] = "news.google.com";
3829 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3830 scoped_ptr
<SpdyFrame
> connect2(
3831 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3833 scoped_ptr
<SpdyFrame
> conn_resp2(
3834 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3836 // Fetch https://news.google.com/ via HTTP.
3837 const char get2
[] = "GET / HTTP/1.1\r\n"
3838 "Host: news.google.com\r\n"
3839 "Connection: keep-alive\r\n\r\n";
3840 scoped_ptr
<SpdyFrame
> wrapped_get2(
3841 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3842 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3843 "Content-Length: 2\r\n\r\n";
3844 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3845 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3846 scoped_ptr
<SpdyFrame
> wrapped_body2(
3847 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3849 MockWrite spdy_writes
[] = {
3850 CreateMockWrite(*connect1
, 0),
3851 CreateMockWrite(*wrapped_get1
, 2),
3852 CreateMockWrite(*connect2
, 5),
3853 CreateMockWrite(*wrapped_get2
, 7),
3856 MockRead spdy_reads
[] = {
3857 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3858 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3859 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3860 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3861 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3862 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3863 MockRead(ASYNC
, 0, 10),
3866 DeterministicSocketData
spdy_data(
3867 spdy_reads
, arraysize(spdy_reads
),
3868 spdy_writes
, arraysize(spdy_writes
));
3869 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3871 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3872 ssl
.SetNextProto(GetParam());
3873 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3874 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3875 ssl2
.was_npn_negotiated
= false;
3876 ssl2
.protocol_negotiated
= kProtoUnknown
;
3877 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3878 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3879 ssl3
.was_npn_negotiated
= false;
3880 ssl3
.protocol_negotiated
= kProtoUnknown
;
3881 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3883 TestCompletionCallback callback
;
3885 scoped_ptr
<HttpTransaction
> trans(
3886 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3887 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3888 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3889 // The first connect and request, each of their responses, and the body.
3890 spdy_data
.RunFor(5);
3892 rv
= callback
.WaitForResult();
3895 LoadTimingInfo load_timing_info
;
3896 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3897 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3899 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3900 ASSERT_TRUE(response
!= NULL
);
3901 ASSERT_TRUE(response
->headers
.get() != NULL
);
3902 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3904 std::string response_data
;
3905 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3906 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3908 scoped_ptr
<HttpTransaction
> trans2(
3909 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3910 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3911 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3913 // The second connect and request, each of their responses, and the body.
3914 spdy_data
.RunFor(5);
3915 rv
= callback
.WaitForResult();
3918 LoadTimingInfo load_timing_info2
;
3919 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3920 // Even though the SPDY connection is reused, a new tunnelled connection has
3921 // to be created, so the socket's load timing looks like a fresh connection.
3922 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3924 // The requests should have different IDs, since they each are using their own
3926 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3928 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3931 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3932 // HTTPS Proxy to the same server.
3933 TEST_P(HttpNetworkTransactionTest
,
3934 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3935 // Configure against https proxy server "proxy:70".
3936 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3937 "https://proxy:70"));
3938 CapturingBoundNetLog log
;
3939 session_deps_
.net_log
= log
.bound().net_log();
3940 scoped_refptr
<HttpNetworkSession
> session(
3941 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3943 HttpRequestInfo request1
;
3944 request1
.method
= "GET";
3945 request1
.url
= GURL("https://www.google.com/");
3946 request1
.load_flags
= 0;
3948 HttpRequestInfo request2
;
3949 request2
.method
= "GET";
3950 request2
.url
= GURL("https://www.google.com/2");
3951 request2
.load_flags
= 0;
3953 // CONNECT to www.google.com:443 via SPDY.
3954 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3955 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
3956 scoped_ptr
<SpdyFrame
> conn_resp1(
3957 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3959 // Fetch https://www.google.com/ via HTTP.
3960 const char get1
[] = "GET / HTTP/1.1\r\n"
3961 "Host: www.google.com\r\n"
3962 "Connection: keep-alive\r\n\r\n";
3963 scoped_ptr
<SpdyFrame
> wrapped_get1(
3964 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3965 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3966 "Content-Length: 1\r\n\r\n";
3967 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3968 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3969 scoped_ptr
<SpdyFrame
> wrapped_body1(
3970 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3971 scoped_ptr
<SpdyFrame
> window_update(
3972 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3974 // Fetch https://www.google.com/2 via HTTP.
3975 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3976 "Host: www.google.com\r\n"
3977 "Connection: keep-alive\r\n\r\n";
3978 scoped_ptr
<SpdyFrame
> wrapped_get2(
3979 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3980 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3981 "Content-Length: 2\r\n\r\n";
3982 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3983 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3984 scoped_ptr
<SpdyFrame
> wrapped_body2(
3985 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3987 MockWrite spdy_writes
[] = {
3988 CreateMockWrite(*connect1
, 0),
3989 CreateMockWrite(*wrapped_get1
, 2),
3990 CreateMockWrite(*wrapped_get2
, 5),
3993 MockRead spdy_reads
[] = {
3994 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3995 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3996 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3997 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3998 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3999 MockRead(ASYNC
, 0, 8),
4002 DeterministicSocketData
spdy_data(
4003 spdy_reads
, arraysize(spdy_reads
),
4004 spdy_writes
, arraysize(spdy_writes
));
4005 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4007 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4008 ssl
.SetNextProto(GetParam());
4009 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4010 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4011 ssl2
.was_npn_negotiated
= false;
4012 ssl2
.protocol_negotiated
= kProtoUnknown
;
4013 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4015 TestCompletionCallback callback
;
4017 scoped_ptr
<HttpTransaction
> trans(
4018 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4019 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4020 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4021 // The first connect and request, each of their responses, and the body.
4022 spdy_data
.RunFor(5);
4024 rv
= callback
.WaitForResult();
4027 LoadTimingInfo load_timing_info
;
4028 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4029 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4031 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4032 ASSERT_TRUE(response
!= NULL
);
4033 ASSERT_TRUE(response
->headers
.get() != NULL
);
4034 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4036 std::string response_data
;
4037 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
4038 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4041 scoped_ptr
<HttpTransaction
> trans2(
4042 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4043 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4044 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4046 // The second request, response, and body. There should not be a second
4048 spdy_data
.RunFor(3);
4049 rv
= callback
.WaitForResult();
4052 LoadTimingInfo load_timing_info2
;
4053 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4054 TestLoadTimingReused(load_timing_info2
);
4056 // The requests should have the same ID.
4057 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4059 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4062 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4063 // Proxy to different servers.
4064 TEST_P(HttpNetworkTransactionTest
,
4065 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4066 // Configure against https proxy server "proxy:70".
4067 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4068 "https://proxy:70"));
4069 CapturingBoundNetLog log
;
4070 session_deps_
.net_log
= log
.bound().net_log();
4071 scoped_refptr
<HttpNetworkSession
> session(
4072 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
4074 HttpRequestInfo request1
;
4075 request1
.method
= "GET";
4076 request1
.url
= GURL("http://www.google.com/");
4077 request1
.load_flags
= 0;
4079 HttpRequestInfo request2
;
4080 request2
.method
= "GET";
4081 request2
.url
= GURL("http://news.google.com/");
4082 request2
.load_flags
= 0;
4084 // http://www.google.com/
4085 scoped_ptr
<SpdyHeaderBlock
> headers(
4086 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
4087 scoped_ptr
<SpdyFrame
> get1(
4088 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4089 scoped_ptr
<SpdyFrame
> get_resp1(
4090 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4091 scoped_ptr
<SpdyFrame
> body1(
4092 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4094 // http://news.google.com/
4095 scoped_ptr
<SpdyHeaderBlock
> headers2(
4096 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
4097 scoped_ptr
<SpdyFrame
> get2(
4098 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4099 scoped_ptr
<SpdyFrame
> get_resp2(
4100 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4101 scoped_ptr
<SpdyFrame
> body2(
4102 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4104 MockWrite spdy_writes
[] = {
4105 CreateMockWrite(*get1
, 0),
4106 CreateMockWrite(*get2
, 3),
4109 MockRead spdy_reads
[] = {
4110 CreateMockRead(*get_resp1
, 1, ASYNC
),
4111 CreateMockRead(*body1
, 2, ASYNC
),
4112 CreateMockRead(*get_resp2
, 4, ASYNC
),
4113 CreateMockRead(*body2
, 5, ASYNC
),
4114 MockRead(ASYNC
, 0, 6),
4117 DeterministicSocketData
spdy_data(
4118 spdy_reads
, arraysize(spdy_reads
),
4119 spdy_writes
, arraysize(spdy_writes
));
4120 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4122 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4123 ssl
.SetNextProto(GetParam());
4124 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4126 TestCompletionCallback callback
;
4128 scoped_ptr
<HttpTransaction
> trans(
4129 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4130 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4131 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4132 spdy_data
.RunFor(2);
4134 rv
= callback
.WaitForResult();
4137 LoadTimingInfo load_timing_info
;
4138 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4139 TestLoadTimingNotReused(load_timing_info
,
4140 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4142 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4143 ASSERT_TRUE(response
!= NULL
);
4144 ASSERT_TRUE(response
->headers
.get() != NULL
);
4145 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4147 std::string response_data
;
4148 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
4149 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
4150 spdy_data
.RunFor(1);
4151 EXPECT_EQ(1, callback
.WaitForResult());
4152 // Delete the first request, so the second one can reuse the socket.
4155 scoped_ptr
<HttpTransaction
> trans2(
4156 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4157 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4158 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4160 spdy_data
.RunFor(2);
4161 rv
= callback
.WaitForResult();
4164 LoadTimingInfo load_timing_info2
;
4165 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4166 TestLoadTimingReused(load_timing_info2
);
4168 // The requests should have the same ID.
4169 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4171 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
4172 spdy_data
.RunFor(1);
4173 EXPECT_EQ(2, callback
.WaitForResult());
4176 // Test the challenge-response-retry sequence through an HTTPS Proxy
4177 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4178 HttpRequestInfo request
;
4179 request
.method
= "GET";
4180 request
.url
= GURL("http://www.google.com/");
4181 // when the no authentication data flag is set.
4182 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
4184 // Configure against https proxy server "myproxy:70".
4185 session_deps_
.proxy_service
.reset(
4186 ProxyService::CreateFixed("https://myproxy:70"));
4187 CapturingBoundNetLog log
;
4188 session_deps_
.net_log
= log
.bound().net_log();
4189 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4191 // Since we have proxy, should use full url
4192 MockWrite data_writes1
[] = {
4193 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4194 "Host: www.google.com\r\n"
4195 "Proxy-Connection: keep-alive\r\n\r\n"),
4197 // After calling trans->RestartWithAuth(), this is the request we should
4198 // be issuing -- the final header line contains the credentials.
4199 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4200 "Host: www.google.com\r\n"
4201 "Proxy-Connection: keep-alive\r\n"
4202 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4205 // The proxy responds to the GET with a 407, using a persistent
4207 MockRead data_reads1
[] = {
4209 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4210 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4211 MockRead("Proxy-Connection: keep-alive\r\n"),
4212 MockRead("Content-Length: 0\r\n\r\n"),
4214 MockRead("HTTP/1.1 200 OK\r\n"),
4215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4216 MockRead("Content-Length: 100\r\n\r\n"),
4217 MockRead(SYNCHRONOUS
, OK
),
4220 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4221 data_writes1
, arraysize(data_writes1
));
4222 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4223 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4224 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4226 TestCompletionCallback callback1
;
4228 scoped_ptr
<HttpTransaction
> trans(
4229 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4231 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4232 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4234 rv
= callback1
.WaitForResult();
4237 LoadTimingInfo load_timing_info
;
4238 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4239 TestLoadTimingNotReused(load_timing_info
,
4240 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4242 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4243 ASSERT_TRUE(response
!= NULL
);
4244 ASSERT_FALSE(response
->headers
.get() == NULL
);
4245 EXPECT_EQ(407, response
->headers
->response_code());
4246 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4247 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4249 TestCompletionCallback callback2
;
4251 rv
= trans
->RestartWithAuth(
4252 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4255 rv
= callback2
.WaitForResult();
4258 load_timing_info
= LoadTimingInfo();
4259 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4260 // Retrying with HTTP AUTH is considered to be reusing a socket.
4261 TestLoadTimingReused(load_timing_info
);
4263 response
= trans
->GetResponseInfo();
4264 ASSERT_TRUE(response
!= NULL
);
4266 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4267 EXPECT_EQ(200, response
->headers
->response_code());
4268 EXPECT_EQ(100, response
->headers
->GetContentLength());
4269 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4271 // The password prompt info should not be set.
4272 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4275 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4276 const MockRead
& status
, int expected_status
) {
4277 HttpRequestInfo request
;
4278 request
.method
= "GET";
4279 request
.url
= GURL("https://www.google.com/");
4280 request
.load_flags
= 0;
4282 // Configure against proxy server "myproxy:70".
4283 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4284 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4286 // Since we have proxy, should try to establish tunnel.
4287 MockWrite data_writes
[] = {
4288 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4289 "Host: www.google.com\r\n"
4290 "Proxy-Connection: keep-alive\r\n\r\n"),
4293 MockRead data_reads
[] = {
4295 MockRead("Content-Length: 10\r\n\r\n"),
4296 // No response body because the test stops reading here.
4297 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4300 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4301 data_writes
, arraysize(data_writes
));
4302 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4304 TestCompletionCallback callback
;
4306 scoped_ptr
<HttpTransaction
> trans(
4307 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4309 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4312 rv
= callback
.WaitForResult();
4313 EXPECT_EQ(expected_status
, rv
);
4316 void HttpNetworkTransactionTest::ConnectStatusHelper(
4317 const MockRead
& status
) {
4318 ConnectStatusHelperWithExpectedStatus(
4319 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4322 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4323 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4326 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4327 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4330 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4331 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4334 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4335 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4338 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4339 ConnectStatusHelper(
4340 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4343 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4344 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4347 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4348 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4351 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4352 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4355 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4356 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4359 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4360 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4363 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4364 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4367 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4368 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4371 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4372 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4375 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4376 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4379 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4380 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4383 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4384 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4387 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4388 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4391 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4392 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4395 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4396 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4399 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4400 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4403 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4404 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4407 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4408 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4411 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4412 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4415 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4416 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4419 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4420 ConnectStatusHelperWithExpectedStatus(
4421 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4422 ERR_PROXY_AUTH_UNSUPPORTED
);
4425 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4426 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4429 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4430 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4433 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4434 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4437 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4438 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4441 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4442 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4445 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4446 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4449 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4450 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4453 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4454 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4457 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4458 ConnectStatusHelper(
4459 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4462 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4463 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4466 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4467 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4470 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4471 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4474 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4475 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4478 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4479 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4482 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4483 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4486 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4487 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4490 // Test the flow when both the proxy server AND origin server require
4491 // authentication. Again, this uses basic auth for both since that is
4492 // the simplest to mock.
4493 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4494 HttpRequestInfo request
;
4495 request
.method
= "GET";
4496 request
.url
= GURL("http://www.google.com/");
4497 request
.load_flags
= 0;
4499 // Configure against proxy server "myproxy:70".
4500 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4501 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4503 scoped_ptr
<HttpTransaction
> trans(
4504 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4506 MockWrite data_writes1
[] = {
4507 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4508 "Host: www.google.com\r\n"
4509 "Proxy-Connection: keep-alive\r\n\r\n"),
4512 MockRead data_reads1
[] = {
4513 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4514 // Give a couple authenticate options (only the middle one is actually
4516 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4517 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4518 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4519 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4520 // Large content-length -- won't matter, as connection will be reset.
4521 MockRead("Content-Length: 10000\r\n\r\n"),
4522 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4525 // After calling trans->RestartWithAuth() the first time, this is the
4526 // request we should be issuing -- the final header line contains the
4527 // proxy's credentials.
4528 MockWrite data_writes2
[] = {
4529 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4530 "Host: www.google.com\r\n"
4531 "Proxy-Connection: keep-alive\r\n"
4532 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4535 // Now the proxy server lets the request pass through to origin server.
4536 // The origin server responds with a 401.
4537 MockRead data_reads2
[] = {
4538 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4539 // Note: We are using the same realm-name as the proxy server. This is
4540 // completely valid, as realms are unique across hosts.
4541 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4542 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4543 MockRead("Content-Length: 2000\r\n\r\n"),
4544 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4547 // After calling trans->RestartWithAuth() the second time, we should send
4548 // the credentials for both the proxy and origin server.
4549 MockWrite data_writes3
[] = {
4550 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4551 "Host: www.google.com\r\n"
4552 "Proxy-Connection: keep-alive\r\n"
4553 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4554 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4557 // Lastly we get the desired content.
4558 MockRead data_reads3
[] = {
4559 MockRead("HTTP/1.0 200 OK\r\n"),
4560 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4561 MockRead("Content-Length: 100\r\n\r\n"),
4562 MockRead(SYNCHRONOUS
, OK
),
4565 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4566 data_writes1
, arraysize(data_writes1
));
4567 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4568 data_writes2
, arraysize(data_writes2
));
4569 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4570 data_writes3
, arraysize(data_writes3
));
4571 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4572 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4573 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4575 TestCompletionCallback callback1
;
4577 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4578 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4580 rv
= callback1
.WaitForResult();
4583 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4584 ASSERT_TRUE(response
!= NULL
);
4585 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4587 TestCompletionCallback callback2
;
4589 rv
= trans
->RestartWithAuth(
4590 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4591 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4593 rv
= callback2
.WaitForResult();
4596 response
= trans
->GetResponseInfo();
4597 ASSERT_TRUE(response
!= NULL
);
4598 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4600 TestCompletionCallback callback3
;
4602 rv
= trans
->RestartWithAuth(
4603 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4604 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4606 rv
= callback3
.WaitForResult();
4609 response
= trans
->GetResponseInfo();
4610 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4611 EXPECT_EQ(100, response
->headers
->GetContentLength());
4614 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4615 // can't hook into its internals to cause it to generate predictable NTLM
4616 // authorization headers.
4617 #if defined(NTLM_PORTABLE)
4618 // The NTLM authentication unit tests were generated by capturing the HTTP
4619 // requests and responses using Fiddler 2 and inspecting the generated random
4620 // bytes in the debugger.
4622 // Enter the correct password and authenticate successfully.
4623 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4624 HttpRequestInfo request
;
4625 request
.method
= "GET";
4626 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4628 // Ensure load is not disrupted by flags which suppress behaviour specific
4629 // to other auth schemes.
4630 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4632 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4634 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4636 MockWrite data_writes1
[] = {
4637 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4638 "Host: 172.22.68.17\r\n"
4639 "Connection: keep-alive\r\n\r\n"),
4642 MockRead data_reads1
[] = {
4643 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4644 // Negotiate and NTLM are often requested together. However, we only want
4645 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4646 // the header that requests Negotiate for this test.
4647 MockRead("WWW-Authenticate: NTLM\r\n"),
4648 MockRead("Connection: close\r\n"),
4649 MockRead("Content-Length: 42\r\n"),
4650 MockRead("Content-Type: text/html\r\n\r\n"),
4651 // Missing content -- won't matter, as connection will be reset.
4652 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4655 MockWrite data_writes2
[] = {
4656 // After restarting with a null identity, this is the
4657 // request we should be issuing -- the final header line contains a Type
4659 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4660 "Host: 172.22.68.17\r\n"
4661 "Connection: keep-alive\r\n"
4662 "Authorization: NTLM "
4663 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4665 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4666 // (the credentials for the origin server). The second request continues
4667 // on the same connection.
4668 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4669 "Host: 172.22.68.17\r\n"
4670 "Connection: keep-alive\r\n"
4671 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4672 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4673 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4674 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4675 "ahlhx5I=\r\n\r\n"),
4678 MockRead data_reads2
[] = {
4679 // The origin server responds with a Type 2 message.
4680 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4681 MockRead("WWW-Authenticate: NTLM "
4682 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4683 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4684 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4685 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4686 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4687 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4689 MockRead("Content-Length: 42\r\n"),
4690 MockRead("Content-Type: text/html\r\n\r\n"),
4691 MockRead("You are not authorized to view this page\r\n"),
4693 // Lastly we get the desired content.
4694 MockRead("HTTP/1.1 200 OK\r\n"),
4695 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4696 MockRead("Content-Length: 13\r\n\r\n"),
4697 MockRead("Please Login\r\n"),
4698 MockRead(SYNCHRONOUS
, OK
),
4701 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4702 data_writes1
, arraysize(data_writes1
));
4703 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4704 data_writes2
, arraysize(data_writes2
));
4705 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4706 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4708 TestCompletionCallback callback1
;
4710 scoped_ptr
<HttpTransaction
> trans(
4711 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4713 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4716 rv
= callback1
.WaitForResult();
4719 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4721 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4722 ASSERT_FALSE(response
== NULL
);
4723 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4725 TestCompletionCallback callback2
;
4727 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4728 callback2
.callback());
4729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4731 rv
= callback2
.WaitForResult();
4734 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4736 response
= trans
->GetResponseInfo();
4737 ASSERT_TRUE(response
!= NULL
);
4738 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4740 TestCompletionCallback callback3
;
4742 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4743 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4745 rv
= callback3
.WaitForResult();
4748 response
= trans
->GetResponseInfo();
4749 ASSERT_TRUE(response
!= NULL
);
4750 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4751 EXPECT_EQ(13, response
->headers
->GetContentLength());
4754 // Enter a wrong password, and then the correct one.
4755 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4756 HttpRequestInfo request
;
4757 request
.method
= "GET";
4758 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4759 request
.load_flags
= 0;
4761 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4763 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4765 MockWrite data_writes1
[] = {
4766 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4767 "Host: 172.22.68.17\r\n"
4768 "Connection: keep-alive\r\n\r\n"),
4771 MockRead data_reads1
[] = {
4772 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4773 // Negotiate and NTLM are often requested together. However, we only want
4774 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4775 // the header that requests Negotiate for this test.
4776 MockRead("WWW-Authenticate: NTLM\r\n"),
4777 MockRead("Connection: close\r\n"),
4778 MockRead("Content-Length: 42\r\n"),
4779 MockRead("Content-Type: text/html\r\n\r\n"),
4780 // Missing content -- won't matter, as connection will be reset.
4781 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4784 MockWrite data_writes2
[] = {
4785 // After restarting with a null identity, this is the
4786 // request we should be issuing -- the final header line contains a Type
4788 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4789 "Host: 172.22.68.17\r\n"
4790 "Connection: keep-alive\r\n"
4791 "Authorization: NTLM "
4792 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4794 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4795 // (the credentials for the origin server). The second request continues
4796 // on the same connection.
4797 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4798 "Host: 172.22.68.17\r\n"
4799 "Connection: keep-alive\r\n"
4800 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4801 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4802 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4803 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4804 "4Ww7b7E=\r\n\r\n"),
4807 MockRead data_reads2
[] = {
4808 // The origin server responds with a Type 2 message.
4809 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4810 MockRead("WWW-Authenticate: NTLM "
4811 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4812 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4813 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4814 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4815 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4816 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4818 MockRead("Content-Length: 42\r\n"),
4819 MockRead("Content-Type: text/html\r\n\r\n"),
4820 MockRead("You are not authorized to view this page\r\n"),
4823 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4824 MockRead("WWW-Authenticate: NTLM\r\n"),
4825 MockRead("Connection: close\r\n"),
4826 MockRead("Content-Length: 42\r\n"),
4827 MockRead("Content-Type: text/html\r\n\r\n"),
4828 // Missing content -- won't matter, as connection will be reset.
4829 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4832 MockWrite data_writes3
[] = {
4833 // After restarting with a null identity, this is the
4834 // request we should be issuing -- the final header line contains a Type
4836 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4837 "Host: 172.22.68.17\r\n"
4838 "Connection: keep-alive\r\n"
4839 "Authorization: NTLM "
4840 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4842 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4843 // (the credentials for the origin server). The second request continues
4844 // on the same connection.
4845 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4846 "Host: 172.22.68.17\r\n"
4847 "Connection: keep-alive\r\n"
4848 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4849 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4850 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4851 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4852 "+4MUm7c=\r\n\r\n"),
4855 MockRead data_reads3
[] = {
4856 // The origin server responds with a Type 2 message.
4857 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4858 MockRead("WWW-Authenticate: NTLM "
4859 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4860 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4861 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4862 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4863 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4864 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4866 MockRead("Content-Length: 42\r\n"),
4867 MockRead("Content-Type: text/html\r\n\r\n"),
4868 MockRead("You are not authorized to view this page\r\n"),
4870 // Lastly we get the desired content.
4871 MockRead("HTTP/1.1 200 OK\r\n"),
4872 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4873 MockRead("Content-Length: 13\r\n\r\n"),
4874 MockRead("Please Login\r\n"),
4875 MockRead(SYNCHRONOUS
, OK
),
4878 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4879 data_writes1
, arraysize(data_writes1
));
4880 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4881 data_writes2
, arraysize(data_writes2
));
4882 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4883 data_writes3
, arraysize(data_writes3
));
4884 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4885 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4886 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4888 TestCompletionCallback callback1
;
4890 scoped_ptr
<HttpTransaction
> trans(
4891 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4893 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4894 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4896 rv
= callback1
.WaitForResult();
4899 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4901 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4902 ASSERT_TRUE(response
!= NULL
);
4903 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4905 TestCompletionCallback callback2
;
4907 // Enter the wrong password.
4908 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4909 callback2
.callback());
4910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4912 rv
= callback2
.WaitForResult();
4915 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4916 TestCompletionCallback callback3
;
4917 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4918 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4919 rv
= callback3
.WaitForResult();
4921 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4923 response
= trans
->GetResponseInfo();
4924 ASSERT_FALSE(response
== NULL
);
4925 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4927 TestCompletionCallback callback4
;
4929 // Now enter the right password.
4930 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4931 callback4
.callback());
4932 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4934 rv
= callback4
.WaitForResult();
4937 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4939 TestCompletionCallback callback5
;
4941 // One more roundtrip
4942 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4943 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4945 rv
= callback5
.WaitForResult();
4948 response
= trans
->GetResponseInfo();
4949 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4950 EXPECT_EQ(13, response
->headers
->GetContentLength());
4952 #endif // NTLM_PORTABLE
4954 // Test reading a server response which has only headers, and no body.
4955 // After some maximum number of bytes is consumed, the transaction should
4956 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4957 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4958 HttpRequestInfo request
;
4959 request
.method
= "GET";
4960 request
.url
= GURL("http://www.google.com/");
4961 request
.load_flags
= 0;
4963 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4964 scoped_ptr
<HttpTransaction
> trans(
4965 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4967 // Respond with 300 kb of headers (we should fail after 256 kb).
4968 std::string large_headers_string
;
4969 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4971 MockRead data_reads
[] = {
4972 MockRead("HTTP/1.0 200 OK\r\n"),
4973 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4974 MockRead("\r\nBODY"),
4975 MockRead(SYNCHRONOUS
, OK
),
4977 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4978 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4980 TestCompletionCallback callback
;
4982 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4983 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4985 rv
= callback
.WaitForResult();
4986 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4988 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4989 EXPECT_TRUE(response
== NULL
);
4992 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4993 // establish tunnel.
4994 // http://code.google.com/p/chromium/issues/detail?id=3772
4995 TEST_P(HttpNetworkTransactionTest
,
4996 DontRecycleTransportSocketForSSLTunnel
) {
4997 HttpRequestInfo request
;
4998 request
.method
= "GET";
4999 request
.url
= GURL("https://www.google.com/");
5000 request
.load_flags
= 0;
5002 // Configure against proxy server "myproxy:70".
5003 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5005 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5007 scoped_ptr
<HttpTransaction
> trans(
5008 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5010 // Since we have proxy, should try to establish tunnel.
5011 MockWrite data_writes1
[] = {
5012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5013 "Host: www.google.com\r\n"
5014 "Proxy-Connection: keep-alive\r\n\r\n"),
5017 // The proxy responds to the connect with a 404, using a persistent
5018 // connection. Usually a proxy would return 501 (not implemented),
5019 // or 200 (tunnel established).
5020 MockRead data_reads1
[] = {
5021 MockRead("HTTP/1.1 404 Not Found\r\n"),
5022 MockRead("Content-Length: 10\r\n\r\n"),
5023 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5026 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5027 data_writes1
, arraysize(data_writes1
));
5028 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5030 TestCompletionCallback callback1
;
5032 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5033 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5035 rv
= callback1
.WaitForResult();
5036 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5038 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5039 EXPECT_TRUE(response
== NULL
);
5041 // Empty the current queue. This is necessary because idle sockets are
5042 // added to the connection pool asynchronously with a PostTask.
5043 base::MessageLoop::current()->RunUntilIdle();
5045 // We now check to make sure the TCPClientSocket was not added back to
5047 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5049 base::MessageLoop::current()->RunUntilIdle();
5050 // Make sure that the socket didn't get recycled after calling the destructor.
5051 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5054 // Make sure that we recycle a socket after reading all of the response body.
5055 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5056 HttpRequestInfo request
;
5057 request
.method
= "GET";
5058 request
.url
= GURL("http://www.google.com/");
5059 request
.load_flags
= 0;
5061 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5063 scoped_ptr
<HttpTransaction
> trans(
5064 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5066 MockRead data_reads
[] = {
5067 // A part of the response body is received with the response headers.
5068 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5069 // The rest of the response body is received in two parts.
5072 MockRead("junk"), // Should not be read!!
5073 MockRead(SYNCHRONOUS
, OK
),
5076 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5077 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5079 TestCompletionCallback callback
;
5081 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5082 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5084 rv
= callback
.WaitForResult();
5087 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5088 ASSERT_TRUE(response
!= NULL
);
5090 EXPECT_TRUE(response
->headers
.get() != NULL
);
5091 std::string status_line
= response
->headers
->GetStatusLine();
5092 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5094 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5096 std::string response_data
;
5097 rv
= ReadTransaction(trans
.get(), &response_data
);
5099 EXPECT_EQ("hello world", response_data
);
5101 // Empty the current queue. This is necessary because idle sockets are
5102 // added to the connection pool asynchronously with a PostTask.
5103 base::MessageLoop::current()->RunUntilIdle();
5105 // We now check to make sure the socket was added back to the pool.
5106 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5109 // Make sure that we recycle a SSL socket after reading all of the response
5111 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5112 HttpRequestInfo request
;
5113 request
.method
= "GET";
5114 request
.url
= GURL("https://www.google.com/");
5115 request
.load_flags
= 0;
5117 MockWrite data_writes
[] = {
5118 MockWrite("GET / HTTP/1.1\r\n"
5119 "Host: www.google.com\r\n"
5120 "Connection: keep-alive\r\n\r\n"),
5123 MockRead data_reads
[] = {
5124 MockRead("HTTP/1.1 200 OK\r\n"),
5125 MockRead("Content-Length: 11\r\n\r\n"),
5126 MockRead("hello world"),
5127 MockRead(SYNCHRONOUS
, OK
),
5130 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5131 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5133 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5134 data_writes
, arraysize(data_writes
));
5135 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5137 TestCompletionCallback callback
;
5139 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5140 scoped_ptr
<HttpTransaction
> trans(
5141 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5143 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5145 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5146 EXPECT_EQ(OK
, callback
.WaitForResult());
5148 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5149 ASSERT_TRUE(response
!= NULL
);
5150 ASSERT_TRUE(response
->headers
.get() != NULL
);
5151 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5153 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5155 std::string response_data
;
5156 rv
= ReadTransaction(trans
.get(), &response_data
);
5158 EXPECT_EQ("hello world", response_data
);
5160 // Empty the current queue. This is necessary because idle sockets are
5161 // added to the connection pool asynchronously with a PostTask.
5162 base::MessageLoop::current()->RunUntilIdle();
5164 // We now check to make sure the socket was added back to the pool.
5165 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5168 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5169 // from the pool and make sure that we recover okay.
5170 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5171 HttpRequestInfo request
;
5172 request
.method
= "GET";
5173 request
.url
= GURL("https://www.google.com/");
5174 request
.load_flags
= 0;
5176 MockWrite data_writes
[] = {
5177 MockWrite("GET / HTTP/1.1\r\n"
5178 "Host: www.google.com\r\n"
5179 "Connection: keep-alive\r\n\r\n"),
5180 MockWrite("GET / HTTP/1.1\r\n"
5181 "Host: www.google.com\r\n"
5182 "Connection: keep-alive\r\n\r\n"),
5185 MockRead data_reads
[] = {
5186 MockRead("HTTP/1.1 200 OK\r\n"),
5187 MockRead("Content-Length: 11\r\n\r\n"),
5188 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5189 MockRead("hello world"),
5190 MockRead(ASYNC
, 0, 0) // EOF
5193 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5194 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5195 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5196 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5198 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5199 data_writes
, arraysize(data_writes
));
5200 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5201 data_writes
, arraysize(data_writes
));
5202 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5203 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5205 TestCompletionCallback callback
;
5207 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5208 scoped_ptr
<HttpTransaction
> trans(
5209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5211 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5214 EXPECT_EQ(OK
, callback
.WaitForResult());
5216 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5217 ASSERT_TRUE(response
!= NULL
);
5218 ASSERT_TRUE(response
->headers
.get() != NULL
);
5219 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5221 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5223 std::string response_data
;
5224 rv
= ReadTransaction(trans
.get(), &response_data
);
5226 EXPECT_EQ("hello world", response_data
);
5228 // Empty the current queue. This is necessary because idle sockets are
5229 // added to the connection pool asynchronously with a PostTask.
5230 base::MessageLoop::current()->RunUntilIdle();
5232 // We now check to make sure the socket was added back to the pool.
5233 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5235 // Now start the second transaction, which should reuse the previous socket.
5237 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5239 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5241 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5242 EXPECT_EQ(OK
, callback
.WaitForResult());
5244 response
= trans
->GetResponseInfo();
5245 ASSERT_TRUE(response
!= NULL
);
5246 ASSERT_TRUE(response
->headers
.get() != NULL
);
5247 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5249 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5251 rv
= ReadTransaction(trans
.get(), &response_data
);
5253 EXPECT_EQ("hello world", response_data
);
5255 // Empty the current queue. This is necessary because idle sockets are
5256 // added to the connection pool asynchronously with a PostTask.
5257 base::MessageLoop::current()->RunUntilIdle();
5259 // We now check to make sure the socket was added back to the pool.
5260 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5263 // Make sure that we recycle a socket after a zero-length response.
5264 // http://crbug.com/9880
5265 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5266 HttpRequestInfo request
;
5267 request
.method
= "GET";
5268 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
5269 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5270 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5271 "rt=prt.2642,ol.2649,xjs.2951");
5272 request
.load_flags
= 0;
5274 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5276 scoped_ptr
<HttpTransaction
> trans(
5277 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5279 MockRead data_reads
[] = {
5280 MockRead("HTTP/1.1 204 No Content\r\n"
5281 "Content-Length: 0\r\n"
5282 "Content-Type: text/html\r\n\r\n"),
5283 MockRead("junk"), // Should not be read!!
5284 MockRead(SYNCHRONOUS
, OK
),
5287 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5288 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5290 TestCompletionCallback callback
;
5292 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5295 rv
= callback
.WaitForResult();
5298 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5299 ASSERT_TRUE(response
!= NULL
);
5301 EXPECT_TRUE(response
->headers
.get() != NULL
);
5302 std::string status_line
= response
->headers
->GetStatusLine();
5303 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5305 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5307 std::string response_data
;
5308 rv
= ReadTransaction(trans
.get(), &response_data
);
5310 EXPECT_EQ("", response_data
);
5312 // Empty the current queue. This is necessary because idle sockets are
5313 // added to the connection pool asynchronously with a PostTask.
5314 base::MessageLoop::current()->RunUntilIdle();
5316 // We now check to make sure the socket was added back to the pool.
5317 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5320 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5321 ScopedVector
<UploadElementReader
> element_readers
;
5322 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5323 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5325 HttpRequestInfo request
[2];
5326 // Transaction 1: a GET request that succeeds. The socket is recycled
5328 request
[0].method
= "GET";
5329 request
[0].url
= GURL("http://www.google.com/");
5330 request
[0].load_flags
= 0;
5331 // Transaction 2: a POST request. Reuses the socket kept alive from
5332 // transaction 1. The first attempts fails when writing the POST data.
5333 // This causes the transaction to retry with a new socket. The second
5334 // attempt succeeds.
5335 request
[1].method
= "POST";
5336 request
[1].url
= GURL("http://www.google.com/login.cgi");
5337 request
[1].upload_data_stream
= &upload_data_stream
;
5338 request
[1].load_flags
= 0;
5340 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5342 // The first socket is used for transaction 1 and the first attempt of
5345 // The response of transaction 1.
5346 MockRead data_reads1
[] = {
5347 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5348 MockRead("hello world"),
5349 MockRead(SYNCHRONOUS
, OK
),
5351 // The mock write results of transaction 1 and the first attempt of
5353 MockWrite data_writes1
[] = {
5354 MockWrite(SYNCHRONOUS
, 64), // GET
5355 MockWrite(SYNCHRONOUS
, 93), // POST
5356 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5358 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5359 data_writes1
, arraysize(data_writes1
));
5361 // The second socket is used for the second attempt of transaction 2.
5363 // The response of transaction 2.
5364 MockRead data_reads2
[] = {
5365 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5366 MockRead("welcome"),
5367 MockRead(SYNCHRONOUS
, OK
),
5369 // The mock write results of the second attempt of transaction 2.
5370 MockWrite data_writes2
[] = {
5371 MockWrite(SYNCHRONOUS
, 93), // POST
5372 MockWrite(SYNCHRONOUS
, 3), // POST data
5374 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5375 data_writes2
, arraysize(data_writes2
));
5377 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5378 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5380 const char* const kExpectedResponseData
[] = {
5381 "hello world", "welcome"
5384 for (int i
= 0; i
< 2; ++i
) {
5385 scoped_ptr
<HttpTransaction
> trans(
5386 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5388 TestCompletionCallback callback
;
5390 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5391 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5393 rv
= callback
.WaitForResult();
5396 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5397 ASSERT_TRUE(response
!= NULL
);
5399 EXPECT_TRUE(response
->headers
.get() != NULL
);
5400 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5402 std::string response_data
;
5403 rv
= ReadTransaction(trans
.get(), &response_data
);
5405 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5409 // Test the request-challenge-retry sequence for basic auth when there is
5410 // an identity in the URL. The request should be sent as normal, but when
5411 // it fails the identity from the URL is used to answer the challenge.
5412 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5413 HttpRequestInfo request
;
5414 request
.method
= "GET";
5415 request
.url
= GURL("http://foo:b@r@www.google.com/");
5416 request
.load_flags
= LOAD_NORMAL
;
5418 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5419 scoped_ptr
<HttpTransaction
> trans(
5420 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5422 // The password contains an escaped character -- for this test to pass it
5423 // will need to be unescaped by HttpNetworkTransaction.
5424 EXPECT_EQ("b%40r", request
.url
.password());
5426 MockWrite data_writes1
[] = {
5427 MockWrite("GET / HTTP/1.1\r\n"
5428 "Host: www.google.com\r\n"
5429 "Connection: keep-alive\r\n\r\n"),
5432 MockRead data_reads1
[] = {
5433 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5434 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5435 MockRead("Content-Length: 10\r\n\r\n"),
5436 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5439 // After the challenge above, the transaction will be restarted using the
5440 // identity from the url (foo, b@r) to answer the challenge.
5441 MockWrite data_writes2
[] = {
5442 MockWrite("GET / HTTP/1.1\r\n"
5443 "Host: www.google.com\r\n"
5444 "Connection: keep-alive\r\n"
5445 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5448 MockRead data_reads2
[] = {
5449 MockRead("HTTP/1.0 200 OK\r\n"),
5450 MockRead("Content-Length: 100\r\n\r\n"),
5451 MockRead(SYNCHRONOUS
, OK
),
5454 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5455 data_writes1
, arraysize(data_writes1
));
5456 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5457 data_writes2
, arraysize(data_writes2
));
5458 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5459 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5461 TestCompletionCallback callback1
;
5462 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5463 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5464 rv
= callback1
.WaitForResult();
5466 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5468 TestCompletionCallback callback2
;
5469 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5470 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5471 rv
= callback2
.WaitForResult();
5473 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5475 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5476 ASSERT_TRUE(response
!= NULL
);
5478 // There is no challenge info, since the identity in URL worked.
5479 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5481 EXPECT_EQ(100, response
->headers
->GetContentLength());
5483 // Empty the current queue.
5484 base::MessageLoop::current()->RunUntilIdle();
5487 // Test the request-challenge-retry sequence for basic auth when there is an
5488 // incorrect identity in the URL. The identity from the URL should be used only
5490 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5491 HttpRequestInfo request
;
5492 request
.method
= "GET";
5493 // Note: the URL has a username:password in it. The password "baz" is
5494 // wrong (should be "bar").
5495 request
.url
= GURL("http://foo:baz@www.google.com/");
5497 request
.load_flags
= LOAD_NORMAL
;
5499 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5500 scoped_ptr
<HttpTransaction
> trans(
5501 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5503 MockWrite data_writes1
[] = {
5504 MockWrite("GET / HTTP/1.1\r\n"
5505 "Host: www.google.com\r\n"
5506 "Connection: keep-alive\r\n\r\n"),
5509 MockRead data_reads1
[] = {
5510 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5511 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5512 MockRead("Content-Length: 10\r\n\r\n"),
5513 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5516 // After the challenge above, the transaction will be restarted using the
5517 // identity from the url (foo, baz) to answer the challenge.
5518 MockWrite data_writes2
[] = {
5519 MockWrite("GET / HTTP/1.1\r\n"
5520 "Host: www.google.com\r\n"
5521 "Connection: keep-alive\r\n"
5522 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5525 MockRead data_reads2
[] = {
5526 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5527 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5528 MockRead("Content-Length: 10\r\n\r\n"),
5529 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5532 // After the challenge above, the transaction will be restarted using the
5533 // identity supplied by the user (foo, bar) to answer the challenge.
5534 MockWrite data_writes3
[] = {
5535 MockWrite("GET / HTTP/1.1\r\n"
5536 "Host: www.google.com\r\n"
5537 "Connection: keep-alive\r\n"
5538 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5541 MockRead data_reads3
[] = {
5542 MockRead("HTTP/1.0 200 OK\r\n"),
5543 MockRead("Content-Length: 100\r\n\r\n"),
5544 MockRead(SYNCHRONOUS
, OK
),
5547 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5548 data_writes1
, arraysize(data_writes1
));
5549 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5550 data_writes2
, arraysize(data_writes2
));
5551 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5552 data_writes3
, arraysize(data_writes3
));
5553 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5554 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5555 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5557 TestCompletionCallback callback1
;
5559 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5560 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5562 rv
= callback1
.WaitForResult();
5565 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5566 TestCompletionCallback callback2
;
5567 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5569 rv
= callback2
.WaitForResult();
5571 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5573 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5574 ASSERT_TRUE(response
!= NULL
);
5575 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5577 TestCompletionCallback callback3
;
5578 rv
= trans
->RestartWithAuth(
5579 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5581 rv
= callback3
.WaitForResult();
5583 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5585 response
= trans
->GetResponseInfo();
5586 ASSERT_TRUE(response
!= NULL
);
5588 // There is no challenge info, since the identity worked.
5589 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5591 EXPECT_EQ(100, response
->headers
->GetContentLength());
5593 // Empty the current queue.
5594 base::MessageLoop::current()->RunUntilIdle();
5598 // Test the request-challenge-retry sequence for basic auth when there is a
5599 // correct identity in the URL, but its use is being suppressed. The identity
5600 // from the URL should never be used.
5601 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5602 HttpRequestInfo request
;
5603 request
.method
= "GET";
5604 request
.url
= GURL("http://foo:bar@www.google.com/");
5605 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5607 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5608 scoped_ptr
<HttpTransaction
> trans(
5609 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5611 MockWrite data_writes1
[] = {
5612 MockWrite("GET / HTTP/1.1\r\n"
5613 "Host: www.google.com\r\n"
5614 "Connection: keep-alive\r\n\r\n"),
5617 MockRead data_reads1
[] = {
5618 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5619 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5620 MockRead("Content-Length: 10\r\n\r\n"),
5621 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5624 // After the challenge above, the transaction will be restarted using the
5625 // identity supplied by the user, not the one in the URL, to answer the
5627 MockWrite data_writes3
[] = {
5628 MockWrite("GET / HTTP/1.1\r\n"
5629 "Host: www.google.com\r\n"
5630 "Connection: keep-alive\r\n"
5631 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5634 MockRead data_reads3
[] = {
5635 MockRead("HTTP/1.0 200 OK\r\n"),
5636 MockRead("Content-Length: 100\r\n\r\n"),
5637 MockRead(SYNCHRONOUS
, OK
),
5640 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5641 data_writes1
, arraysize(data_writes1
));
5642 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5643 data_writes3
, arraysize(data_writes3
));
5644 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5645 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5647 TestCompletionCallback callback1
;
5648 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5649 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5650 rv
= callback1
.WaitForResult();
5652 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5654 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5655 ASSERT_TRUE(response
!= NULL
);
5656 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5658 TestCompletionCallback callback3
;
5659 rv
= trans
->RestartWithAuth(
5660 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5661 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5662 rv
= callback3
.WaitForResult();
5664 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5666 response
= trans
->GetResponseInfo();
5667 ASSERT_TRUE(response
!= NULL
);
5669 // There is no challenge info, since the identity worked.
5670 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5671 EXPECT_EQ(100, response
->headers
->GetContentLength());
5673 // Empty the current queue.
5674 base::MessageLoop::current()->RunUntilIdle();
5677 // Test that previously tried username/passwords for a realm get re-used.
5678 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5679 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5681 // Transaction 1: authenticate (foo, bar) on MyRealm1
5683 HttpRequestInfo request
;
5684 request
.method
= "GET";
5685 request
.url
= GURL("http://www.google.com/x/y/z");
5686 request
.load_flags
= 0;
5688 scoped_ptr
<HttpTransaction
> trans(
5689 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5691 MockWrite data_writes1
[] = {
5692 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5693 "Host: www.google.com\r\n"
5694 "Connection: keep-alive\r\n\r\n"),
5697 MockRead data_reads1
[] = {
5698 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5699 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5700 MockRead("Content-Length: 10000\r\n\r\n"),
5701 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5704 // Resend with authorization (username=foo, password=bar)
5705 MockWrite data_writes2
[] = {
5706 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5707 "Host: www.google.com\r\n"
5708 "Connection: keep-alive\r\n"
5709 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5712 // Sever accepts the authorization.
5713 MockRead data_reads2
[] = {
5714 MockRead("HTTP/1.0 200 OK\r\n"),
5715 MockRead("Content-Length: 100\r\n\r\n"),
5716 MockRead(SYNCHRONOUS
, OK
),
5719 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5720 data_writes1
, arraysize(data_writes1
));
5721 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5722 data_writes2
, arraysize(data_writes2
));
5723 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5724 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5726 TestCompletionCallback callback1
;
5728 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5731 rv
= callback1
.WaitForResult();
5734 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5735 ASSERT_TRUE(response
!= NULL
);
5736 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5738 TestCompletionCallback callback2
;
5740 rv
= trans
->RestartWithAuth(
5741 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5742 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5744 rv
= callback2
.WaitForResult();
5747 response
= trans
->GetResponseInfo();
5748 ASSERT_TRUE(response
!= NULL
);
5749 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5750 EXPECT_EQ(100, response
->headers
->GetContentLength());
5753 // ------------------------------------------------------------------------
5755 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5757 HttpRequestInfo request
;
5758 request
.method
= "GET";
5759 // Note that Transaction 1 was at /x/y/z, so this is in the same
5760 // protection space as MyRealm1.
5761 request
.url
= GURL("http://www.google.com/x/y/a/b");
5762 request
.load_flags
= 0;
5764 scoped_ptr
<HttpTransaction
> trans(
5765 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5767 MockWrite data_writes1
[] = {
5768 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5769 "Host: www.google.com\r\n"
5770 "Connection: keep-alive\r\n"
5771 // Send preemptive authorization for MyRealm1
5772 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5775 // The server didn't like the preemptive authorization, and
5776 // challenges us for a different realm (MyRealm2).
5777 MockRead data_reads1
[] = {
5778 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5779 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5780 MockRead("Content-Length: 10000\r\n\r\n"),
5781 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5784 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5785 MockWrite data_writes2
[] = {
5786 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5787 "Host: www.google.com\r\n"
5788 "Connection: keep-alive\r\n"
5789 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5792 // Sever accepts the authorization.
5793 MockRead data_reads2
[] = {
5794 MockRead("HTTP/1.0 200 OK\r\n"),
5795 MockRead("Content-Length: 100\r\n\r\n"),
5796 MockRead(SYNCHRONOUS
, OK
),
5799 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5800 data_writes1
, arraysize(data_writes1
));
5801 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5802 data_writes2
, arraysize(data_writes2
));
5803 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5804 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5806 TestCompletionCallback callback1
;
5808 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5809 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5811 rv
= callback1
.WaitForResult();
5814 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5815 ASSERT_TRUE(response
!= NULL
);
5816 ASSERT_TRUE(response
->auth_challenge
.get());
5817 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5818 EXPECT_EQ("www.google.com:80",
5819 response
->auth_challenge
->challenger
.ToString());
5820 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5821 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5823 TestCompletionCallback callback2
;
5825 rv
= trans
->RestartWithAuth(
5826 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5827 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5829 rv
= callback2
.WaitForResult();
5832 response
= trans
->GetResponseInfo();
5833 ASSERT_TRUE(response
!= NULL
);
5834 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5835 EXPECT_EQ(100, response
->headers
->GetContentLength());
5838 // ------------------------------------------------------------------------
5840 // Transaction 3: Resend a request in MyRealm's protection space --
5841 // succeed with preemptive authorization.
5843 HttpRequestInfo request
;
5844 request
.method
= "GET";
5845 request
.url
= GURL("http://www.google.com/x/y/z2");
5846 request
.load_flags
= 0;
5848 scoped_ptr
<HttpTransaction
> trans(
5849 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5851 MockWrite data_writes1
[] = {
5852 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5853 "Host: www.google.com\r\n"
5854 "Connection: keep-alive\r\n"
5855 // The authorization for MyRealm1 gets sent preemptively
5856 // (since the url is in the same protection space)
5857 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5860 // Sever accepts the preemptive authorization
5861 MockRead data_reads1
[] = {
5862 MockRead("HTTP/1.0 200 OK\r\n"),
5863 MockRead("Content-Length: 100\r\n\r\n"),
5864 MockRead(SYNCHRONOUS
, OK
),
5867 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5868 data_writes1
, arraysize(data_writes1
));
5869 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5871 TestCompletionCallback callback1
;
5873 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5874 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5876 rv
= callback1
.WaitForResult();
5879 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5880 ASSERT_TRUE(response
!= NULL
);
5882 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5883 EXPECT_EQ(100, response
->headers
->GetContentLength());
5886 // ------------------------------------------------------------------------
5888 // Transaction 4: request another URL in MyRealm (however the
5889 // url is not known to belong to the protection space, so no pre-auth).
5891 HttpRequestInfo request
;
5892 request
.method
= "GET";
5893 request
.url
= GURL("http://www.google.com/x/1");
5894 request
.load_flags
= 0;
5896 scoped_ptr
<HttpTransaction
> trans(
5897 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5899 MockWrite data_writes1
[] = {
5900 MockWrite("GET /x/1 HTTP/1.1\r\n"
5901 "Host: www.google.com\r\n"
5902 "Connection: keep-alive\r\n\r\n"),
5905 MockRead data_reads1
[] = {
5906 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5907 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5908 MockRead("Content-Length: 10000\r\n\r\n"),
5909 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5912 // Resend with authorization from MyRealm's cache.
5913 MockWrite data_writes2
[] = {
5914 MockWrite("GET /x/1 HTTP/1.1\r\n"
5915 "Host: www.google.com\r\n"
5916 "Connection: keep-alive\r\n"
5917 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5920 // Sever accepts the authorization.
5921 MockRead data_reads2
[] = {
5922 MockRead("HTTP/1.0 200 OK\r\n"),
5923 MockRead("Content-Length: 100\r\n\r\n"),
5924 MockRead(SYNCHRONOUS
, OK
),
5927 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5928 data_writes1
, arraysize(data_writes1
));
5929 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5930 data_writes2
, arraysize(data_writes2
));
5931 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5932 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5934 TestCompletionCallback callback1
;
5936 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5937 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5939 rv
= callback1
.WaitForResult();
5942 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5943 TestCompletionCallback callback2
;
5944 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5946 rv
= callback2
.WaitForResult();
5948 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5950 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5951 ASSERT_TRUE(response
!= NULL
);
5952 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5953 EXPECT_EQ(100, response
->headers
->GetContentLength());
5956 // ------------------------------------------------------------------------
5958 // Transaction 5: request a URL in MyRealm, but the server rejects the
5959 // cached identity. Should invalidate and re-prompt.
5961 HttpRequestInfo request
;
5962 request
.method
= "GET";
5963 request
.url
= GURL("http://www.google.com/p/q/t");
5964 request
.load_flags
= 0;
5966 scoped_ptr
<HttpTransaction
> trans(
5967 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5969 MockWrite data_writes1
[] = {
5970 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5971 "Host: www.google.com\r\n"
5972 "Connection: keep-alive\r\n\r\n"),
5975 MockRead data_reads1
[] = {
5976 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5977 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5978 MockRead("Content-Length: 10000\r\n\r\n"),
5979 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5982 // Resend with authorization from cache for MyRealm.
5983 MockWrite data_writes2
[] = {
5984 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5985 "Host: www.google.com\r\n"
5986 "Connection: keep-alive\r\n"
5987 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5990 // Sever rejects the authorization.
5991 MockRead data_reads2
[] = {
5992 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5993 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5994 MockRead("Content-Length: 10000\r\n\r\n"),
5995 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5998 // At this point we should prompt for new credentials for MyRealm.
5999 // Restart with username=foo3, password=foo4.
6000 MockWrite data_writes3
[] = {
6001 MockWrite("GET /p/q/t HTTP/1.1\r\n"
6002 "Host: www.google.com\r\n"
6003 "Connection: keep-alive\r\n"
6004 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6007 // Sever accepts the authorization.
6008 MockRead data_reads3
[] = {
6009 MockRead("HTTP/1.0 200 OK\r\n"),
6010 MockRead("Content-Length: 100\r\n\r\n"),
6011 MockRead(SYNCHRONOUS
, OK
),
6014 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6015 data_writes1
, arraysize(data_writes1
));
6016 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6017 data_writes2
, arraysize(data_writes2
));
6018 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6019 data_writes3
, arraysize(data_writes3
));
6020 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6021 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6022 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6024 TestCompletionCallback callback1
;
6026 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6027 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6029 rv
= callback1
.WaitForResult();
6032 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6033 TestCompletionCallback callback2
;
6034 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6036 rv
= callback2
.WaitForResult();
6038 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6040 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6041 ASSERT_TRUE(response
!= NULL
);
6042 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6044 TestCompletionCallback callback3
;
6046 rv
= trans
->RestartWithAuth(
6047 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6048 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6050 rv
= callback3
.WaitForResult();
6053 response
= trans
->GetResponseInfo();
6054 ASSERT_TRUE(response
!= NULL
);
6055 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6056 EXPECT_EQ(100, response
->headers
->GetContentLength());
6060 // Tests that nonce count increments when multiple auth attempts
6061 // are started with the same nonce.
6062 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6063 HttpAuthHandlerDigest::Factory
* digest_factory
=
6064 new HttpAuthHandlerDigest::Factory();
6065 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6066 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6067 digest_factory
->set_nonce_generator(nonce_generator
);
6068 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6069 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6071 // Transaction 1: authenticate (foo, bar) on MyRealm1
6073 HttpRequestInfo request
;
6074 request
.method
= "GET";
6075 request
.url
= GURL("http://www.google.com/x/y/z");
6076 request
.load_flags
= 0;
6078 scoped_ptr
<HttpTransaction
> trans(
6079 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6081 MockWrite data_writes1
[] = {
6082 MockWrite("GET /x/y/z HTTP/1.1\r\n"
6083 "Host: www.google.com\r\n"
6084 "Connection: keep-alive\r\n\r\n"),
6087 MockRead data_reads1
[] = {
6088 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6089 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6090 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6091 MockRead(SYNCHRONOUS
, OK
),
6094 // Resend with authorization (username=foo, password=bar)
6095 MockWrite data_writes2
[] = {
6096 MockWrite("GET /x/y/z HTTP/1.1\r\n"
6097 "Host: www.google.com\r\n"
6098 "Connection: keep-alive\r\n"
6099 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6100 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6101 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6102 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6105 // Sever accepts the authorization.
6106 MockRead data_reads2
[] = {
6107 MockRead("HTTP/1.0 200 OK\r\n"),
6108 MockRead(SYNCHRONOUS
, OK
),
6111 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6112 data_writes1
, arraysize(data_writes1
));
6113 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6114 data_writes2
, arraysize(data_writes2
));
6115 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6116 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6118 TestCompletionCallback callback1
;
6120 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6121 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6123 rv
= callback1
.WaitForResult();
6126 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6127 ASSERT_TRUE(response
!= NULL
);
6128 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6130 TestCompletionCallback callback2
;
6132 rv
= trans
->RestartWithAuth(
6133 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6134 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6136 rv
= callback2
.WaitForResult();
6139 response
= trans
->GetResponseInfo();
6140 ASSERT_TRUE(response
!= NULL
);
6141 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6144 // ------------------------------------------------------------------------
6146 // Transaction 2: Request another resource in digestive's protection space.
6147 // This will preemptively add an Authorization header which should have an
6148 // "nc" value of 2 (as compared to 1 in the first use.
6150 HttpRequestInfo request
;
6151 request
.method
= "GET";
6152 // Note that Transaction 1 was at /x/y/z, so this is in the same
6153 // protection space as digest.
6154 request
.url
= GURL("http://www.google.com/x/y/a/b");
6155 request
.load_flags
= 0;
6157 scoped_ptr
<HttpTransaction
> trans(
6158 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6160 MockWrite data_writes1
[] = {
6161 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
6162 "Host: www.google.com\r\n"
6163 "Connection: keep-alive\r\n"
6164 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6165 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6166 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6167 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6170 // Sever accepts the authorization.
6171 MockRead data_reads1
[] = {
6172 MockRead("HTTP/1.0 200 OK\r\n"),
6173 MockRead("Content-Length: 100\r\n\r\n"),
6174 MockRead(SYNCHRONOUS
, OK
),
6177 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6178 data_writes1
, arraysize(data_writes1
));
6179 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6181 TestCompletionCallback callback1
;
6183 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6184 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6186 rv
= callback1
.WaitForResult();
6189 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6190 ASSERT_TRUE(response
!= NULL
);
6191 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6195 // Test the ResetStateForRestart() private method.
6196 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6197 // Create a transaction (the dependencies aren't important).
6198 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6199 scoped_ptr
<HttpNetworkTransaction
> trans(
6200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6202 // Setup some state (which we expect ResetStateForRestart() will clear).
6203 trans
->read_buf_
= new IOBuffer(15);
6204 trans
->read_buf_len_
= 15;
6205 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6207 // Setup state in response_
6208 HttpResponseInfo
* response
= &trans
->response_
;
6209 response
->auth_challenge
= new AuthChallengeInfo();
6210 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6211 response
->response_time
= base::Time::Now();
6212 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6214 { // Setup state for response_.vary_data
6215 HttpRequestInfo request
;
6216 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6217 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6218 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6219 request
.extra_headers
.SetHeader("Foo", "1");
6220 request
.extra_headers
.SetHeader("bar", "23");
6221 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6224 // Cause the above state to be reset.
6225 trans
->ResetStateForRestart();
6227 // Verify that the state that needed to be reset, has been reset.
6228 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6229 EXPECT_EQ(0, trans
->read_buf_len_
);
6230 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6231 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6232 EXPECT_TRUE(response
->headers
.get() == NULL
);
6233 EXPECT_FALSE(response
->was_cached
);
6234 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6235 EXPECT_FALSE(response
->vary_data
.is_valid());
6238 // Test HTTPS connections to a site with a bad certificate
6239 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6240 HttpRequestInfo request
;
6241 request
.method
= "GET";
6242 request
.url
= GURL("https://www.google.com/");
6243 request
.load_flags
= 0;
6245 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6246 scoped_ptr
<HttpTransaction
> trans(
6247 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6249 MockWrite data_writes
[] = {
6250 MockWrite("GET / HTTP/1.1\r\n"
6251 "Host: www.google.com\r\n"
6252 "Connection: keep-alive\r\n\r\n"),
6255 MockRead data_reads
[] = {
6256 MockRead("HTTP/1.0 200 OK\r\n"),
6257 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6258 MockRead("Content-Length: 100\r\n\r\n"),
6259 MockRead(SYNCHRONOUS
, OK
),
6262 StaticSocketDataProvider ssl_bad_certificate
;
6263 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6264 data_writes
, arraysize(data_writes
));
6265 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6266 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6268 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6269 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6270 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6271 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6273 TestCompletionCallback callback
;
6275 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6276 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6278 rv
= callback
.WaitForResult();
6279 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6281 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6284 rv
= callback
.WaitForResult();
6287 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6289 ASSERT_TRUE(response
!= NULL
);
6290 EXPECT_EQ(100, response
->headers
->GetContentLength());
6293 // Test HTTPS connections to a site with a bad certificate, going through a
6295 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6296 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6298 HttpRequestInfo request
;
6299 request
.method
= "GET";
6300 request
.url
= GURL("https://www.google.com/");
6301 request
.load_flags
= 0;
6303 MockWrite proxy_writes
[] = {
6304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6305 "Host: www.google.com\r\n"
6306 "Proxy-Connection: keep-alive\r\n\r\n"),
6309 MockRead proxy_reads
[] = {
6310 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6311 MockRead(SYNCHRONOUS
, OK
)
6314 MockWrite data_writes
[] = {
6315 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6316 "Host: www.google.com\r\n"
6317 "Proxy-Connection: keep-alive\r\n\r\n"),
6318 MockWrite("GET / HTTP/1.1\r\n"
6319 "Host: www.google.com\r\n"
6320 "Connection: keep-alive\r\n\r\n"),
6323 MockRead data_reads
[] = {
6324 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6325 MockRead("HTTP/1.0 200 OK\r\n"),
6326 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6327 MockRead("Content-Length: 100\r\n\r\n"),
6328 MockRead(SYNCHRONOUS
, OK
),
6331 StaticSocketDataProvider
ssl_bad_certificate(
6332 proxy_reads
, arraysize(proxy_reads
),
6333 proxy_writes
, arraysize(proxy_writes
));
6334 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6335 data_writes
, arraysize(data_writes
));
6336 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6337 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6339 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6340 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6341 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6342 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6344 TestCompletionCallback callback
;
6346 for (int i
= 0; i
< 2; i
++) {
6347 session_deps_
.socket_factory
->ResetNextMockIndexes();
6349 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6350 scoped_ptr
<HttpTransaction
> trans(
6351 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6353 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6354 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6356 rv
= callback
.WaitForResult();
6357 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6359 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6360 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6362 rv
= callback
.WaitForResult();
6365 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6367 ASSERT_TRUE(response
!= NULL
);
6368 EXPECT_EQ(100, response
->headers
->GetContentLength());
6373 // Test HTTPS connections to a site, going through an HTTPS proxy
6374 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6375 session_deps_
.proxy_service
.reset(
6376 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6377 CapturingNetLog net_log
;
6378 session_deps_
.net_log
= &net_log
;
6380 HttpRequestInfo request
;
6381 request
.method
= "GET";
6382 request
.url
= GURL("https://www.google.com/");
6383 request
.load_flags
= 0;
6385 MockWrite data_writes
[] = {
6386 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6387 "Host: www.google.com\r\n"
6388 "Proxy-Connection: keep-alive\r\n\r\n"),
6389 MockWrite("GET / HTTP/1.1\r\n"
6390 "Host: www.google.com\r\n"
6391 "Connection: keep-alive\r\n\r\n"),
6394 MockRead data_reads
[] = {
6395 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6396 MockRead("HTTP/1.1 200 OK\r\n"),
6397 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6398 MockRead("Content-Length: 100\r\n\r\n"),
6399 MockRead(SYNCHRONOUS
, OK
),
6402 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6403 data_writes
, arraysize(data_writes
));
6404 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6405 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6407 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6408 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6409 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6411 TestCompletionCallback callback
;
6413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6414 scoped_ptr
<HttpTransaction
> trans(
6415 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6417 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6418 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6420 rv
= callback
.WaitForResult();
6422 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6424 ASSERT_TRUE(response
!= NULL
);
6426 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6427 EXPECT_EQ(200, response
->headers
->response_code());
6428 EXPECT_EQ(100, response
->headers
->GetContentLength());
6429 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6431 LoadTimingInfo load_timing_info
;
6432 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6433 TestLoadTimingNotReusedWithPac(load_timing_info
,
6434 CONNECT_TIMING_HAS_SSL_TIMES
);
6437 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6438 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6439 session_deps_
.proxy_service
.reset(
6440 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6441 CapturingNetLog net_log
;
6442 session_deps_
.net_log
= &net_log
;
6444 HttpRequestInfo request
;
6445 request
.method
= "GET";
6446 request
.url
= GURL("https://www.google.com/");
6447 request
.load_flags
= 0;
6449 MockWrite data_writes
[] = {
6450 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6451 "Host: www.google.com\r\n"
6452 "Proxy-Connection: keep-alive\r\n\r\n"),
6455 MockRead data_reads
[] = {
6456 MockRead("HTTP/1.1 302 Redirect\r\n"),
6457 MockRead("Location: http://login.example.com/\r\n"),
6458 MockRead("Content-Length: 0\r\n\r\n"),
6459 MockRead(SYNCHRONOUS
, OK
),
6462 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6463 data_writes
, arraysize(data_writes
));
6464 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6466 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6467 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6469 TestCompletionCallback callback
;
6471 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6472 scoped_ptr
<HttpTransaction
> trans(
6473 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6475 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6476 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6478 rv
= callback
.WaitForResult();
6480 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6482 ASSERT_TRUE(response
!= NULL
);
6484 EXPECT_EQ(302, response
->headers
->response_code());
6486 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6487 EXPECT_EQ("http://login.example.com/", url
);
6489 // In the case of redirects from proxies, HttpNetworkTransaction returns
6490 // timing for the proxy connection instead of the connection to the host,
6491 // and no send / receive times.
6492 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6493 LoadTimingInfo load_timing_info
;
6494 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6496 EXPECT_FALSE(load_timing_info
.socket_reused
);
6497 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6499 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6500 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6501 load_timing_info
.proxy_resolve_end
);
6502 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6503 load_timing_info
.connect_timing
.connect_start
);
6504 ExpectConnectTimingHasTimes(
6505 load_timing_info
.connect_timing
,
6506 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6508 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6509 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6510 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6513 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6514 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6515 session_deps_
.proxy_service
.reset(
6516 ProxyService::CreateFixed("https://proxy:70"));
6518 HttpRequestInfo request
;
6519 request
.method
= "GET";
6520 request
.url
= GURL("https://www.google.com/");
6521 request
.load_flags
= 0;
6523 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6524 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
6525 scoped_ptr
<SpdyFrame
> goaway(
6526 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6527 MockWrite data_writes
[] = {
6528 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6529 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6532 static const char* const kExtraHeaders
[] = {
6534 "http://login.example.com/",
6536 scoped_ptr
<SpdyFrame
> resp(
6537 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6538 arraysize(kExtraHeaders
)/2, 1));
6539 MockRead data_reads
[] = {
6540 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6541 MockRead(ASYNC
, 0, 2), // EOF
6544 DelayedSocketData
data(
6545 1, // wait for one write to finish before reading.
6546 data_reads
, arraysize(data_reads
),
6547 data_writes
, arraysize(data_writes
));
6548 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6549 proxy_ssl
.SetNextProto(GetParam());
6551 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6552 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6554 TestCompletionCallback callback
;
6556 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6557 scoped_ptr
<HttpTransaction
> trans(
6558 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6560 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6561 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6563 rv
= callback
.WaitForResult();
6565 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6567 ASSERT_TRUE(response
!= NULL
);
6569 EXPECT_EQ(302, response
->headers
->response_code());
6571 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6572 EXPECT_EQ("http://login.example.com/", url
);
6575 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6576 TEST_P(HttpNetworkTransactionTest
,
6577 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6578 session_deps_
.proxy_service
.reset(
6579 ProxyService::CreateFixed("https://proxy:70"));
6581 HttpRequestInfo request
;
6582 request
.method
= "GET";
6583 request
.url
= GURL("https://www.google.com/");
6584 request
.load_flags
= 0;
6586 MockWrite data_writes
[] = {
6587 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6588 "Host: www.google.com\r\n"
6589 "Proxy-Connection: keep-alive\r\n\r\n"),
6592 MockRead data_reads
[] = {
6593 MockRead("HTTP/1.1 404 Not Found\r\n"),
6594 MockRead("Content-Length: 23\r\n\r\n"),
6595 MockRead("The host does not exist"),
6596 MockRead(SYNCHRONOUS
, OK
),
6599 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6600 data_writes
, arraysize(data_writes
));
6601 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6603 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6604 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6606 TestCompletionCallback callback
;
6608 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6609 scoped_ptr
<HttpTransaction
> trans(
6610 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6612 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6613 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6615 rv
= callback
.WaitForResult();
6616 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6618 // TODO(ttuttle): Anything else to check here?
6621 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6622 TEST_P(HttpNetworkTransactionTest
,
6623 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6624 session_deps_
.proxy_service
.reset(
6625 ProxyService::CreateFixed("https://proxy:70"));
6627 HttpRequestInfo request
;
6628 request
.method
= "GET";
6629 request
.url
= GURL("https://www.google.com/");
6630 request
.load_flags
= 0;
6632 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6633 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
6634 scoped_ptr
<SpdyFrame
> rst(
6635 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6636 MockWrite data_writes
[] = {
6637 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6638 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6641 static const char* const kExtraHeaders
[] = {
6643 "http://login.example.com/",
6645 scoped_ptr
<SpdyFrame
> resp(
6646 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6647 arraysize(kExtraHeaders
)/2, 1));
6648 scoped_ptr
<SpdyFrame
> body(
6649 spdy_util_
.ConstructSpdyBodyFrame(
6650 1, "The host does not exist", 23, true));
6651 MockRead data_reads
[] = {
6652 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6653 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6654 MockRead(ASYNC
, 0, 4), // EOF
6657 DelayedSocketData
data(
6658 1, // wait for one write to finish before reading.
6659 data_reads
, arraysize(data_reads
),
6660 data_writes
, arraysize(data_writes
));
6661 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6662 proxy_ssl
.SetNextProto(GetParam());
6664 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6665 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6667 TestCompletionCallback callback
;
6669 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6670 scoped_ptr
<HttpTransaction
> trans(
6671 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6673 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6674 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6676 rv
= callback
.WaitForResult();
6677 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6679 // TODO(ttuttle): Anything else to check here?
6682 // Test the request-challenge-retry sequence for basic auth, through
6683 // a SPDY proxy over a single SPDY session.
6684 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6685 HttpRequestInfo request
;
6686 request
.method
= "GET";
6687 request
.url
= GURL("https://www.google.com/");
6688 // when the no authentication data flag is set.
6689 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6691 // Configure against https proxy server "myproxy:70".
6692 session_deps_
.proxy_service
.reset(
6693 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6694 CapturingBoundNetLog log
;
6695 session_deps_
.net_log
= log
.bound().net_log();
6696 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6698 // Since we have proxy, should try to establish tunnel.
6699 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6700 NULL
, 0, 1, LOWEST
, HostPortPair("www.google.com", 443)));
6701 scoped_ptr
<SpdyFrame
> rst(
6702 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6704 // After calling trans->RestartWithAuth(), this is the request we should
6705 // be issuing -- the final header line contains the credentials.
6706 const char* const kAuthCredentials
[] = {
6707 "proxy-authorization", "Basic Zm9vOmJhcg==",
6709 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6710 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6711 HostPortPair("www.google.com", 443)));
6712 // fetch https://www.google.com/ via HTTP
6713 const char get
[] = "GET / HTTP/1.1\r\n"
6714 "Host: www.google.com\r\n"
6715 "Connection: keep-alive\r\n\r\n";
6716 scoped_ptr
<SpdyFrame
> wrapped_get(
6717 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6719 MockWrite spdy_writes
[] = {
6720 CreateMockWrite(*req
, 1, ASYNC
),
6721 CreateMockWrite(*rst
, 4, ASYNC
),
6722 CreateMockWrite(*connect2
, 5),
6723 CreateMockWrite(*wrapped_get
, 8),
6726 // The proxy responds to the connect with a 407, using a persistent
6728 const char kAuthStatus
[] = "407";
6729 const char* const kAuthChallenge
[] = {
6730 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6732 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6733 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6735 scoped_ptr
<SpdyFrame
> conn_resp(
6736 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6737 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6738 "Content-Length: 5\r\n\r\n";
6740 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6741 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6742 scoped_ptr
<SpdyFrame
> wrapped_body(
6743 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6744 MockRead spdy_reads
[] = {
6745 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6746 CreateMockRead(*conn_resp
, 6, ASYNC
),
6747 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6748 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6749 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6752 OrderedSocketData
spdy_data(
6753 spdy_reads
, arraysize(spdy_reads
),
6754 spdy_writes
, arraysize(spdy_writes
));
6755 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6756 // Negotiate SPDY to the proxy
6757 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6758 proxy
.SetNextProto(GetParam());
6759 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6760 // Vanilla SSL to the server
6761 SSLSocketDataProvider
server(ASYNC
, OK
);
6762 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6764 TestCompletionCallback callback1
;
6766 scoped_ptr
<HttpTransaction
> trans(
6767 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6769 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6770 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6772 rv
= callback1
.WaitForResult();
6774 net::CapturingNetLog::CapturedEntryList entries
;
6775 log
.GetEntries(&entries
);
6776 size_t pos
= ExpectLogContainsSomewhere(
6777 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6778 NetLog::PHASE_NONE
);
6779 ExpectLogContainsSomewhere(
6781 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6782 NetLog::PHASE_NONE
);
6784 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6785 ASSERT_TRUE(response
!= NULL
);
6786 ASSERT_FALSE(response
->headers
.get() == NULL
);
6787 EXPECT_EQ(407, response
->headers
->response_code());
6788 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6789 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6790 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6792 TestCompletionCallback callback2
;
6794 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6795 callback2
.callback());
6796 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6798 rv
= callback2
.WaitForResult();
6801 response
= trans
->GetResponseInfo();
6802 ASSERT_TRUE(response
!= NULL
);
6804 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6805 EXPECT_EQ(200, response
->headers
->response_code());
6806 EXPECT_EQ(5, response
->headers
->GetContentLength());
6807 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6809 // The password prompt info should not be set.
6810 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6812 LoadTimingInfo load_timing_info
;
6813 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6814 TestLoadTimingNotReusedWithPac(load_timing_info
,
6815 CONNECT_TIMING_HAS_SSL_TIMES
);
6818 session
->CloseAllConnections();
6821 // Test that an explicitly trusted SPDY proxy can push a resource from an
6822 // origin that is different from that of its associated resource.
6823 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6824 HttpRequestInfo request
;
6825 HttpRequestInfo push_request
;
6827 request
.method
= "GET";
6828 request
.url
= GURL("http://www.google.com/");
6829 push_request
.method
= "GET";
6830 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6832 // Configure against https proxy server "myproxy:70".
6833 session_deps_
.proxy_service
.reset(
6834 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6835 CapturingBoundNetLog log
;
6836 session_deps_
.net_log
= log
.bound().net_log();
6838 // Enable cross-origin push.
6839 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6841 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6843 scoped_ptr
<SpdyFrame
> stream1_syn(
6844 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6846 MockWrite spdy_writes
[] = {
6847 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6850 scoped_ptr
<SpdyFrame
>
6851 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6853 scoped_ptr
<SpdyFrame
>
6854 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6856 scoped_ptr
<SpdyFrame
>
6857 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6861 "http://www.another-origin.com/foo.dat"));
6862 const char kPushedData
[] = "pushed";
6863 scoped_ptr
<SpdyFrame
> stream2_body(
6864 spdy_util_
.ConstructSpdyBodyFrame(
6865 2, kPushedData
, strlen(kPushedData
), true));
6867 MockRead spdy_reads
[] = {
6868 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6869 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6870 CreateMockRead(*stream1_body
, 4, ASYNC
),
6871 CreateMockRead(*stream2_body
, 5, ASYNC
),
6872 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6875 OrderedSocketData
spdy_data(
6876 spdy_reads
, arraysize(spdy_reads
),
6877 spdy_writes
, arraysize(spdy_writes
));
6878 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6879 // Negotiate SPDY to the proxy
6880 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6881 proxy
.SetNextProto(GetParam());
6882 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6884 scoped_ptr
<HttpTransaction
> trans(
6885 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6886 TestCompletionCallback callback
;
6887 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6888 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6890 rv
= callback
.WaitForResult();
6892 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6894 scoped_ptr
<HttpTransaction
> push_trans(
6895 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6896 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6897 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6899 rv
= callback
.WaitForResult();
6901 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6903 ASSERT_TRUE(response
!= NULL
);
6904 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6906 EXPECT_EQ(200, response
->headers
->response_code());
6907 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6909 std::string response_data
;
6910 rv
= ReadTransaction(trans
.get(), &response_data
);
6912 EXPECT_EQ("hello!", response_data
);
6914 LoadTimingInfo load_timing_info
;
6915 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6916 TestLoadTimingNotReusedWithPac(load_timing_info
,
6917 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6919 // Verify the pushed stream.
6920 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6921 EXPECT_EQ(200, push_response
->headers
->response_code());
6923 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6925 EXPECT_EQ("pushed", response_data
);
6927 LoadTimingInfo push_load_timing_info
;
6928 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6929 TestLoadTimingReusedWithPac(push_load_timing_info
);
6930 // The transactions should share a socket ID, despite being for different
6932 EXPECT_EQ(load_timing_info
.socket_log_id
,
6933 push_load_timing_info
.socket_log_id
);
6937 session
->CloseAllConnections();
6940 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6941 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6942 HttpRequestInfo request
;
6944 request
.method
= "GET";
6945 request
.url
= GURL("http://www.google.com/");
6947 // Configure against https proxy server "myproxy:70".
6948 session_deps_
.proxy_service
.reset(
6949 ProxyService::CreateFixed("https://myproxy:70"));
6950 CapturingBoundNetLog log
;
6951 session_deps_
.net_log
= log
.bound().net_log();
6953 // Enable cross-origin push.
6954 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6956 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6958 scoped_ptr
<SpdyFrame
> stream1_syn(
6959 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6961 scoped_ptr
<SpdyFrame
> push_rst(
6962 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6964 MockWrite spdy_writes
[] = {
6965 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6966 CreateMockWrite(*push_rst
, 4),
6969 scoped_ptr
<SpdyFrame
>
6970 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6972 scoped_ptr
<SpdyFrame
>
6973 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6975 scoped_ptr
<SpdyFrame
>
6976 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6980 "https://www.another-origin.com/foo.dat"));
6982 MockRead spdy_reads
[] = {
6983 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6984 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6985 CreateMockRead(*stream1_body
, 5, ASYNC
),
6986 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6989 OrderedSocketData
spdy_data(
6990 spdy_reads
, arraysize(spdy_reads
),
6991 spdy_writes
, arraysize(spdy_writes
));
6992 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6993 // Negotiate SPDY to the proxy
6994 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6995 proxy
.SetNextProto(GetParam());
6996 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6998 scoped_ptr
<HttpTransaction
> trans(
6999 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7000 TestCompletionCallback callback
;
7001 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7004 rv
= callback
.WaitForResult();
7006 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7008 ASSERT_TRUE(response
!= NULL
);
7009 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7011 EXPECT_EQ(200, response
->headers
->response_code());
7012 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7014 std::string response_data
;
7015 rv
= ReadTransaction(trans
.get(), &response_data
);
7017 EXPECT_EQ("hello!", response_data
);
7020 session
->CloseAllConnections();
7023 // Test HTTPS connections to a site with a bad certificate, going through an
7025 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7026 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7027 "https://proxy:70"));
7029 HttpRequestInfo request
;
7030 request
.method
= "GET";
7031 request
.url
= GURL("https://www.google.com/");
7032 request
.load_flags
= 0;
7034 // Attempt to fetch the URL from a server with a bad cert
7035 MockWrite bad_cert_writes
[] = {
7036 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7037 "Host: www.google.com\r\n"
7038 "Proxy-Connection: keep-alive\r\n\r\n"),
7041 MockRead bad_cert_reads
[] = {
7042 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7043 MockRead(SYNCHRONOUS
, OK
)
7046 // Attempt to fetch the URL with a good cert
7047 MockWrite good_data_writes
[] = {
7048 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7049 "Host: www.google.com\r\n"
7050 "Proxy-Connection: keep-alive\r\n\r\n"),
7051 MockWrite("GET / HTTP/1.1\r\n"
7052 "Host: www.google.com\r\n"
7053 "Connection: keep-alive\r\n\r\n"),
7056 MockRead good_cert_reads
[] = {
7057 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7058 MockRead("HTTP/1.0 200 OK\r\n"),
7059 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7060 MockRead("Content-Length: 100\r\n\r\n"),
7061 MockRead(SYNCHRONOUS
, OK
),
7064 StaticSocketDataProvider
ssl_bad_certificate(
7065 bad_cert_reads
, arraysize(bad_cert_reads
),
7066 bad_cert_writes
, arraysize(bad_cert_writes
));
7067 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7068 good_data_writes
, arraysize(good_data_writes
));
7069 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7070 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7072 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7073 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7074 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7075 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7077 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7078 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7079 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7080 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7082 TestCompletionCallback callback
;
7084 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7085 scoped_ptr
<HttpTransaction
> trans(
7086 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7088 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7089 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7091 rv
= callback
.WaitForResult();
7092 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7094 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7097 rv
= callback
.WaitForResult();
7100 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7102 ASSERT_TRUE(response
!= NULL
);
7103 EXPECT_EQ(100, response
->headers
->GetContentLength());
7106 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7107 HttpRequestInfo request
;
7108 request
.method
= "GET";
7109 request
.url
= GURL("http://www.google.com/");
7110 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7111 "Chromium Ultra Awesome X Edition");
7113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7114 scoped_ptr
<HttpTransaction
> trans(
7115 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7117 MockWrite data_writes
[] = {
7118 MockWrite("GET / HTTP/1.1\r\n"
7119 "Host: www.google.com\r\n"
7120 "Connection: keep-alive\r\n"
7121 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7124 // Lastly, the server responds with the actual content.
7125 MockRead data_reads
[] = {
7126 MockRead("HTTP/1.0 200 OK\r\n"),
7127 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7128 MockRead("Content-Length: 100\r\n\r\n"),
7129 MockRead(SYNCHRONOUS
, OK
),
7132 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7133 data_writes
, arraysize(data_writes
));
7134 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7136 TestCompletionCallback callback
;
7138 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7139 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7141 rv
= callback
.WaitForResult();
7145 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7146 HttpRequestInfo request
;
7147 request
.method
= "GET";
7148 request
.url
= GURL("https://www.google.com/");
7149 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7150 "Chromium Ultra Awesome X Edition");
7152 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7153 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7154 scoped_ptr
<HttpTransaction
> trans(
7155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7157 MockWrite data_writes
[] = {
7158 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7159 "Host: www.google.com\r\n"
7160 "Proxy-Connection: keep-alive\r\n"
7161 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7163 MockRead data_reads
[] = {
7164 // Return an error, so the transaction stops here (this test isn't
7165 // interested in the rest).
7166 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7167 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7168 MockRead("Proxy-Connection: close\r\n\r\n"),
7171 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7172 data_writes
, arraysize(data_writes
));
7173 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7175 TestCompletionCallback callback
;
7177 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7178 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7180 rv
= callback
.WaitForResult();
7184 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7185 HttpRequestInfo request
;
7186 request
.method
= "GET";
7187 request
.url
= GURL("http://www.google.com/");
7188 request
.load_flags
= 0;
7189 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7190 "http://the.previous.site.com/");
7192 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7193 scoped_ptr
<HttpTransaction
> trans(
7194 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7196 MockWrite data_writes
[] = {
7197 MockWrite("GET / HTTP/1.1\r\n"
7198 "Host: www.google.com\r\n"
7199 "Connection: keep-alive\r\n"
7200 "Referer: http://the.previous.site.com/\r\n\r\n"),
7203 // Lastly, the server responds with the actual content.
7204 MockRead data_reads
[] = {
7205 MockRead("HTTP/1.0 200 OK\r\n"),
7206 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7207 MockRead("Content-Length: 100\r\n\r\n"),
7208 MockRead(SYNCHRONOUS
, OK
),
7211 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7212 data_writes
, arraysize(data_writes
));
7213 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7215 TestCompletionCallback callback
;
7217 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7218 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7220 rv
= callback
.WaitForResult();
7224 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7225 HttpRequestInfo request
;
7226 request
.method
= "POST";
7227 request
.url
= GURL("http://www.google.com/");
7229 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7230 scoped_ptr
<HttpTransaction
> trans(
7231 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7233 MockWrite data_writes
[] = {
7234 MockWrite("POST / HTTP/1.1\r\n"
7235 "Host: www.google.com\r\n"
7236 "Connection: keep-alive\r\n"
7237 "Content-Length: 0\r\n\r\n"),
7240 // Lastly, the server responds with the actual content.
7241 MockRead data_reads
[] = {
7242 MockRead("HTTP/1.0 200 OK\r\n"),
7243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7244 MockRead("Content-Length: 100\r\n\r\n"),
7245 MockRead(SYNCHRONOUS
, OK
),
7248 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7249 data_writes
, arraysize(data_writes
));
7250 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7252 TestCompletionCallback callback
;
7254 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7255 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7257 rv
= callback
.WaitForResult();
7261 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7262 HttpRequestInfo request
;
7263 request
.method
= "PUT";
7264 request
.url
= GURL("http://www.google.com/");
7266 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7267 scoped_ptr
<HttpTransaction
> trans(
7268 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7270 MockWrite data_writes
[] = {
7271 MockWrite("PUT / HTTP/1.1\r\n"
7272 "Host: www.google.com\r\n"
7273 "Connection: keep-alive\r\n"
7274 "Content-Length: 0\r\n\r\n"),
7277 // Lastly, the server responds with the actual content.
7278 MockRead data_reads
[] = {
7279 MockRead("HTTP/1.0 200 OK\r\n"),
7280 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7281 MockRead("Content-Length: 100\r\n\r\n"),
7282 MockRead(SYNCHRONOUS
, OK
),
7285 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7286 data_writes
, arraysize(data_writes
));
7287 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7289 TestCompletionCallback callback
;
7291 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7292 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7294 rv
= callback
.WaitForResult();
7298 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7299 HttpRequestInfo request
;
7300 request
.method
= "HEAD";
7301 request
.url
= GURL("http://www.google.com/");
7303 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7304 scoped_ptr
<HttpTransaction
> trans(
7305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7307 MockWrite data_writes
[] = {
7308 MockWrite("HEAD / HTTP/1.1\r\n"
7309 "Host: www.google.com\r\n"
7310 "Connection: keep-alive\r\n"
7311 "Content-Length: 0\r\n\r\n"),
7314 // Lastly, the server responds with the actual content.
7315 MockRead data_reads
[] = {
7316 MockRead("HTTP/1.0 200 OK\r\n"),
7317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7318 MockRead("Content-Length: 100\r\n\r\n"),
7319 MockRead(SYNCHRONOUS
, OK
),
7322 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7323 data_writes
, arraysize(data_writes
));
7324 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7326 TestCompletionCallback callback
;
7328 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7329 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7331 rv
= callback
.WaitForResult();
7335 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7336 HttpRequestInfo request
;
7337 request
.method
= "GET";
7338 request
.url
= GURL("http://www.google.com/");
7339 request
.load_flags
= LOAD_BYPASS_CACHE
;
7341 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7342 scoped_ptr
<HttpTransaction
> trans(
7343 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7345 MockWrite data_writes
[] = {
7346 MockWrite("GET / HTTP/1.1\r\n"
7347 "Host: www.google.com\r\n"
7348 "Connection: keep-alive\r\n"
7349 "Pragma: no-cache\r\n"
7350 "Cache-Control: no-cache\r\n\r\n"),
7353 // Lastly, the server responds with the actual content.
7354 MockRead data_reads
[] = {
7355 MockRead("HTTP/1.0 200 OK\r\n"),
7356 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7357 MockRead("Content-Length: 100\r\n\r\n"),
7358 MockRead(SYNCHRONOUS
, OK
),
7361 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7362 data_writes
, arraysize(data_writes
));
7363 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7365 TestCompletionCallback callback
;
7367 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7370 rv
= callback
.WaitForResult();
7374 TEST_P(HttpNetworkTransactionTest
,
7375 BuildRequest_CacheControlValidateCache
) {
7376 HttpRequestInfo request
;
7377 request
.method
= "GET";
7378 request
.url
= GURL("http://www.google.com/");
7379 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7381 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7382 scoped_ptr
<HttpTransaction
> trans(
7383 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7385 MockWrite data_writes
[] = {
7386 MockWrite("GET / HTTP/1.1\r\n"
7387 "Host: www.google.com\r\n"
7388 "Connection: keep-alive\r\n"
7389 "Cache-Control: max-age=0\r\n\r\n"),
7392 // Lastly, the server responds with the actual content.
7393 MockRead data_reads
[] = {
7394 MockRead("HTTP/1.0 200 OK\r\n"),
7395 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7396 MockRead("Content-Length: 100\r\n\r\n"),
7397 MockRead(SYNCHRONOUS
, OK
),
7400 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7401 data_writes
, arraysize(data_writes
));
7402 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7404 TestCompletionCallback callback
;
7406 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7407 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7409 rv
= callback
.WaitForResult();
7413 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7414 HttpRequestInfo request
;
7415 request
.method
= "GET";
7416 request
.url
= GURL("http://www.google.com/");
7417 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7419 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7420 scoped_ptr
<HttpTransaction
> trans(
7421 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7423 MockWrite data_writes
[] = {
7424 MockWrite("GET / HTTP/1.1\r\n"
7425 "Host: www.google.com\r\n"
7426 "Connection: keep-alive\r\n"
7427 "FooHeader: Bar\r\n\r\n"),
7430 // Lastly, the server responds with the actual content.
7431 MockRead data_reads
[] = {
7432 MockRead("HTTP/1.0 200 OK\r\n"),
7433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7434 MockRead("Content-Length: 100\r\n\r\n"),
7435 MockRead(SYNCHRONOUS
, OK
),
7438 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7439 data_writes
, arraysize(data_writes
));
7440 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7442 TestCompletionCallback callback
;
7444 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7445 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7447 rv
= callback
.WaitForResult();
7451 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7452 HttpRequestInfo request
;
7453 request
.method
= "GET";
7454 request
.url
= GURL("http://www.google.com/");
7455 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7456 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7457 request
.extra_headers
.SetHeader("FoO", "bar");
7459 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7460 scoped_ptr
<HttpTransaction
> trans(
7461 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7463 MockWrite data_writes
[] = {
7464 MockWrite("GET / HTTP/1.1\r\n"
7465 "Host: www.google.com\r\n"
7466 "Connection: keep-alive\r\n"
7467 "referer: www.foo.com\r\n"
7469 "FoO: bar\r\n\r\n"),
7472 // Lastly, the server responds with the actual content.
7473 MockRead data_reads
[] = {
7474 MockRead("HTTP/1.0 200 OK\r\n"),
7475 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7476 MockRead("Content-Length: 100\r\n\r\n"),
7477 MockRead(SYNCHRONOUS
, OK
),
7480 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7481 data_writes
, arraysize(data_writes
));
7482 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7484 TestCompletionCallback callback
;
7486 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7487 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7489 rv
= callback
.WaitForResult();
7493 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7494 HttpRequestInfo request
;
7495 request
.method
= "GET";
7496 request
.url
= GURL("http://www.google.com/");
7497 request
.load_flags
= 0;
7499 session_deps_
.proxy_service
.reset(
7500 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7501 CapturingNetLog net_log
;
7502 session_deps_
.net_log
= &net_log
;
7504 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7505 scoped_ptr
<HttpTransaction
> trans(
7506 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7508 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7509 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7511 MockWrite data_writes
[] = {
7512 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7513 MockWrite("GET / HTTP/1.1\r\n"
7514 "Host: www.google.com\r\n"
7515 "Connection: keep-alive\r\n\r\n")
7518 MockRead data_reads
[] = {
7519 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7520 MockRead("HTTP/1.0 200 OK\r\n"),
7521 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7522 MockRead("Payload"),
7523 MockRead(SYNCHRONOUS
, OK
)
7526 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7527 data_writes
, arraysize(data_writes
));
7528 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7530 TestCompletionCallback callback
;
7532 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7533 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7535 rv
= callback
.WaitForResult();
7538 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7539 ASSERT_TRUE(response
!= NULL
);
7541 LoadTimingInfo load_timing_info
;
7542 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7543 TestLoadTimingNotReusedWithPac(load_timing_info
,
7544 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7546 std::string response_text
;
7547 rv
= ReadTransaction(trans
.get(), &response_text
);
7549 EXPECT_EQ("Payload", response_text
);
7552 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7553 HttpRequestInfo request
;
7554 request
.method
= "GET";
7555 request
.url
= GURL("https://www.google.com/");
7556 request
.load_flags
= 0;
7558 session_deps_
.proxy_service
.reset(
7559 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7560 CapturingNetLog net_log
;
7561 session_deps_
.net_log
= &net_log
;
7563 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7564 scoped_ptr
<HttpTransaction
> trans(
7565 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7567 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7568 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7570 MockWrite data_writes
[] = {
7571 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7572 arraysize(write_buffer
)),
7573 MockWrite("GET / HTTP/1.1\r\n"
7574 "Host: www.google.com\r\n"
7575 "Connection: keep-alive\r\n\r\n")
7578 MockRead data_reads
[] = {
7579 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7580 arraysize(read_buffer
)),
7581 MockRead("HTTP/1.0 200 OK\r\n"),
7582 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7583 MockRead("Payload"),
7584 MockRead(SYNCHRONOUS
, OK
)
7587 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7588 data_writes
, arraysize(data_writes
));
7589 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7591 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7592 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7594 TestCompletionCallback callback
;
7596 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7597 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7599 rv
= callback
.WaitForResult();
7602 LoadTimingInfo load_timing_info
;
7603 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7604 TestLoadTimingNotReusedWithPac(load_timing_info
,
7605 CONNECT_TIMING_HAS_SSL_TIMES
);
7607 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7608 ASSERT_TRUE(response
!= NULL
);
7610 std::string response_text
;
7611 rv
= ReadTransaction(trans
.get(), &response_text
);
7613 EXPECT_EQ("Payload", response_text
);
7616 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7617 HttpRequestInfo request
;
7618 request
.method
= "GET";
7619 request
.url
= GURL("http://www.google.com/");
7620 request
.load_flags
= 0;
7622 session_deps_
.proxy_service
.reset(
7623 ProxyService::CreateFixed("socks4://myproxy:1080"));
7624 CapturingNetLog net_log
;
7625 session_deps_
.net_log
= &net_log
;
7627 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7628 scoped_ptr
<HttpTransaction
> trans(
7629 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7631 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7632 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7634 MockWrite data_writes
[] = {
7635 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7636 MockWrite("GET / HTTP/1.1\r\n"
7637 "Host: www.google.com\r\n"
7638 "Connection: keep-alive\r\n\r\n")
7641 MockRead data_reads
[] = {
7642 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7643 MockRead("HTTP/1.0 200 OK\r\n"),
7644 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7645 MockRead("Payload"),
7646 MockRead(SYNCHRONOUS
, OK
)
7649 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7650 data_writes
, arraysize(data_writes
));
7651 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7653 TestCompletionCallback callback
;
7655 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7656 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7658 rv
= callback
.WaitForResult();
7661 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7662 ASSERT_TRUE(response
!= NULL
);
7664 LoadTimingInfo load_timing_info
;
7665 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7666 TestLoadTimingNotReused(load_timing_info
,
7667 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7669 std::string response_text
;
7670 rv
= ReadTransaction(trans
.get(), &response_text
);
7672 EXPECT_EQ("Payload", response_text
);
7675 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7676 HttpRequestInfo request
;
7677 request
.method
= "GET";
7678 request
.url
= GURL("http://www.google.com/");
7679 request
.load_flags
= 0;
7681 session_deps_
.proxy_service
.reset(
7682 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7683 CapturingNetLog net_log
;
7684 session_deps_
.net_log
= &net_log
;
7686 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7687 scoped_ptr
<HttpTransaction
> trans(
7688 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7690 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7691 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7692 const char kSOCKS5OkRequest
[] = {
7694 0x01, // Command (CONNECT)
7696 0x03, // Address type (DOMAINNAME).
7697 0x0E, // Length of domain (14)
7699 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7700 0x00, 0x50, // 16-bit port (80)
7702 const char kSOCKS5OkResponse
[] =
7703 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7705 MockWrite data_writes
[] = {
7706 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7707 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7708 MockWrite("GET / HTTP/1.1\r\n"
7709 "Host: www.google.com\r\n"
7710 "Connection: keep-alive\r\n\r\n")
7713 MockRead data_reads
[] = {
7714 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7715 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7716 MockRead("HTTP/1.0 200 OK\r\n"),
7717 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7718 MockRead("Payload"),
7719 MockRead(SYNCHRONOUS
, OK
)
7722 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7723 data_writes
, arraysize(data_writes
));
7724 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7726 TestCompletionCallback callback
;
7728 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7731 rv
= callback
.WaitForResult();
7734 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7735 ASSERT_TRUE(response
!= NULL
);
7737 LoadTimingInfo load_timing_info
;
7738 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7739 TestLoadTimingNotReusedWithPac(load_timing_info
,
7740 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7742 std::string response_text
;
7743 rv
= ReadTransaction(trans
.get(), &response_text
);
7745 EXPECT_EQ("Payload", response_text
);
7748 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7749 HttpRequestInfo request
;
7750 request
.method
= "GET";
7751 request
.url
= GURL("https://www.google.com/");
7752 request
.load_flags
= 0;
7754 session_deps_
.proxy_service
.reset(
7755 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7756 CapturingNetLog net_log
;
7757 session_deps_
.net_log
= &net_log
;
7759 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7760 scoped_ptr
<HttpTransaction
> trans(
7761 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7763 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7764 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7765 const unsigned char kSOCKS5OkRequest
[] = {
7767 0x01, // Command (CONNECT)
7769 0x03, // Address type (DOMAINNAME).
7770 0x0E, // Length of domain (14)
7772 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7773 0x01, 0xBB, // 16-bit port (443)
7776 const char kSOCKS5OkResponse
[] =
7777 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7779 MockWrite data_writes
[] = {
7780 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7781 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7782 arraysize(kSOCKS5OkRequest
)),
7783 MockWrite("GET / HTTP/1.1\r\n"
7784 "Host: www.google.com\r\n"
7785 "Connection: keep-alive\r\n\r\n")
7788 MockRead data_reads
[] = {
7789 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7790 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7791 MockRead("HTTP/1.0 200 OK\r\n"),
7792 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7793 MockRead("Payload"),
7794 MockRead(SYNCHRONOUS
, OK
)
7797 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7798 data_writes
, arraysize(data_writes
));
7799 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7801 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7802 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7804 TestCompletionCallback callback
;
7806 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7809 rv
= callback
.WaitForResult();
7812 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7813 ASSERT_TRUE(response
!= NULL
);
7815 LoadTimingInfo load_timing_info
;
7816 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7817 TestLoadTimingNotReusedWithPac(load_timing_info
,
7818 CONNECT_TIMING_HAS_SSL_TIMES
);
7820 std::string response_text
;
7821 rv
= ReadTransaction(trans
.get(), &response_text
);
7823 EXPECT_EQ("Payload", response_text
);
7828 // Tests that for connection endpoints the group names are correctly set.
7830 struct GroupNameTest
{
7831 std::string proxy_server
;
7833 std::string expected_group_name
;
7837 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7838 NextProto next_proto
,
7839 SpdySessionDependencies
* session_deps_
) {
7840 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7842 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7843 session
->http_server_properties();
7844 AlternativeService
alternative_service(
7845 AlternateProtocolFromNextProto(next_proto
), "", 443);
7846 http_server_properties
->SetAlternativeService(
7847 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0);
7852 int GroupNameTransactionHelper(
7853 const std::string
& url
,
7854 const scoped_refptr
<HttpNetworkSession
>& session
) {
7855 HttpRequestInfo request
;
7856 request
.method
= "GET";
7857 request
.url
= GURL(url
);
7858 request
.load_flags
= 0;
7860 scoped_ptr
<HttpTransaction
> trans(
7861 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7863 TestCompletionCallback callback
;
7865 // We do not complete this request, the dtor will clean the transaction up.
7866 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7871 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7872 const GroupNameTest tests
[] = {
7875 "http://www.google.com/direct",
7876 "www.google.com:80",
7881 "http://[2001:1418:13:1::25]/direct",
7882 "[2001:1418:13:1::25]:80",
7889 "https://www.google.com/direct_ssl",
7890 "ssl/www.google.com:443",
7895 "https://[2001:1418:13:1::25]/direct",
7896 "ssl/[2001:1418:13:1::25]:443",
7901 "http://host.with.alternate/direct",
7902 "ssl/host.with.alternate:443",
7907 session_deps_
.use_alternate_protocols
= true;
7909 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7910 session_deps_
.proxy_service
.reset(
7911 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7912 scoped_refptr
<HttpNetworkSession
> session(
7913 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7915 HttpNetworkSessionPeer
peer(session
);
7916 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7917 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7918 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7919 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7920 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7921 new MockClientSocketPoolManager
);
7922 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7923 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7924 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7926 EXPECT_EQ(ERR_IO_PENDING
,
7927 GroupNameTransactionHelper(tests
[i
].url
, session
));
7929 EXPECT_EQ(tests
[i
].expected_group_name
,
7930 ssl_conn_pool
->last_group_name_received());
7932 EXPECT_EQ(tests
[i
].expected_group_name
,
7933 transport_conn_pool
->last_group_name_received());
7938 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7939 const GroupNameTest tests
[] = {
7942 "http://www.google.com/http_proxy_normal",
7943 "www.google.com:80",
7950 "https://www.google.com/http_connect_ssl",
7951 "ssl/www.google.com:443",
7957 "http://host.with.alternate/direct",
7958 "ssl/host.with.alternate:443",
7964 "ftp://ftp.google.com/http_proxy_normal",
7965 "ftp/ftp.google.com:21",
7970 session_deps_
.use_alternate_protocols
= true;
7972 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7973 session_deps_
.proxy_service
.reset(
7974 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7975 scoped_refptr
<HttpNetworkSession
> session(
7976 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7978 HttpNetworkSessionPeer
peer(session
);
7980 HostPortPair
proxy_host("http_proxy", 80);
7981 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7982 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7983 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7984 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7986 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7987 new MockClientSocketPoolManager
);
7988 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7989 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7990 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7992 EXPECT_EQ(ERR_IO_PENDING
,
7993 GroupNameTransactionHelper(tests
[i
].url
, session
));
7995 EXPECT_EQ(tests
[i
].expected_group_name
,
7996 ssl_conn_pool
->last_group_name_received());
7998 EXPECT_EQ(tests
[i
].expected_group_name
,
7999 http_proxy_pool
->last_group_name_received());
8003 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8004 const GroupNameTest tests
[] = {
8006 "socks4://socks_proxy:1080",
8007 "http://www.google.com/socks4_direct",
8008 "socks4/www.google.com:80",
8012 "socks5://socks_proxy:1080",
8013 "http://www.google.com/socks5_direct",
8014 "socks5/www.google.com:80",
8020 "socks4://socks_proxy:1080",
8021 "https://www.google.com/socks4_ssl",
8022 "socks4/ssl/www.google.com:443",
8026 "socks5://socks_proxy:1080",
8027 "https://www.google.com/socks5_ssl",
8028 "socks5/ssl/www.google.com:443",
8033 "socks4://socks_proxy:1080",
8034 "http://host.with.alternate/direct",
8035 "socks4/ssl/host.with.alternate:443",
8040 session_deps_
.use_alternate_protocols
= true;
8042 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8043 session_deps_
.proxy_service
.reset(
8044 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8045 scoped_refptr
<HttpNetworkSession
> session(
8046 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8048 HttpNetworkSessionPeer
peer(session
);
8050 HostPortPair
proxy_host("socks_proxy", 1080);
8051 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8052 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8053 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8054 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8056 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8057 new MockClientSocketPoolManager
);
8058 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8059 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8060 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8062 scoped_ptr
<HttpTransaction
> trans(
8063 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8065 EXPECT_EQ(ERR_IO_PENDING
,
8066 GroupNameTransactionHelper(tests
[i
].url
, session
));
8068 EXPECT_EQ(tests
[i
].expected_group_name
,
8069 ssl_conn_pool
->last_group_name_received());
8071 EXPECT_EQ(tests
[i
].expected_group_name
,
8072 socks_conn_pool
->last_group_name_received());
8076 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8077 HttpRequestInfo request
;
8078 request
.method
= "GET";
8079 request
.url
= GURL("http://www.google.com/");
8081 session_deps_
.proxy_service
.reset(
8082 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8084 // This simulates failure resolving all hostnames; that means we will fail
8085 // connecting to both proxies (myproxy:70 and foobar:80).
8086 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8088 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8089 scoped_ptr
<HttpTransaction
> trans(
8090 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8092 TestCompletionCallback callback
;
8094 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8097 rv
= callback
.WaitForResult();
8098 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8101 // Base test to make sure that when the load flags for a request specify to
8102 // bypass the cache, the DNS cache is not used.
8103 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8105 // Issue a request, asking to bypass the cache(s).
8106 HttpRequestInfo request
;
8107 request
.method
= "GET";
8108 request
.load_flags
= load_flags
;
8109 request
.url
= GURL("http://www.google.com/");
8111 // Select a host resolver that does caching.
8112 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8114 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8115 scoped_ptr
<HttpTransaction
> trans(
8116 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8118 // Warm up the host cache so it has an entry for "www.google.com".
8119 AddressList addrlist
;
8120 TestCompletionCallback callback
;
8121 int rv
= session_deps_
.host_resolver
->Resolve(
8122 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
8125 callback
.callback(),
8128 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8129 rv
= callback
.WaitForResult();
8132 // Verify that it was added to host cache, by doing a subsequent async lookup
8133 // and confirming it completes synchronously.
8134 rv
= session_deps_
.host_resolver
->Resolve(
8135 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
8138 callback
.callback(),
8143 // Inject a failure the next time that "www.google.com" is resolved. This way
8144 // we can tell if the next lookup hit the cache, or the "network".
8145 // (cache --> success, "network" --> failure).
8146 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
8148 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8149 // first read -- this won't be reached as the host resolution will fail first.
8150 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8151 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8152 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8155 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8156 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8157 rv
= callback
.WaitForResult();
8159 // If we bypassed the cache, we would have gotten a failure while resolving
8160 // "www.google.com".
8161 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8164 // There are multiple load flags that should trigger the host cache bypass.
8165 // Test each in isolation:
8166 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8167 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8170 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8171 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8174 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8175 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8178 // Make sure we can handle an error when writing the request.
8179 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8180 HttpRequestInfo request
;
8181 request
.method
= "GET";
8182 request
.url
= GURL("http://www.foo.com/");
8183 request
.load_flags
= 0;
8185 MockWrite write_failure
[] = {
8186 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8188 StaticSocketDataProvider
data(NULL
, 0,
8189 write_failure
, arraysize(write_failure
));
8190 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8191 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8193 TestCompletionCallback callback
;
8195 scoped_ptr
<HttpTransaction
> trans(
8196 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8198 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8199 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8201 rv
= callback
.WaitForResult();
8202 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8205 // Check that a connection closed after the start of the headers finishes ok.
8206 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8207 HttpRequestInfo request
;
8208 request
.method
= "GET";
8209 request
.url
= GURL("http://www.foo.com/");
8210 request
.load_flags
= 0;
8212 MockRead data_reads
[] = {
8213 MockRead("HTTP/1."),
8214 MockRead(SYNCHRONOUS
, OK
),
8217 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8218 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8219 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8221 TestCompletionCallback callback
;
8223 scoped_ptr
<HttpTransaction
> trans(
8224 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8226 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8229 rv
= callback
.WaitForResult();
8232 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8233 ASSERT_TRUE(response
!= NULL
);
8235 EXPECT_TRUE(response
->headers
.get() != NULL
);
8236 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8238 std::string response_data
;
8239 rv
= ReadTransaction(trans
.get(), &response_data
);
8241 EXPECT_EQ("", response_data
);
8244 // Make sure that a dropped connection while draining the body for auth
8245 // restart does the right thing.
8246 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8247 HttpRequestInfo request
;
8248 request
.method
= "GET";
8249 request
.url
= GURL("http://www.google.com/");
8250 request
.load_flags
= 0;
8252 MockWrite data_writes1
[] = {
8253 MockWrite("GET / HTTP/1.1\r\n"
8254 "Host: www.google.com\r\n"
8255 "Connection: keep-alive\r\n\r\n"),
8258 MockRead data_reads1
[] = {
8259 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8260 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8261 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8262 MockRead("Content-Length: 14\r\n\r\n"),
8264 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8267 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8268 data_writes1
, arraysize(data_writes1
));
8269 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8271 // After calling trans->RestartWithAuth(), this is the request we should
8272 // be issuing -- the final header line contains the credentials.
8273 MockWrite data_writes2
[] = {
8274 MockWrite("GET / HTTP/1.1\r\n"
8275 "Host: www.google.com\r\n"
8276 "Connection: keep-alive\r\n"
8277 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8280 // Lastly, the server responds with the actual content.
8281 MockRead data_reads2
[] = {
8282 MockRead("HTTP/1.1 200 OK\r\n"),
8283 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8284 MockRead("Content-Length: 100\r\n\r\n"),
8285 MockRead(SYNCHRONOUS
, OK
),
8288 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8289 data_writes2
, arraysize(data_writes2
));
8290 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8291 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8293 TestCompletionCallback callback1
;
8295 scoped_ptr
<HttpTransaction
> trans(
8296 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8298 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8299 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8301 rv
= callback1
.WaitForResult();
8304 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8305 ASSERT_TRUE(response
!= NULL
);
8306 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8308 TestCompletionCallback callback2
;
8310 rv
= trans
->RestartWithAuth(
8311 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8312 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8314 rv
= callback2
.WaitForResult();
8317 response
= trans
->GetResponseInfo();
8318 ASSERT_TRUE(response
!= NULL
);
8319 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8320 EXPECT_EQ(100, response
->headers
->GetContentLength());
8323 // Test HTTPS connections going through a proxy that sends extra data.
8324 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8325 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8327 HttpRequestInfo request
;
8328 request
.method
= "GET";
8329 request
.url
= GURL("https://www.google.com/");
8330 request
.load_flags
= 0;
8332 MockRead proxy_reads
[] = {
8333 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8334 MockRead(SYNCHRONOUS
, OK
)
8337 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8338 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8340 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8341 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8343 TestCompletionCallback callback
;
8345 session_deps_
.socket_factory
->ResetNextMockIndexes();
8347 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8348 scoped_ptr
<HttpTransaction
> trans(
8349 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8351 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8352 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8354 rv
= callback
.WaitForResult();
8355 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8358 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8359 HttpRequestInfo request
;
8360 request
.method
= "GET";
8361 request
.url
= GURL("http://www.google.com/");
8362 request
.load_flags
= 0;
8364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8365 scoped_ptr
<HttpTransaction
> trans(
8366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8368 MockRead data_reads
[] = {
8369 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8370 MockRead(SYNCHRONOUS
, OK
),
8373 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8374 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8376 TestCompletionCallback callback
;
8378 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8379 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8381 EXPECT_EQ(OK
, callback
.WaitForResult());
8383 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8384 ASSERT_TRUE(response
!= NULL
);
8386 EXPECT_TRUE(response
->headers
.get() != NULL
);
8387 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8389 std::string response_data
;
8390 rv
= ReadTransaction(trans
.get(), &response_data
);
8391 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8394 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8395 base::FilePath temp_file_path
;
8396 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8397 const uint64 kFakeSize
= 100000; // file is actually blank
8398 UploadFileElementReader::ScopedOverridingContentLengthForTests
8399 overriding_content_length(kFakeSize
);
8401 ScopedVector
<UploadElementReader
> element_readers
;
8402 element_readers
.push_back(
8403 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8408 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8410 HttpRequestInfo request
;
8411 request
.method
= "POST";
8412 request
.url
= GURL("http://www.google.com/upload");
8413 request
.upload_data_stream
= &upload_data_stream
;
8414 request
.load_flags
= 0;
8416 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8417 scoped_ptr
<HttpTransaction
> trans(
8418 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8420 MockRead data_reads
[] = {
8421 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8422 MockRead("hello world"),
8423 MockRead(SYNCHRONOUS
, OK
),
8425 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8426 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8428 TestCompletionCallback callback
;
8430 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8431 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8433 rv
= callback
.WaitForResult();
8436 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8437 ASSERT_TRUE(response
!= NULL
);
8439 EXPECT_TRUE(response
->headers
.get() != NULL
);
8440 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8442 std::string response_data
;
8443 rv
= ReadTransaction(trans
.get(), &response_data
);
8445 EXPECT_EQ("hello world", response_data
);
8447 base::DeleteFile(temp_file_path
, false);
8450 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8451 base::FilePath temp_file
;
8452 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8453 std::string
temp_file_content("Unreadable file.");
8454 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8455 temp_file_content
.length()));
8456 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8458 ScopedVector
<UploadElementReader
> element_readers
;
8459 element_readers
.push_back(
8460 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8465 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8467 HttpRequestInfo request
;
8468 request
.method
= "POST";
8469 request
.url
= GURL("http://www.google.com/upload");
8470 request
.upload_data_stream
= &upload_data_stream
;
8471 request
.load_flags
= 0;
8473 // If we try to upload an unreadable file, the transaction should fail.
8474 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8475 scoped_ptr
<HttpTransaction
> trans(
8476 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8478 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8479 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8481 TestCompletionCallback callback
;
8483 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8484 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8486 rv
= callback
.WaitForResult();
8487 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8489 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8490 EXPECT_FALSE(response
);
8492 base::DeleteFile(temp_file
, false);
8495 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8496 class FakeUploadElementReader
: public UploadElementReader
{
8498 FakeUploadElementReader() {}
8499 ~FakeUploadElementReader() override
{}
8501 const CompletionCallback
& callback() const { return callback_
; }
8503 // UploadElementReader overrides:
8504 int Init(const CompletionCallback
& callback
) override
{
8505 callback_
= callback
;
8506 return ERR_IO_PENDING
;
8508 uint64
GetContentLength() const override
{ return 0; }
8509 uint64
BytesRemaining() const override
{ return 0; }
8510 int Read(IOBuffer
* buf
,
8512 const CompletionCallback
& callback
) override
{
8517 CompletionCallback callback_
;
8520 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8521 ScopedVector
<UploadElementReader
> element_readers
;
8522 element_readers
.push_back(fake_reader
);
8523 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8525 HttpRequestInfo request
;
8526 request
.method
= "POST";
8527 request
.url
= GURL("http://www.google.com/upload");
8528 request
.upload_data_stream
= &upload_data_stream
;
8529 request
.load_flags
= 0;
8531 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8532 scoped_ptr
<HttpTransaction
> trans(
8533 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8535 StaticSocketDataProvider data
;
8536 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8538 TestCompletionCallback callback
;
8539 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8540 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8541 base::MessageLoop::current()->RunUntilIdle();
8543 // Transaction is pending on request body initialization.
8544 ASSERT_FALSE(fake_reader
->callback().is_null());
8546 // Return Init()'s result after the transaction gets destroyed.
8548 fake_reader
->callback().Run(OK
); // Should not crash.
8551 // Tests that changes to Auth realms are treated like auth rejections.
8552 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8554 HttpRequestInfo request
;
8555 request
.method
= "GET";
8556 request
.url
= GURL("http://www.google.com/");
8557 request
.load_flags
= 0;
8559 // First transaction will request a resource and receive a Basic challenge
8560 // with realm="first_realm".
8561 MockWrite data_writes1
[] = {
8562 MockWrite("GET / HTTP/1.1\r\n"
8563 "Host: www.google.com\r\n"
8564 "Connection: keep-alive\r\n"
8567 MockRead data_reads1
[] = {
8568 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8569 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8573 // After calling trans->RestartWithAuth(), provide an Authentication header
8574 // for first_realm. The server will reject and provide a challenge with
8576 MockWrite data_writes2
[] = {
8577 MockWrite("GET / HTTP/1.1\r\n"
8578 "Host: www.google.com\r\n"
8579 "Connection: keep-alive\r\n"
8580 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8583 MockRead data_reads2
[] = {
8584 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8585 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8589 // This again fails, and goes back to first_realm. Make sure that the
8590 // entry is removed from cache.
8591 MockWrite data_writes3
[] = {
8592 MockWrite("GET / HTTP/1.1\r\n"
8593 "Host: www.google.com\r\n"
8594 "Connection: keep-alive\r\n"
8595 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8598 MockRead data_reads3
[] = {
8599 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8600 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8604 // Try one last time (with the correct password) and get the resource.
8605 MockWrite data_writes4
[] = {
8606 MockWrite("GET / HTTP/1.1\r\n"
8607 "Host: www.google.com\r\n"
8608 "Connection: keep-alive\r\n"
8609 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8612 MockRead data_reads4
[] = {
8613 MockRead("HTTP/1.1 200 OK\r\n"
8614 "Content-Type: text/html; charset=iso-8859-1\r\n"
8615 "Content-Length: 5\r\n"
8620 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8621 data_writes1
, arraysize(data_writes1
));
8622 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8623 data_writes2
, arraysize(data_writes2
));
8624 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8625 data_writes3
, arraysize(data_writes3
));
8626 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8627 data_writes4
, arraysize(data_writes4
));
8628 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8629 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8630 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8631 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8633 TestCompletionCallback callback1
;
8635 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8636 scoped_ptr
<HttpTransaction
> trans(
8637 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8639 // Issue the first request with Authorize headers. There should be a
8640 // password prompt for first_realm waiting to be filled in after the
8641 // transaction completes.
8642 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8643 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8644 rv
= callback1
.WaitForResult();
8646 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8647 ASSERT_TRUE(response
!= NULL
);
8648 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8649 ASSERT_FALSE(challenge
== NULL
);
8650 EXPECT_FALSE(challenge
->is_proxy
);
8651 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8652 EXPECT_EQ("first_realm", challenge
->realm
);
8653 EXPECT_EQ("basic", challenge
->scheme
);
8655 // Issue the second request with an incorrect password. There should be a
8656 // password prompt for second_realm waiting to be filled in after the
8657 // transaction completes.
8658 TestCompletionCallback callback2
;
8659 rv
= trans
->RestartWithAuth(
8660 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8661 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8662 rv
= callback2
.WaitForResult();
8664 response
= trans
->GetResponseInfo();
8665 ASSERT_TRUE(response
!= NULL
);
8666 challenge
= response
->auth_challenge
.get();
8667 ASSERT_FALSE(challenge
== NULL
);
8668 EXPECT_FALSE(challenge
->is_proxy
);
8669 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8670 EXPECT_EQ("second_realm", challenge
->realm
);
8671 EXPECT_EQ("basic", challenge
->scheme
);
8673 // Issue the third request with another incorrect password. There should be
8674 // a password prompt for first_realm waiting to be filled in. If the password
8675 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8676 // first_realm was not correctly removed.
8677 TestCompletionCallback callback3
;
8678 rv
= trans
->RestartWithAuth(
8679 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8681 rv
= callback3
.WaitForResult();
8683 response
= trans
->GetResponseInfo();
8684 ASSERT_TRUE(response
!= NULL
);
8685 challenge
= response
->auth_challenge
.get();
8686 ASSERT_FALSE(challenge
== NULL
);
8687 EXPECT_FALSE(challenge
->is_proxy
);
8688 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8689 EXPECT_EQ("first_realm", challenge
->realm
);
8690 EXPECT_EQ("basic", challenge
->scheme
);
8692 // Issue the fourth request with the correct password and username.
8693 TestCompletionCallback callback4
;
8694 rv
= trans
->RestartWithAuth(
8695 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8696 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8697 rv
= callback4
.WaitForResult();
8699 response
= trans
->GetResponseInfo();
8700 ASSERT_TRUE(response
!= NULL
);
8701 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8704 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8705 session_deps_
.next_protos
= SpdyNextProtos();
8706 session_deps_
.use_alternate_protocols
= true;
8708 std::string alternate_protocol_http_header
=
8709 GetAlternateProtocolHttpHeader();
8711 MockRead data_reads
[] = {
8712 MockRead("HTTP/1.1 200 OK\r\n"),
8713 MockRead(alternate_protocol_http_header
.c_str()),
8714 MockRead("hello world"),
8715 MockRead(SYNCHRONOUS
, OK
),
8718 HttpRequestInfo request
;
8719 request
.method
= "GET";
8720 request
.url
= GURL("http://www.google.com/");
8721 request
.load_flags
= 0;
8723 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8725 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8727 TestCompletionCallback callback
;
8729 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8730 scoped_ptr
<HttpTransaction
> trans(
8731 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8733 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8734 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8736 HostPortPair
http_host_port_pair("www.google.com", 80);
8737 HttpServerProperties
& http_server_properties
=
8738 *session
->http_server_properties();
8739 AlternativeService alternative_service
=
8740 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8741 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8743 EXPECT_EQ(OK
, callback
.WaitForResult());
8745 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8746 ASSERT_TRUE(response
!= NULL
);
8747 ASSERT_TRUE(response
->headers
.get() != NULL
);
8748 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8749 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8750 EXPECT_FALSE(response
->was_npn_negotiated
);
8752 std::string response_data
;
8753 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8754 EXPECT_EQ("hello world", response_data
);
8756 alternative_service
=
8757 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8758 EXPECT_EQ(443, alternative_service
.port
);
8759 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8760 alternative_service
.protocol
);
8763 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8764 session_deps_
.next_protos
= SpdyNextProtos();
8765 session_deps_
.use_alternate_protocols
= true;
8767 MockRead data_reads
[] = {
8768 MockRead("HTTP/1.1 200 OK\r\n"),
8769 MockRead("Alternate-Protocol: \r\n\r\n"),
8770 MockRead("hello world"),
8771 MockRead(SYNCHRONOUS
, OK
),
8774 HttpRequestInfo request
;
8775 request
.method
= "GET";
8776 request
.url
= GURL("http://www.google.com/");
8777 request
.load_flags
= 0;
8779 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8781 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8783 TestCompletionCallback callback
;
8785 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8787 HostPortPair
http_host_port_pair("www.google.com", 80);
8788 HttpServerProperties
& http_server_properties
=
8789 *session
->http_server_properties();
8790 AlternativeService
alternative_service(QUIC
, "", 80);
8791 http_server_properties
.SetAlternativeService(http_host_port_pair
,
8792 alternative_service
, 1.0);
8794 alternative_service
=
8795 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8796 EXPECT_EQ(alternative_service
.protocol
, QUIC
);
8798 scoped_ptr
<HttpTransaction
> trans(
8799 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8801 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8802 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8804 EXPECT_EQ(OK
, callback
.WaitForResult());
8806 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8807 ASSERT_TRUE(response
!= NULL
);
8808 ASSERT_TRUE(response
->headers
.get() != NULL
);
8809 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8810 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8811 EXPECT_FALSE(response
->was_npn_negotiated
);
8813 std::string response_data
;
8814 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8815 EXPECT_EQ("hello world", response_data
);
8817 alternative_service
=
8818 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8819 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8822 TEST_P(HttpNetworkTransactionTest
,
8823 MarkBrokenAlternateProtocolAndFallback
) {
8824 session_deps_
.use_alternate_protocols
= true;
8826 HttpRequestInfo request
;
8827 request
.method
= "GET";
8828 request
.url
= GURL("http://www.google.com/");
8829 request
.load_flags
= 0;
8831 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8832 StaticSocketDataProvider first_data
;
8833 first_data
.set_connect_data(mock_connect
);
8834 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8836 MockRead data_reads
[] = {
8837 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8838 MockRead("hello world"),
8839 MockRead(ASYNC
, OK
),
8841 StaticSocketDataProvider
second_data(
8842 data_reads
, arraysize(data_reads
), NULL
, 0);
8843 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8845 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8847 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8848 session
->http_server_properties();
8849 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
8850 // Port must be < 1024, or the header will be ignored (since initial port was
8851 // port 80 (another restricted port).
8852 AlternativeService
alternative_service(
8853 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
8854 666); /* port is ignored by MockConnect anyway */
8855 http_server_properties
->SetAlternativeService(host_port_pair
,
8856 alternative_service
, 1.0);
8858 scoped_ptr
<HttpTransaction
> trans(
8859 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8860 TestCompletionCallback callback
;
8862 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8863 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8864 EXPECT_EQ(OK
, callback
.WaitForResult());
8866 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8867 ASSERT_TRUE(response
!= NULL
);
8868 ASSERT_TRUE(response
->headers
.get() != NULL
);
8869 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8871 std::string response_data
;
8872 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8873 EXPECT_EQ("hello world", response_data
);
8875 alternative_service
=
8876 http_server_properties
->GetAlternativeService(host_port_pair
);
8877 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL
, alternative_service
.protocol
);
8879 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
8882 TEST_P(HttpNetworkTransactionTest
,
8883 AlternateProtocolPortRestrictedBlocked
) {
8884 // Ensure that we're not allowed to redirect traffic via an alternate
8885 // protocol to an unrestricted (port >= 1024) when the original traffic was
8886 // on a restricted port (port < 1024). Ensure that we can redirect in all
8888 session_deps_
.use_alternate_protocols
= true;
8890 HttpRequestInfo restricted_port_request
;
8891 restricted_port_request
.method
= "GET";
8892 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8893 restricted_port_request
.load_flags
= 0;
8895 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8896 StaticSocketDataProvider first_data
;
8897 first_data
.set_connect_data(mock_connect
);
8898 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8900 MockRead data_reads
[] = {
8901 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8902 MockRead("hello world"),
8903 MockRead(ASYNC
, OK
),
8905 StaticSocketDataProvider
second_data(
8906 data_reads
, arraysize(data_reads
), NULL
, 0);
8907 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8909 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8911 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8912 session
->http_server_properties();
8913 const int kUnrestrictedAlternatePort
= 1024;
8914 AlternativeService
alternative_service(
8915 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
8916 kUnrestrictedAlternatePort
);
8917 http_server_properties
->SetAlternativeService(
8918 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8921 scoped_ptr
<HttpTransaction
> trans(
8922 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8923 TestCompletionCallback callback
;
8925 int rv
= trans
->Start(
8926 &restricted_port_request
,
8927 callback
.callback(), BoundNetLog());
8928 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8929 // Invalid change to unrestricted port should fail.
8930 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8933 TEST_P(HttpNetworkTransactionTest
,
8934 AlternateProtocolPortRestrictedPermitted
) {
8935 // Ensure that we're allowed to redirect traffic via an alternate
8936 // protocol to an unrestricted (port >= 1024) when the original traffic was
8937 // on a restricted port (port < 1024) if we set
8938 // enable_user_alternate_protocol_ports.
8940 session_deps_
.use_alternate_protocols
= true;
8941 session_deps_
.enable_user_alternate_protocol_ports
= true;
8943 HttpRequestInfo restricted_port_request
;
8944 restricted_port_request
.method
= "GET";
8945 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8946 restricted_port_request
.load_flags
= 0;
8948 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8949 StaticSocketDataProvider first_data
;
8950 first_data
.set_connect_data(mock_connect
);
8951 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8953 MockRead data_reads
[] = {
8954 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8955 MockRead("hello world"),
8956 MockRead(ASYNC
, OK
),
8958 StaticSocketDataProvider
second_data(
8959 data_reads
, arraysize(data_reads
), NULL
, 0);
8960 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8962 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8964 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8965 session
->http_server_properties();
8966 const int kUnrestrictedAlternatePort
= 1024;
8967 AlternativeService
alternative_service(
8968 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
8969 kUnrestrictedAlternatePort
);
8970 http_server_properties
->SetAlternativeService(
8971 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8974 scoped_ptr
<HttpTransaction
> trans(
8975 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8976 TestCompletionCallback callback
;
8978 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8979 &restricted_port_request
,
8980 callback
.callback(), BoundNetLog()));
8981 // Change to unrestricted port should succeed.
8982 EXPECT_EQ(OK
, callback
.WaitForResult());
8985 TEST_P(HttpNetworkTransactionTest
,
8986 AlternateProtocolPortRestrictedAllowed
) {
8987 // Ensure that we're not allowed to redirect traffic via an alternate
8988 // protocol to an unrestricted (port >= 1024) when the original traffic was
8989 // on a restricted port (port < 1024). Ensure that we can redirect in all
8991 session_deps_
.use_alternate_protocols
= true;
8993 HttpRequestInfo restricted_port_request
;
8994 restricted_port_request
.method
= "GET";
8995 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8996 restricted_port_request
.load_flags
= 0;
8998 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8999 StaticSocketDataProvider first_data
;
9000 first_data
.set_connect_data(mock_connect
);
9001 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9003 MockRead data_reads
[] = {
9004 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9005 MockRead("hello world"),
9006 MockRead(ASYNC
, OK
),
9008 StaticSocketDataProvider
second_data(
9009 data_reads
, arraysize(data_reads
), NULL
, 0);
9010 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9012 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9014 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9015 session
->http_server_properties();
9016 const int kRestrictedAlternatePort
= 80;
9017 AlternativeService
alternative_service(
9018 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
9019 kRestrictedAlternatePort
);
9020 http_server_properties
->SetAlternativeService(
9021 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9024 scoped_ptr
<HttpTransaction
> trans(
9025 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9026 TestCompletionCallback callback
;
9028 int rv
= trans
->Start(
9029 &restricted_port_request
,
9030 callback
.callback(), BoundNetLog());
9031 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9032 // Valid change to restricted port should pass.
9033 EXPECT_EQ(OK
, callback
.WaitForResult());
9036 TEST_P(HttpNetworkTransactionTest
,
9037 AlternateProtocolPortUnrestrictedAllowed1
) {
9038 // Ensure that we're not allowed to redirect traffic via an alternate
9039 // protocol to an unrestricted (port >= 1024) when the original traffic was
9040 // on a restricted port (port < 1024). Ensure that we can redirect in all
9042 session_deps_
.use_alternate_protocols
= true;
9044 HttpRequestInfo unrestricted_port_request
;
9045 unrestricted_port_request
.method
= "GET";
9046 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
9047 unrestricted_port_request
.load_flags
= 0;
9049 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9050 StaticSocketDataProvider first_data
;
9051 first_data
.set_connect_data(mock_connect
);
9052 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9054 MockRead data_reads
[] = {
9055 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9056 MockRead("hello world"),
9057 MockRead(ASYNC
, OK
),
9059 StaticSocketDataProvider
second_data(
9060 data_reads
, arraysize(data_reads
), NULL
, 0);
9061 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9065 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9066 session
->http_server_properties();
9067 const int kRestrictedAlternatePort
= 80;
9068 AlternativeService
alternative_service(
9069 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
9070 kRestrictedAlternatePort
);
9071 http_server_properties
->SetAlternativeService(
9072 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9075 scoped_ptr
<HttpTransaction
> trans(
9076 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9077 TestCompletionCallback callback
;
9079 int rv
= trans
->Start(
9080 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9081 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9082 // Valid change to restricted port should pass.
9083 EXPECT_EQ(OK
, callback
.WaitForResult());
9086 TEST_P(HttpNetworkTransactionTest
,
9087 AlternateProtocolPortUnrestrictedAllowed2
) {
9088 // Ensure that we're not allowed to redirect traffic via an alternate
9089 // protocol to an unrestricted (port >= 1024) when the original traffic was
9090 // on a restricted port (port < 1024). Ensure that we can redirect in all
9092 session_deps_
.use_alternate_protocols
= true;
9094 HttpRequestInfo unrestricted_port_request
;
9095 unrestricted_port_request
.method
= "GET";
9096 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
9097 unrestricted_port_request
.load_flags
= 0;
9099 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9100 StaticSocketDataProvider first_data
;
9101 first_data
.set_connect_data(mock_connect
);
9102 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9104 MockRead data_reads
[] = {
9105 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9106 MockRead("hello world"),
9107 MockRead(ASYNC
, OK
),
9109 StaticSocketDataProvider
second_data(
9110 data_reads
, arraysize(data_reads
), NULL
, 0);
9111 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9113 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9115 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9116 session
->http_server_properties();
9117 const int kUnrestrictedAlternatePort
= 1024;
9118 AlternativeService
alternative_service(
9119 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
9120 kUnrestrictedAlternatePort
);
9121 http_server_properties
->SetAlternativeService(
9122 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9125 scoped_ptr
<HttpTransaction
> trans(
9126 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9127 TestCompletionCallback callback
;
9129 int rv
= trans
->Start(
9130 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9131 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9132 // Valid change to an unrestricted port should pass.
9133 EXPECT_EQ(OK
, callback
.WaitForResult());
9136 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9137 // Ensure that we're not allowed to redirect traffic via an alternate
9138 // protocol to an unsafe port, and that we resume the second
9139 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9140 session_deps_
.use_alternate_protocols
= true;
9142 HttpRequestInfo request
;
9143 request
.method
= "GET";
9144 request
.url
= GURL("http://www.google.com/");
9145 request
.load_flags
= 0;
9147 // The alternate protocol request will error out before we attempt to connect,
9148 // so only the standard HTTP request will try to connect.
9149 MockRead data_reads
[] = {
9150 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9151 MockRead("hello world"),
9152 MockRead(ASYNC
, OK
),
9154 StaticSocketDataProvider
data(
9155 data_reads
, arraysize(data_reads
), NULL
, 0);
9156 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9158 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9160 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9161 session
->http_server_properties();
9162 const int kUnsafePort
= 7;
9163 AlternativeService
alternative_service(
9164 AlternateProtocolFromNextProto(GetParam()), "www.google.com",
9166 http_server_properties
->SetAlternativeService(
9167 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0);
9169 scoped_ptr
<HttpTransaction
> trans(
9170 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9171 TestCompletionCallback callback
;
9173 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9174 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9175 // The HTTP request should succeed.
9176 EXPECT_EQ(OK
, callback
.WaitForResult());
9178 // Disable alternate protocol before the asserts.
9179 // HttpStreamFactory::set_use_alternate_protocols(false);
9181 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9182 ASSERT_TRUE(response
!= NULL
);
9183 ASSERT_TRUE(response
->headers
.get() != NULL
);
9184 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9186 std::string response_data
;
9187 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9188 EXPECT_EQ("hello world", response_data
);
9191 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9192 session_deps_
.use_alternate_protocols
= true;
9193 session_deps_
.next_protos
= SpdyNextProtos();
9195 HttpRequestInfo request
;
9196 request
.method
= "GET";
9197 request
.url
= GURL("http://www.google.com/");
9198 request
.load_flags
= 0;
9200 std::string alternate_protocol_http_header
=
9201 GetAlternateProtocolHttpHeader();
9203 MockRead data_reads
[] = {
9204 MockRead("HTTP/1.1 200 OK\r\n"),
9205 MockRead(alternate_protocol_http_header
.c_str()),
9206 MockRead("hello world"),
9207 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9211 StaticSocketDataProvider
first_transaction(
9212 data_reads
, arraysize(data_reads
), NULL
, 0);
9213 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9215 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9216 ssl
.SetNextProto(GetParam());
9217 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9219 scoped_ptr
<SpdyFrame
> req(
9220 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9221 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9223 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9224 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9225 MockRead spdy_reads
[] = {
9226 CreateMockRead(*resp
),
9227 CreateMockRead(*data
),
9228 MockRead(ASYNC
, 0, 0),
9231 DelayedSocketData
spdy_data(
9232 1, // wait for one write to finish before reading.
9233 spdy_reads
, arraysize(spdy_reads
),
9234 spdy_writes
, arraysize(spdy_writes
));
9235 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9237 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9238 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9240 hanging_non_alternate_protocol_socket
.set_connect_data(
9241 never_finishing_connect
);
9242 session_deps_
.socket_factory
->AddSocketDataProvider(
9243 &hanging_non_alternate_protocol_socket
);
9245 TestCompletionCallback callback
;
9247 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9248 scoped_ptr
<HttpTransaction
> trans(
9249 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9251 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9252 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9253 EXPECT_EQ(OK
, callback
.WaitForResult());
9255 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9256 ASSERT_TRUE(response
!= NULL
);
9257 ASSERT_TRUE(response
->headers
.get() != NULL
);
9258 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9260 std::string response_data
;
9261 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9262 EXPECT_EQ("hello world", response_data
);
9264 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9266 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9268 EXPECT_EQ(OK
, callback
.WaitForResult());
9270 response
= trans
->GetResponseInfo();
9271 ASSERT_TRUE(response
!= NULL
);
9272 ASSERT_TRUE(response
->headers
.get() != NULL
);
9273 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9274 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9275 EXPECT_TRUE(response
->was_npn_negotiated
);
9277 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9278 EXPECT_EQ("hello!", response_data
);
9281 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9282 session_deps_
.use_alternate_protocols
= true;
9283 session_deps_
.next_protos
= SpdyNextProtos();
9285 HttpRequestInfo request
;
9286 request
.method
= "GET";
9287 request
.url
= GURL("http://www.google.com/");
9288 request
.load_flags
= 0;
9290 std::string alternate_protocol_http_header
=
9291 GetAlternateProtocolHttpHeader();
9293 MockRead data_reads
[] = {
9294 MockRead("HTTP/1.1 200 OK\r\n"),
9295 MockRead(alternate_protocol_http_header
.c_str()),
9296 MockRead("hello world"),
9297 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9298 MockRead(ASYNC
, OK
),
9301 StaticSocketDataProvider
first_transaction(
9302 data_reads
, arraysize(data_reads
), NULL
, 0);
9303 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9304 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9306 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9307 StaticSocketDataProvider
hanging_socket(
9309 hanging_socket
.set_connect_data(never_finishing_connect
);
9310 // Socket 2 and 3 are the hanging Alternate-Protocol and
9311 // non-Alternate-Protocol jobs from the 2nd transaction.
9312 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9313 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9315 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9316 ssl
.SetNextProto(GetParam());
9317 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9319 scoped_ptr
<SpdyFrame
> req1(
9320 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9321 scoped_ptr
<SpdyFrame
> req2(
9322 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9323 MockWrite spdy_writes
[] = {
9324 CreateMockWrite(*req1
),
9325 CreateMockWrite(*req2
),
9327 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9328 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9329 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9330 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9331 MockRead spdy_reads
[] = {
9332 CreateMockRead(*resp1
),
9333 CreateMockRead(*data1
),
9334 CreateMockRead(*resp2
),
9335 CreateMockRead(*data2
),
9336 MockRead(ASYNC
, 0, 0),
9339 DelayedSocketData
spdy_data(
9340 2, // wait for writes to finish before reading.
9341 spdy_reads
, arraysize(spdy_reads
),
9342 spdy_writes
, arraysize(spdy_writes
));
9343 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9344 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9346 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9347 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9349 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9350 TestCompletionCallback callback1
;
9351 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9353 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9354 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9355 EXPECT_EQ(OK
, callback1
.WaitForResult());
9357 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9358 ASSERT_TRUE(response
!= NULL
);
9359 ASSERT_TRUE(response
->headers
.get() != NULL
);
9360 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9362 std::string response_data
;
9363 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9364 EXPECT_EQ("hello world", response_data
);
9366 TestCompletionCallback callback2
;
9367 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9368 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9371 TestCompletionCallback callback3
;
9372 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9373 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9374 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9376 EXPECT_EQ(OK
, callback2
.WaitForResult());
9377 EXPECT_EQ(OK
, callback3
.WaitForResult());
9379 response
= trans2
.GetResponseInfo();
9380 ASSERT_TRUE(response
!= NULL
);
9381 ASSERT_TRUE(response
->headers
.get() != NULL
);
9382 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9383 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9384 EXPECT_TRUE(response
->was_npn_negotiated
);
9385 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9386 EXPECT_EQ("hello!", response_data
);
9388 response
= trans3
.GetResponseInfo();
9389 ASSERT_TRUE(response
!= NULL
);
9390 ASSERT_TRUE(response
->headers
.get() != NULL
);
9391 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9392 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9393 EXPECT_TRUE(response
->was_npn_negotiated
);
9394 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9395 EXPECT_EQ("hello!", response_data
);
9398 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9399 session_deps_
.use_alternate_protocols
= true;
9400 session_deps_
.next_protos
= SpdyNextProtos();
9402 HttpRequestInfo request
;
9403 request
.method
= "GET";
9404 request
.url
= GURL("http://www.google.com/");
9405 request
.load_flags
= 0;
9407 std::string alternate_protocol_http_header
=
9408 GetAlternateProtocolHttpHeader();
9410 MockRead data_reads
[] = {
9411 MockRead("HTTP/1.1 200 OK\r\n"),
9412 MockRead(alternate_protocol_http_header
.c_str()),
9413 MockRead("hello world"),
9414 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9415 MockRead(ASYNC
, OK
),
9418 StaticSocketDataProvider
first_transaction(
9419 data_reads
, arraysize(data_reads
), NULL
, 0);
9420 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9422 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9423 ssl
.SetNextProto(GetParam());
9424 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9426 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9427 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9429 hanging_alternate_protocol_socket
.set_connect_data(
9430 never_finishing_connect
);
9431 session_deps_
.socket_factory
->AddSocketDataProvider(
9432 &hanging_alternate_protocol_socket
);
9434 // 2nd request is just a copy of the first one, over HTTP again.
9435 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9437 TestCompletionCallback callback
;
9439 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9440 scoped_ptr
<HttpTransaction
> trans(
9441 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9443 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9444 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9445 EXPECT_EQ(OK
, callback
.WaitForResult());
9447 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9448 ASSERT_TRUE(response
!= NULL
);
9449 ASSERT_TRUE(response
->headers
.get() != NULL
);
9450 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9452 std::string response_data
;
9453 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9454 EXPECT_EQ("hello world", response_data
);
9456 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9458 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9459 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9460 EXPECT_EQ(OK
, callback
.WaitForResult());
9462 response
= trans
->GetResponseInfo();
9463 ASSERT_TRUE(response
!= NULL
);
9464 ASSERT_TRUE(response
->headers
.get() != NULL
);
9465 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9466 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9467 EXPECT_FALSE(response
->was_npn_negotiated
);
9469 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9470 EXPECT_EQ("hello world", response_data
);
9473 class CapturingProxyResolver
: public ProxyResolver
{
9475 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9476 ~CapturingProxyResolver() override
{}
9478 int GetProxyForURL(const GURL
& url
,
9480 const CompletionCallback
& callback
,
9481 RequestHandle
* request
,
9482 const BoundNetLog
& net_log
) override
{
9483 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9484 HostPortPair("myproxy", 80));
9485 results
->UseProxyServer(proxy_server
);
9486 resolved_
.push_back(url
);
9490 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9492 LoadState
GetLoadState(RequestHandle request
) const override
{
9494 return LOAD_STATE_IDLE
;
9497 void CancelSetPacScript() override
{ NOTREACHED(); }
9499 int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9500 const CompletionCallback
& /*callback*/) override
{
9504 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9507 std::vector
<GURL
> resolved_
;
9509 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9512 TEST_P(HttpNetworkTransactionTest
,
9513 UseAlternateProtocolForTunneledNpnSpdy
) {
9514 session_deps_
.use_alternate_protocols
= true;
9515 session_deps_
.next_protos
= SpdyNextProtos();
9517 ProxyConfig proxy_config
;
9518 proxy_config
.set_auto_detect(true);
9519 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9521 CapturingProxyResolver capturing_proxy_resolver
;
9522 session_deps_
.proxy_service
.reset(new ProxyService(
9523 new ProxyConfigServiceFixed(proxy_config
),
9525 new ForwardingProxyResolverFactory(&capturing_proxy_resolver
)),
9527 CapturingNetLog net_log
;
9528 session_deps_
.net_log
= &net_log
;
9530 HttpRequestInfo request
;
9531 request
.method
= "GET";
9532 request
.url
= GURL("http://www.google.com/");
9533 request
.load_flags
= 0;
9535 std::string alternate_protocol_http_header
=
9536 GetAlternateProtocolHttpHeader();
9538 MockRead data_reads
[] = {
9539 MockRead("HTTP/1.1 200 OK\r\n"),
9540 MockRead(alternate_protocol_http_header
.c_str()),
9541 MockRead("hello world"),
9542 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9543 MockRead(ASYNC
, OK
),
9546 StaticSocketDataProvider
first_transaction(
9547 data_reads
, arraysize(data_reads
), NULL
, 0);
9548 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9550 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9551 ssl
.SetNextProto(GetParam());
9552 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9554 scoped_ptr
<SpdyFrame
> req(
9555 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9556 MockWrite spdy_writes
[] = {
9557 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9558 "Host: www.google.com\r\n"
9559 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9560 CreateMockWrite(*req
), // 3
9563 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9565 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9566 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9567 MockRead spdy_reads
[] = {
9568 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9569 CreateMockRead(*resp
.get(), 4), // 2, 4
9570 CreateMockRead(*data
.get(), 4), // 5
9571 MockRead(ASYNC
, 0, 0, 4), // 6
9574 OrderedSocketData
spdy_data(
9575 spdy_reads
, arraysize(spdy_reads
),
9576 spdy_writes
, arraysize(spdy_writes
));
9577 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9579 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9580 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9582 hanging_non_alternate_protocol_socket
.set_connect_data(
9583 never_finishing_connect
);
9584 session_deps_
.socket_factory
->AddSocketDataProvider(
9585 &hanging_non_alternate_protocol_socket
);
9587 TestCompletionCallback callback
;
9589 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9590 scoped_ptr
<HttpTransaction
> trans(
9591 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9593 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9594 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9595 EXPECT_EQ(OK
, callback
.WaitForResult());
9597 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9598 ASSERT_TRUE(response
!= NULL
);
9599 ASSERT_TRUE(response
->headers
.get() != NULL
);
9600 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9601 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9602 EXPECT_FALSE(response
->was_npn_negotiated
);
9604 std::string response_data
;
9605 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9606 EXPECT_EQ("hello world", response_data
);
9608 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9610 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9611 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9612 EXPECT_EQ(OK
, callback
.WaitForResult());
9614 response
= trans
->GetResponseInfo();
9615 ASSERT_TRUE(response
!= NULL
);
9616 ASSERT_TRUE(response
->headers
.get() != NULL
);
9617 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9618 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9619 EXPECT_TRUE(response
->was_npn_negotiated
);
9621 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9622 EXPECT_EQ("hello!", response_data
);
9623 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9624 EXPECT_EQ("http://www.google.com/",
9625 capturing_proxy_resolver
.resolved()[0].spec());
9626 EXPECT_EQ("https://www.google.com/",
9627 capturing_proxy_resolver
.resolved()[1].spec());
9629 LoadTimingInfo load_timing_info
;
9630 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9631 TestLoadTimingNotReusedWithPac(load_timing_info
,
9632 CONNECT_TIMING_HAS_SSL_TIMES
);
9635 TEST_P(HttpNetworkTransactionTest
,
9636 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9637 session_deps_
.use_alternate_protocols
= true;
9638 session_deps_
.next_protos
= SpdyNextProtos();
9640 HttpRequestInfo request
;
9641 request
.method
= "GET";
9642 request
.url
= GURL("http://www.google.com/");
9643 request
.load_flags
= 0;
9645 std::string alternate_protocol_http_header
=
9646 GetAlternateProtocolHttpHeader();
9648 MockRead data_reads
[] = {
9649 MockRead("HTTP/1.1 200 OK\r\n"),
9650 MockRead(alternate_protocol_http_header
.c_str()),
9651 MockRead("hello world"),
9652 MockRead(ASYNC
, OK
),
9655 StaticSocketDataProvider
first_transaction(
9656 data_reads
, arraysize(data_reads
), NULL
, 0);
9657 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9659 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9660 ssl
.SetNextProto(GetParam());
9661 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9663 scoped_ptr
<SpdyFrame
> req(
9664 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9665 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9667 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9668 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9669 MockRead spdy_reads
[] = {
9670 CreateMockRead(*resp
),
9671 CreateMockRead(*data
),
9672 MockRead(ASYNC
, 0, 0),
9675 DelayedSocketData
spdy_data(
9676 1, // wait for one write to finish before reading.
9677 spdy_reads
, arraysize(spdy_reads
),
9678 spdy_writes
, arraysize(spdy_writes
));
9679 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9681 TestCompletionCallback callback
;
9683 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9685 scoped_ptr
<HttpTransaction
> trans(
9686 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9688 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9689 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9690 EXPECT_EQ(OK
, callback
.WaitForResult());
9692 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9693 ASSERT_TRUE(response
!= NULL
);
9694 ASSERT_TRUE(response
->headers
.get() != NULL
);
9695 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9697 std::string response_data
;
9698 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9699 EXPECT_EQ("hello world", response_data
);
9701 // Set up an initial SpdySession in the pool to reuse.
9702 HostPortPair
host_port_pair("www.google.com", 443);
9703 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9704 PRIVACY_MODE_DISABLED
);
9705 base::WeakPtr
<SpdySession
> spdy_session
=
9706 CreateSecureSpdySession(session
, key
, BoundNetLog());
9708 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9710 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9711 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9712 EXPECT_EQ(OK
, callback
.WaitForResult());
9714 response
= trans
->GetResponseInfo();
9715 ASSERT_TRUE(response
!= NULL
);
9716 ASSERT_TRUE(response
->headers
.get() != NULL
);
9717 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9718 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9719 EXPECT_TRUE(response
->was_npn_negotiated
);
9721 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9722 EXPECT_EQ("hello!", response_data
);
9725 // GenerateAuthToken is a mighty big test.
9726 // It tests all permutation of GenerateAuthToken behavior:
9727 // - Synchronous and Asynchronous completion.
9728 // - OK or error on completion.
9729 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9730 // - HTTP or HTTPS backend (to include proxy tunneling).
9731 // - Non-authenticating and authenticating backend.
9733 // In all, there are 44 reasonable permuations (for example, if there are
9734 // problems generating an auth token for an authenticating proxy, we don't
9735 // need to test all permutations of the backend server).
9737 // The test proceeds by going over each of the configuration cases, and
9738 // potentially running up to three rounds in each of the tests. The TestConfig
9739 // specifies both the configuration for the test as well as the expectations
9741 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9742 static const char kServer
[] = "http://www.example.com";
9743 static const char kSecureServer
[] = "https://www.example.com";
9744 static const char kProxy
[] = "myproxy:70";
9745 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9753 const MockWrite
kGet(
9754 "GET / HTTP/1.1\r\n"
9755 "Host: www.example.com\r\n"
9756 "Connection: keep-alive\r\n\r\n");
9757 const MockWrite
kGetProxy(
9758 "GET http://www.example.com/ HTTP/1.1\r\n"
9759 "Host: www.example.com\r\n"
9760 "Proxy-Connection: keep-alive\r\n\r\n");
9761 const MockWrite
kGetAuth(
9762 "GET / HTTP/1.1\r\n"
9763 "Host: www.example.com\r\n"
9764 "Connection: keep-alive\r\n"
9765 "Authorization: auth_token\r\n\r\n");
9766 const MockWrite
kGetProxyAuth(
9767 "GET http://www.example.com/ HTTP/1.1\r\n"
9768 "Host: www.example.com\r\n"
9769 "Proxy-Connection: keep-alive\r\n"
9770 "Proxy-Authorization: auth_token\r\n\r\n");
9771 const MockWrite
kGetAuthThroughProxy(
9772 "GET http://www.example.com/ HTTP/1.1\r\n"
9773 "Host: www.example.com\r\n"
9774 "Proxy-Connection: keep-alive\r\n"
9775 "Authorization: auth_token\r\n\r\n");
9776 const MockWrite
kGetAuthWithProxyAuth(
9777 "GET http://www.example.com/ HTTP/1.1\r\n"
9778 "Host: www.example.com\r\n"
9779 "Proxy-Connection: keep-alive\r\n"
9780 "Proxy-Authorization: auth_token\r\n"
9781 "Authorization: auth_token\r\n\r\n");
9782 const MockWrite
kConnect(
9783 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9784 "Host: www.example.com\r\n"
9785 "Proxy-Connection: keep-alive\r\n\r\n");
9786 const MockWrite
kConnectProxyAuth(
9787 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9788 "Host: www.example.com\r\n"
9789 "Proxy-Connection: keep-alive\r\n"
9790 "Proxy-Authorization: auth_token\r\n\r\n");
9792 const MockRead
kSuccess(
9793 "HTTP/1.1 200 OK\r\n"
9794 "Content-Type: text/html; charset=iso-8859-1\r\n"
9795 "Content-Length: 3\r\n\r\n"
9797 const MockRead
kFailure(
9798 "Should not be called.");
9799 const MockRead
kServerChallenge(
9800 "HTTP/1.1 401 Unauthorized\r\n"
9801 "WWW-Authenticate: Mock realm=server\r\n"
9802 "Content-Type: text/html; charset=iso-8859-1\r\n"
9803 "Content-Length: 14\r\n\r\n"
9804 "Unauthorized\r\n");
9805 const MockRead
kProxyChallenge(
9806 "HTTP/1.1 407 Unauthorized\r\n"
9807 "Proxy-Authenticate: Mock realm=proxy\r\n"
9808 "Proxy-Connection: close\r\n"
9809 "Content-Type: text/html; charset=iso-8859-1\r\n"
9810 "Content-Length: 14\r\n\r\n"
9811 "Unauthorized\r\n");
9812 const MockRead
kProxyConnected(
9813 "HTTP/1.1 200 Connection Established\r\n\r\n");
9815 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9816 // no constructors, but the C++ compiler on Windows warns about
9817 // unspecified data in compound literals. So, moved to using constructors,
9818 // and TestRound's created with the default constructor should not be used.
9821 : expected_rv(ERR_UNEXPECTED
),
9825 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9826 int expected_rv_arg
)
9829 expected_rv(expected_rv_arg
),
9833 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9834 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9835 const MockRead
* extra_read_arg
)
9838 expected_rv(expected_rv_arg
),
9839 extra_write(extra_write_arg
),
9840 extra_read(extra_read_arg
) {
9845 const MockWrite
* extra_write
;
9846 const MockRead
* extra_read
;
9849 static const int kNoSSL
= 500;
9852 const char* const proxy_url
;
9853 AuthTiming proxy_auth_timing
;
9855 const char* const server_url
;
9856 AuthTiming server_auth_timing
;
9858 int num_auth_rounds
;
9859 int first_ssl_round
;
9860 TestRound rounds
[3];
9861 } test_configs
[] = {
9862 // Non-authenticating HTTP server with a direct connection.
9863 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9864 { TestRound(kGet
, kSuccess
, OK
)}},
9865 // Authenticating HTTP server with a direct connection.
9866 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9867 { TestRound(kGet
, kServerChallenge
, OK
),
9868 TestRound(kGetAuth
, kSuccess
, OK
)}},
9869 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9870 { TestRound(kGet
, kServerChallenge
, OK
),
9871 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9872 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9873 { TestRound(kGet
, kServerChallenge
, OK
),
9874 TestRound(kGetAuth
, kSuccess
, OK
)}},
9875 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9876 { TestRound(kGet
, kServerChallenge
, OK
),
9877 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9878 // Non-authenticating HTTP server through a non-authenticating proxy.
9879 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9880 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9881 // Authenticating HTTP server through a non-authenticating proxy.
9882 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9883 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9884 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9885 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9886 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9887 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9888 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9889 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9890 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9891 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9892 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9893 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9894 // Non-authenticating HTTP server through an authenticating proxy.
9895 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9896 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9897 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9898 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9899 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9900 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9901 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9902 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9903 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9904 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9905 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9906 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9907 // Authenticating HTTP server through an authenticating proxy.
9908 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9909 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9910 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9911 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9912 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9913 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9914 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9915 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9916 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9917 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9918 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9919 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9920 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9921 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9922 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9923 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9924 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9925 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9926 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9927 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9928 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9929 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9930 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9931 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9932 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9933 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9934 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9935 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9936 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9937 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9938 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9939 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9940 // Non-authenticating HTTPS server with a direct connection.
9941 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9942 { TestRound(kGet
, kSuccess
, OK
)}},
9943 // Authenticating HTTPS server with a direct connection.
9944 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9945 { TestRound(kGet
, kServerChallenge
, OK
),
9946 TestRound(kGetAuth
, kSuccess
, OK
)}},
9947 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9948 { TestRound(kGet
, kServerChallenge
, OK
),
9949 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9950 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9951 { TestRound(kGet
, kServerChallenge
, OK
),
9952 TestRound(kGetAuth
, kSuccess
, OK
)}},
9953 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9954 { TestRound(kGet
, kServerChallenge
, OK
),
9955 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9956 // Non-authenticating HTTPS server with a non-authenticating proxy.
9957 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9958 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9959 // Authenticating HTTPS server through a non-authenticating proxy.
9960 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9961 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9962 TestRound(kGetAuth
, kSuccess
, OK
)}},
9963 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9964 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9965 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9966 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9967 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9968 TestRound(kGetAuth
, kSuccess
, OK
)}},
9969 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9970 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9971 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9972 // Non-Authenticating HTTPS server through an authenticating proxy.
9973 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9974 { TestRound(kConnect
, kProxyChallenge
, OK
),
9975 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9976 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9977 { TestRound(kConnect
, kProxyChallenge
, OK
),
9978 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9979 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9980 { TestRound(kConnect
, kProxyChallenge
, OK
),
9981 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9982 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9983 { TestRound(kConnect
, kProxyChallenge
, OK
),
9984 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9985 // Authenticating HTTPS server through an authenticating proxy.
9986 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9987 { TestRound(kConnect
, kProxyChallenge
, OK
),
9988 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9989 &kGet
, &kServerChallenge
),
9990 TestRound(kGetAuth
, kSuccess
, OK
)}},
9991 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9992 { TestRound(kConnect
, kProxyChallenge
, OK
),
9993 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9994 &kGet
, &kServerChallenge
),
9995 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9996 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9997 { TestRound(kConnect
, kProxyChallenge
, OK
),
9998 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9999 &kGet
, &kServerChallenge
),
10000 TestRound(kGetAuth
, kSuccess
, OK
)}},
10001 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10002 { TestRound(kConnect
, kProxyChallenge
, OK
),
10003 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10004 &kGet
, &kServerChallenge
),
10005 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10006 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10007 { TestRound(kConnect
, kProxyChallenge
, OK
),
10008 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10009 &kGet
, &kServerChallenge
),
10010 TestRound(kGetAuth
, kSuccess
, OK
)}},
10011 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10012 { TestRound(kConnect
, kProxyChallenge
, OK
),
10013 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10014 &kGet
, &kServerChallenge
),
10015 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10016 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10017 { TestRound(kConnect
, kProxyChallenge
, OK
),
10018 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10019 &kGet
, &kServerChallenge
),
10020 TestRound(kGetAuth
, kSuccess
, OK
)}},
10021 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10022 { TestRound(kConnect
, kProxyChallenge
, OK
),
10023 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10024 &kGet
, &kServerChallenge
),
10025 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10028 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10029 HttpAuthHandlerMock::Factory
* auth_factory(
10030 new HttpAuthHandlerMock::Factory());
10031 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10032 const TestConfig
& test_config
= test_configs
[i
];
10034 // Set up authentication handlers as necessary.
10035 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10036 for (int n
= 0; n
< 2; n
++) {
10037 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10038 std::string auth_challenge
= "Mock realm=proxy";
10039 GURL
origin(test_config
.proxy_url
);
10040 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10041 auth_challenge
.end());
10042 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10043 origin
, BoundNetLog());
10044 auth_handler
->SetGenerateExpectation(
10045 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10046 test_config
.proxy_auth_rv
);
10047 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10050 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10051 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10052 std::string auth_challenge
= "Mock realm=server";
10053 GURL
origin(test_config
.server_url
);
10054 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10055 auth_challenge
.end());
10056 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10057 origin
, BoundNetLog());
10058 auth_handler
->SetGenerateExpectation(
10059 test_config
.server_auth_timing
== AUTH_ASYNC
,
10060 test_config
.server_auth_rv
);
10061 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10063 if (test_config
.proxy_url
) {
10064 session_deps_
.proxy_service
.reset(
10065 ProxyService::CreateFixed(test_config
.proxy_url
));
10067 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10070 HttpRequestInfo request
;
10071 request
.method
= "GET";
10072 request
.url
= GURL(test_config
.server_url
);
10073 request
.load_flags
= 0;
10075 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10076 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10078 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10079 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10081 // Set up expected reads and writes.
10083 reads
[0] = read_write_round
.read
;
10084 size_t length_reads
= 1;
10085 if (read_write_round
.extra_read
) {
10086 reads
[1] = *read_write_round
.extra_read
;
10090 MockWrite writes
[2];
10091 writes
[0] = read_write_round
.write
;
10092 size_t length_writes
= 1;
10093 if (read_write_round
.extra_write
) {
10094 writes
[1] = *read_write_round
.extra_write
;
10097 StaticSocketDataProvider
data_provider(
10098 reads
, length_reads
, writes
, length_writes
);
10099 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10101 // Add an SSL sequence if necessary.
10102 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10103 if (round
>= test_config
.first_ssl_round
)
10104 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10105 &ssl_socket_data_provider
);
10107 // Start or restart the transaction.
10108 TestCompletionCallback callback
;
10111 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10113 rv
= trans
.RestartWithAuth(
10114 AuthCredentials(kFoo
, kBar
), callback
.callback());
10116 if (rv
== ERR_IO_PENDING
)
10117 rv
= callback
.WaitForResult();
10119 // Compare results with expected data.
10120 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10121 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10122 if (read_write_round
.expected_rv
== OK
) {
10123 ASSERT_TRUE(response
!= NULL
);
10125 EXPECT_TRUE(response
== NULL
);
10126 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10129 if (round
+ 1 < test_config
.num_auth_rounds
) {
10130 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10132 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10138 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10139 // Do multi-round authentication and make sure it works correctly.
10140 HttpAuthHandlerMock::Factory
* auth_factory(
10141 new HttpAuthHandlerMock::Factory());
10142 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10143 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10144 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10145 session_deps_
.host_resolver
->set_synchronous_mode(true);
10147 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10148 auth_handler
->set_connection_based(true);
10149 std::string auth_challenge
= "Mock realm=server";
10150 GURL
origin("http://www.example.com");
10151 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10152 auth_challenge
.end());
10153 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10154 origin
, BoundNetLog());
10155 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10158 const HttpResponseInfo
* response
= NULL
;
10159 HttpRequestInfo request
;
10160 request
.method
= "GET";
10161 request
.url
= origin
;
10162 request
.load_flags
= 0;
10164 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10166 // Use a TCP Socket Pool with only one connection per group. This is used
10167 // to validate that the TCP socket is not released to the pool between
10168 // each round of multi-round authentication.
10169 HttpNetworkSessionPeer
session_peer(session
);
10170 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10171 50, // Max sockets for pool
10172 1, // Max sockets per group
10173 session_deps_
.host_resolver
.get(),
10174 session_deps_
.socket_factory
.get(),
10175 session_deps_
.net_log
);
10176 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10177 new MockClientSocketPoolManager
);
10178 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10179 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10181 scoped_ptr
<HttpTransaction
> trans(
10182 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10183 TestCompletionCallback callback
;
10185 const MockWrite
kGet(
10186 "GET / HTTP/1.1\r\n"
10187 "Host: www.example.com\r\n"
10188 "Connection: keep-alive\r\n\r\n");
10189 const MockWrite
kGetAuth(
10190 "GET / HTTP/1.1\r\n"
10191 "Host: www.example.com\r\n"
10192 "Connection: keep-alive\r\n"
10193 "Authorization: auth_token\r\n\r\n");
10195 const MockRead
kServerChallenge(
10196 "HTTP/1.1 401 Unauthorized\r\n"
10197 "WWW-Authenticate: Mock realm=server\r\n"
10198 "Content-Type: text/html; charset=iso-8859-1\r\n"
10199 "Content-Length: 14\r\n\r\n"
10200 "Unauthorized\r\n");
10201 const MockRead
kSuccess(
10202 "HTTP/1.1 200 OK\r\n"
10203 "Content-Type: text/html; charset=iso-8859-1\r\n"
10204 "Content-Length: 3\r\n\r\n"
10207 MockWrite writes
[] = {
10216 // Competing request
10219 MockRead reads
[] = {
10228 // Competing response
10231 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10232 writes
, arraysize(writes
));
10233 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10235 const char kSocketGroup
[] = "www.example.com:80";
10237 // First round of authentication.
10238 auth_handler
->SetGenerateExpectation(false, OK
);
10239 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10240 if (rv
== ERR_IO_PENDING
)
10241 rv
= callback
.WaitForResult();
10243 response
= trans
->GetResponseInfo();
10244 ASSERT_TRUE(response
!= NULL
);
10245 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10246 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10248 // In between rounds, another request comes in for the same domain.
10249 // It should not be able to grab the TCP socket that trans has already
10251 scoped_ptr
<HttpTransaction
> trans_compete(
10252 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10253 TestCompletionCallback callback_compete
;
10254 rv
= trans_compete
->Start(
10255 &request
, callback_compete
.callback(), BoundNetLog());
10256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10257 // callback_compete.WaitForResult at this point would stall forever,
10258 // since the HttpNetworkTransaction does not release the request back to
10259 // the pool until after authentication completes.
10261 // Second round of authentication.
10262 auth_handler
->SetGenerateExpectation(false, OK
);
10263 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10264 if (rv
== ERR_IO_PENDING
)
10265 rv
= callback
.WaitForResult();
10267 response
= trans
->GetResponseInfo();
10268 ASSERT_TRUE(response
!= NULL
);
10269 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10270 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10272 // Third round of authentication.
10273 auth_handler
->SetGenerateExpectation(false, OK
);
10274 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10275 if (rv
== ERR_IO_PENDING
)
10276 rv
= callback
.WaitForResult();
10278 response
= trans
->GetResponseInfo();
10279 ASSERT_TRUE(response
!= NULL
);
10280 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10281 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10283 // Fourth round of authentication, which completes successfully.
10284 auth_handler
->SetGenerateExpectation(false, OK
);
10285 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10286 if (rv
== ERR_IO_PENDING
)
10287 rv
= callback
.WaitForResult();
10289 response
= trans
->GetResponseInfo();
10290 ASSERT_TRUE(response
!= NULL
);
10291 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10292 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10294 // Read the body since the fourth round was successful. This will also
10295 // release the socket back to the pool.
10296 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10297 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10298 if (rv
== ERR_IO_PENDING
)
10299 rv
= callback
.WaitForResult();
10301 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10303 // There are still 0 idle sockets, since the trans_compete transaction
10304 // will be handed it immediately after trans releases it to the group.
10305 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10307 // The competing request can now finish. Wait for the headers and then
10309 rv
= callback_compete
.WaitForResult();
10311 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10312 if (rv
== ERR_IO_PENDING
)
10313 rv
= callback
.WaitForResult();
10315 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10318 // Finally, the socket is released to the group.
10319 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10322 // This tests the case that a request is issued via http instead of spdy after
10323 // npn is negotiated.
10324 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10325 session_deps_
.use_alternate_protocols
= true;
10326 NextProtoVector next_protos
;
10327 next_protos
.push_back(kProtoHTTP11
);
10328 session_deps_
.next_protos
= next_protos
;
10330 HttpRequestInfo request
;
10331 request
.method
= "GET";
10332 request
.url
= GURL("https://www.google.com/");
10333 request
.load_flags
= 0;
10335 MockWrite data_writes
[] = {
10336 MockWrite("GET / HTTP/1.1\r\n"
10337 "Host: www.google.com\r\n"
10338 "Connection: keep-alive\r\n\r\n"),
10341 std::string alternate_protocol_http_header
=
10342 GetAlternateProtocolHttpHeader();
10344 MockRead data_reads
[] = {
10345 MockRead("HTTP/1.1 200 OK\r\n"),
10346 MockRead(alternate_protocol_http_header
.c_str()),
10347 MockRead("hello world"),
10348 MockRead(SYNCHRONOUS
, OK
),
10351 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10352 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
10353 ssl
.next_proto
= "http/1.1";
10354 ssl
.protocol_negotiated
= kProtoHTTP11
;
10356 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10358 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10359 data_writes
, arraysize(data_writes
));
10360 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10362 TestCompletionCallback callback
;
10364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10365 scoped_ptr
<HttpTransaction
> trans(
10366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10368 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10370 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10371 EXPECT_EQ(OK
, callback
.WaitForResult());
10373 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10374 ASSERT_TRUE(response
!= NULL
);
10375 ASSERT_TRUE(response
->headers
.get() != NULL
);
10376 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10378 std::string response_data
;
10379 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10380 EXPECT_EQ("hello world", response_data
);
10382 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10383 EXPECT_TRUE(response
->was_npn_negotiated
);
10386 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10387 // Simulate the SSL handshake completing with an NPN negotiation
10388 // followed by an immediate server closing of the socket.
10389 // Fix crash: http://crbug.com/46369
10390 session_deps_
.use_alternate_protocols
= true;
10391 session_deps_
.next_protos
= SpdyNextProtos();
10393 HttpRequestInfo request
;
10394 request
.method
= "GET";
10395 request
.url
= GURL("https://www.google.com/");
10396 request
.load_flags
= 0;
10398 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10399 ssl
.SetNextProto(GetParam());
10400 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10402 scoped_ptr
<SpdyFrame
> req(
10403 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10404 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10406 MockRead spdy_reads
[] = {
10407 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10410 DelayedSocketData
spdy_data(
10411 0, // don't wait in this case, immediate hangup.
10412 spdy_reads
, arraysize(spdy_reads
),
10413 spdy_writes
, arraysize(spdy_writes
));
10414 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10416 TestCompletionCallback callback
;
10418 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10419 scoped_ptr
<HttpTransaction
> trans(
10420 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10422 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10424 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10427 // A subclass of HttpAuthHandlerMock that records the request URL when
10428 // it gets it. This is needed since the auth handler may get destroyed
10429 // before we get a chance to query it.
10430 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10432 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10434 ~UrlRecordingHttpAuthHandlerMock() override
{}
10437 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10438 const HttpRequestInfo
* request
,
10439 const CompletionCallback
& callback
,
10440 std::string
* auth_token
) override
{
10441 *url_
= request
->url
;
10442 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10443 credentials
, request
, callback
, auth_token
);
10450 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10451 // This test ensures that the URL passed into the proxy is upgraded
10452 // to https when doing an Alternate Protocol upgrade.
10453 session_deps_
.use_alternate_protocols
= true;
10454 session_deps_
.next_protos
= SpdyNextProtos();
10456 session_deps_
.proxy_service
.reset(
10457 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10458 CapturingNetLog net_log
;
10459 session_deps_
.net_log
= &net_log
;
10462 HttpAuthHandlerMock::Factory
* auth_factory
=
10463 new HttpAuthHandlerMock::Factory();
10464 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10465 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10466 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10467 auth_factory
->set_do_init_from_challenge(true);
10468 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10471 HttpRequestInfo request
;
10472 request
.method
= "GET";
10473 request
.url
= GURL("http://www.google.com");
10474 request
.load_flags
= 0;
10476 // First round goes unauthenticated through the proxy.
10477 MockWrite data_writes_1
[] = {
10478 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10479 "Host: www.google.com\r\n"
10480 "Proxy-Connection: keep-alive\r\n"
10483 MockRead data_reads_1
[] = {
10484 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10485 MockRead("HTTP/1.1 200 OK\r\n"),
10486 MockRead("Alternate-Protocol: 443:"),
10487 MockRead(GetAlternateProtocolFromParam()),
10489 MockRead("Proxy-Connection: close\r\n"),
10492 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10493 data_writes_1
, arraysize(data_writes_1
));
10495 // Second round tries to tunnel to www.google.com due to the
10496 // Alternate-Protocol announcement in the first round. It fails due
10497 // to a proxy authentication challenge.
10498 // After the failure, a tunnel is established to www.google.com using
10499 // Proxy-Authorization headers. There is then a SPDY request round.
10501 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10502 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10503 // does a Disconnect and Connect on the same socket, rather than trying
10504 // to obtain a new one.
10506 // NOTE: Originally, the proxy response to the second CONNECT request
10507 // simply returned another 407 so the unit test could skip the SSL connection
10508 // establishment and SPDY framing issues. Alas, the
10509 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10510 // complicated to set up expectations for than the SPDY session.
10512 scoped_ptr
<SpdyFrame
> req(
10513 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10514 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10515 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10517 MockWrite data_writes_2
[] = {
10518 // First connection attempt without Proxy-Authorization.
10519 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10520 "Host: www.google.com\r\n"
10521 "Proxy-Connection: keep-alive\r\n"
10524 // Second connection attempt with Proxy-Authorization.
10525 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10526 "Host: www.google.com\r\n"
10527 "Proxy-Connection: keep-alive\r\n"
10528 "Proxy-Authorization: auth_token\r\n"
10532 CreateMockWrite(*req
),
10534 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10535 "Proxy-Authenticate: Mock\r\n"
10536 "Proxy-Connection: close\r\n"
10538 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10539 MockRead data_reads_2
[] = {
10540 // First connection attempt fails
10541 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10542 MockRead(ASYNC
, kRejectConnectResponse
,
10543 arraysize(kRejectConnectResponse
) - 1, 1),
10545 // Second connection attempt passes
10546 MockRead(ASYNC
, kAcceptConnectResponse
,
10547 arraysize(kAcceptConnectResponse
) -1, 4),
10550 CreateMockRead(*resp
.get(), 6),
10551 CreateMockRead(*data
.get(), 6),
10552 MockRead(ASYNC
, 0, 0, 6),
10554 OrderedSocketData
data_2(
10555 data_reads_2
, arraysize(data_reads_2
),
10556 data_writes_2
, arraysize(data_writes_2
));
10558 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10559 ssl
.SetNextProto(GetParam());
10561 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10562 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10564 hanging_non_alternate_protocol_socket
.set_connect_data(
10565 never_finishing_connect
);
10567 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10568 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10569 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10570 session_deps_
.socket_factory
->AddSocketDataProvider(
10571 &hanging_non_alternate_protocol_socket
);
10572 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10574 // First round should work and provide the Alternate-Protocol state.
10575 TestCompletionCallback callback_1
;
10576 scoped_ptr
<HttpTransaction
> trans_1(
10577 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10578 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10579 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10580 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10582 // Second round should attempt a tunnel connect and get an auth challenge.
10583 TestCompletionCallback callback_2
;
10584 scoped_ptr
<HttpTransaction
> trans_2(
10585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10586 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10587 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10588 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10589 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10590 ASSERT_TRUE(response
!= NULL
);
10591 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10593 // Restart with auth. Tunnel should work and response received.
10594 TestCompletionCallback callback_3
;
10595 rv
= trans_2
->RestartWithAuth(
10596 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10597 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10598 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10600 // After all that work, these two lines (or actually, just the scheme) are
10601 // what this test is all about. Make sure it happens correctly.
10602 EXPECT_EQ("https", request_url
.scheme());
10603 EXPECT_EQ("www.google.com", request_url
.host());
10605 LoadTimingInfo load_timing_info
;
10606 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10607 TestLoadTimingNotReusedWithPac(load_timing_info
,
10608 CONNECT_TIMING_HAS_SSL_TIMES
);
10611 // Test that if we cancel the transaction as the connection is completing, that
10612 // everything tears down correctly.
10613 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10614 // Setup everything about the connection to complete synchronously, so that
10615 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10616 // for is the callback from the HttpStreamRequest.
10617 // Then cancel the transaction.
10618 // Verify that we don't crash.
10619 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10620 MockRead data_reads
[] = {
10621 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10622 MockRead(SYNCHRONOUS
, "hello world"),
10623 MockRead(SYNCHRONOUS
, OK
),
10626 HttpRequestInfo request
;
10627 request
.method
= "GET";
10628 request
.url
= GURL("http://www.google.com/");
10629 request
.load_flags
= 0;
10631 session_deps_
.host_resolver
->set_synchronous_mode(true);
10632 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10633 scoped_ptr
<HttpTransaction
> trans(
10634 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10636 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10637 data
.set_connect_data(mock_connect
);
10638 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10640 TestCompletionCallback callback
;
10642 CapturingBoundNetLog log
;
10643 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10644 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10645 trans
.reset(); // Cancel the transaction here.
10647 base::MessageLoop::current()->RunUntilIdle();
10650 // Test that if a transaction is cancelled after receiving the headers, the
10651 // stream is drained properly and added back to the socket pool. The main
10652 // purpose of this test is to make sure that an HttpStreamParser can be read
10653 // from after the HttpNetworkTransaction and the objects it owns have been
10655 // See http://crbug.com/368418
10656 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10657 MockRead data_reads
[] = {
10658 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10659 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10660 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10661 MockRead(ASYNC
, "1"),
10662 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10663 // HttpNetworkTransaction has been deleted.
10664 MockRead(ASYNC
, "2"),
10665 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10667 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10668 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10670 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10673 HttpRequestInfo request
;
10674 request
.method
= "GET";
10675 request
.url
= GURL("http://www.google.com/");
10676 request
.load_flags
= 0;
10678 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10679 TestCompletionCallback callback
;
10681 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10682 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10683 callback
.WaitForResult();
10685 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10686 ASSERT_TRUE(response
!= NULL
);
10687 EXPECT_TRUE(response
->headers
.get() != NULL
);
10688 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10690 // The transaction and HttpRequestInfo are deleted.
10693 // Let the HttpResponseBodyDrainer drain the socket.
10694 base::MessageLoop::current()->RunUntilIdle();
10696 // Socket should now be idle, waiting to be reused.
10697 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10700 // Test a basic GET request through a proxy.
10701 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10702 session_deps_
.proxy_service
.reset(
10703 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10704 CapturingBoundNetLog log
;
10705 session_deps_
.net_log
= log
.bound().net_log();
10706 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10708 HttpRequestInfo request
;
10709 request
.method
= "GET";
10710 request
.url
= GURL("http://www.google.com/");
10712 MockWrite data_writes1
[] = {
10713 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10714 "Host: www.google.com\r\n"
10715 "Proxy-Connection: keep-alive\r\n\r\n"),
10718 MockRead data_reads1
[] = {
10719 MockRead("HTTP/1.1 200 OK\r\n"),
10720 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10721 MockRead("Content-Length: 100\r\n\r\n"),
10722 MockRead(SYNCHRONOUS
, OK
),
10725 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10726 data_writes1
, arraysize(data_writes1
));
10727 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10729 TestCompletionCallback callback1
;
10731 scoped_ptr
<HttpTransaction
> trans(
10732 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10733 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10734 trans
->SetBeforeProxyHeadersSentCallback(
10735 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10736 base::Unretained(&proxy_headers_handler
)));
10738 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10741 rv
= callback1
.WaitForResult();
10744 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10745 ASSERT_TRUE(response
!= NULL
);
10747 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10748 EXPECT_EQ(200, response
->headers
->response_code());
10749 EXPECT_EQ(100, response
->headers
->GetContentLength());
10750 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10752 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10753 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10754 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10755 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10757 LoadTimingInfo load_timing_info
;
10758 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10759 TestLoadTimingNotReusedWithPac(load_timing_info
,
10760 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10763 // Test a basic HTTPS GET request through a proxy.
10764 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10765 session_deps_
.proxy_service
.reset(
10766 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10767 CapturingBoundNetLog log
;
10768 session_deps_
.net_log
= log
.bound().net_log();
10769 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10771 HttpRequestInfo request
;
10772 request
.method
= "GET";
10773 request
.url
= GURL("https://www.google.com/");
10775 // Since we have proxy, should try to establish tunnel.
10776 MockWrite data_writes1
[] = {
10777 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10778 "Host: www.google.com\r\n"
10779 "Proxy-Connection: keep-alive\r\n\r\n"),
10781 MockWrite("GET / HTTP/1.1\r\n"
10782 "Host: www.google.com\r\n"
10783 "Connection: keep-alive\r\n\r\n"),
10786 MockRead data_reads1
[] = {
10787 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10789 MockRead("HTTP/1.1 200 OK\r\n"),
10790 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10791 MockRead("Content-Length: 100\r\n\r\n"),
10792 MockRead(SYNCHRONOUS
, OK
),
10795 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10796 data_writes1
, arraysize(data_writes1
));
10797 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10798 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10799 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10801 TestCompletionCallback callback1
;
10803 scoped_ptr
<HttpTransaction
> trans(
10804 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10806 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10809 rv
= callback1
.WaitForResult();
10811 net::CapturingNetLog::CapturedEntryList entries
;
10812 log
.GetEntries(&entries
);
10813 size_t pos
= ExpectLogContainsSomewhere(
10814 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10815 NetLog::PHASE_NONE
);
10816 ExpectLogContainsSomewhere(
10818 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10819 NetLog::PHASE_NONE
);
10821 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10822 ASSERT_TRUE(response
!= NULL
);
10824 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10825 EXPECT_EQ(200, response
->headers
->response_code());
10826 EXPECT_EQ(100, response
->headers
->GetContentLength());
10827 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10828 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10830 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10832 LoadTimingInfo load_timing_info
;
10833 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10834 TestLoadTimingNotReusedWithPac(load_timing_info
,
10835 CONNECT_TIMING_HAS_SSL_TIMES
);
10838 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10839 // while establishing the tunnel.
10840 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10841 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10842 CapturingBoundNetLog log
;
10843 session_deps_
.net_log
= log
.bound().net_log();
10844 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10846 HttpRequestInfo request
;
10847 request
.method
= "GET";
10848 request
.url
= GURL("https://www.google.com/");
10850 // Since we have proxy, should try to establish tunnel.
10851 MockWrite data_writes1
[] = {
10852 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10853 "Host: www.google.com\r\n"
10854 "Proxy-Connection: keep-alive\r\n\r\n"),
10856 MockWrite("GET / HTTP/1.1\r\n"
10857 "Host: www.google.com\r\n"
10858 "Connection: keep-alive\r\n\r\n"),
10861 MockRead data_reads1
[] = {
10862 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10863 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10864 MockRead(ASYNC
, 0, 0), // EOF
10867 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10868 data_writes1
, arraysize(data_writes1
));
10869 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10870 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10871 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10873 TestCompletionCallback callback1
;
10875 scoped_ptr
<HttpTransaction
> trans(
10876 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10878 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10881 rv
= callback1
.WaitForResult();
10882 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10883 net::CapturingNetLog::CapturedEntryList entries
;
10884 log
.GetEntries(&entries
);
10885 size_t pos
= ExpectLogContainsSomewhere(
10886 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10887 NetLog::PHASE_NONE
);
10888 ExpectLogContainsSomewhere(
10890 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10891 NetLog::PHASE_NONE
);
10894 // Test for crbug.com/55424.
10895 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10896 scoped_ptr
<SpdyFrame
> req(
10897 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10898 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10900 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10901 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10902 MockRead spdy_reads
[] = {
10903 CreateMockRead(*resp
),
10904 CreateMockRead(*data
),
10905 MockRead(ASYNC
, 0, 0),
10908 DelayedSocketData
spdy_data(
10909 1, // wait for one write to finish before reading.
10910 spdy_reads
, arraysize(spdy_reads
),
10911 spdy_writes
, arraysize(spdy_writes
));
10912 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10914 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10915 ssl
.SetNextProto(GetParam());
10916 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10918 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10920 // Set up an initial SpdySession in the pool to reuse.
10921 HostPortPair
host_port_pair("www.google.com", 443);
10922 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10923 PRIVACY_MODE_DISABLED
);
10924 base::WeakPtr
<SpdySession
> spdy_session
=
10925 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10927 HttpRequestInfo request
;
10928 request
.method
= "GET";
10929 request
.url
= GURL("https://www.google.com/");
10930 request
.load_flags
= 0;
10932 // This is the important line that marks this as a preconnect.
10933 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10935 scoped_ptr
<HttpTransaction
> trans(
10936 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10938 TestCompletionCallback callback
;
10939 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10940 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10941 EXPECT_EQ(OK
, callback
.WaitForResult());
10944 // Given a net error, cause that error to be returned from the first Write()
10945 // call and verify that the HttpTransaction fails with that error.
10946 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10947 int error
, IoMode mode
) {
10948 net::HttpRequestInfo request_info
;
10949 request_info
.url
= GURL("https://www.example.com/");
10950 request_info
.method
= "GET";
10951 request_info
.load_flags
= net::LOAD_NORMAL
;
10953 SSLSocketDataProvider
ssl_data(mode
, OK
);
10954 net::MockWrite data_writes
[] = {
10955 net::MockWrite(mode
, error
),
10957 net::StaticSocketDataProvider
data(NULL
, 0,
10958 data_writes
, arraysize(data_writes
));
10959 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10960 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10962 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10963 scoped_ptr
<HttpTransaction
> trans(
10964 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10966 TestCompletionCallback callback
;
10967 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10968 if (rv
== net::ERR_IO_PENDING
)
10969 rv
= callback
.WaitForResult();
10970 ASSERT_EQ(error
, rv
);
10973 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10974 // Just check a grab bag of cert errors.
10975 static const int kErrors
[] = {
10976 ERR_CERT_COMMON_NAME_INVALID
,
10977 ERR_CERT_AUTHORITY_INVALID
,
10978 ERR_CERT_DATE_INVALID
,
10980 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10981 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10982 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10986 // Ensure that a client certificate is removed from the SSL client auth
10988 // 1) No proxy is involved.
10989 // 2) TLS False Start is disabled.
10990 // 3) The initial TLS handshake requests a client certificate.
10991 // 4) The client supplies an invalid/unacceptable certificate.
10992 TEST_P(HttpNetworkTransactionTest
,
10993 ClientAuthCertCache_Direct_NoFalseStart
) {
10994 net::HttpRequestInfo request_info
;
10995 request_info
.url
= GURL("https://www.example.com/");
10996 request_info
.method
= "GET";
10997 request_info
.load_flags
= net::LOAD_NORMAL
;
10999 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11000 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11002 // [ssl_]data1 contains the data for the first SSL handshake. When a
11003 // CertificateRequest is received for the first time, the handshake will
11004 // be aborted to allow the caller to provide a certificate.
11005 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11006 ssl_data1
.cert_request_info
= cert_request
.get();
11007 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11008 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11009 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11011 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11012 // False Start is not being used, the result of the SSL handshake will be
11013 // returned as part of the SSLClientSocket::Connect() call. This test
11014 // matches the result of a server sending a handshake_failure alert,
11015 // rather than a Finished message, because it requires a client
11016 // certificate and none was supplied.
11017 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
11018 ssl_data2
.cert_request_info
= cert_request
.get();
11019 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11020 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11021 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11023 // [ssl_]data3 contains the data for the third SSL handshake. When a
11024 // connection to a server fails during an SSL handshake,
11025 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11026 // connection was attempted with TLSv1.1. This is transparent to the caller
11027 // of the HttpNetworkTransaction. Because this test failure is due to
11028 // requiring a client certificate, this fallback handshake should also
11030 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
11031 ssl_data3
.cert_request_info
= cert_request
.get();
11032 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11033 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11034 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11036 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11037 // connection to a server fails during an SSL handshake,
11038 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
11039 // connection was attempted with TLSv1. This is transparent to the caller
11040 // of the HttpNetworkTransaction. Because this test failure is due to
11041 // requiring a client certificate, this fallback handshake should also
11043 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
11044 ssl_data4
.cert_request_info
= cert_request
.get();
11045 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11046 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11047 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11049 // Need one more if TLSv1.2 is enabled.
11050 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
11051 ssl_data5
.cert_request_info
= cert_request
.get();
11052 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11053 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
11054 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11056 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11057 scoped_ptr
<HttpTransaction
> trans(
11058 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11060 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11061 TestCompletionCallback callback
;
11062 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
11063 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
11065 // Complete the SSL handshake, which should abort due to requiring a
11066 // client certificate.
11067 rv
= callback
.WaitForResult();
11068 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11070 // Indicate that no certificate should be supplied. From the perspective
11071 // of SSLClientCertCache, NULL is just as meaningful as a real
11072 // certificate, so this is the same as supply a
11073 // legitimate-but-unacceptable certificate.
11074 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11075 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
11077 // Ensure the certificate was added to the client auth cache before
11078 // allowing the connection to continue restarting.
11079 scoped_refptr
<X509Certificate
> client_cert
;
11080 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11081 HostPortPair("www.example.com", 443), &client_cert
));
11082 ASSERT_EQ(NULL
, client_cert
.get());
11084 // Restart the handshake. This will consume ssl_data2, which fails, and
11085 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11086 // The result code is checked against what ssl_data4 should return.
11087 rv
= callback
.WaitForResult();
11088 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
11090 // Ensure that the client certificate is removed from the cache on a
11091 // handshake failure.
11092 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11093 HostPortPair("www.example.com", 443), &client_cert
));
11096 // Ensure that a client certificate is removed from the SSL client auth
11098 // 1) No proxy is involved.
11099 // 2) TLS False Start is enabled.
11100 // 3) The initial TLS handshake requests a client certificate.
11101 // 4) The client supplies an invalid/unacceptable certificate.
11102 TEST_P(HttpNetworkTransactionTest
,
11103 ClientAuthCertCache_Direct_FalseStart
) {
11104 net::HttpRequestInfo request_info
;
11105 request_info
.url
= GURL("https://www.example.com/");
11106 request_info
.method
= "GET";
11107 request_info
.load_flags
= net::LOAD_NORMAL
;
11109 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11110 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11112 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11113 // return successfully after reading up to the peer's Certificate message.
11114 // This is to allow the caller to call SSLClientSocket::Write(), which can
11115 // enqueue application data to be sent in the same packet as the
11116 // ChangeCipherSpec and Finished messages.
11117 // The actual handshake will be finished when SSLClientSocket::Read() is
11118 // called, which expects to process the peer's ChangeCipherSpec and
11119 // Finished messages. If there was an error negotiating with the peer,
11120 // such as due to the peer requiring a client certificate when none was
11121 // supplied, the alert sent by the peer won't be processed until Read() is
11124 // Like the non-False Start case, when a client certificate is requested by
11125 // the peer, the handshake is aborted during the Connect() call.
11126 // [ssl_]data1 represents the initial SSL handshake with the peer.
11127 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11128 ssl_data1
.cert_request_info
= cert_request
.get();
11129 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11130 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11131 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11133 // When a client certificate is supplied, Connect() will not be aborted
11134 // when the peer requests the certificate. Instead, the handshake will
11135 // artificially succeed, allowing the caller to write the HTTP request to
11136 // the socket. The handshake messages are not processed until Read() is
11137 // called, which then detects that the handshake was aborted, due to the
11138 // peer sending a handshake_failure because it requires a client
11140 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
11141 ssl_data2
.cert_request_info
= cert_request
.get();
11142 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11143 net::MockRead data2_reads
[] = {
11144 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
11146 net::StaticSocketDataProvider
data2(
11147 data2_reads
, arraysize(data2_reads
), NULL
, 0);
11148 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11150 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11151 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11152 // TLSv1. It has the same behaviour as [ssl_]data2.
11153 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
11154 ssl_data3
.cert_request_info
= cert_request
.get();
11155 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11156 net::StaticSocketDataProvider
data3(
11157 data2_reads
, arraysize(data2_reads
), NULL
, 0);
11158 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11160 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11161 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11162 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
11163 ssl_data4
.cert_request_info
= cert_request
.get();
11164 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11165 net::StaticSocketDataProvider
data4(
11166 data2_reads
, arraysize(data2_reads
), NULL
, 0);
11167 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11169 // Need one more if TLSv1.2 is enabled.
11170 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
11171 ssl_data5
.cert_request_info
= cert_request
.get();
11172 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11173 net::StaticSocketDataProvider
data5(
11174 data2_reads
, arraysize(data2_reads
), NULL
, 0);
11175 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11177 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11178 scoped_ptr
<HttpTransaction
> trans(
11179 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11181 // Begin the initial SSL handshake.
11182 TestCompletionCallback callback
;
11183 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
11184 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
11186 // Complete the SSL handshake, which should abort due to requiring a
11187 // client certificate.
11188 rv
= callback
.WaitForResult();
11189 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11191 // Indicate that no certificate should be supplied. From the perspective
11192 // of SSLClientCertCache, NULL is just as meaningful as a real
11193 // certificate, so this is the same as supply a
11194 // legitimate-but-unacceptable certificate.
11195 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11196 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
11198 // Ensure the certificate was added to the client auth cache before
11199 // allowing the connection to continue restarting.
11200 scoped_refptr
<X509Certificate
> client_cert
;
11201 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11202 HostPortPair("www.example.com", 443), &client_cert
));
11203 ASSERT_EQ(NULL
, client_cert
.get());
11205 // Restart the handshake. This will consume ssl_data2, which fails, and
11206 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11207 // The result code is checked against what ssl_data4 should return.
11208 rv
= callback
.WaitForResult();
11209 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
11211 // Ensure that the client certificate is removed from the cache on a
11212 // handshake failure.
11213 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11214 HostPortPair("www.example.com", 443), &client_cert
));
11217 // Ensure that a client certificate is removed from the SSL client auth
11219 // 1) An HTTPS proxy is involved.
11220 // 3) The HTTPS proxy requests a client certificate.
11221 // 4) The client supplies an invalid/unacceptable certificate for the
11223 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11224 // then for connecting to an HTTP endpoint.
11225 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11226 session_deps_
.proxy_service
.reset(
11227 ProxyService::CreateFixed("https://proxy:70"));
11228 CapturingBoundNetLog log
;
11229 session_deps_
.net_log
= log
.bound().net_log();
11231 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11232 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11234 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11235 // [ssl_]data[1-3]. Rather than represending the endpoint
11236 // (www.example.com:443), they represent failures with the HTTPS proxy
11238 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11239 ssl_data1
.cert_request_info
= cert_request
.get();
11240 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11241 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11242 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11244 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
11245 ssl_data2
.cert_request_info
= cert_request
.get();
11246 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11247 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11248 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11250 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11252 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
11253 ssl_data3
.cert_request_info
= cert_request
.get();
11254 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11255 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11256 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11259 net::HttpRequestInfo requests
[2];
11260 requests
[0].url
= GURL("https://www.example.com/");
11261 requests
[0].method
= "GET";
11262 requests
[0].load_flags
= net::LOAD_NORMAL
;
11264 requests
[1].url
= GURL("http://www.example.com/");
11265 requests
[1].method
= "GET";
11266 requests
[1].load_flags
= net::LOAD_NORMAL
;
11268 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11269 session_deps_
.socket_factory
->ResetNextMockIndexes();
11270 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11271 scoped_ptr
<HttpNetworkTransaction
> trans(
11272 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11274 // Begin the SSL handshake with the proxy.
11275 TestCompletionCallback callback
;
11276 int rv
= trans
->Start(
11277 &requests
[i
], callback
.callback(), net::BoundNetLog());
11278 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
11280 // Complete the SSL handshake, which should abort due to requiring a
11281 // client certificate.
11282 rv
= callback
.WaitForResult();
11283 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11285 // Indicate that no certificate should be supplied. From the perspective
11286 // of SSLClientCertCache, NULL is just as meaningful as a real
11287 // certificate, so this is the same as supply a
11288 // legitimate-but-unacceptable certificate.
11289 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11290 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
11292 // Ensure the certificate was added to the client auth cache before
11293 // allowing the connection to continue restarting.
11294 scoped_refptr
<X509Certificate
> client_cert
;
11295 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11296 HostPortPair("proxy", 70), &client_cert
));
11297 ASSERT_EQ(NULL
, client_cert
.get());
11298 // Ensure the certificate was NOT cached for the endpoint. This only
11299 // applies to HTTPS requests, but is fine to check for HTTP requests.
11300 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11301 HostPortPair("www.example.com", 443), &client_cert
));
11303 // Restart the handshake. This will consume ssl_data2, which fails, and
11304 // then consume ssl_data3, which should also fail. The result code is
11305 // checked against what ssl_data3 should return.
11306 rv
= callback
.WaitForResult();
11307 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
11309 // Now that the new handshake has failed, ensure that the client
11310 // certificate was removed from the client auth cache.
11311 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11312 HostPortPair("proxy", 70), &client_cert
));
11313 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11314 HostPortPair("www.example.com", 443), &client_cert
));
11318 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11319 // TEST_P is a macro that expands directly to code that stringizes the
11320 // arguments. As a result, macros passed as parameters (such as prefix
11321 // or test_case_name) will not be expanded by the preprocessor. To
11322 // work around this, indirect the macro for TEST_P, so that the
11323 // pre-processor will expand macros such as MAYBE_test_name before
11324 // instantiating the test.
11325 #define WRAPPED_TEST_P(test_case_name, test_name) \
11326 TEST_P(test_case_name, test_name)
11328 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11329 #if defined(OS_WIN)
11330 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11332 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11334 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
11335 session_deps_
.use_alternate_protocols
= true;
11336 session_deps_
.next_protos
= SpdyNextProtos();
11338 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11339 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11340 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11341 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11342 pool_peer
.DisableDomainAuthenticationVerification();
11344 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11345 ssl
.SetNextProto(GetParam());
11346 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11348 scoped_ptr
<SpdyFrame
> host1_req(
11349 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11350 scoped_ptr
<SpdyFrame
> host2_req(
11351 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11352 MockWrite spdy_writes
[] = {
11353 CreateMockWrite(*host1_req
, 1),
11354 CreateMockWrite(*host2_req
, 4),
11356 scoped_ptr
<SpdyFrame
> host1_resp(
11357 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11358 scoped_ptr
<SpdyFrame
> host1_resp_body(
11359 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11360 scoped_ptr
<SpdyFrame
> host2_resp(
11361 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11362 scoped_ptr
<SpdyFrame
> host2_resp_body(
11363 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11364 MockRead spdy_reads
[] = {
11365 CreateMockRead(*host1_resp
, 2),
11366 CreateMockRead(*host1_resp_body
, 3),
11367 CreateMockRead(*host2_resp
, 5),
11368 CreateMockRead(*host2_resp_body
, 6),
11369 MockRead(ASYNC
, 0, 7),
11372 IPAddressNumber ip
;
11373 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11374 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11375 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11376 OrderedSocketData
spdy_data(
11378 spdy_reads
, arraysize(spdy_reads
),
11379 spdy_writes
, arraysize(spdy_writes
));
11380 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11382 TestCompletionCallback callback
;
11383 HttpRequestInfo request1
;
11384 request1
.method
= "GET";
11385 request1
.url
= GURL("https://www.google.com/");
11386 request1
.load_flags
= 0;
11387 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11389 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11390 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11391 EXPECT_EQ(OK
, callback
.WaitForResult());
11393 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11394 ASSERT_TRUE(response
!= NULL
);
11395 ASSERT_TRUE(response
->headers
.get() != NULL
);
11396 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11398 std::string response_data
;
11399 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11400 EXPECT_EQ("hello!", response_data
);
11402 // Preload www.gmail.com into HostCache.
11403 HostPortPair
host_port("www.gmail.com", 443);
11404 HostResolver::RequestInfo
resolve_info(host_port
);
11405 AddressList ignored
;
11406 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11409 callback
.callback(),
11412 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11413 rv
= callback
.WaitForResult();
11416 HttpRequestInfo request2
;
11417 request2
.method
= "GET";
11418 request2
.url
= GURL("https://www.gmail.com/");
11419 request2
.load_flags
= 0;
11420 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11422 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11424 EXPECT_EQ(OK
, callback
.WaitForResult());
11426 response
= trans2
.GetResponseInfo();
11427 ASSERT_TRUE(response
!= NULL
);
11428 ASSERT_TRUE(response
->headers
.get() != NULL
);
11429 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11430 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11431 EXPECT_TRUE(response
->was_npn_negotiated
);
11432 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11433 EXPECT_EQ("hello!", response_data
);
11435 #undef MAYBE_UseIPConnectionPooling
11437 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11438 session_deps_
.use_alternate_protocols
= true;
11439 session_deps_
.next_protos
= SpdyNextProtos();
11441 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11442 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11443 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11444 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11445 pool_peer
.DisableDomainAuthenticationVerification();
11447 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11448 ssl
.SetNextProto(GetParam());
11449 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11451 scoped_ptr
<SpdyFrame
> host1_req(
11452 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11453 scoped_ptr
<SpdyFrame
> host2_req(
11454 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11455 MockWrite spdy_writes
[] = {
11456 CreateMockWrite(*host1_req
, 1),
11457 CreateMockWrite(*host2_req
, 4),
11459 scoped_ptr
<SpdyFrame
> host1_resp(
11460 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11461 scoped_ptr
<SpdyFrame
> host1_resp_body(
11462 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11463 scoped_ptr
<SpdyFrame
> host2_resp(
11464 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11465 scoped_ptr
<SpdyFrame
> host2_resp_body(
11466 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11467 MockRead spdy_reads
[] = {
11468 CreateMockRead(*host1_resp
, 2),
11469 CreateMockRead(*host1_resp_body
, 3),
11470 CreateMockRead(*host2_resp
, 5),
11471 CreateMockRead(*host2_resp_body
, 6),
11472 MockRead(ASYNC
, 0, 7),
11475 IPAddressNumber ip
;
11476 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11477 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11478 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11479 OrderedSocketData
spdy_data(
11481 spdy_reads
, arraysize(spdy_reads
),
11482 spdy_writes
, arraysize(spdy_writes
));
11483 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11485 TestCompletionCallback callback
;
11486 HttpRequestInfo request1
;
11487 request1
.method
= "GET";
11488 request1
.url
= GURL("https://www.google.com/");
11489 request1
.load_flags
= 0;
11490 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11492 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11493 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11494 EXPECT_EQ(OK
, callback
.WaitForResult());
11496 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11497 ASSERT_TRUE(response
!= NULL
);
11498 ASSERT_TRUE(response
->headers
.get() != NULL
);
11499 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11501 std::string response_data
;
11502 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11503 EXPECT_EQ("hello!", response_data
);
11505 HttpRequestInfo request2
;
11506 request2
.method
= "GET";
11507 request2
.url
= GURL("https://www.gmail.com/");
11508 request2
.load_flags
= 0;
11509 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11511 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11512 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11513 EXPECT_EQ(OK
, callback
.WaitForResult());
11515 response
= trans2
.GetResponseInfo();
11516 ASSERT_TRUE(response
!= NULL
);
11517 ASSERT_TRUE(response
->headers
.get() != NULL
);
11518 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11519 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11520 EXPECT_TRUE(response
->was_npn_negotiated
);
11521 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11522 EXPECT_EQ("hello!", response_data
);
11525 class OneTimeCachingHostResolver
: public net::HostResolver
{
11527 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11528 : host_port_(host_port
) {}
11529 ~OneTimeCachingHostResolver() override
{}
11531 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11533 // HostResolver methods:
11534 int Resolve(const RequestInfo
& info
,
11535 RequestPriority priority
,
11536 AddressList
* addresses
,
11537 const CompletionCallback
& callback
,
11538 RequestHandle
* out_req
,
11539 const BoundNetLog
& net_log
) override
{
11540 return host_resolver_
.Resolve(
11541 info
, priority
, addresses
, callback
, out_req
, net_log
);
11544 int ResolveFromCache(const RequestInfo
& info
,
11545 AddressList
* addresses
,
11546 const BoundNetLog
& net_log
) override
{
11547 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11548 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11549 host_resolver_
.GetHostCache()->clear();
11553 void CancelRequest(RequestHandle req
) override
{
11554 host_resolver_
.CancelRequest(req
);
11557 MockCachingHostResolver
* GetMockHostResolver() {
11558 return &host_resolver_
;
11562 MockCachingHostResolver host_resolver_
;
11563 const HostPortPair host_port_
;
11566 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11567 #if defined(OS_WIN)
11568 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11569 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11571 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11572 UseIPConnectionPoolingWithHostCacheExpiration
11574 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11575 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11576 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11577 // prefix doesn't work with parametrized tests).
11578 #if defined(OS_WIN)
11581 session_deps_
.use_alternate_protocols
= true;
11582 session_deps_
.next_protos
= SpdyNextProtos();
11584 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11585 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11586 HttpNetworkSession::Params params
=
11587 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11588 params
.host_resolver
= &host_resolver
;
11589 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11590 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11591 pool_peer
.DisableDomainAuthenticationVerification();
11593 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11594 ssl
.SetNextProto(GetParam());
11595 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11597 scoped_ptr
<SpdyFrame
> host1_req(
11598 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11599 scoped_ptr
<SpdyFrame
> host2_req(
11600 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11601 MockWrite spdy_writes
[] = {
11602 CreateMockWrite(*host1_req
, 1),
11603 CreateMockWrite(*host2_req
, 4),
11605 scoped_ptr
<SpdyFrame
> host1_resp(
11606 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11607 scoped_ptr
<SpdyFrame
> host1_resp_body(
11608 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11609 scoped_ptr
<SpdyFrame
> host2_resp(
11610 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11611 scoped_ptr
<SpdyFrame
> host2_resp_body(
11612 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11613 MockRead spdy_reads
[] = {
11614 CreateMockRead(*host1_resp
, 2),
11615 CreateMockRead(*host1_resp_body
, 3),
11616 CreateMockRead(*host2_resp
, 5),
11617 CreateMockRead(*host2_resp_body
, 6),
11618 MockRead(ASYNC
, 0, 7),
11621 IPAddressNumber ip
;
11622 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11623 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11624 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11625 OrderedSocketData
spdy_data(
11627 spdy_reads
, arraysize(spdy_reads
),
11628 spdy_writes
, arraysize(spdy_writes
));
11629 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11631 TestCompletionCallback callback
;
11632 HttpRequestInfo request1
;
11633 request1
.method
= "GET";
11634 request1
.url
= GURL("https://www.google.com/");
11635 request1
.load_flags
= 0;
11636 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11638 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11640 EXPECT_EQ(OK
, callback
.WaitForResult());
11642 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11643 ASSERT_TRUE(response
!= NULL
);
11644 ASSERT_TRUE(response
->headers
.get() != NULL
);
11645 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11647 std::string response_data
;
11648 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11649 EXPECT_EQ("hello!", response_data
);
11651 // Preload cache entries into HostCache.
11652 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11653 AddressList ignored
;
11654 rv
= host_resolver
.Resolve(resolve_info
,
11657 callback
.callback(),
11660 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11661 rv
= callback
.WaitForResult();
11664 HttpRequestInfo request2
;
11665 request2
.method
= "GET";
11666 request2
.url
= GURL("https://www.gmail.com/");
11667 request2
.load_flags
= 0;
11668 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11670 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11672 EXPECT_EQ(OK
, callback
.WaitForResult());
11674 response
= trans2
.GetResponseInfo();
11675 ASSERT_TRUE(response
!= NULL
);
11676 ASSERT_TRUE(response
->headers
.get() != NULL
);
11677 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11678 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11679 EXPECT_TRUE(response
->was_npn_negotiated
);
11680 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11681 EXPECT_EQ("hello!", response_data
);
11684 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11686 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11687 const std::string https_url
= "https://www.google.com:8080/";
11688 const std::string http_url
= "http://www.google.com:8080/";
11690 // SPDY GET for HTTPS URL
11691 scoped_ptr
<SpdyFrame
> req1(
11692 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11694 MockWrite writes1
[] = {
11695 CreateMockWrite(*req1
, 0),
11698 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11699 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11700 MockRead reads1
[] = {
11701 CreateMockRead(*resp1
, 1),
11702 CreateMockRead(*body1
, 2),
11703 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11706 DelayedSocketData
data1(
11707 1, reads1
, arraysize(reads1
),
11708 writes1
, arraysize(writes1
));
11709 MockConnect
connect_data1(ASYNC
, OK
);
11710 data1
.set_connect_data(connect_data1
);
11712 // HTTP GET for the HTTP URL
11713 MockWrite writes2
[] = {
11714 MockWrite(ASYNC
, 4,
11715 "GET / HTTP/1.1\r\n"
11716 "Host: www.google.com:8080\r\n"
11717 "Connection: keep-alive\r\n\r\n"),
11720 MockRead reads2
[] = {
11721 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11722 MockRead(ASYNC
, 6, "hello"),
11723 MockRead(ASYNC
, 7, OK
),
11726 DelayedSocketData
data2(
11727 1, reads2
, arraysize(reads2
),
11728 writes2
, arraysize(writes2
));
11730 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11731 ssl
.SetNextProto(GetParam());
11732 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11733 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11734 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11736 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11738 // Start the first transaction to set up the SpdySession
11739 HttpRequestInfo request1
;
11740 request1
.method
= "GET";
11741 request1
.url
= GURL(https_url
);
11742 request1
.load_flags
= 0;
11743 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11744 TestCompletionCallback callback1
;
11745 EXPECT_EQ(ERR_IO_PENDING
,
11746 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11747 base::MessageLoop::current()->RunUntilIdle();
11749 EXPECT_EQ(OK
, callback1
.WaitForResult());
11750 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11752 // Now, start the HTTP request
11753 HttpRequestInfo request2
;
11754 request2
.method
= "GET";
11755 request2
.url
= GURL(http_url
);
11756 request2
.load_flags
= 0;
11757 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11758 TestCompletionCallback callback2
;
11759 EXPECT_EQ(ERR_IO_PENDING
,
11760 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11761 base::MessageLoop::current()->RunUntilIdle();
11763 EXPECT_EQ(OK
, callback2
.WaitForResult());
11764 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11767 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11768 const std::string https_url
= "https://www.google.com:8080/";
11769 const std::string http_url
= "http://www.google.com:8080/";
11771 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11772 const HostPortPair
host_port_pair("www.google.com", 8080);
11773 scoped_ptr
<SpdyFrame
> connect(
11774 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
11775 scoped_ptr
<SpdyFrame
> req1(
11776 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11777 scoped_ptr
<SpdyFrame
> wrapped_req1(
11778 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11780 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11781 SpdyHeaderBlock req2_block
;
11782 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11783 req2_block
[spdy_util_
.GetPathKey()] = "/";
11784 req2_block
[spdy_util_
.GetHostKey()] = "www.google.com:8080";
11785 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11786 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11787 scoped_ptr
<SpdyFrame
> req2(
11788 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11790 MockWrite writes1
[] = {
11791 CreateMockWrite(*connect
, 0),
11792 CreateMockWrite(*wrapped_req1
, 2),
11793 CreateMockWrite(*req2
, 5),
11796 scoped_ptr
<SpdyFrame
> conn_resp(
11797 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11798 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11799 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11800 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11801 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11802 scoped_ptr
<SpdyFrame
> wrapped_body1(
11803 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11804 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11805 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11806 MockRead reads1
[] = {
11807 CreateMockRead(*conn_resp
, 1),
11808 CreateMockRead(*wrapped_resp1
, 3),
11809 CreateMockRead(*wrapped_body1
, 4),
11810 CreateMockRead(*resp2
, 6),
11811 CreateMockRead(*body2
, 7),
11812 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11815 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11816 writes1
, arraysize(writes1
));
11817 MockConnect
connect_data1(ASYNC
, OK
);
11818 data1
.set_connect_data(connect_data1
);
11820 session_deps_
.proxy_service
.reset(
11821 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11822 CapturingNetLog log
;
11823 session_deps_
.net_log
= &log
;
11824 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11825 ssl1
.SetNextProto(GetParam());
11826 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11827 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11828 ssl2
.SetNextProto(GetParam());
11829 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11830 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11832 scoped_refptr
<HttpNetworkSession
> session(
11833 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11835 // Start the first transaction to set up the SpdySession
11836 HttpRequestInfo request1
;
11837 request1
.method
= "GET";
11838 request1
.url
= GURL(https_url
);
11839 request1
.load_flags
= 0;
11840 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11841 TestCompletionCallback callback1
;
11842 EXPECT_EQ(ERR_IO_PENDING
,
11843 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11844 base::MessageLoop::current()->RunUntilIdle();
11847 EXPECT_EQ(OK
, callback1
.WaitForResult());
11848 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11850 LoadTimingInfo load_timing_info1
;
11851 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11852 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11853 CONNECT_TIMING_HAS_SSL_TIMES
);
11855 // Now, start the HTTP request
11856 HttpRequestInfo request2
;
11857 request2
.method
= "GET";
11858 request2
.url
= GURL(http_url
);
11859 request2
.load_flags
= 0;
11860 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11861 TestCompletionCallback callback2
;
11862 EXPECT_EQ(ERR_IO_PENDING
,
11863 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11864 base::MessageLoop::current()->RunUntilIdle();
11867 EXPECT_EQ(OK
, callback2
.WaitForResult());
11868 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11870 LoadTimingInfo load_timing_info2
;
11871 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11872 // The established SPDY sessions is considered reused by the HTTP request.
11873 TestLoadTimingReusedWithPac(load_timing_info2
);
11874 // HTTP requests over a SPDY session should have a different connection
11875 // socket_log_id than requests over a tunnel.
11876 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11879 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11880 session_deps_
.force_spdy_always
= true;
11881 const std::string https_url
= "https://www.google.com:8080/";
11882 const std::string http_url
= "http://www.google.com:8080/";
11884 // SPDY GET for HTTPS URL
11885 scoped_ptr
<SpdyFrame
> req1(
11886 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11887 // SPDY GET for the HTTP URL
11888 scoped_ptr
<SpdyFrame
> req2(
11889 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11891 MockWrite writes
[] = {
11892 CreateMockWrite(*req1
, 1),
11893 CreateMockWrite(*req2
, 4),
11896 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11897 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11898 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11899 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11900 MockRead reads
[] = {
11901 CreateMockRead(*resp1
, 2),
11902 CreateMockRead(*body1
, 3),
11903 CreateMockRead(*resp2
, 5),
11904 CreateMockRead(*body2
, 6),
11905 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11908 OrderedSocketData
data(reads
, arraysize(reads
),
11909 writes
, arraysize(writes
));
11911 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11912 ssl
.SetNextProto(GetParam());
11913 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11914 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11916 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11918 // Start the first transaction to set up the SpdySession
11919 HttpRequestInfo request1
;
11920 request1
.method
= "GET";
11921 request1
.url
= GURL(https_url
);
11922 request1
.load_flags
= 0;
11923 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11924 TestCompletionCallback callback1
;
11925 EXPECT_EQ(ERR_IO_PENDING
,
11926 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11927 base::MessageLoop::current()->RunUntilIdle();
11929 EXPECT_EQ(OK
, callback1
.WaitForResult());
11930 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11932 // Now, start the HTTP request
11933 HttpRequestInfo request2
;
11934 request2
.method
= "GET";
11935 request2
.url
= GURL(http_url
);
11936 request2
.load_flags
= 0;
11937 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11938 TestCompletionCallback callback2
;
11939 EXPECT_EQ(ERR_IO_PENDING
,
11940 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11941 base::MessageLoop::current()->RunUntilIdle();
11943 EXPECT_EQ(OK
, callback2
.WaitForResult());
11944 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11947 // Test that in the case where we have a SPDY session to a SPDY proxy
11948 // that we do not pool other origins that resolve to the same IP when
11949 // the certificate does not match the new origin.
11950 // http://crbug.com/134690
11951 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11952 const std::string url1
= "http://www.google.com/";
11953 const std::string url2
= "https://mail.google.com/";
11954 const std::string ip_addr
= "1.2.3.4";
11956 // SPDY GET for HTTP URL (through SPDY proxy)
11957 scoped_ptr
<SpdyHeaderBlock
> headers(
11958 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11959 scoped_ptr
<SpdyFrame
> req1(
11960 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
11962 MockWrite writes1
[] = {
11963 CreateMockWrite(*req1
, 0),
11966 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11967 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11968 MockRead reads1
[] = {
11969 CreateMockRead(*resp1
, 1),
11970 CreateMockRead(*body1
, 2),
11971 MockRead(ASYNC
, OK
, 3) // EOF
11974 scoped_ptr
<DeterministicSocketData
> data1(
11975 new DeterministicSocketData(reads1
, arraysize(reads1
),
11976 writes1
, arraysize(writes1
)));
11977 IPAddressNumber ip
;
11978 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11979 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11980 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11981 data1
->set_connect_data(connect_data1
);
11983 // SPDY GET for HTTPS URL (direct)
11984 scoped_ptr
<SpdyFrame
> req2(
11985 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11987 MockWrite writes2
[] = {
11988 CreateMockWrite(*req2
, 0),
11991 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11992 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11993 MockRead reads2
[] = {
11994 CreateMockRead(*resp2
, 1),
11995 CreateMockRead(*body2
, 2),
11996 MockRead(ASYNC
, OK
, 3) // EOF
11999 scoped_ptr
<DeterministicSocketData
> data2(
12000 new DeterministicSocketData(reads2
, arraysize(reads2
),
12001 writes2
, arraysize(writes2
)));
12002 MockConnect
connect_data2(ASYNC
, OK
);
12003 data2
->set_connect_data(connect_data2
);
12005 // Set up a proxy config that sends HTTP requests to a proxy, and
12006 // all others direct.
12007 ProxyConfig proxy_config
;
12008 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12009 session_deps_
.proxy_service
.reset(new ProxyService(
12010 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12012 // Load a valid cert. Note, that this does not need to
12013 // be valid for proxy because the MockSSLClientSocket does
12014 // not actually verify it. But SpdySession will use this
12015 // to see if it is valid for the new origin
12016 base::FilePath certs_dir
= GetTestCertsDirectory();
12017 scoped_refptr
<X509Certificate
> server_cert(
12018 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
12019 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
.get());
12021 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12022 ssl1
.SetNextProto(GetParam());
12023 ssl1
.cert
= server_cert
;
12024 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12025 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12028 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12029 ssl2
.SetNextProto(GetParam());
12030 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12031 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12034 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12035 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
12036 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12038 scoped_refptr
<HttpNetworkSession
> session(
12039 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12041 // Start the first transaction to set up the SpdySession
12042 HttpRequestInfo request1
;
12043 request1
.method
= "GET";
12044 request1
.url
= GURL(url1
);
12045 request1
.load_flags
= 0;
12046 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12047 TestCompletionCallback callback1
;
12048 ASSERT_EQ(ERR_IO_PENDING
,
12049 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12052 ASSERT_TRUE(callback1
.have_result());
12053 EXPECT_EQ(OK
, callback1
.WaitForResult());
12054 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12056 // Now, start the HTTP request
12057 HttpRequestInfo request2
;
12058 request2
.method
= "GET";
12059 request2
.url
= GURL(url2
);
12060 request2
.load_flags
= 0;
12061 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12062 TestCompletionCallback callback2
;
12063 EXPECT_EQ(ERR_IO_PENDING
,
12064 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12065 base::MessageLoop::current()->RunUntilIdle();
12068 ASSERT_TRUE(callback2
.have_result());
12069 EXPECT_EQ(OK
, callback2
.WaitForResult());
12070 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12073 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12074 // error) in SPDY session, removes the socket from pool and closes the SPDY
12075 // session. Verify that new url's from the same HttpNetworkSession (and a new
12076 // SpdySession) do work. http://crbug.com/224701
12077 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12078 const std::string https_url
= "https://www.google.com/";
12080 MockRead reads1
[] = {
12081 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12084 scoped_ptr
<DeterministicSocketData
> data1(
12085 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
12088 scoped_ptr
<SpdyFrame
> req2(
12089 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12090 MockWrite writes2
[] = {
12091 CreateMockWrite(*req2
, 0),
12094 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12095 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12096 MockRead reads2
[] = {
12097 CreateMockRead(*resp2
, 1),
12098 CreateMockRead(*body2
, 2),
12099 MockRead(ASYNC
, OK
, 3) // EOF
12102 scoped_ptr
<DeterministicSocketData
> data2(
12103 new DeterministicSocketData(reads2
, arraysize(reads2
),
12104 writes2
, arraysize(writes2
)));
12106 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12107 ssl1
.SetNextProto(GetParam());
12108 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12109 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12112 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12113 ssl2
.SetNextProto(GetParam());
12114 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12115 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12118 scoped_refptr
<HttpNetworkSession
> session(
12119 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12121 // Start the first transaction to set up the SpdySession and verify that
12122 // connection was closed.
12123 HttpRequestInfo request1
;
12124 request1
.method
= "GET";
12125 request1
.url
= GURL(https_url
);
12126 request1
.load_flags
= 0;
12127 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12128 TestCompletionCallback callback1
;
12129 EXPECT_EQ(ERR_IO_PENDING
,
12130 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12131 base::MessageLoop::current()->RunUntilIdle();
12132 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12134 // Now, start the second request and make sure it succeeds.
12135 HttpRequestInfo request2
;
12136 request2
.method
= "GET";
12137 request2
.url
= GURL(https_url
);
12138 request2
.load_flags
= 0;
12139 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12140 TestCompletionCallback callback2
;
12141 EXPECT_EQ(ERR_IO_PENDING
,
12142 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12143 base::MessageLoop::current()->RunUntilIdle();
12146 ASSERT_TRUE(callback2
.have_result());
12147 EXPECT_EQ(OK
, callback2
.WaitForResult());
12148 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12151 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12152 session_deps_
.next_protos
= SpdyNextProtos();
12153 ClientSocketPoolManager::set_max_sockets_per_group(
12154 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12155 ClientSocketPoolManager::set_max_sockets_per_pool(
12156 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12158 // Use two different hosts with different IPs so they don't get pooled.
12159 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12160 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12161 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12163 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12164 ssl1
.SetNextProto(GetParam());
12165 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12166 ssl2
.SetNextProto(GetParam());
12167 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12168 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12170 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12171 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12172 MockWrite spdy1_writes
[] = {
12173 CreateMockWrite(*host1_req
, 1),
12175 scoped_ptr
<SpdyFrame
> host1_resp(
12176 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12177 scoped_ptr
<SpdyFrame
> host1_resp_body(
12178 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12179 MockRead spdy1_reads
[] = {
12180 CreateMockRead(*host1_resp
, 2),
12181 CreateMockRead(*host1_resp_body
, 3),
12182 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
12185 scoped_ptr
<OrderedSocketData
> spdy1_data(
12186 new OrderedSocketData(
12187 spdy1_reads
, arraysize(spdy1_reads
),
12188 spdy1_writes
, arraysize(spdy1_writes
)));
12189 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12191 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12192 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12193 MockWrite spdy2_writes
[] = {
12194 CreateMockWrite(*host2_req
, 1),
12196 scoped_ptr
<SpdyFrame
> host2_resp(
12197 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12198 scoped_ptr
<SpdyFrame
> host2_resp_body(
12199 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12200 MockRead spdy2_reads
[] = {
12201 CreateMockRead(*host2_resp
, 2),
12202 CreateMockRead(*host2_resp_body
, 3),
12203 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
12206 scoped_ptr
<OrderedSocketData
> spdy2_data(
12207 new OrderedSocketData(
12208 spdy2_reads
, arraysize(spdy2_reads
),
12209 spdy2_writes
, arraysize(spdy2_writes
)));
12210 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12212 MockWrite http_write
[] = {
12213 MockWrite("GET / HTTP/1.1\r\n"
12214 "Host: www.a.com\r\n"
12215 "Connection: keep-alive\r\n\r\n"),
12218 MockRead http_read
[] = {
12219 MockRead("HTTP/1.1 200 OK\r\n"),
12220 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12221 MockRead("Content-Length: 6\r\n\r\n"),
12222 MockRead("hello!"),
12224 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12225 http_write
, arraysize(http_write
));
12226 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12228 HostPortPair
host_port_pair_a("www.a.com", 443);
12229 SpdySessionKey
spdy_session_key_a(
12230 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12232 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12234 TestCompletionCallback callback
;
12235 HttpRequestInfo request1
;
12236 request1
.method
= "GET";
12237 request1
.url
= GURL("https://www.a.com/");
12238 request1
.load_flags
= 0;
12239 scoped_ptr
<HttpNetworkTransaction
> trans(
12240 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12242 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12244 EXPECT_EQ(OK
, callback
.WaitForResult());
12246 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12247 ASSERT_TRUE(response
!= NULL
);
12248 ASSERT_TRUE(response
->headers
.get() != NULL
);
12249 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12250 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12251 EXPECT_TRUE(response
->was_npn_negotiated
);
12253 std::string response_data
;
12254 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12255 EXPECT_EQ("hello!", response_data
);
12258 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12260 HostPortPair
host_port_pair_b("www.b.com", 443);
12261 SpdySessionKey
spdy_session_key_b(
12262 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12264 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12265 HttpRequestInfo request2
;
12266 request2
.method
= "GET";
12267 request2
.url
= GURL("https://www.b.com/");
12268 request2
.load_flags
= 0;
12269 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12271 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12273 EXPECT_EQ(OK
, callback
.WaitForResult());
12275 response
= trans
->GetResponseInfo();
12276 ASSERT_TRUE(response
!= NULL
);
12277 ASSERT_TRUE(response
->headers
.get() != NULL
);
12278 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12279 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12280 EXPECT_TRUE(response
->was_npn_negotiated
);
12281 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12282 EXPECT_EQ("hello!", response_data
);
12284 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12286 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12288 HostPortPair
host_port_pair_a1("www.a.com", 80);
12289 SpdySessionKey
spdy_session_key_a1(
12290 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12292 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12293 HttpRequestInfo request3
;
12294 request3
.method
= "GET";
12295 request3
.url
= GURL("http://www.a.com/");
12296 request3
.load_flags
= 0;
12297 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12299 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12300 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12301 EXPECT_EQ(OK
, callback
.WaitForResult());
12303 response
= trans
->GetResponseInfo();
12304 ASSERT_TRUE(response
!= NULL
);
12305 ASSERT_TRUE(response
->headers
.get() != NULL
);
12306 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12307 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12308 EXPECT_FALSE(response
->was_npn_negotiated
);
12309 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12310 EXPECT_EQ("hello!", response_data
);
12312 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12314 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12317 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12318 HttpRequestInfo request
;
12319 request
.method
= "GET";
12320 request
.url
= GURL("http://www.google.com/");
12321 request
.load_flags
= 0;
12323 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12324 scoped_ptr
<HttpTransaction
> trans(
12325 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12327 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12328 StaticSocketDataProvider data
;
12329 data
.set_connect_data(mock_connect
);
12330 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12332 TestCompletionCallback callback
;
12334 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12335 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12337 rv
= callback
.WaitForResult();
12338 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12340 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12342 // We don't care whether this succeeds or fails, but it shouldn't crash.
12343 HttpRequestHeaders request_headers
;
12344 trans
->GetFullRequestHeaders(&request_headers
);
12347 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12348 HttpRequestInfo request
;
12349 request
.method
= "GET";
12350 request
.url
= GURL("http://www.google.com/");
12351 request
.load_flags
= 0;
12353 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12354 scoped_ptr
<HttpTransaction
> trans(
12355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12357 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12358 StaticSocketDataProvider data
;
12359 data
.set_connect_data(mock_connect
);
12360 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12362 TestCompletionCallback callback
;
12364 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12365 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12367 rv
= callback
.WaitForResult();
12368 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12370 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12372 // We don't care whether this succeeds or fails, but it shouldn't crash.
12373 HttpRequestHeaders request_headers
;
12374 trans
->GetFullRequestHeaders(&request_headers
);
12377 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12378 HttpRequestInfo request
;
12379 request
.method
= "GET";
12380 request
.url
= GURL("http://www.google.com/");
12381 request
.load_flags
= 0;
12383 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12384 scoped_ptr
<HttpTransaction
> trans(
12385 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12387 MockWrite data_writes
[] = {
12388 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12390 MockRead data_reads
[] = {
12391 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12394 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12395 data_writes
, arraysize(data_writes
));
12396 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12398 TestCompletionCallback callback
;
12400 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12401 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12403 rv
= callback
.WaitForResult();
12404 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12406 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12408 HttpRequestHeaders request_headers
;
12409 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12410 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12413 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12414 HttpRequestInfo request
;
12415 request
.method
= "GET";
12416 request
.url
= GURL("http://www.google.com/");
12417 request
.load_flags
= 0;
12419 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12420 scoped_ptr
<HttpTransaction
> trans(
12421 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12423 MockWrite data_writes
[] = {
12424 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12426 MockRead data_reads
[] = {
12427 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12430 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12431 data_writes
, arraysize(data_writes
));
12432 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12434 TestCompletionCallback callback
;
12436 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12439 rv
= callback
.WaitForResult();
12440 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12442 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12444 HttpRequestHeaders request_headers
;
12445 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12446 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12449 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12450 HttpRequestInfo request
;
12451 request
.method
= "GET";
12452 request
.url
= GURL("http://www.google.com/");
12453 request
.load_flags
= 0;
12455 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12456 scoped_ptr
<HttpTransaction
> trans(
12457 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12459 MockWrite data_writes
[] = {
12460 MockWrite("GET / HTTP/1.1\r\n"
12461 "Host: www.google.com\r\n"
12462 "Connection: keep-alive\r\n\r\n"),
12464 MockRead data_reads
[] = {
12465 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12468 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12469 data_writes
, arraysize(data_writes
));
12470 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12472 TestCompletionCallback callback
;
12474 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12475 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12477 rv
= callback
.WaitForResult();
12478 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12480 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12482 HttpRequestHeaders request_headers
;
12483 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12484 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12487 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12488 HttpRequestInfo request
;
12489 request
.method
= "GET";
12490 request
.url
= GURL("http://www.google.com/");
12491 request
.load_flags
= 0;
12493 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12494 scoped_ptr
<HttpTransaction
> trans(
12495 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12497 MockWrite data_writes
[] = {
12498 MockWrite("GET / HTTP/1.1\r\n"
12499 "Host: www.google.com\r\n"
12500 "Connection: keep-alive\r\n\r\n"),
12502 MockRead data_reads
[] = {
12503 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12506 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12507 data_writes
, arraysize(data_writes
));
12508 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12510 TestCompletionCallback callback
;
12512 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12513 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12515 rv
= callback
.WaitForResult();
12516 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12518 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12520 HttpRequestHeaders request_headers
;
12521 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12522 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12525 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12526 HttpRequestInfo request
;
12527 request
.method
= "GET";
12528 request
.url
= GURL("http://www.google.com/");
12529 request
.load_flags
= 0;
12530 request
.extra_headers
.SetHeader("X-Foo", "bar");
12532 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12533 scoped_ptr
<HttpTransaction
> trans(
12534 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12536 MockWrite data_writes
[] = {
12537 MockWrite("GET / HTTP/1.1\r\n"
12538 "Host: www.google.com\r\n"
12539 "Connection: keep-alive\r\n"
12540 "X-Foo: bar\r\n\r\n"),
12542 MockRead data_reads
[] = {
12543 MockRead("HTTP/1.1 200 OK\r\n"
12544 "Content-Length: 5\r\n\r\n"
12546 MockRead(ASYNC
, ERR_UNEXPECTED
),
12549 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12550 data_writes
, arraysize(data_writes
));
12551 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12553 TestCompletionCallback callback
;
12555 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12558 rv
= callback
.WaitForResult();
12561 HttpRequestHeaders request_headers
;
12562 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12564 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12565 EXPECT_EQ("bar", foo
);
12570 // Fake HttpStream that simply records calls to SetPriority().
12571 class FakeStream
: public HttpStream
,
12572 public base::SupportsWeakPtr
<FakeStream
> {
12574 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12575 ~FakeStream() override
{}
12577 RequestPriority
priority() const { return priority_
; }
12579 int InitializeStream(const HttpRequestInfo
* request_info
,
12580 RequestPriority priority
,
12581 const BoundNetLog
& net_log
,
12582 const CompletionCallback
& callback
) override
{
12583 return ERR_IO_PENDING
;
12586 int SendRequest(const HttpRequestHeaders
& request_headers
,
12587 HttpResponseInfo
* response
,
12588 const CompletionCallback
& callback
) override
{
12590 return ERR_UNEXPECTED
;
12593 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12595 return ERR_UNEXPECTED
;
12598 int ReadResponseBody(IOBuffer
* buf
,
12600 const CompletionCallback
& callback
) override
{
12602 return ERR_UNEXPECTED
;
12605 void Close(bool not_reusable
) override
{}
12607 bool IsResponseBodyComplete() const override
{
12612 bool CanFindEndOfResponse() const override
{ return false; }
12614 bool IsConnectionReused() const override
{
12619 void SetConnectionReused() override
{ ADD_FAILURE(); }
12621 bool IsConnectionReusable() const override
{
12626 int64
GetTotalReceivedBytes() const override
{
12631 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12636 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
12638 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12642 bool IsSpdyHttpStream() const override
{
12647 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
12649 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12651 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
12653 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
12656 RequestPriority priority_
;
12658 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12661 // Fake HttpStreamRequest that simply records calls to SetPriority()
12662 // and vends FakeStreams with its current priority.
12663 class FakeStreamRequest
: public HttpStreamRequest
,
12664 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12666 FakeStreamRequest(RequestPriority priority
,
12667 HttpStreamRequest::Delegate
* delegate
)
12668 : priority_(priority
),
12669 delegate_(delegate
),
12670 websocket_stream_create_helper_(NULL
) {}
12672 FakeStreamRequest(RequestPriority priority
,
12673 HttpStreamRequest::Delegate
* delegate
,
12674 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12675 : priority_(priority
),
12676 delegate_(delegate
),
12677 websocket_stream_create_helper_(create_helper
) {}
12679 ~FakeStreamRequest() override
{}
12681 RequestPriority
priority() const { return priority_
; }
12683 const WebSocketHandshakeStreamBase::CreateHelper
*
12684 websocket_stream_create_helper() const {
12685 return websocket_stream_create_helper_
;
12688 // Create a new FakeStream and pass it to the request's
12689 // delegate. Returns a weak pointer to the FakeStream.
12690 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12691 FakeStream
* fake_stream
= new FakeStream(priority_
);
12692 // Do this before calling OnStreamReady() as OnStreamReady() may
12693 // immediately delete |fake_stream|.
12694 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12695 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12696 return weak_stream
;
12699 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
12701 return ERR_UNEXPECTED
;
12704 LoadState
GetLoadState() const override
{
12706 return LoadState();
12709 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12711 bool was_npn_negotiated() const override
{ return false; }
12713 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
12715 bool using_spdy() const override
{ return false; }
12718 RequestPriority priority_
;
12719 HttpStreamRequest::Delegate
* const delegate_
;
12720 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12722 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12725 // Fake HttpStreamFactory that vends FakeStreamRequests.
12726 class FakeStreamFactory
: public HttpStreamFactory
{
12728 FakeStreamFactory() {}
12729 ~FakeStreamFactory() override
{}
12731 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12732 // RequestStream() (which may be NULL if it was destroyed already).
12733 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12734 return last_stream_request_
;
12737 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
12738 RequestPriority priority
,
12739 const SSLConfig
& server_ssl_config
,
12740 const SSLConfig
& proxy_ssl_config
,
12741 HttpStreamRequest::Delegate
* delegate
,
12742 const BoundNetLog
& net_log
) override
{
12743 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12744 last_stream_request_
= fake_request
->AsWeakPtr();
12745 return fake_request
;
12748 HttpStreamRequest
* RequestWebSocketHandshakeStream(
12749 const HttpRequestInfo
& info
,
12750 RequestPriority priority
,
12751 const SSLConfig
& server_ssl_config
,
12752 const SSLConfig
& proxy_ssl_config
,
12753 HttpStreamRequest::Delegate
* delegate
,
12754 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12755 const BoundNetLog
& net_log
) override
{
12756 FakeStreamRequest
* fake_request
=
12757 new FakeStreamRequest(priority
, delegate
, create_helper
);
12758 last_stream_request_
= fake_request
->AsWeakPtr();
12759 return fake_request
;
12762 void PreconnectStreams(int num_streams
,
12763 const HttpRequestInfo
& info
,
12764 RequestPriority priority
,
12765 const SSLConfig
& server_ssl_config
,
12766 const SSLConfig
& proxy_ssl_config
) override
{
12770 const HostMappingRules
* GetHostMappingRules() const override
{
12776 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12778 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12781 // TODO(ricea): Maybe unify this with the one in
12782 // url_request_http_job_unittest.cc ?
12783 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
12785 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
12787 : state_(connection
.release(), using_proxy
) {}
12789 // Fake implementation of HttpStreamBase methods.
12790 // This ends up being quite "real" because this object has to really send data
12791 // on the mock socket. It might be easier to use the real implementation, but
12792 // the fact that the WebSocket code is not compiled on iOS makes that
12794 int InitializeStream(const HttpRequestInfo
* request_info
,
12795 RequestPriority priority
,
12796 const BoundNetLog
& net_log
,
12797 const CompletionCallback
& callback
) override
{
12798 state_
.Initialize(request_info
, priority
, net_log
, callback
);
12802 int SendRequest(const HttpRequestHeaders
& request_headers
,
12803 HttpResponseInfo
* response
,
12804 const CompletionCallback
& callback
) override
{
12805 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
12806 response
, callback
);
12809 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12810 return parser()->ReadResponseHeaders(callback
);
12813 int ReadResponseBody(IOBuffer
* buf
,
12815 const CompletionCallback
& callback
) override
{
12817 return ERR_IO_PENDING
;
12820 void Close(bool not_reusable
) override
{
12822 parser()->Close(true);
12825 bool IsResponseBodyComplete() const override
{
12830 bool CanFindEndOfResponse() const override
{
12831 return parser()->CanFindEndOfResponse();
12834 bool IsConnectionReused() const override
{
12838 void SetConnectionReused() override
{ NOTREACHED(); }
12840 bool IsConnectionReusable() const override
{
12845 int64
GetTotalReceivedBytes() const override
{
12850 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12855 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
12857 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12861 bool IsSpdyHttpStream() const override
{
12866 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
12868 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
12870 UploadProgress
GetUploadProgress() const override
{
12872 return UploadProgress();
12875 HttpStream
* RenewStreamForAuth() override
{
12880 // Fake implementation of WebSocketHandshakeStreamBase method(s)
12881 scoped_ptr
<WebSocketStream
> Upgrade() override
{
12883 return scoped_ptr
<WebSocketStream
>();
12887 HttpStreamParser
* parser() const { return state_
.parser(); }
12888 HttpBasicState state_
;
12890 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
12893 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12895 class FakeWebSocketStreamCreateHelper
:
12896 public WebSocketHandshakeStreamBase::CreateHelper
{
12898 WebSocketHandshakeStreamBase
* CreateBasicStream(
12899 scoped_ptr
<ClientSocketHandle
> connection
,
12900 bool using_proxy
) override
{
12901 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
12905 WebSocketHandshakeStreamBase
* CreateSpdyStream(
12906 const base::WeakPtr
<SpdySession
>& session
,
12907 bool use_relative_url
) override
{
12912 ~FakeWebSocketStreamCreateHelper() override
{}
12914 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12916 return scoped_ptr
<WebSocketStream
>();
12922 // Make sure that HttpNetworkTransaction passes on its priority to its
12923 // stream request on start.
12924 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12925 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12926 HttpNetworkSessionPeer
peer(session
);
12927 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12928 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12930 HttpNetworkTransaction
trans(LOW
, session
.get());
12932 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12934 HttpRequestInfo request
;
12935 TestCompletionCallback callback
;
12936 EXPECT_EQ(ERR_IO_PENDING
,
12937 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12939 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12940 fake_factory
->last_stream_request();
12941 ASSERT_TRUE(fake_request
!= NULL
);
12942 EXPECT_EQ(LOW
, fake_request
->priority());
12945 // Make sure that HttpNetworkTransaction passes on its priority
12946 // updates to its stream request.
12947 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12948 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12949 HttpNetworkSessionPeer
peer(session
);
12950 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12951 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12953 HttpNetworkTransaction
trans(LOW
, session
.get());
12955 HttpRequestInfo request
;
12956 TestCompletionCallback callback
;
12957 EXPECT_EQ(ERR_IO_PENDING
,
12958 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12960 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12961 fake_factory
->last_stream_request();
12962 ASSERT_TRUE(fake_request
!= NULL
);
12963 EXPECT_EQ(LOW
, fake_request
->priority());
12965 trans
.SetPriority(LOWEST
);
12966 ASSERT_TRUE(fake_request
!= NULL
);
12967 EXPECT_EQ(LOWEST
, fake_request
->priority());
12970 // Make sure that HttpNetworkTransaction passes on its priority
12971 // updates to its stream.
12972 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12973 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12974 HttpNetworkSessionPeer
peer(session
);
12975 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12976 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12978 HttpNetworkTransaction
trans(LOW
, session
.get());
12980 HttpRequestInfo request
;
12981 TestCompletionCallback callback
;
12982 EXPECT_EQ(ERR_IO_PENDING
,
12983 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12985 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12986 fake_factory
->last_stream_request();
12987 ASSERT_TRUE(fake_request
!= NULL
);
12988 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12989 ASSERT_TRUE(fake_stream
!= NULL
);
12990 EXPECT_EQ(LOW
, fake_stream
->priority());
12992 trans
.SetPriority(LOWEST
);
12993 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12996 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12997 // The same logic needs to be tested for both ws: and wss: schemes, but this
12998 // test is already parameterised on NextProto, so it uses a loop to verify
12999 // that the different schemes work.
13000 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
13001 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13002 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13003 HttpNetworkSessionPeer
peer(session
);
13004 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13005 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13006 peer
.SetHttpStreamFactoryForWebSocket(
13007 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13009 HttpNetworkTransaction
trans(LOW
, session
.get());
13010 trans
.SetWebSocketHandshakeStreamCreateHelper(
13011 &websocket_stream_create_helper
);
13013 HttpRequestInfo request
;
13014 TestCompletionCallback callback
;
13015 request
.method
= "GET";
13016 request
.url
= GURL(test_cases
[i
]);
13018 EXPECT_EQ(ERR_IO_PENDING
,
13019 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13021 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13022 fake_factory
->last_stream_request();
13023 ASSERT_TRUE(fake_request
!= NULL
);
13024 EXPECT_EQ(&websocket_stream_create_helper
,
13025 fake_request
->websocket_stream_create_helper());
13029 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13030 // if the transport socket pool is stalled on the global socket limit.
13031 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13032 ClientSocketPoolManager::set_max_sockets_per_group(
13033 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13034 ClientSocketPoolManager::set_max_sockets_per_pool(
13035 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13037 // Set up SSL request.
13039 HttpRequestInfo ssl_request
;
13040 ssl_request
.method
= "GET";
13041 ssl_request
.url
= GURL("https://www.google.com/");
13043 MockWrite ssl_writes
[] = {
13044 MockWrite("GET / HTTP/1.1\r\n"
13045 "Host: www.google.com\r\n"
13046 "Connection: keep-alive\r\n\r\n"),
13048 MockRead ssl_reads
[] = {
13049 MockRead("HTTP/1.1 200 OK\r\n"),
13050 MockRead("Content-Length: 11\r\n\r\n"),
13051 MockRead("hello world"),
13052 MockRead(SYNCHRONOUS
, OK
),
13054 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13055 ssl_writes
, arraysize(ssl_writes
));
13056 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13058 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13059 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13061 // Set up HTTP request.
13063 HttpRequestInfo http_request
;
13064 http_request
.method
= "GET";
13065 http_request
.url
= GURL("http://www.google.com/");
13067 MockWrite http_writes
[] = {
13068 MockWrite("GET / HTTP/1.1\r\n"
13069 "Host: www.google.com\r\n"
13070 "Connection: keep-alive\r\n\r\n"),
13072 MockRead http_reads
[] = {
13073 MockRead("HTTP/1.1 200 OK\r\n"),
13074 MockRead("Content-Length: 7\r\n\r\n"),
13075 MockRead("falafel"),
13076 MockRead(SYNCHRONOUS
, OK
),
13078 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13079 http_writes
, arraysize(http_writes
));
13080 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13082 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13084 // Start the SSL request.
13085 TestCompletionCallback ssl_callback
;
13086 scoped_ptr
<HttpTransaction
> ssl_trans(
13087 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13088 ASSERT_EQ(ERR_IO_PENDING
,
13089 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13092 // Start the HTTP request. Pool should stall.
13093 TestCompletionCallback http_callback
;
13094 scoped_ptr
<HttpTransaction
> http_trans(
13095 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13096 ASSERT_EQ(ERR_IO_PENDING
,
13097 http_trans
->Start(&http_request
, http_callback
.callback(),
13099 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13101 // Wait for response from SSL request.
13102 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13103 std::string response_data
;
13104 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13105 EXPECT_EQ("hello world", response_data
);
13107 // The SSL socket should automatically be closed, so the HTTP request can
13109 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13110 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13112 // The HTTP request can now complete.
13113 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13114 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13115 EXPECT_EQ("falafel", response_data
);
13117 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13120 // Tests that when a SSL connection is established but there's no corresponding
13121 // request that needs it, the new socket is closed if the transport socket pool
13122 // is stalled on the global socket limit.
13123 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13124 ClientSocketPoolManager::set_max_sockets_per_group(
13125 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13126 ClientSocketPoolManager::set_max_sockets_per_pool(
13127 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13129 // Set up an ssl request.
13131 HttpRequestInfo ssl_request
;
13132 ssl_request
.method
= "GET";
13133 ssl_request
.url
= GURL("https://www.foopy.com/");
13135 // No data will be sent on the SSL socket.
13136 StaticSocketDataProvider ssl_data
;
13137 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13139 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13140 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13142 // Set up HTTP request.
13144 HttpRequestInfo http_request
;
13145 http_request
.method
= "GET";
13146 http_request
.url
= GURL("http://www.google.com/");
13148 MockWrite http_writes
[] = {
13149 MockWrite("GET / HTTP/1.1\r\n"
13150 "Host: www.google.com\r\n"
13151 "Connection: keep-alive\r\n\r\n"),
13153 MockRead http_reads
[] = {
13154 MockRead("HTTP/1.1 200 OK\r\n"),
13155 MockRead("Content-Length: 7\r\n\r\n"),
13156 MockRead("falafel"),
13157 MockRead(SYNCHRONOUS
, OK
),
13159 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13160 http_writes
, arraysize(http_writes
));
13161 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13163 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13165 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13166 // cancelled when a normal transaction is cancelled.
13167 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13168 net::SSLConfig ssl_config
;
13169 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13170 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
13171 ssl_config
, ssl_config
);
13172 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13174 // Start the HTTP request. Pool should stall.
13175 TestCompletionCallback http_callback
;
13176 scoped_ptr
<HttpTransaction
> http_trans(
13177 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13178 ASSERT_EQ(ERR_IO_PENDING
,
13179 http_trans
->Start(&http_request
, http_callback
.callback(),
13181 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13183 // The SSL connection will automatically be closed once the connection is
13184 // established, to let the HTTP request start.
13185 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13186 std::string response_data
;
13187 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13188 EXPECT_EQ("falafel", response_data
);
13190 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13193 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13194 ScopedVector
<UploadElementReader
> element_readers
;
13195 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13196 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13198 HttpRequestInfo request
;
13199 request
.method
= "POST";
13200 request
.url
= GURL("http://www.foo.com/");
13201 request
.upload_data_stream
= &upload_data_stream
;
13202 request
.load_flags
= 0;
13204 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13205 scoped_ptr
<HttpTransaction
> trans(
13206 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13207 // Send headers successfully, but get an error while sending the body.
13208 MockWrite data_writes
[] = {
13209 MockWrite("POST / HTTP/1.1\r\n"
13210 "Host: www.foo.com\r\n"
13211 "Connection: keep-alive\r\n"
13212 "Content-Length: 3\r\n\r\n"),
13213 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13216 MockRead data_reads
[] = {
13217 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13218 MockRead("hello world"),
13219 MockRead(SYNCHRONOUS
, OK
),
13221 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13222 arraysize(data_writes
));
13223 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13225 TestCompletionCallback callback
;
13227 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13228 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13230 rv
= callback
.WaitForResult();
13233 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13234 ASSERT_TRUE(response
!= NULL
);
13236 EXPECT_TRUE(response
->headers
.get() != NULL
);
13237 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13239 std::string response_data
;
13240 rv
= ReadTransaction(trans
.get(), &response_data
);
13242 EXPECT_EQ("hello world", response_data
);
13245 // This test makes sure the retry logic doesn't trigger when reading an error
13246 // response from a server that rejected a POST with a CONNECTION_RESET.
13247 TEST_P(HttpNetworkTransactionTest
,
13248 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13249 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13250 MockWrite data_writes
[] = {
13251 MockWrite("GET / HTTP/1.1\r\n"
13252 "Host: www.foo.com\r\n"
13253 "Connection: keep-alive\r\n\r\n"),
13254 MockWrite("POST / HTTP/1.1\r\n"
13255 "Host: www.foo.com\r\n"
13256 "Connection: keep-alive\r\n"
13257 "Content-Length: 3\r\n\r\n"),
13258 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13261 MockRead data_reads
[] = {
13262 MockRead("HTTP/1.1 200 Peachy\r\n"
13263 "Content-Length: 14\r\n\r\n"),
13264 MockRead("first response"),
13265 MockRead("HTTP/1.1 400 Not OK\r\n"
13266 "Content-Length: 15\r\n\r\n"),
13267 MockRead("second response"),
13268 MockRead(SYNCHRONOUS
, OK
),
13270 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13271 arraysize(data_writes
));
13272 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13274 TestCompletionCallback callback
;
13275 HttpRequestInfo request1
;
13276 request1
.method
= "GET";
13277 request1
.url
= GURL("http://www.foo.com/");
13278 request1
.load_flags
= 0;
13280 scoped_ptr
<HttpTransaction
> trans1(
13281 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13282 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13283 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13285 rv
= callback
.WaitForResult();
13288 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13289 ASSERT_TRUE(response1
!= NULL
);
13291 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13292 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13294 std::string response_data1
;
13295 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13297 EXPECT_EQ("first response", response_data1
);
13298 // Delete the transaction to release the socket back into the socket pool.
13301 ScopedVector
<UploadElementReader
> element_readers
;
13302 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13303 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13305 HttpRequestInfo request2
;
13306 request2
.method
= "POST";
13307 request2
.url
= GURL("http://www.foo.com/");
13308 request2
.upload_data_stream
= &upload_data_stream
;
13309 request2
.load_flags
= 0;
13311 scoped_ptr
<HttpTransaction
> trans2(
13312 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13313 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13314 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13316 rv
= callback
.WaitForResult();
13319 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13320 ASSERT_TRUE(response2
!= NULL
);
13322 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13323 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13325 std::string response_data2
;
13326 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13328 EXPECT_EQ("second response", response_data2
);
13331 TEST_P(HttpNetworkTransactionTest
,
13332 PostReadsErrorResponseAfterResetPartialBodySent
) {
13333 ScopedVector
<UploadElementReader
> element_readers
;
13334 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13335 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13337 HttpRequestInfo request
;
13338 request
.method
= "POST";
13339 request
.url
= GURL("http://www.foo.com/");
13340 request
.upload_data_stream
= &upload_data_stream
;
13341 request
.load_flags
= 0;
13343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13344 scoped_ptr
<HttpTransaction
> trans(
13345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13346 // Send headers successfully, but get an error while sending the body.
13347 MockWrite data_writes
[] = {
13348 MockWrite("POST / HTTP/1.1\r\n"
13349 "Host: www.foo.com\r\n"
13350 "Connection: keep-alive\r\n"
13351 "Content-Length: 3\r\n\r\n"
13353 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13356 MockRead data_reads
[] = {
13357 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13358 MockRead("hello world"),
13359 MockRead(SYNCHRONOUS
, OK
),
13361 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13362 arraysize(data_writes
));
13363 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13365 TestCompletionCallback callback
;
13367 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13370 rv
= callback
.WaitForResult();
13373 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13374 ASSERT_TRUE(response
!= NULL
);
13376 EXPECT_TRUE(response
->headers
.get() != NULL
);
13377 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13379 std::string response_data
;
13380 rv
= ReadTransaction(trans
.get(), &response_data
);
13382 EXPECT_EQ("hello world", response_data
);
13385 // This tests the more common case than the previous test, where headers and
13386 // body are not merged into a single request.
13387 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13388 ScopedVector
<UploadElementReader
> element_readers
;
13389 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13390 ChunkedUploadDataStream
upload_data_stream(0);
13392 HttpRequestInfo request
;
13393 request
.method
= "POST";
13394 request
.url
= GURL("http://www.foo.com/");
13395 request
.upload_data_stream
= &upload_data_stream
;
13396 request
.load_flags
= 0;
13398 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13399 scoped_ptr
<HttpTransaction
> trans(
13400 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13401 // Send headers successfully, but get an error while sending the body.
13402 MockWrite data_writes
[] = {
13403 MockWrite("POST / HTTP/1.1\r\n"
13404 "Host: www.foo.com\r\n"
13405 "Connection: keep-alive\r\n"
13406 "Transfer-Encoding: chunked\r\n\r\n"),
13407 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13410 MockRead data_reads
[] = {
13411 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13412 MockRead("hello world"),
13413 MockRead(SYNCHRONOUS
, OK
),
13415 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13416 arraysize(data_writes
));
13417 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13419 TestCompletionCallback callback
;
13421 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13423 // Make sure the headers are sent before adding a chunk. This ensures that
13424 // they can't be merged with the body in a single send. Not currently
13425 // necessary since a chunked body is never merged with headers, but this makes
13426 // the test more future proof.
13427 base::RunLoop().RunUntilIdle();
13429 upload_data_stream
.AppendData("last chunk", 10, true);
13431 rv
= callback
.WaitForResult();
13434 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13435 ASSERT_TRUE(response
!= NULL
);
13437 EXPECT_TRUE(response
->headers
.get() != NULL
);
13438 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13440 std::string response_data
;
13441 rv
= ReadTransaction(trans
.get(), &response_data
);
13443 EXPECT_EQ("hello world", response_data
);
13446 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13447 ScopedVector
<UploadElementReader
> element_readers
;
13448 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13449 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13451 HttpRequestInfo request
;
13452 request
.method
= "POST";
13453 request
.url
= GURL("http://www.foo.com/");
13454 request
.upload_data_stream
= &upload_data_stream
;
13455 request
.load_flags
= 0;
13457 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13458 scoped_ptr
<HttpTransaction
> trans(
13459 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13461 MockWrite data_writes
[] = {
13462 MockWrite("POST / HTTP/1.1\r\n"
13463 "Host: www.foo.com\r\n"
13464 "Connection: keep-alive\r\n"
13465 "Content-Length: 3\r\n\r\n"),
13466 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13469 MockRead data_reads
[] = {
13470 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13471 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13472 MockRead("hello world"),
13473 MockRead(SYNCHRONOUS
, OK
),
13475 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13476 arraysize(data_writes
));
13477 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13479 TestCompletionCallback callback
;
13481 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13482 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13484 rv
= callback
.WaitForResult();
13487 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13488 ASSERT_TRUE(response
!= NULL
);
13490 EXPECT_TRUE(response
->headers
.get() != NULL
);
13491 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13493 std::string response_data
;
13494 rv
= ReadTransaction(trans
.get(), &response_data
);
13496 EXPECT_EQ("hello world", response_data
);
13499 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13500 ScopedVector
<UploadElementReader
> element_readers
;
13501 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13502 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13504 HttpRequestInfo request
;
13505 request
.method
= "POST";
13506 request
.url
= GURL("http://www.foo.com/");
13507 request
.upload_data_stream
= &upload_data_stream
;
13508 request
.load_flags
= 0;
13510 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13511 scoped_ptr
<HttpTransaction
> trans(
13512 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13513 // Send headers successfully, but get an error while sending the body.
13514 MockWrite data_writes
[] = {
13515 MockWrite("POST / HTTP/1.1\r\n"
13516 "Host: www.foo.com\r\n"
13517 "Connection: keep-alive\r\n"
13518 "Content-Length: 3\r\n\r\n"),
13519 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13522 MockRead data_reads
[] = {
13523 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13524 MockRead("hello world"),
13525 MockRead(SYNCHRONOUS
, OK
),
13527 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13528 arraysize(data_writes
));
13529 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13531 TestCompletionCallback callback
;
13533 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13534 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13536 rv
= callback
.WaitForResult();
13537 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13539 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13540 EXPECT_TRUE(response
== NULL
);
13543 TEST_P(HttpNetworkTransactionTest
,
13544 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13545 ScopedVector
<UploadElementReader
> element_readers
;
13546 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13547 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13549 HttpRequestInfo request
;
13550 request
.method
= "POST";
13551 request
.url
= GURL("http://www.foo.com/");
13552 request
.upload_data_stream
= &upload_data_stream
;
13553 request
.load_flags
= 0;
13555 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13556 scoped_ptr
<HttpTransaction
> trans(
13557 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13558 // Send headers successfully, but get an error while sending the body.
13559 MockWrite data_writes
[] = {
13560 MockWrite("POST / HTTP/1.1\r\n"
13561 "Host: www.foo.com\r\n"
13562 "Connection: keep-alive\r\n"
13563 "Content-Length: 3\r\n\r\n"),
13564 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13567 MockRead data_reads
[] = {
13568 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13569 MockRead("HTTP/1.0 302 Redirect\r\n"),
13570 MockRead("Location: http://somewhere-else.com/\r\n"),
13571 MockRead("Content-Length: 0\r\n\r\n"),
13572 MockRead(SYNCHRONOUS
, OK
),
13574 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13575 arraysize(data_writes
));
13576 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13578 TestCompletionCallback callback
;
13580 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13581 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13583 rv
= callback
.WaitForResult();
13584 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13586 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13587 EXPECT_TRUE(response
== NULL
);
13590 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13591 ScopedVector
<UploadElementReader
> element_readers
;
13592 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13593 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13595 HttpRequestInfo request
;
13596 request
.method
= "POST";
13597 request
.url
= GURL("http://www.foo.com/");
13598 request
.upload_data_stream
= &upload_data_stream
;
13599 request
.load_flags
= 0;
13601 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13602 scoped_ptr
<HttpTransaction
> trans(
13603 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13604 // Send headers successfully, but get an error while sending the body.
13605 MockWrite data_writes
[] = {
13606 MockWrite("POST / HTTP/1.1\r\n"
13607 "Host: www.foo.com\r\n"
13608 "Connection: keep-alive\r\n"
13609 "Content-Length: 3\r\n\r\n"),
13610 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13613 MockRead data_reads
[] = {
13614 MockRead("HTTP 0.9 rocks!"),
13615 MockRead(SYNCHRONOUS
, OK
),
13617 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13618 arraysize(data_writes
));
13619 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13621 TestCompletionCallback callback
;
13623 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13624 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13626 rv
= callback
.WaitForResult();
13627 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13629 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13630 EXPECT_TRUE(response
== NULL
);
13633 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13634 ScopedVector
<UploadElementReader
> element_readers
;
13635 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13636 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13638 HttpRequestInfo request
;
13639 request
.method
= "POST";
13640 request
.url
= GURL("http://www.foo.com/");
13641 request
.upload_data_stream
= &upload_data_stream
;
13642 request
.load_flags
= 0;
13644 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13645 scoped_ptr
<HttpTransaction
> trans(
13646 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13647 // Send headers successfully, but get an error while sending the body.
13648 MockWrite data_writes
[] = {
13649 MockWrite("POST / HTTP/1.1\r\n"
13650 "Host: www.foo.com\r\n"
13651 "Connection: keep-alive\r\n"
13652 "Content-Length: 3\r\n\r\n"),
13653 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13656 MockRead data_reads
[] = {
13657 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13658 MockRead(SYNCHRONOUS
, OK
),
13660 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13661 arraysize(data_writes
));
13662 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13664 TestCompletionCallback callback
;
13666 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13667 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13669 rv
= callback
.WaitForResult();
13670 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13672 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13673 EXPECT_TRUE(response
== NULL
);
13676 // Verify that proxy headers are not sent to the destination server when
13677 // establishing a tunnel for a secure WebSocket connection.
13678 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
13679 HttpRequestInfo request
;
13680 request
.method
= "GET";
13681 request
.url
= GURL("wss://www.google.com/");
13682 AddWebSocketHeaders(&request
.extra_headers
);
13684 // Configure against proxy server "myproxy:70".
13685 session_deps_
.proxy_service
.reset(
13686 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13688 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13690 // Since a proxy is configured, try to establish a tunnel.
13691 MockWrite data_writes
[] = {
13693 "CONNECT www.google.com:443 HTTP/1.1\r\n"
13694 "Host: www.google.com\r\n"
13695 "Proxy-Connection: keep-alive\r\n\r\n"),
13697 // After calling trans->RestartWithAuth(), this is the request we should
13698 // be issuing -- the final header line contains the credentials.
13700 "CONNECT www.google.com:443 HTTP/1.1\r\n"
13701 "Host: www.google.com\r\n"
13702 "Proxy-Connection: keep-alive\r\n"
13703 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13706 "GET / HTTP/1.1\r\n"
13707 "Host: www.google.com\r\n"
13708 "Connection: Upgrade\r\n"
13709 "Upgrade: websocket\r\n"
13710 "Origin: http://www.google.com\r\n"
13711 "Sec-WebSocket-Version: 13\r\n"
13712 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13715 // The proxy responds to the connect with a 407, using a persistent
13717 MockRead data_reads
[] = {
13719 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
13720 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13721 MockRead("Proxy-Connection: close\r\n\r\n"),
13723 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13725 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13726 MockRead("Upgrade: websocket\r\n"),
13727 MockRead("Connection: Upgrade\r\n"),
13728 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13731 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13732 arraysize(data_writes
));
13733 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13734 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13735 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13737 scoped_ptr
<HttpTransaction
> trans(
13738 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13739 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13740 trans
->SetWebSocketHandshakeStreamCreateHelper(
13741 &websocket_stream_create_helper
);
13744 TestCompletionCallback callback
;
13746 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13747 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13749 rv
= callback
.WaitForResult();
13753 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13754 ASSERT_TRUE(response
);
13755 ASSERT_TRUE(response
->headers
.get());
13756 EXPECT_EQ(407, response
->headers
->response_code());
13759 TestCompletionCallback callback
;
13761 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
13762 callback
.callback());
13763 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13765 rv
= callback
.WaitForResult();
13769 response
= trans
->GetResponseInfo();
13770 ASSERT_TRUE(response
);
13771 ASSERT_TRUE(response
->headers
.get());
13773 EXPECT_EQ(101, response
->headers
->response_code());
13776 session
->CloseAllConnections();
13779 // Verify that proxy headers are not sent to the destination server when
13780 // establishing a tunnel for an insecure WebSocket connection.
13781 // This requires the authentication info to be injected into the auth cache
13782 // due to crbug.com/395064
13783 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
13784 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
13785 HttpRequestInfo request
;
13786 request
.method
= "GET";
13787 request
.url
= GURL("ws://www.google.com/");
13788 AddWebSocketHeaders(&request
.extra_headers
);
13790 // Configure against proxy server "myproxy:70".
13791 session_deps_
.proxy_service
.reset(
13792 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13794 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13796 MockWrite data_writes
[] = {
13797 // Try to establish a tunnel for the WebSocket connection, with
13798 // credentials. Because WebSockets have a separate set of socket pools,
13799 // they cannot and will not use the same TCP/IP connection as the
13800 // preflight HTTP request.
13802 "CONNECT www.google.com:80 HTTP/1.1\r\n"
13803 "Host: www.google.com:80\r\n"
13804 "Proxy-Connection: keep-alive\r\n"
13805 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13808 "GET / HTTP/1.1\r\n"
13809 "Host: www.google.com\r\n"
13810 "Connection: Upgrade\r\n"
13811 "Upgrade: websocket\r\n"
13812 "Origin: http://www.google.com\r\n"
13813 "Sec-WebSocket-Version: 13\r\n"
13814 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13817 MockRead data_reads
[] = {
13818 // HTTP CONNECT with credentials.
13819 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13821 // WebSocket connection established inside tunnel.
13822 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13823 MockRead("Upgrade: websocket\r\n"),
13824 MockRead("Connection: Upgrade\r\n"),
13825 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13828 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13829 arraysize(data_writes
));
13830 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13832 session
->http_auth_cache()->Add(
13833 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
13834 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
13836 scoped_ptr
<HttpTransaction
> trans(
13837 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13838 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13839 trans
->SetWebSocketHandshakeStreamCreateHelper(
13840 &websocket_stream_create_helper
);
13842 TestCompletionCallback callback
;
13844 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13845 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13847 rv
= callback
.WaitForResult();
13850 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13851 ASSERT_TRUE(response
);
13852 ASSERT_TRUE(response
->headers
.get());
13854 EXPECT_EQ(101, response
->headers
->response_code());
13857 session
->CloseAllConnections();