1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/json/json_writer.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/run_loop.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/test_file_util.h"
23 #include "net/base/auth.h"
24 #include "net/base/capturing_net_log.h"
25 #include "net/base/completion_callback.h"
26 #include "net/base/load_timing_info.h"
27 #include "net/base/load_timing_info_test_util.h"
28 #include "net/base/net_log.h"
29 #include "net/base/net_log_unittest.h"
30 #include "net/base/request_priority.h"
31 #include "net/base/test_completion_callback.h"
32 #include "net/base/test_data_directory.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/base/upload_data_stream.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_stream.h"
44 #include "net/http/http_network_session.h"
45 #include "net/http/http_network_session_peer.h"
46 #include "net/http/http_server_properties_impl.h"
47 #include "net/http/http_stream.h"
48 #include "net/http/http_stream_factory.h"
49 #include "net/http/http_transaction_test_util.h"
50 #include "net/proxy/proxy_config_service_fixed.h"
51 #include "net/proxy/proxy_info.h"
52 #include "net/proxy/proxy_resolver.h"
53 #include "net/proxy/proxy_service.h"
54 #include "net/socket/client_socket_factory.h"
55 #include "net/socket/client_socket_pool_manager.h"
56 #include "net/socket/mock_client_socket_pool_manager.h"
57 #include "net/socket/next_proto.h"
58 #include "net/socket/socket_test_util.h"
59 #include "net/socket/ssl_client_socket.h"
60 #include "net/spdy/spdy_framer.h"
61 #include "net/spdy/spdy_session.h"
62 #include "net/spdy/spdy_session_pool.h"
63 #include "net/spdy/spdy_test_util_common.h"
64 #include "net/ssl/ssl_cert_request_info.h"
65 #include "net/ssl/ssl_config_service.h"
66 #include "net/ssl/ssl_config_service_defaults.h"
67 #include "net/ssl/ssl_info.h"
68 #include "net/test/cert_test_util.h"
69 #include "net/websockets/websocket_handshake_stream_base.h"
70 #include "testing/gtest/include/gtest/gtest.h"
71 #include "testing/platform_test.h"
74 using base::ASCIIToUTF16
;
76 //-----------------------------------------------------------------------------
80 const base::string16
kBar(ASCIIToUTF16("bar"));
81 const base::string16
kBar2(ASCIIToUTF16("bar2"));
82 const base::string16
kBar3(ASCIIToUTF16("bar3"));
83 const base::string16
kBaz(ASCIIToUTF16("baz"));
84 const base::string16
kFirst(ASCIIToUTF16("first"));
85 const base::string16
kFoo(ASCIIToUTF16("foo"));
86 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
87 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
88 const base::string16
kFou(ASCIIToUTF16("fou"));
89 const base::string16
kSecond(ASCIIToUTF16("second"));
90 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
91 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
93 int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession
* session
) {
94 return session
->GetTransportSocketPool(
95 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
98 int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession
* session
) {
99 return session
->GetSSLSocketPool(
100 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IdleSocketCount();
103 bool IsTransportSocketPoolStalled(net::HttpNetworkSession
* session
) {
104 return session
->GetTransportSocketPool(
105 net::HttpNetworkSession::NORMAL_SOCKET_POOL
)->IsStalled();
108 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
109 // a JSONified list of headers as a single string. Uses single quotes instead
110 // of double quotes for easier comparison. Returns false on failure.
111 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
114 base::ListValue
* header_list
;
115 if (!params
->GetList("headers", &header_list
))
117 std::string double_quote_headers
;
118 base::JSONWriter::Write(header_list
, &double_quote_headers
);
119 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
123 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
125 void TestLoadTimingReused(const net::LoadTimingInfo
& load_timing_info
) {
126 EXPECT_TRUE(load_timing_info
.socket_reused
);
127 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
129 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
130 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
132 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
133 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
135 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
137 // Set at a higher level.
138 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
139 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
140 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
143 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
145 void TestLoadTimingNotReused(const net::LoadTimingInfo
& load_timing_info
,
146 int connect_timing_flags
) {
147 EXPECT_FALSE(load_timing_info
.socket_reused
);
148 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
150 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
151 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
153 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
154 connect_timing_flags
);
155 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
156 load_timing_info
.send_start
);
158 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
160 // Set at a higher level.
161 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
162 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
163 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
166 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
168 void TestLoadTimingReusedWithPac(const net::LoadTimingInfo
& load_timing_info
) {
169 EXPECT_TRUE(load_timing_info
.socket_reused
);
170 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
172 net::ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
174 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
175 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
176 load_timing_info
.proxy_resolve_end
);
177 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
178 load_timing_info
.send_start
);
179 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
181 // Set at a higher level.
182 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
183 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
184 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
187 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
189 void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo
& load_timing_info
,
190 int connect_timing_flags
) {
191 EXPECT_FALSE(load_timing_info
.socket_reused
);
192 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
194 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
195 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
196 load_timing_info
.proxy_resolve_end
);
197 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
198 load_timing_info
.connect_timing
.connect_start
);
199 net::ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
200 connect_timing_flags
);
201 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
202 load_timing_info
.send_start
);
204 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
206 // Set at a higher level.
207 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
208 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
209 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
218 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
219 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
224 class HttpNetworkTransactionTest
225 : public PlatformTest
,
226 public ::testing::WithParamInterface
<NextProto
> {
228 virtual ~HttpNetworkTransactionTest() {
229 // Important to restore the per-pool limit first, since the pool limit must
230 // always be greater than group limit, and the tests reduce both limits.
231 ClientSocketPoolManager::set_max_sockets_per_pool(
232 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
233 ClientSocketPoolManager::set_max_sockets_per_group(
234 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
238 HttpNetworkTransactionTest()
239 : spdy_util_(GetParam()),
240 session_deps_(GetParam()),
241 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
242 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
243 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
244 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
247 struct SimpleGetHelperResult
{
249 std::string status_line
;
250 std::string response_data
;
251 int64 totalReceivedBytes
;
252 LoadTimingInfo load_timing_info
;
255 virtual void SetUp() {
256 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
257 base::MessageLoop::current()->RunUntilIdle();
260 virtual void TearDown() {
261 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
262 base::MessageLoop::current()->RunUntilIdle();
263 // Empty the current queue.
264 base::MessageLoop::current()->RunUntilIdle();
265 PlatformTest::TearDown();
266 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
267 base::MessageLoop::current()->RunUntilIdle();
270 // This is the expected return from a current server advertising SPDY.
271 std::string
GetAlternateProtocolHttpHeader() {
273 std::string("Alternate-Protocol: 443:") +
274 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
278 // Either |write_failure| specifies a write failure or |read_failure|
279 // specifies a read failure when using a reused socket. In either case, the
280 // failure should cause the network transaction to resend the request, and the
281 // other argument should be NULL.
282 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
283 const MockRead
* read_failure
);
285 // Either |write_failure| specifies a write failure or |read_failure|
286 // specifies a read failure when using a reused socket. In either case, the
287 // failure should cause the network transaction to resend the request, and the
288 // other argument should be NULL.
289 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
290 const MockRead
* read_failure
,
293 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
295 SimpleGetHelperResult out
;
297 HttpRequestInfo request
;
298 request
.method
= "GET";
299 request
.url
= GURL("http://www.google.com/");
300 request
.load_flags
= 0;
302 CapturingBoundNetLog log
;
303 session_deps_
.net_log
= log
.bound().net_log();
304 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
305 scoped_ptr
<HttpTransaction
> trans(
306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
308 for (size_t i
= 0; i
< data_count
; ++i
) {
309 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
312 TestCompletionCallback callback
;
314 EXPECT_TRUE(log
.bound().IsLogging());
315 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
316 EXPECT_EQ(ERR_IO_PENDING
, rv
);
318 out
.rv
= callback
.WaitForResult();
320 // Even in the failure cases that use this function, connections are always
321 // successfully established before the error.
322 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
323 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
328 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
329 // Can't use ASSERT_* inside helper functions like this, so
331 if (response
== NULL
|| response
->headers
.get() == NULL
) {
332 out
.rv
= ERR_UNEXPECTED
;
335 out
.status_line
= response
->headers
->GetStatusLine();
337 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
338 EXPECT_EQ(80, response
->socket_address
.port());
340 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
343 net::CapturingNetLog::CapturedEntryList entries
;
344 log
.GetEntries(&entries
);
345 size_t pos
= ExpectLogContainsSomewhere(
346 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
348 ExpectLogContainsSomewhere(
350 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
354 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
355 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
357 HttpRequestHeaders request_headers
;
358 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
360 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
361 EXPECT_EQ("www.google.com", value
);
362 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
363 EXPECT_EQ("keep-alive", value
);
365 std::string response_headers
;
366 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
367 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
370 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
374 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
375 size_t reads_count
) {
376 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
377 StaticSocketDataProvider
* data
[] = { &reads
};
378 return SimpleGetHelperForData(data
, 1);
381 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
383 for (size_t i
= 0; i
< reads_count
; ++i
)
384 size
+= data_reads
[i
].data_len
;
388 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
389 int expected_status
);
391 void ConnectStatusHelper(const MockRead
& status
);
393 void BypassHostCacheOnRefreshHelper(int load_flags
);
395 void CheckErrorIsPassedBack(int error
, IoMode mode
);
397 SpdyTestUtil spdy_util_
;
398 SpdySessionDependencies session_deps_
;
400 // Original socket limits. Some tests set these. Safest to always restore
401 // them once each test has been run.
402 int old_max_group_sockets_
;
403 int old_max_pool_sockets_
;
406 INSTANTIATE_TEST_CASE_P(
408 HttpNetworkTransactionTest
,
409 testing::Values(kProtoDeprecatedSPDY2
,
410 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4
));
414 class BeforeNetworkStartHandler
{
416 explicit BeforeNetworkStartHandler(bool defer
)
417 : defer_on_before_network_start_(defer
),
418 observed_before_network_start_(false) {}
420 void OnBeforeNetworkStart(bool* defer
) {
421 *defer
= defer_on_before_network_start_
;
422 observed_before_network_start_
= true;
425 bool observed_before_network_start() const {
426 return observed_before_network_start_
;
430 const bool defer_on_before_network_start_
;
431 bool observed_before_network_start_
;
433 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
436 // Fill |str| with a long header list that consumes >= |size| bytes.
437 void FillLargeHeadersString(std::string
* str
, int size
) {
439 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
440 const int sizeof_row
= strlen(row
);
441 const int num_rows
= static_cast<int>(
442 ceil(static_cast<float>(size
) / sizeof_row
));
443 const int sizeof_data
= num_rows
* sizeof_row
;
444 DCHECK(sizeof_data
>= size
);
445 str
->reserve(sizeof_data
);
447 for (int i
= 0; i
< num_rows
; ++i
)
448 str
->append(row
, sizeof_row
);
451 // Alternative functions that eliminate randomness and dependency on the local
452 // host name so that the generated NTLM messages are reproducible.
453 void MockGenerateRandom1(uint8
* output
, size_t n
) {
454 static const uint8 bytes
[] = {
455 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
457 static size_t current_byte
= 0;
458 for (size_t i
= 0; i
< n
; ++i
) {
459 output
[i
] = bytes
[current_byte
++];
460 current_byte
%= arraysize(bytes
);
464 void MockGenerateRandom2(uint8
* output
, size_t n
) {
465 static const uint8 bytes
[] = {
466 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
467 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
469 static size_t current_byte
= 0;
470 for (size_t i
= 0; i
< n
; ++i
) {
471 output
[i
] = bytes
[current_byte
++];
472 current_byte
%= arraysize(bytes
);
476 std::string
MockGetHostName() {
480 template<typename ParentPool
>
481 class CaptureGroupNameSocketPool
: public ParentPool
{
483 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
484 CertVerifier
* cert_verifier
);
486 const std::string
last_group_name_received() const {
487 return last_group_name_
;
490 virtual int RequestSocket(const std::string
& group_name
,
491 const void* socket_params
,
492 RequestPriority priority
,
493 ClientSocketHandle
* handle
,
494 const CompletionCallback
& callback
,
495 const BoundNetLog
& net_log
) {
496 last_group_name_
= group_name
;
497 return ERR_IO_PENDING
;
499 virtual void CancelRequest(const std::string
& group_name
,
500 ClientSocketHandle
* handle
) {}
501 virtual void ReleaseSocket(const std::string
& group_name
,
502 scoped_ptr
<StreamSocket
> socket
,
504 virtual void CloseIdleSockets() {}
505 virtual int IdleSocketCount() const {
508 virtual int IdleSocketCountInGroup(const std::string
& group_name
) const {
511 virtual LoadState
GetLoadState(const std::string
& group_name
,
512 const ClientSocketHandle
* handle
) const {
513 return LOAD_STATE_IDLE
;
515 virtual base::TimeDelta
ConnectionTimeout() const {
516 return base::TimeDelta();
520 std::string last_group_name_
;
523 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
524 CaptureGroupNameTransportSocketPool
;
525 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
526 CaptureGroupNameHttpProxySocketPool
;
527 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
528 CaptureGroupNameSOCKSSocketPool
;
529 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
530 CaptureGroupNameSSLSocketPool
;
532 template<typename ParentPool
>
533 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
534 HostResolver
* host_resolver
,
535 CertVerifier
* /* cert_verifier */)
536 : ParentPool(0, 0, NULL
, host_resolver
, NULL
, NULL
) {}
539 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
540 HostResolver
* host_resolver
,
541 CertVerifier
* /* cert_verifier */)
542 : HttpProxyClientSocketPool(0, 0, NULL
, host_resolver
, NULL
, NULL
, NULL
) {}
545 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
546 HostResolver
* host_resolver
,
547 CertVerifier
* cert_verifier
)
548 : SSLClientSocketPool(0,
564 //-----------------------------------------------------------------------------
566 // Helper functions for validating that AuthChallengeInfo's are correctly
567 // configured for common cases.
568 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
571 EXPECT_FALSE(auth_challenge
->is_proxy
);
572 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
573 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
574 EXPECT_EQ("basic", auth_challenge
->scheme
);
578 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
581 EXPECT_TRUE(auth_challenge
->is_proxy
);
582 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
583 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
584 EXPECT_EQ("basic", auth_challenge
->scheme
);
588 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
591 EXPECT_FALSE(auth_challenge
->is_proxy
);
592 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
593 EXPECT_EQ("digestive", auth_challenge
->realm
);
594 EXPECT_EQ("digest", auth_challenge
->scheme
);
598 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
601 EXPECT_FALSE(auth_challenge
->is_proxy
);
602 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
603 EXPECT_EQ(std::string(), auth_challenge
->realm
);
604 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
610 TEST_P(HttpNetworkTransactionTest
, Basic
) {
611 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
612 scoped_ptr
<HttpTransaction
> trans(
613 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
616 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
617 MockRead data_reads
[] = {
618 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
619 MockRead("hello world"),
620 MockRead(SYNCHRONOUS
, OK
),
622 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
623 arraysize(data_reads
));
624 EXPECT_EQ(OK
, out
.rv
);
625 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
626 EXPECT_EQ("hello world", out
.response_data
);
627 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
628 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
631 // Response with no status line.
632 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
633 MockRead data_reads
[] = {
634 MockRead("hello world"),
635 MockRead(SYNCHRONOUS
, OK
),
637 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
638 arraysize(data_reads
));
639 EXPECT_EQ(OK
, out
.rv
);
640 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
641 EXPECT_EQ("hello world", out
.response_data
);
642 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
643 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
646 // Allow up to 4 bytes of junk to precede status line.
647 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
648 MockRead data_reads
[] = {
649 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
650 MockRead(SYNCHRONOUS
, OK
),
652 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
653 arraysize(data_reads
));
654 EXPECT_EQ(OK
, out
.rv
);
655 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
656 EXPECT_EQ("DATA", out
.response_data
);
657 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
658 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
661 // Allow up to 4 bytes of junk to precede status line.
662 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
663 MockRead data_reads
[] = {
664 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
665 MockRead(SYNCHRONOUS
, OK
),
667 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
668 arraysize(data_reads
));
669 EXPECT_EQ(OK
, out
.rv
);
670 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
671 EXPECT_EQ("DATA", out
.response_data
);
672 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
673 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
676 // Beyond 4 bytes of slop and it should fail to find a status line.
677 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
678 MockRead data_reads
[] = {
679 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
680 MockRead(SYNCHRONOUS
, OK
),
682 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
683 arraysize(data_reads
));
684 EXPECT_EQ(OK
, out
.rv
);
685 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
686 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
687 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
688 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
691 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
692 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
693 MockRead data_reads
[] = {
698 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
699 MockRead(SYNCHRONOUS
, OK
),
701 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
702 arraysize(data_reads
));
703 EXPECT_EQ(OK
, out
.rv
);
704 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
705 EXPECT_EQ("DATA", out
.response_data
);
706 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
707 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
710 // Close the connection before enough bytes to have a status line.
711 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
712 MockRead data_reads
[] = {
714 MockRead(SYNCHRONOUS
, OK
),
716 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
717 arraysize(data_reads
));
718 EXPECT_EQ(OK
, out
.rv
);
719 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
720 EXPECT_EQ("HTT", out
.response_data
);
721 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
722 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
725 // Simulate a 204 response, lacking a Content-Length header, sent over a
726 // persistent connection. The response should still terminate since a 204
727 // cannot have a response body.
728 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
729 char junk
[] = "junk";
730 MockRead data_reads
[] = {
731 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
732 MockRead(junk
), // Should not be read!!
733 MockRead(SYNCHRONOUS
, OK
),
735 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
736 arraysize(data_reads
));
737 EXPECT_EQ(OK
, out
.rv
);
738 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
739 EXPECT_EQ("", out
.response_data
);
740 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
741 int64 response_size
= reads_size
- strlen(junk
);
742 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
745 // A simple request using chunked encoding with some extra data after.
746 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
747 std::string final_chunk
= "0\r\n\r\n";
748 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
749 std::string last_read
= final_chunk
+ extra_data
;
750 MockRead data_reads
[] = {
751 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
752 MockRead("5\r\nHello\r\n"),
755 MockRead("5\r\nworld\r\n"),
756 MockRead(last_read
.data()),
757 MockRead(SYNCHRONOUS
, OK
),
759 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
760 arraysize(data_reads
));
761 EXPECT_EQ(OK
, out
.rv
);
762 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
763 EXPECT_EQ("Hello world", out
.response_data
);
764 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
765 int64 response_size
= reads_size
- extra_data
.size();
766 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
769 // Next tests deal with http://crbug.com/56344.
771 TEST_P(HttpNetworkTransactionTest
,
772 MultipleContentLengthHeadersNoTransferEncoding
) {
773 MockRead data_reads
[] = {
774 MockRead("HTTP/1.1 200 OK\r\n"),
775 MockRead("Content-Length: 10\r\n"),
776 MockRead("Content-Length: 5\r\n\r\n"),
778 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
779 arraysize(data_reads
));
780 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
783 TEST_P(HttpNetworkTransactionTest
,
784 DuplicateContentLengthHeadersNoTransferEncoding
) {
785 MockRead data_reads
[] = {
786 MockRead("HTTP/1.1 200 OK\r\n"),
787 MockRead("Content-Length: 5\r\n"),
788 MockRead("Content-Length: 5\r\n\r\n"),
791 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
792 arraysize(data_reads
));
793 EXPECT_EQ(OK
, out
.rv
);
794 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
795 EXPECT_EQ("Hello", out
.response_data
);
798 TEST_P(HttpNetworkTransactionTest
,
799 ComplexContentLengthHeadersNoTransferEncoding
) {
800 // More than 2 dupes.
802 MockRead data_reads
[] = {
803 MockRead("HTTP/1.1 200 OK\r\n"),
804 MockRead("Content-Length: 5\r\n"),
805 MockRead("Content-Length: 5\r\n"),
806 MockRead("Content-Length: 5\r\n\r\n"),
809 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
810 arraysize(data_reads
));
811 EXPECT_EQ(OK
, out
.rv
);
812 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
813 EXPECT_EQ("Hello", out
.response_data
);
817 MockRead data_reads
[] = {
818 MockRead("HTTP/1.0 200 OK\r\n"),
819 MockRead("Content-Length: 5\r\n"),
820 MockRead("Content-Length: 5\r\n"),
821 MockRead("Content-Length: 5\r\n\r\n"),
824 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
825 arraysize(data_reads
));
826 EXPECT_EQ(OK
, out
.rv
);
827 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
828 EXPECT_EQ("Hello", out
.response_data
);
830 // 2 dupes and one mismatched.
832 MockRead data_reads
[] = {
833 MockRead("HTTP/1.1 200 OK\r\n"),
834 MockRead("Content-Length: 10\r\n"),
835 MockRead("Content-Length: 10\r\n"),
836 MockRead("Content-Length: 5\r\n\r\n"),
838 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
839 arraysize(data_reads
));
840 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
844 TEST_P(HttpNetworkTransactionTest
,
845 MultipleContentLengthHeadersTransferEncoding
) {
846 MockRead data_reads
[] = {
847 MockRead("HTTP/1.1 200 OK\r\n"),
848 MockRead("Content-Length: 666\r\n"),
849 MockRead("Content-Length: 1337\r\n"),
850 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
851 MockRead("5\r\nHello\r\n"),
854 MockRead("5\r\nworld\r\n"),
855 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
856 MockRead(SYNCHRONOUS
, OK
),
858 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
859 arraysize(data_reads
));
860 EXPECT_EQ(OK
, out
.rv
);
861 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
862 EXPECT_EQ("Hello world", out
.response_data
);
865 // Next tests deal with http://crbug.com/98895.
867 // Checks that a single Content-Disposition header results in no error.
868 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
869 MockRead data_reads
[] = {
870 MockRead("HTTP/1.1 200 OK\r\n"),
871 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
872 MockRead("Content-Length: 5\r\n\r\n"),
875 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
876 arraysize(data_reads
));
877 EXPECT_EQ(OK
, out
.rv
);
878 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
879 EXPECT_EQ("Hello", out
.response_data
);
882 // Checks that two identical Content-Disposition headers result in no error.
883 TEST_P(HttpNetworkTransactionTest
,
884 TwoIdenticalContentDispositionHeaders
) {
885 MockRead data_reads
[] = {
886 MockRead("HTTP/1.1 200 OK\r\n"),
887 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
888 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
889 MockRead("Content-Length: 5\r\n\r\n"),
892 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
893 arraysize(data_reads
));
894 EXPECT_EQ(OK
, out
.rv
);
895 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
896 EXPECT_EQ("Hello", out
.response_data
);
899 // Checks that two distinct Content-Disposition headers result in an error.
900 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
901 MockRead data_reads
[] = {
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
904 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
905 MockRead("Content-Length: 5\r\n\r\n"),
908 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
909 arraysize(data_reads
));
910 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
913 // Checks that two identical Location headers result in no error.
914 // Also tests Location header behavior.
915 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
916 MockRead data_reads
[] = {
917 MockRead("HTTP/1.1 302 Redirect\r\n"),
918 MockRead("Location: http://good.com/\r\n"),
919 MockRead("Location: http://good.com/\r\n"),
920 MockRead("Content-Length: 0\r\n\r\n"),
921 MockRead(SYNCHRONOUS
, OK
),
924 HttpRequestInfo request
;
925 request
.method
= "GET";
926 request
.url
= GURL("http://redirect.com/");
927 request
.load_flags
= 0;
929 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
930 scoped_ptr
<HttpTransaction
> trans(
931 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
933 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
934 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
936 TestCompletionCallback callback
;
938 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
939 EXPECT_EQ(ERR_IO_PENDING
, rv
);
941 EXPECT_EQ(OK
, callback
.WaitForResult());
943 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
944 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
945 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
947 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
948 EXPECT_EQ("http://good.com/", url
);
951 // Checks that two distinct Location headers result in an error.
952 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
953 MockRead data_reads
[] = {
954 MockRead("HTTP/1.1 302 Redirect\r\n"),
955 MockRead("Location: http://good.com/\r\n"),
956 MockRead("Location: http://evil.com/\r\n"),
957 MockRead("Content-Length: 0\r\n\r\n"),
958 MockRead(SYNCHRONOUS
, OK
),
960 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
961 arraysize(data_reads
));
962 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
965 // Do a request using the HEAD method. Verify that we don't try to read the
966 // message body (since HEAD has none).
967 TEST_P(HttpNetworkTransactionTest
, Head
) {
968 HttpRequestInfo request
;
969 request
.method
= "HEAD";
970 request
.url
= GURL("http://www.google.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
));
977 MockWrite data_writes1
[] = {
978 MockWrite("HEAD / HTTP/1.1\r\n"
979 "Host: www.google.com\r\n"
980 "Connection: keep-alive\r\n"
981 "Content-Length: 0\r\n\r\n"),
983 MockRead data_reads1
[] = {
984 MockRead("HTTP/1.1 404 Not Found\r\n"),
985 MockRead("Server: Blah\r\n"),
986 MockRead("Content-Length: 1234\r\n\r\n"),
988 // No response body because the test stops reading here.
989 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
992 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
993 data_writes1
, arraysize(data_writes1
));
994 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
996 TestCompletionCallback callback1
;
998 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
999 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1001 rv
= callback1
.WaitForResult();
1004 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1005 ASSERT_TRUE(response
!= NULL
);
1007 // Check that the headers got parsed.
1008 EXPECT_TRUE(response
->headers
.get() != NULL
);
1009 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1010 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1012 std::string server_header
;
1014 bool has_server_header
= response
->headers
->EnumerateHeader(
1015 &iter
, "Server", &server_header
);
1016 EXPECT_TRUE(has_server_header
);
1017 EXPECT_EQ("Blah", server_header
);
1019 // Reading should give EOF right away, since there is no message body
1020 // (despite non-zero content-length).
1021 std::string response_data
;
1022 rv
= ReadTransaction(trans
.get(), &response_data
);
1024 EXPECT_EQ("", response_data
);
1027 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1028 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1030 MockRead data_reads
[] = {
1031 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1033 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1035 MockRead(SYNCHRONOUS
, OK
),
1037 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1038 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1040 const char* const kExpectedResponseData
[] = {
1044 for (int i
= 0; i
< 2; ++i
) {
1045 HttpRequestInfo request
;
1046 request
.method
= "GET";
1047 request
.url
= GURL("http://www.google.com/");
1048 request
.load_flags
= 0;
1050 scoped_ptr
<HttpTransaction
> trans(
1051 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1053 TestCompletionCallback callback
;
1055 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1056 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1058 rv
= callback
.WaitForResult();
1061 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1062 ASSERT_TRUE(response
!= NULL
);
1064 EXPECT_TRUE(response
->headers
.get() != NULL
);
1065 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1067 std::string response_data
;
1068 rv
= ReadTransaction(trans
.get(), &response_data
);
1070 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1074 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1075 ScopedVector
<UploadElementReader
> element_readers
;
1076 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1077 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1079 HttpRequestInfo request
;
1080 request
.method
= "POST";
1081 request
.url
= GURL("http://www.foo.com/");
1082 request
.upload_data_stream
= &upload_data_stream
;
1083 request
.load_flags
= 0;
1085 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1086 scoped_ptr
<HttpTransaction
> trans(
1087 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1089 MockRead data_reads
[] = {
1090 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1091 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1092 MockRead("hello world"),
1093 MockRead(SYNCHRONOUS
, OK
),
1095 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1096 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1098 TestCompletionCallback callback
;
1100 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1101 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1103 rv
= callback
.WaitForResult();
1106 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1107 ASSERT_TRUE(response
!= NULL
);
1109 EXPECT_TRUE(response
->headers
.get() != NULL
);
1110 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1112 std::string response_data
;
1113 rv
= ReadTransaction(trans
.get(), &response_data
);
1115 EXPECT_EQ("hello world", response_data
);
1118 // This test is almost the same as Ignores100 above, but the response contains
1119 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1120 // HTTP/1.1 and the two status headers are read in one read.
1121 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1122 HttpRequestInfo request
;
1123 request
.method
= "GET";
1124 request
.url
= GURL("http://www.foo.com/");
1125 request
.load_flags
= 0;
1127 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1128 scoped_ptr
<HttpTransaction
> trans(
1129 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1131 MockRead data_reads
[] = {
1132 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1133 "HTTP/1.1 200 OK\r\n\r\n"),
1134 MockRead("hello world"),
1135 MockRead(SYNCHRONOUS
, OK
),
1137 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1138 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1140 TestCompletionCallback callback
;
1142 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1143 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1145 rv
= callback
.WaitForResult();
1148 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1149 ASSERT_TRUE(response
!= NULL
);
1151 EXPECT_TRUE(response
->headers
.get() != NULL
);
1152 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1154 std::string response_data
;
1155 rv
= ReadTransaction(trans
.get(), &response_data
);
1157 EXPECT_EQ("hello world", response_data
);
1160 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1161 HttpRequestInfo request
;
1162 request
.method
= "POST";
1163 request
.url
= GURL("http://www.foo.com/");
1164 request
.load_flags
= 0;
1166 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1167 scoped_ptr
<HttpTransaction
> trans(
1168 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1170 MockRead data_reads
[] = {
1171 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1174 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1175 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1177 TestCompletionCallback callback
;
1179 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1182 rv
= callback
.WaitForResult();
1185 std::string response_data
;
1186 rv
= ReadTransaction(trans
.get(), &response_data
);
1188 EXPECT_EQ("", response_data
);
1191 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1192 HttpRequestInfo request
;
1193 request
.method
= "POST";
1194 request
.url
= GURL("http://www.foo.com/");
1195 request
.load_flags
= 0;
1197 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1198 scoped_ptr
<HttpTransaction
> trans(
1199 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1202 MockRead data_reads
[] = {
1205 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1206 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1208 TestCompletionCallback callback
;
1210 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1211 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1213 rv
= callback
.WaitForResult();
1214 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1217 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1218 const MockWrite
* write_failure
,
1219 const MockRead
* read_failure
) {
1220 HttpRequestInfo request
;
1221 request
.method
= "GET";
1222 request
.url
= GURL("http://www.foo.com/");
1223 request
.load_flags
= 0;
1225 CapturingNetLog net_log
;
1226 session_deps_
.net_log
= &net_log
;
1227 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1229 // Written data for successfully sending both requests.
1230 MockWrite data1_writes
[] = {
1231 MockWrite("GET / HTTP/1.1\r\n"
1232 "Host: www.foo.com\r\n"
1233 "Connection: keep-alive\r\n\r\n"),
1234 MockWrite("GET / HTTP/1.1\r\n"
1235 "Host: www.foo.com\r\n"
1236 "Connection: keep-alive\r\n\r\n")
1239 // Read results for the first request.
1240 MockRead data1_reads
[] = {
1241 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1243 MockRead(ASYNC
, OK
),
1246 if (write_failure
) {
1247 ASSERT_FALSE(read_failure
);
1248 data1_writes
[1] = *write_failure
;
1250 ASSERT_TRUE(read_failure
);
1251 data1_reads
[2] = *read_failure
;
1254 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1255 data1_writes
, arraysize(data1_writes
));
1256 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1258 MockRead data2_reads
[] = {
1259 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1261 MockRead(ASYNC
, OK
),
1263 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1264 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1266 const char* kExpectedResponseData
[] = {
1270 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1271 for (int i
= 0; i
< 2; ++i
) {
1272 TestCompletionCallback callback
;
1274 scoped_ptr
<HttpTransaction
> trans(
1275 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1277 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1278 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1280 rv
= callback
.WaitForResult();
1283 LoadTimingInfo load_timing_info
;
1284 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1285 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1287 first_socket_log_id
= load_timing_info
.socket_log_id
;
1289 // The second request should be using a new socket.
1290 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1293 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1294 ASSERT_TRUE(response
!= NULL
);
1296 EXPECT_TRUE(response
->headers
.get() != NULL
);
1297 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1299 std::string response_data
;
1300 rv
= ReadTransaction(trans
.get(), &response_data
);
1302 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1306 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1307 const MockWrite
* write_failure
,
1308 const MockRead
* read_failure
,
1310 HttpRequestInfo request
;
1311 request
.method
= "GET";
1312 request
.url
= GURL("https://www.foo.com/");
1313 request
.load_flags
= 0;
1315 CapturingNetLog net_log
;
1316 session_deps_
.net_log
= &net_log
;
1317 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1319 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1320 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1322 ssl1
.SetNextProto(GetParam());
1323 ssl2
.SetNextProto(GetParam());
1325 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1326 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1328 // SPDY versions of the request and response.
1329 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1330 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1331 scoped_ptr
<SpdyFrame
> spdy_response(
1332 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1333 scoped_ptr
<SpdyFrame
> spdy_data(
1334 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1336 // HTTP/1.1 versions of the request and response.
1337 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1338 "Host: www.foo.com\r\n"
1339 "Connection: keep-alive\r\n\r\n";
1340 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1341 const char kHttpData
[] = "hello";
1343 std::vector
<MockRead
> data1_reads
;
1344 std::vector
<MockWrite
> data1_writes
;
1345 if (write_failure
) {
1346 ASSERT_FALSE(read_failure
);
1347 data1_writes
.push_back(*write_failure
);
1348 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1350 ASSERT_TRUE(read_failure
);
1352 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1354 data1_writes
.push_back(MockWrite(kHttpRequest
));
1356 data1_reads
.push_back(*read_failure
);
1359 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1360 &data1_writes
[0], data1_writes
.size());
1361 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1363 std::vector
<MockRead
> data2_reads
;
1364 std::vector
<MockWrite
> data2_writes
;
1367 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1369 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1370 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1371 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1373 data2_writes
.push_back(
1374 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1376 data2_reads
.push_back(
1377 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1378 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1379 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1381 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1382 &data2_writes
[0], data2_writes
.size());
1383 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1385 // Preconnect a socket.
1386 net::SSLConfig ssl_config
;
1387 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1388 session
->GetNextProtos(&ssl_config
.next_protos
);
1389 session
->http_stream_factory()->PreconnectStreams(
1390 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1391 // Wait for the preconnect to complete.
1392 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1393 base::RunLoop().RunUntilIdle();
1394 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1396 // Make the request.
1397 TestCompletionCallback callback
;
1399 scoped_ptr
<HttpTransaction
> trans(
1400 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1402 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1403 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1405 rv
= callback
.WaitForResult();
1408 LoadTimingInfo load_timing_info
;
1409 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1410 TestLoadTimingNotReused(
1412 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1414 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1415 ASSERT_TRUE(response
!= NULL
);
1417 EXPECT_TRUE(response
->headers
.get() != NULL
);
1418 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1420 std::string response_data
;
1421 rv
= ReadTransaction(trans
.get(), &response_data
);
1423 EXPECT_EQ(kHttpData
, response_data
);
1426 TEST_P(HttpNetworkTransactionTest
,
1427 KeepAliveConnectionNotConnectedOnWrite
) {
1428 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1429 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1432 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1433 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1434 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1437 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1438 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1439 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1442 TEST_P(HttpNetworkTransactionTest
,
1443 PreconnectErrorNotConnectedOnWrite
) {
1444 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1445 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1448 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1449 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1450 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1453 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1454 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1455 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1458 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1459 MockRead
read_failure(ASYNC
, OK
); // EOF
1460 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1463 TEST_P(HttpNetworkTransactionTest
,
1464 SpdyPreconnectErrorNotConnectedOnWrite
) {
1465 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1466 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1469 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1470 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1471 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1474 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1475 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1476 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1479 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1480 MockRead
read_failure(ASYNC
, OK
); // EOF
1481 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1484 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1485 HttpRequestInfo request
;
1486 request
.method
= "GET";
1487 request
.url
= GURL("http://www.google.com/");
1488 request
.load_flags
= 0;
1490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1491 scoped_ptr
<HttpTransaction
> trans(
1492 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1494 MockRead data_reads
[] = {
1495 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1496 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1497 MockRead("hello world"),
1498 MockRead(SYNCHRONOUS
, OK
),
1500 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1501 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1503 TestCompletionCallback callback
;
1505 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1506 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1508 rv
= callback
.WaitForResult();
1509 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1511 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1512 EXPECT_TRUE(response
== NULL
);
1515 // What do various browsers do when the server closes a non-keepalive
1516 // connection without sending any response header or body?
1519 // Safari 3.1.2 (Windows): error page
1520 // Firefox 3.0.1: blank page
1521 // Opera 9.52: after five attempts, blank page
1522 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1523 // Us: error page (EMPTY_RESPONSE)
1524 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1525 MockRead data_reads
[] = {
1526 MockRead(SYNCHRONOUS
, OK
), // EOF
1527 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1528 MockRead("hello world"),
1529 MockRead(SYNCHRONOUS
, OK
),
1531 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1532 arraysize(data_reads
));
1533 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1536 // Test that network access can be deferred and resumed.
1537 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1538 HttpRequestInfo request
;
1539 request
.method
= "GET";
1540 request
.url
= GURL("http://www.google.com/");
1541 request
.load_flags
= 0;
1543 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1544 scoped_ptr
<HttpTransaction
> trans(
1545 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1547 // Defer on OnBeforeNetworkStart.
1548 BeforeNetworkStartHandler
net_start_handler(true); // defer
1549 trans
->SetBeforeNetworkStartCallback(
1550 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1551 base::Unretained(&net_start_handler
)));
1553 MockRead data_reads
[] = {
1554 MockRead("HTTP/1.0 200 OK\r\n"),
1555 MockRead("Content-Length: 5\r\n\r\n"),
1557 MockRead(SYNCHRONOUS
, 0),
1559 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1560 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1562 TestCompletionCallback callback
;
1564 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1565 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1566 base::MessageLoop::current()->RunUntilIdle();
1568 // Should have deferred for network start.
1569 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1570 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1571 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1573 trans
->ResumeNetworkStart();
1574 rv
= callback
.WaitForResult();
1576 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1578 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1579 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1580 if (rv
== ERR_IO_PENDING
)
1581 rv
= callback
.WaitForResult();
1586 // Test that network use can be deferred and canceled.
1587 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1588 HttpRequestInfo request
;
1589 request
.method
= "GET";
1590 request
.url
= GURL("http://www.google.com/");
1591 request
.load_flags
= 0;
1593 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1594 scoped_ptr
<HttpTransaction
> trans(
1595 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1597 // Defer on OnBeforeNetworkStart.
1598 BeforeNetworkStartHandler
net_start_handler(true); // defer
1599 trans
->SetBeforeNetworkStartCallback(
1600 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1601 base::Unretained(&net_start_handler
)));
1603 TestCompletionCallback callback
;
1605 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1607 base::MessageLoop::current()->RunUntilIdle();
1609 // Should have deferred for network start.
1610 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1611 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1612 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1615 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1616 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1617 // destructor in such situations.
1618 // See http://crbug.com/154712 and http://crbug.com/156609.
1619 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1620 HttpRequestInfo request
;
1621 request
.method
= "GET";
1622 request
.url
= GURL("http://www.google.com/");
1623 request
.load_flags
= 0;
1625 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1626 scoped_ptr
<HttpTransaction
> trans(
1627 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1629 MockRead data_reads
[] = {
1630 MockRead("HTTP/1.0 200 OK\r\n"),
1631 MockRead("Connection: keep-alive\r\n"),
1632 MockRead("Content-Length: 100\r\n\r\n"),
1634 MockRead(SYNCHRONOUS
, 0),
1636 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1637 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1639 TestCompletionCallback callback
;
1641 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1642 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1644 rv
= callback
.WaitForResult();
1647 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1648 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1649 if (rv
== ERR_IO_PENDING
)
1650 rv
= callback
.WaitForResult();
1652 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1653 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1656 base::MessageLoop::current()->RunUntilIdle();
1657 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1660 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1661 HttpRequestInfo request
;
1662 request
.method
= "GET";
1663 request
.url
= GURL("http://www.google.com/");
1664 request
.load_flags
= 0;
1666 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1667 scoped_ptr
<HttpTransaction
> trans(
1668 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1670 MockRead data_reads
[] = {
1671 MockRead("HTTP/1.0 200 OK\r\n"),
1672 MockRead("Connection: keep-alive\r\n"),
1673 MockRead("Content-Length: 100\r\n\r\n"),
1674 MockRead(SYNCHRONOUS
, 0),
1676 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1677 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1679 TestCompletionCallback callback
;
1681 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1682 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1684 rv
= callback
.WaitForResult();
1687 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1688 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1689 if (rv
== ERR_IO_PENDING
)
1690 rv
= callback
.WaitForResult();
1691 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1694 base::MessageLoop::current()->RunUntilIdle();
1695 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1698 // Test that we correctly reuse a keep-alive connection after not explicitly
1699 // reading the body.
1700 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1701 HttpRequestInfo request
;
1702 request
.method
= "GET";
1703 request
.url
= GURL("http://www.foo.com/");
1704 request
.load_flags
= 0;
1706 CapturingNetLog net_log
;
1707 session_deps_
.net_log
= &net_log
;
1708 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1710 // Note that because all these reads happen in the same
1711 // StaticSocketDataProvider, it shows that the same socket is being reused for
1712 // all transactions.
1713 MockRead data1_reads
[] = {
1714 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1715 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1716 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1717 MockRead("HTTP/1.1 302 Found\r\n"
1718 "Content-Length: 0\r\n\r\n"),
1719 MockRead("HTTP/1.1 302 Found\r\n"
1720 "Content-Length: 5\r\n\r\n"
1722 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1723 "Content-Length: 0\r\n\r\n"),
1724 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1725 "Content-Length: 5\r\n\r\n"
1727 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1730 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1731 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1733 MockRead data2_reads
[] = {
1734 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1736 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1737 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1739 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1740 std::string response_lines
[kNumUnreadBodies
];
1742 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1743 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1744 TestCompletionCallback callback
;
1746 scoped_ptr
<HttpTransaction
> trans(
1747 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1749 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1750 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1752 rv
= callback
.WaitForResult();
1755 LoadTimingInfo load_timing_info
;
1756 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1758 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1759 first_socket_log_id
= load_timing_info
.socket_log_id
;
1761 TestLoadTimingReused(load_timing_info
);
1762 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1765 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1766 ASSERT_TRUE(response
!= NULL
);
1768 ASSERT_TRUE(response
->headers
.get() != NULL
);
1769 response_lines
[i
] = response
->headers
->GetStatusLine();
1771 // We intentionally don't read the response bodies.
1774 const char* const kStatusLines
[] = {
1775 "HTTP/1.1 204 No Content",
1776 "HTTP/1.1 205 Reset Content",
1777 "HTTP/1.1 304 Not Modified",
1778 "HTTP/1.1 302 Found",
1779 "HTTP/1.1 302 Found",
1780 "HTTP/1.1 301 Moved Permanently",
1781 "HTTP/1.1 301 Moved Permanently",
1784 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1785 forgot_to_update_kStatusLines
);
1787 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1788 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1790 TestCompletionCallback callback
;
1791 scoped_ptr
<HttpTransaction
> trans(
1792 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1793 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1794 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1795 rv
= callback
.WaitForResult();
1797 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1798 ASSERT_TRUE(response
!= NULL
);
1799 ASSERT_TRUE(response
->headers
.get() != NULL
);
1800 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1801 std::string response_data
;
1802 rv
= ReadTransaction(trans
.get(), &response_data
);
1804 EXPECT_EQ("hello", response_data
);
1807 // Test the request-challenge-retry sequence for basic auth.
1808 // (basic auth is the easiest to mock, because it has no randomness).
1809 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1810 HttpRequestInfo request
;
1811 request
.method
= "GET";
1812 request
.url
= GURL("http://www.google.com/");
1813 request
.load_flags
= 0;
1815 CapturingNetLog log
;
1816 session_deps_
.net_log
= &log
;
1817 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1818 scoped_ptr
<HttpTransaction
> trans(
1819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1821 MockWrite data_writes1
[] = {
1822 MockWrite("GET / HTTP/1.1\r\n"
1823 "Host: www.google.com\r\n"
1824 "Connection: keep-alive\r\n\r\n"),
1827 MockRead data_reads1
[] = {
1828 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1829 // Give a couple authenticate options (only the middle one is actually
1831 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1832 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1833 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1834 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1835 // Large content-length -- won't matter, as connection will be reset.
1836 MockRead("Content-Length: 10000\r\n\r\n"),
1837 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1840 // After calling trans->RestartWithAuth(), this is the request we should
1841 // be issuing -- the final header line contains the credentials.
1842 MockWrite data_writes2
[] = {
1843 MockWrite("GET / HTTP/1.1\r\n"
1844 "Host: www.google.com\r\n"
1845 "Connection: keep-alive\r\n"
1846 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1849 // Lastly, the server responds with the actual content.
1850 MockRead data_reads2
[] = {
1851 MockRead("HTTP/1.0 200 OK\r\n"),
1852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1853 MockRead("Content-Length: 100\r\n\r\n"),
1854 MockRead(SYNCHRONOUS
, OK
),
1857 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1858 data_writes1
, arraysize(data_writes1
));
1859 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1860 data_writes2
, arraysize(data_writes2
));
1861 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1862 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1864 TestCompletionCallback callback1
;
1866 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1867 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1869 rv
= callback1
.WaitForResult();
1872 LoadTimingInfo load_timing_info1
;
1873 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1874 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1876 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1877 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1879 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1880 ASSERT_TRUE(response
!= NULL
);
1881 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1883 TestCompletionCallback callback2
;
1885 rv
= trans
->RestartWithAuth(
1886 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1887 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1889 rv
= callback2
.WaitForResult();
1892 LoadTimingInfo load_timing_info2
;
1893 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1894 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1895 // The load timing after restart should have a new socket ID, and times after
1896 // those of the first load timing.
1897 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1898 load_timing_info2
.connect_timing
.connect_start
);
1899 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1901 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1902 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1904 response
= trans
->GetResponseInfo();
1905 ASSERT_TRUE(response
!= NULL
);
1906 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1907 EXPECT_EQ(100, response
->headers
->GetContentLength());
1910 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1911 HttpRequestInfo request
;
1912 request
.method
= "GET";
1913 request
.url
= GURL("http://www.google.com/");
1914 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1916 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1917 scoped_ptr
<HttpTransaction
> trans(
1918 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1920 MockWrite data_writes
[] = {
1921 MockWrite("GET / HTTP/1.1\r\n"
1922 "Host: www.google.com\r\n"
1923 "Connection: keep-alive\r\n\r\n"),
1926 MockRead data_reads
[] = {
1927 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1928 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1930 // Large content-length -- won't matter, as connection will be reset.
1931 MockRead("Content-Length: 10000\r\n\r\n"),
1932 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1935 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1936 data_writes
, arraysize(data_writes
));
1937 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1938 TestCompletionCallback callback
;
1940 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1943 rv
= callback
.WaitForResult();
1946 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
1947 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
1949 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1950 ASSERT_TRUE(response
!= NULL
);
1951 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1954 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1956 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
1957 HttpRequestInfo request
;
1958 request
.method
= "GET";
1959 request
.url
= GURL("http://www.google.com/");
1960 request
.load_flags
= 0;
1962 CapturingNetLog log
;
1963 session_deps_
.net_log
= &log
;
1964 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1966 MockWrite data_writes1
[] = {
1967 MockWrite("GET / HTTP/1.1\r\n"
1968 "Host: www.google.com\r\n"
1969 "Connection: keep-alive\r\n\r\n"),
1971 // After calling trans->RestartWithAuth(), this is the request we should
1972 // be issuing -- the final header line contains the credentials.
1973 MockWrite("GET / HTTP/1.1\r\n"
1974 "Host: www.google.com\r\n"
1975 "Connection: keep-alive\r\n"
1976 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1979 MockRead data_reads1
[] = {
1980 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1981 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1982 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1983 MockRead("Content-Length: 14\r\n\r\n"),
1984 MockRead("Unauthorized\r\n"),
1986 // Lastly, the server responds with the actual content.
1987 MockRead("HTTP/1.1 200 OK\r\n"),
1988 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1989 MockRead("Content-Length: 5\r\n\r\n"),
1993 // If there is a regression where we disconnect a Keep-Alive
1994 // connection during an auth roundtrip, we'll end up reading this.
1995 MockRead data_reads2
[] = {
1996 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1999 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2000 data_writes1
, arraysize(data_writes1
));
2001 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2003 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2004 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2006 TestCompletionCallback callback1
;
2008 scoped_ptr
<HttpTransaction
> trans(
2009 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2010 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2011 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2013 rv
= callback1
.WaitForResult();
2016 LoadTimingInfo load_timing_info1
;
2017 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2018 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2020 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2021 ASSERT_TRUE(response
!= NULL
);
2022 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2024 TestCompletionCallback callback2
;
2026 rv
= trans
->RestartWithAuth(
2027 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2028 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2030 rv
= callback2
.WaitForResult();
2033 LoadTimingInfo load_timing_info2
;
2034 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2035 TestLoadTimingReused(load_timing_info2
);
2036 // The load timing after restart should have the same socket ID, and times
2037 // those of the first load timing.
2038 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2039 load_timing_info2
.send_start
);
2040 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2042 response
= trans
->GetResponseInfo();
2043 ASSERT_TRUE(response
!= NULL
);
2044 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2045 EXPECT_EQ(5, response
->headers
->GetContentLength());
2047 std::string response_data
;
2048 rv
= ReadTransaction(trans
.get(), &response_data
);
2050 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2051 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2054 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2055 // connection and with no response body to drain.
2056 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2057 HttpRequestInfo request
;
2058 request
.method
= "GET";
2059 request
.url
= GURL("http://www.google.com/");
2060 request
.load_flags
= 0;
2062 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2064 MockWrite data_writes1
[] = {
2065 MockWrite("GET / HTTP/1.1\r\n"
2066 "Host: www.google.com\r\n"
2067 "Connection: keep-alive\r\n\r\n"),
2069 // After calling trans->RestartWithAuth(), this is the request we should
2070 // be issuing -- the final header line contains the credentials.
2071 MockWrite("GET / HTTP/1.1\r\n"
2072 "Host: www.google.com\r\n"
2073 "Connection: keep-alive\r\n"
2074 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2077 MockRead data_reads1
[] = {
2078 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2079 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2080 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2082 // Lastly, the server responds with the actual content.
2083 MockRead("HTTP/1.1 200 OK\r\n"),
2084 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2085 MockRead("Content-Length: 5\r\n\r\n"),
2089 // An incorrect reconnect would cause this to be read.
2090 MockRead data_reads2
[] = {
2091 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2094 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2095 data_writes1
, arraysize(data_writes1
));
2096 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2098 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2099 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2101 TestCompletionCallback callback1
;
2103 scoped_ptr
<HttpTransaction
> trans(
2104 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2105 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2108 rv
= callback1
.WaitForResult();
2111 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2112 ASSERT_TRUE(response
!= NULL
);
2113 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2115 TestCompletionCallback callback2
;
2117 rv
= trans
->RestartWithAuth(
2118 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2119 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2121 rv
= callback2
.WaitForResult();
2124 response
= trans
->GetResponseInfo();
2125 ASSERT_TRUE(response
!= NULL
);
2126 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2127 EXPECT_EQ(5, response
->headers
->GetContentLength());
2130 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2131 // connection and with a large response body to drain.
2132 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2133 HttpRequestInfo request
;
2134 request
.method
= "GET";
2135 request
.url
= GURL("http://www.google.com/");
2136 request
.load_flags
= 0;
2138 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2140 MockWrite data_writes1
[] = {
2141 MockWrite("GET / HTTP/1.1\r\n"
2142 "Host: www.google.com\r\n"
2143 "Connection: keep-alive\r\n\r\n"),
2145 // After calling trans->RestartWithAuth(), this is the request we should
2146 // be issuing -- the final header line contains the credentials.
2147 MockWrite("GET / HTTP/1.1\r\n"
2148 "Host: www.google.com\r\n"
2149 "Connection: keep-alive\r\n"
2150 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2153 // Respond with 5 kb of response body.
2154 std::string
large_body_string("Unauthorized");
2155 large_body_string
.append(5 * 1024, ' ');
2156 large_body_string
.append("\r\n");
2158 MockRead data_reads1
[] = {
2159 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2160 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2161 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2162 // 5134 = 12 + 5 * 1024 + 2
2163 MockRead("Content-Length: 5134\r\n\r\n"),
2164 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2166 // Lastly, the server responds with the actual content.
2167 MockRead("HTTP/1.1 200 OK\r\n"),
2168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2169 MockRead("Content-Length: 5\r\n\r\n"),
2173 // An incorrect reconnect would cause this to be read.
2174 MockRead data_reads2
[] = {
2175 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2178 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2179 data_writes1
, arraysize(data_writes1
));
2180 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2182 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2183 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2185 TestCompletionCallback callback1
;
2187 scoped_ptr
<HttpTransaction
> trans(
2188 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2189 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2190 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2192 rv
= callback1
.WaitForResult();
2195 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2196 ASSERT_TRUE(response
!= NULL
);
2197 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2199 TestCompletionCallback callback2
;
2201 rv
= trans
->RestartWithAuth(
2202 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2205 rv
= callback2
.WaitForResult();
2208 response
= trans
->GetResponseInfo();
2209 ASSERT_TRUE(response
!= NULL
);
2210 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2211 EXPECT_EQ(5, response
->headers
->GetContentLength());
2214 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2215 // connection, but the server gets impatient and closes the connection.
2216 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2217 HttpRequestInfo request
;
2218 request
.method
= "GET";
2219 request
.url
= GURL("http://www.google.com/");
2220 request
.load_flags
= 0;
2222 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2224 MockWrite data_writes1
[] = {
2225 MockWrite("GET / HTTP/1.1\r\n"
2226 "Host: www.google.com\r\n"
2227 "Connection: keep-alive\r\n\r\n"),
2228 // This simulates the seemingly successful write to a closed connection
2229 // if the bug is not fixed.
2230 MockWrite("GET / HTTP/1.1\r\n"
2231 "Host: www.google.com\r\n"
2232 "Connection: keep-alive\r\n"
2233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2236 MockRead data_reads1
[] = {
2237 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2238 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2239 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2240 MockRead("Content-Length: 14\r\n\r\n"),
2241 // Tell MockTCPClientSocket to simulate the server closing the connection.
2242 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2243 MockRead("Unauthorized\r\n"),
2244 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2247 // After calling trans->RestartWithAuth(), this is the request we should
2248 // be issuing -- the final header line contains the credentials.
2249 MockWrite data_writes2
[] = {
2250 MockWrite("GET / HTTP/1.1\r\n"
2251 "Host: www.google.com\r\n"
2252 "Connection: keep-alive\r\n"
2253 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2256 // Lastly, the server responds with the actual content.
2257 MockRead data_reads2
[] = {
2258 MockRead("HTTP/1.1 200 OK\r\n"),
2259 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2260 MockRead("Content-Length: 5\r\n\r\n"),
2264 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2265 data_writes1
, arraysize(data_writes1
));
2266 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2267 data_writes2
, arraysize(data_writes2
));
2268 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2269 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2271 TestCompletionCallback callback1
;
2273 scoped_ptr
<HttpTransaction
> trans(
2274 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2275 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2276 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2278 rv
= callback1
.WaitForResult();
2281 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2282 ASSERT_TRUE(response
!= NULL
);
2283 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2285 TestCompletionCallback callback2
;
2287 rv
= trans
->RestartWithAuth(
2288 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2289 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2291 rv
= callback2
.WaitForResult();
2294 response
= trans
->GetResponseInfo();
2295 ASSERT_TRUE(response
!= NULL
);
2296 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2297 EXPECT_EQ(5, response
->headers
->GetContentLength());
2300 // Test the request-challenge-retry sequence for basic auth, over a connection
2301 // that requires a restart when setting up an SSL tunnel.
2302 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
2303 HttpRequestInfo request
;
2304 request
.method
= "GET";
2305 request
.url
= GURL("https://www.google.com/");
2306 // when the no authentication data flag is set.
2307 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2309 // Configure against proxy server "myproxy:70".
2310 session_deps_
.proxy_service
.reset(
2311 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2312 CapturingBoundNetLog log
;
2313 session_deps_
.net_log
= log
.bound().net_log();
2314 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2316 // Since we have proxy, should try to establish tunnel.
2317 MockWrite data_writes1
[] = {
2318 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2319 "Host: www.google.com\r\n"
2320 "Proxy-Connection: keep-alive\r\n\r\n"),
2322 // After calling trans->RestartWithAuth(), this is the request we should
2323 // be issuing -- the final header line contains the credentials.
2324 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2325 "Host: www.google.com\r\n"
2326 "Proxy-Connection: keep-alive\r\n"
2327 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2329 MockWrite("GET / HTTP/1.1\r\n"
2330 "Host: www.google.com\r\n"
2331 "Connection: keep-alive\r\n\r\n"),
2334 // The proxy responds to the connect with a 407, using a persistent
2336 MockRead data_reads1
[] = {
2338 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2339 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2340 MockRead("Proxy-Connection: close\r\n\r\n"),
2342 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2344 MockRead("HTTP/1.1 200 OK\r\n"),
2345 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2346 MockRead("Content-Length: 5\r\n\r\n"),
2347 MockRead(SYNCHRONOUS
, "hello"),
2350 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2351 data_writes1
, arraysize(data_writes1
));
2352 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2353 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2354 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2356 TestCompletionCallback callback1
;
2358 scoped_ptr
<HttpTransaction
> trans(
2359 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2361 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2362 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2364 rv
= callback1
.WaitForResult();
2366 net::CapturingNetLog::CapturedEntryList entries
;
2367 log
.GetEntries(&entries
);
2368 size_t pos
= ExpectLogContainsSomewhere(
2369 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2370 NetLog::PHASE_NONE
);
2371 ExpectLogContainsSomewhere(
2373 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2374 NetLog::PHASE_NONE
);
2376 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2377 ASSERT_TRUE(response
!= NULL
);
2378 ASSERT_FALSE(response
->headers
.get() == NULL
);
2379 EXPECT_EQ(407, response
->headers
->response_code());
2380 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2381 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2383 LoadTimingInfo load_timing_info
;
2384 // CONNECT requests and responses are handled at the connect job level, so
2385 // the transaction does not yet have a connection.
2386 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2388 TestCompletionCallback callback2
;
2390 rv
= trans
->RestartWithAuth(
2391 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2394 rv
= callback2
.WaitForResult();
2397 response
= trans
->GetResponseInfo();
2398 ASSERT_TRUE(response
!= NULL
);
2400 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2401 EXPECT_EQ(200, response
->headers
->response_code());
2402 EXPECT_EQ(5, response
->headers
->GetContentLength());
2403 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2405 // The password prompt info should not be set.
2406 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2408 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2409 TestLoadTimingNotReusedWithPac(load_timing_info
,
2410 CONNECT_TIMING_HAS_SSL_TIMES
);
2413 session
->CloseAllConnections();
2416 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2417 // proxy connection, when setting up an SSL tunnel.
2418 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2419 HttpRequestInfo request
;
2420 request
.method
= "GET";
2421 request
.url
= GURL("https://www.google.com/");
2422 // Ensure that proxy authentication is attempted even
2423 // when the no authentication data flag is set.
2424 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2426 // Configure against proxy server "myproxy:70".
2427 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2428 CapturingBoundNetLog log
;
2429 session_deps_
.net_log
= log
.bound().net_log();
2430 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2432 scoped_ptr
<HttpTransaction
> trans(
2433 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2435 // Since we have proxy, should try to establish tunnel.
2436 MockWrite data_writes1
[] = {
2437 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2438 "Host: www.google.com\r\n"
2439 "Proxy-Connection: keep-alive\r\n\r\n"),
2441 // After calling trans->RestartWithAuth(), this is the request we should
2442 // be issuing -- the final header line contains the credentials.
2443 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2444 "Host: www.google.com\r\n"
2445 "Proxy-Connection: keep-alive\r\n"
2446 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2449 // The proxy responds to the connect with a 407, using a persistent
2451 MockRead data_reads1
[] = {
2453 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2454 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2455 MockRead("Content-Length: 10\r\n\r\n"),
2456 MockRead("0123456789"),
2458 // Wrong credentials (wrong password).
2459 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2460 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2461 MockRead("Content-Length: 10\r\n\r\n"),
2462 // No response body because the test stops reading here.
2463 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2466 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2467 data_writes1
, arraysize(data_writes1
));
2468 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2470 TestCompletionCallback callback1
;
2472 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2473 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2475 rv
= callback1
.WaitForResult();
2477 net::CapturingNetLog::CapturedEntryList entries
;
2478 log
.GetEntries(&entries
);
2479 size_t pos
= ExpectLogContainsSomewhere(
2480 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2481 NetLog::PHASE_NONE
);
2482 ExpectLogContainsSomewhere(
2484 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2485 NetLog::PHASE_NONE
);
2487 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2488 ASSERT_TRUE(response
!= NULL
);
2489 ASSERT_FALSE(response
->headers
.get() == NULL
);
2490 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2491 EXPECT_EQ(407, response
->headers
->response_code());
2492 EXPECT_EQ(10, response
->headers
->GetContentLength());
2493 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2494 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2496 TestCompletionCallback callback2
;
2498 // Wrong password (should be "bar").
2499 rv
= trans
->RestartWithAuth(
2500 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2501 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2503 rv
= callback2
.WaitForResult();
2506 response
= trans
->GetResponseInfo();
2507 ASSERT_TRUE(response
!= NULL
);
2508 ASSERT_FALSE(response
->headers
.get() == NULL
);
2509 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2510 EXPECT_EQ(407, response
->headers
->response_code());
2511 EXPECT_EQ(10, response
->headers
->GetContentLength());
2512 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2513 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2515 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2517 session
->CloseAllConnections();
2520 // Test that we don't read the response body when we fail to establish a tunnel,
2521 // even if the user cancels the proxy's auth attempt.
2522 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2523 HttpRequestInfo request
;
2524 request
.method
= "GET";
2525 request
.url
= GURL("https://www.google.com/");
2526 request
.load_flags
= 0;
2528 // Configure against proxy server "myproxy:70".
2529 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2531 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2533 scoped_ptr
<HttpTransaction
> trans(
2534 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2536 // Since we have proxy, should try to establish tunnel.
2537 MockWrite data_writes
[] = {
2538 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2539 "Host: www.google.com\r\n"
2540 "Proxy-Connection: keep-alive\r\n\r\n"),
2543 // The proxy responds to the connect with a 407.
2544 MockRead data_reads
[] = {
2545 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2546 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2547 MockRead("Content-Length: 10\r\n\r\n"),
2548 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2551 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2552 data_writes
, arraysize(data_writes
));
2553 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2555 TestCompletionCallback callback
;
2557 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2560 rv
= callback
.WaitForResult();
2563 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2564 ASSERT_TRUE(response
!= NULL
);
2566 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2567 EXPECT_EQ(407, response
->headers
->response_code());
2568 EXPECT_EQ(10, response
->headers
->GetContentLength());
2569 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2571 std::string response_data
;
2572 rv
= ReadTransaction(trans
.get(), &response_data
);
2573 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2575 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2576 session
->CloseAllConnections();
2579 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2580 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2581 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2582 HttpRequestInfo request
;
2583 request
.method
= "GET";
2584 request
.url
= GURL("http://www.google.com/");
2585 request
.load_flags
= 0;
2587 // We are using a DIRECT connection (i.e. no proxy) for this session.
2588 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2589 scoped_ptr
<HttpTransaction
> trans(
2590 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
2592 MockWrite data_writes1
[] = {
2593 MockWrite("GET / HTTP/1.1\r\n"
2594 "Host: www.google.com\r\n"
2595 "Connection: keep-alive\r\n\r\n"),
2598 MockRead data_reads1
[] = {
2599 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2600 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2601 // Large content-length -- won't matter, as connection will be reset.
2602 MockRead("Content-Length: 10000\r\n\r\n"),
2603 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2606 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2607 data_writes1
, arraysize(data_writes1
));
2608 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2610 TestCompletionCallback callback
;
2612 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2613 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2615 rv
= callback
.WaitForResult();
2616 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2619 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2620 // through a non-authenticating proxy. The request should fail with
2621 // ERR_UNEXPECTED_PROXY_AUTH.
2622 // Note that it is impossible to detect if an HTTP server returns a 407 through
2623 // a non-authenticating proxy - there is nothing to indicate whether the
2624 // response came from the proxy or the server, so it is treated as if the proxy
2625 // issued the challenge.
2626 TEST_P(HttpNetworkTransactionTest
,
2627 HttpsServerRequestsProxyAuthThroughProxy
) {
2628 HttpRequestInfo request
;
2629 request
.method
= "GET";
2630 request
.url
= GURL("https://www.google.com/");
2632 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2633 CapturingBoundNetLog log
;
2634 session_deps_
.net_log
= log
.bound().net_log();
2635 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2637 // Since we have proxy, should try to establish tunnel.
2638 MockWrite data_writes1
[] = {
2639 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2640 "Host: www.google.com\r\n"
2641 "Proxy-Connection: keep-alive\r\n\r\n"),
2643 MockWrite("GET / HTTP/1.1\r\n"
2644 "Host: www.google.com\r\n"
2645 "Connection: keep-alive\r\n\r\n"),
2648 MockRead data_reads1
[] = {
2649 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2651 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2652 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2654 MockRead(SYNCHRONOUS
, OK
),
2657 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2658 data_writes1
, arraysize(data_writes1
));
2659 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2660 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2661 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2663 TestCompletionCallback callback1
;
2665 scoped_ptr
<HttpTransaction
> trans(
2666 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2668 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2669 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2671 rv
= callback1
.WaitForResult();
2672 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2673 net::CapturingNetLog::CapturedEntryList entries
;
2674 log
.GetEntries(&entries
);
2675 size_t pos
= ExpectLogContainsSomewhere(
2676 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2677 NetLog::PHASE_NONE
);
2678 ExpectLogContainsSomewhere(
2680 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2681 NetLog::PHASE_NONE
);
2684 // Test the load timing for HTTPS requests with an HTTP proxy.
2685 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2686 HttpRequestInfo request1
;
2687 request1
.method
= "GET";
2688 request1
.url
= GURL("https://www.google.com/1");
2690 HttpRequestInfo request2
;
2691 request2
.method
= "GET";
2692 request2
.url
= GURL("https://www.google.com/2");
2694 // Configure against proxy server "myproxy:70".
2695 session_deps_
.proxy_service
.reset(
2696 ProxyService::CreateFixed("PROXY myproxy:70"));
2697 CapturingBoundNetLog log
;
2698 session_deps_
.net_log
= log
.bound().net_log();
2699 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2701 // Since we have proxy, should try to establish tunnel.
2702 MockWrite data_writes1
[] = {
2703 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2704 "Host: www.google.com\r\n"
2705 "Proxy-Connection: keep-alive\r\n\r\n"),
2707 MockWrite("GET /1 HTTP/1.1\r\n"
2708 "Host: www.google.com\r\n"
2709 "Connection: keep-alive\r\n\r\n"),
2711 MockWrite("GET /2 HTTP/1.1\r\n"
2712 "Host: www.google.com\r\n"
2713 "Connection: keep-alive\r\n\r\n"),
2716 // The proxy responds to the connect with a 407, using a persistent
2718 MockRead data_reads1
[] = {
2719 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2721 MockRead("HTTP/1.1 200 OK\r\n"),
2722 MockRead("Content-Length: 1\r\n\r\n"),
2723 MockRead(SYNCHRONOUS
, "1"),
2725 MockRead("HTTP/1.1 200 OK\r\n"),
2726 MockRead("Content-Length: 2\r\n\r\n"),
2727 MockRead(SYNCHRONOUS
, "22"),
2730 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2731 data_writes1
, arraysize(data_writes1
));
2732 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2733 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2734 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2736 TestCompletionCallback callback1
;
2737 scoped_ptr
<HttpTransaction
> trans1(
2738 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2740 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2741 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2743 rv
= callback1
.WaitForResult();
2746 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2747 ASSERT_TRUE(response1
!= NULL
);
2748 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2749 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2751 LoadTimingInfo load_timing_info1
;
2752 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2753 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2757 TestCompletionCallback callback2
;
2758 scoped_ptr
<HttpTransaction
> trans2(
2759 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2761 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2762 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2764 rv
= callback2
.WaitForResult();
2767 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2768 ASSERT_TRUE(response2
!= NULL
);
2769 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2770 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2772 LoadTimingInfo load_timing_info2
;
2773 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2774 TestLoadTimingReused(load_timing_info2
);
2776 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2779 session
->CloseAllConnections();
2782 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2783 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2784 HttpRequestInfo request1
;
2785 request1
.method
= "GET";
2786 request1
.url
= GURL("https://www.google.com/1");
2788 HttpRequestInfo request2
;
2789 request2
.method
= "GET";
2790 request2
.url
= GURL("https://www.google.com/2");
2792 // Configure against proxy server "myproxy:70".
2793 session_deps_
.proxy_service
.reset(
2794 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2795 CapturingBoundNetLog log
;
2796 session_deps_
.net_log
= log
.bound().net_log();
2797 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2799 // Since we have proxy, should try to establish tunnel.
2800 MockWrite data_writes1
[] = {
2801 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2802 "Host: www.google.com\r\n"
2803 "Proxy-Connection: keep-alive\r\n\r\n"),
2805 MockWrite("GET /1 HTTP/1.1\r\n"
2806 "Host: www.google.com\r\n"
2807 "Connection: keep-alive\r\n\r\n"),
2809 MockWrite("GET /2 HTTP/1.1\r\n"
2810 "Host: www.google.com\r\n"
2811 "Connection: keep-alive\r\n\r\n"),
2814 // The proxy responds to the connect with a 407, using a persistent
2816 MockRead data_reads1
[] = {
2817 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2819 MockRead("HTTP/1.1 200 OK\r\n"),
2820 MockRead("Content-Length: 1\r\n\r\n"),
2821 MockRead(SYNCHRONOUS
, "1"),
2823 MockRead("HTTP/1.1 200 OK\r\n"),
2824 MockRead("Content-Length: 2\r\n\r\n"),
2825 MockRead(SYNCHRONOUS
, "22"),
2828 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2829 data_writes1
, arraysize(data_writes1
));
2830 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2831 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2832 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2834 TestCompletionCallback callback1
;
2835 scoped_ptr
<HttpTransaction
> trans1(
2836 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2838 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2839 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2841 rv
= callback1
.WaitForResult();
2844 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2845 ASSERT_TRUE(response1
!= NULL
);
2846 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2847 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2849 LoadTimingInfo load_timing_info1
;
2850 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2851 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2852 CONNECT_TIMING_HAS_SSL_TIMES
);
2856 TestCompletionCallback callback2
;
2857 scoped_ptr
<HttpTransaction
> trans2(
2858 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2860 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2863 rv
= callback2
.WaitForResult();
2866 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2867 ASSERT_TRUE(response2
!= NULL
);
2868 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2869 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2871 LoadTimingInfo load_timing_info2
;
2872 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2873 TestLoadTimingReusedWithPac(load_timing_info2
);
2875 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2878 session
->CloseAllConnections();
2881 // Test a simple get through an HTTPS Proxy.
2882 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2883 HttpRequestInfo request
;
2884 request
.method
= "GET";
2885 request
.url
= GURL("http://www.google.com/");
2887 // Configure against https proxy server "proxy:70".
2888 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2889 "https://proxy:70"));
2890 CapturingBoundNetLog log
;
2891 session_deps_
.net_log
= log
.bound().net_log();
2892 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2894 // Since we have proxy, should use full url
2895 MockWrite data_writes1
[] = {
2896 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2897 "Host: www.google.com\r\n"
2898 "Proxy-Connection: keep-alive\r\n\r\n"),
2901 MockRead data_reads1
[] = {
2902 MockRead("HTTP/1.1 200 OK\r\n"),
2903 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2904 MockRead("Content-Length: 100\r\n\r\n"),
2905 MockRead(SYNCHRONOUS
, OK
),
2908 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2909 data_writes1
, arraysize(data_writes1
));
2910 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2911 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2912 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2914 TestCompletionCallback callback1
;
2916 scoped_ptr
<HttpTransaction
> trans(
2917 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2919 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2920 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2922 rv
= callback1
.WaitForResult();
2925 LoadTimingInfo load_timing_info
;
2926 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2927 TestLoadTimingNotReused(load_timing_info
,
2928 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2930 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2931 ASSERT_TRUE(response
!= NULL
);
2933 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2934 EXPECT_EQ(200, response
->headers
->response_code());
2935 EXPECT_EQ(100, response
->headers
->GetContentLength());
2936 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2938 // The password prompt info should not be set.
2939 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2942 // Test a SPDY get through an HTTPS Proxy.
2943 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
2944 HttpRequestInfo request
;
2945 request
.method
= "GET";
2946 request
.url
= GURL("http://www.google.com/");
2947 request
.load_flags
= 0;
2949 // Configure against https proxy server "proxy:70".
2950 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2951 "https://proxy:70"));
2952 CapturingBoundNetLog log
;
2953 session_deps_
.net_log
= log
.bound().net_log();
2954 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2956 // fetch http://www.google.com/ via SPDY
2957 scoped_ptr
<SpdyFrame
> req(
2958 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
2959 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
2961 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2962 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2963 MockRead spdy_reads
[] = {
2964 CreateMockRead(*resp
),
2965 CreateMockRead(*data
),
2966 MockRead(ASYNC
, 0, 0),
2969 DelayedSocketData
spdy_data(
2970 1, // wait for one write to finish before reading.
2971 spdy_reads
, arraysize(spdy_reads
),
2972 spdy_writes
, arraysize(spdy_writes
));
2973 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
2975 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2976 ssl
.SetNextProto(GetParam());
2977 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2979 TestCompletionCallback callback1
;
2981 scoped_ptr
<HttpTransaction
> trans(
2982 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2984 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2985 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2987 rv
= callback1
.WaitForResult();
2990 LoadTimingInfo load_timing_info
;
2991 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2992 TestLoadTimingNotReused(load_timing_info
,
2993 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2995 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2996 ASSERT_TRUE(response
!= NULL
);
2997 ASSERT_TRUE(response
->headers
.get() != NULL
);
2998 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3000 std::string response_data
;
3001 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3002 EXPECT_EQ(kUploadData
, response_data
);
3005 // Test a SPDY get through an HTTPS Proxy.
3006 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3007 HttpRequestInfo request
;
3008 request
.method
= "GET";
3009 request
.url
= GURL("http://www.google.com/");
3010 request
.load_flags
= 0;
3012 // Configure against https proxy server "myproxy:70".
3013 session_deps_
.proxy_service
.reset(
3014 ProxyService::CreateFixed("https://myproxy:70"));
3015 CapturingBoundNetLog log
;
3016 session_deps_
.net_log
= log
.bound().net_log();
3017 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3019 // The first request will be a bare GET, the second request will be a
3020 // GET with a Proxy-Authorization header.
3021 scoped_ptr
<SpdyFrame
> req_get(
3022 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3023 const char* const kExtraAuthorizationHeaders
[] = {
3024 "proxy-authorization", "Basic Zm9vOmJhcg=="
3026 scoped_ptr
<SpdyFrame
> req_get_authorization(
3027 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3028 arraysize(kExtraAuthorizationHeaders
) / 2,
3033 MockWrite spdy_writes
[] = {
3034 CreateMockWrite(*req_get
, 1),
3035 CreateMockWrite(*req_get_authorization
, 4),
3038 // The first response is a 407 proxy authentication challenge, and the second
3039 // response will be a 200 response since the second request includes a valid
3040 // Authorization header.
3041 const char* const kExtraAuthenticationHeaders
[] = {
3042 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3044 scoped_ptr
<SpdyFrame
> resp_authentication(
3045 spdy_util_
.ConstructSpdySynReplyError(
3046 "407 Proxy Authentication Required",
3047 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3049 scoped_ptr
<SpdyFrame
> body_authentication(
3050 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3051 scoped_ptr
<SpdyFrame
> resp_data(
3052 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3053 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3054 MockRead spdy_reads
[] = {
3055 CreateMockRead(*resp_authentication
, 2),
3056 CreateMockRead(*body_authentication
, 3),
3057 CreateMockRead(*resp_data
, 5),
3058 CreateMockRead(*body_data
, 6),
3059 MockRead(ASYNC
, 0, 7),
3062 OrderedSocketData
data(
3063 spdy_reads
, arraysize(spdy_reads
),
3064 spdy_writes
, arraysize(spdy_writes
));
3065 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3067 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3068 ssl
.SetNextProto(GetParam());
3069 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3071 TestCompletionCallback callback1
;
3073 scoped_ptr
<HttpTransaction
> trans(
3074 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3076 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3077 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3079 rv
= callback1
.WaitForResult();
3082 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3084 ASSERT_TRUE(response
!= NULL
);
3085 ASSERT_TRUE(response
->headers
.get() != NULL
);
3086 EXPECT_EQ(407, response
->headers
->response_code());
3087 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3088 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3090 TestCompletionCallback callback2
;
3092 rv
= trans
->RestartWithAuth(
3093 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3094 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3096 rv
= callback2
.WaitForResult();
3099 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3101 ASSERT_TRUE(response_restart
!= NULL
);
3102 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3103 EXPECT_EQ(200, response_restart
->headers
->response_code());
3104 // The password prompt info should not be set.
3105 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3108 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3109 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3110 HttpRequestInfo request
;
3111 request
.method
= "GET";
3112 request
.url
= GURL("https://www.google.com/");
3113 request
.load_flags
= 0;
3115 // Configure against https proxy server "proxy:70".
3116 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3117 "https://proxy:70"));
3118 CapturingBoundNetLog log
;
3119 session_deps_
.net_log
= log
.bound().net_log();
3120 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3122 scoped_ptr
<HttpTransaction
> trans(
3123 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3125 // CONNECT to www.google.com:443 via SPDY
3126 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3128 // fetch https://www.google.com/ via HTTP
3130 const char get
[] = "GET / HTTP/1.1\r\n"
3131 "Host: www.google.com\r\n"
3132 "Connection: keep-alive\r\n\r\n";
3133 scoped_ptr
<SpdyFrame
> wrapped_get(
3134 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3135 scoped_ptr
<SpdyFrame
> conn_resp(
3136 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3137 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3138 "Content-Length: 10\r\n\r\n";
3139 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3140 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3141 scoped_ptr
<SpdyFrame
> wrapped_body(
3142 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3143 scoped_ptr
<SpdyFrame
> window_update(
3144 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3146 MockWrite spdy_writes
[] = {
3147 CreateMockWrite(*connect
, 1),
3148 CreateMockWrite(*wrapped_get
, 3),
3149 CreateMockWrite(*window_update
, 5),
3152 MockRead spdy_reads
[] = {
3153 CreateMockRead(*conn_resp
, 2, ASYNC
),
3154 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3155 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3156 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3157 MockRead(ASYNC
, 0, 8),
3160 OrderedSocketData
spdy_data(
3161 spdy_reads
, arraysize(spdy_reads
),
3162 spdy_writes
, arraysize(spdy_writes
));
3163 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3165 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3166 ssl
.SetNextProto(GetParam());
3167 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3168 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3169 ssl2
.was_npn_negotiated
= false;
3170 ssl2
.protocol_negotiated
= kProtoUnknown
;
3171 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3173 TestCompletionCallback callback1
;
3175 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3176 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3178 rv
= callback1
.WaitForResult();
3181 LoadTimingInfo load_timing_info
;
3182 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3183 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3185 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3186 ASSERT_TRUE(response
!= NULL
);
3187 ASSERT_TRUE(response
->headers
.get() != NULL
);
3188 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3190 std::string response_data
;
3191 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3192 EXPECT_EQ("1234567890", response_data
);
3195 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3196 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3197 HttpRequestInfo request
;
3198 request
.method
= "GET";
3199 request
.url
= GURL("https://www.google.com/");
3200 request
.load_flags
= 0;
3202 // Configure against https proxy server "proxy:70".
3203 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3204 "https://proxy:70"));
3205 CapturingBoundNetLog log
;
3206 session_deps_
.net_log
= log
.bound().net_log();
3207 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3209 scoped_ptr
<HttpTransaction
> trans(
3210 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3212 // CONNECT to www.google.com:443 via SPDY
3213 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3215 // fetch https://www.google.com/ via SPDY
3216 const char* const kMyUrl
= "https://www.google.com/";
3217 scoped_ptr
<SpdyFrame
> get(
3218 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3219 scoped_ptr
<SpdyFrame
> wrapped_get(
3220 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3221 scoped_ptr
<SpdyFrame
> conn_resp(
3222 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3223 scoped_ptr
<SpdyFrame
> get_resp(
3224 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3225 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3226 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3227 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3228 scoped_ptr
<SpdyFrame
> wrapped_body(
3229 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3230 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3231 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3232 scoped_ptr
<SpdyFrame
> window_update_body(
3233 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3235 MockWrite spdy_writes
[] = {
3236 CreateMockWrite(*connect
, 1),
3237 CreateMockWrite(*wrapped_get
, 3),
3238 CreateMockWrite(*window_update_get_resp
, 5),
3239 CreateMockWrite(*window_update_body
, 7),
3242 MockRead spdy_reads
[] = {
3243 CreateMockRead(*conn_resp
, 2, ASYNC
),
3244 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3245 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3246 MockRead(ASYNC
, 0, 8),
3249 OrderedSocketData
spdy_data(
3250 spdy_reads
, arraysize(spdy_reads
),
3251 spdy_writes
, arraysize(spdy_writes
));
3252 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3254 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3255 ssl
.SetNextProto(GetParam());
3256 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3257 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3258 ssl2
.SetNextProto(GetParam());
3259 ssl2
.protocol_negotiated
= GetParam();
3260 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3262 TestCompletionCallback callback1
;
3264 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3265 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3267 rv
= callback1
.WaitForResult();
3270 LoadTimingInfo load_timing_info
;
3271 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3272 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3274 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3275 ASSERT_TRUE(response
!= NULL
);
3276 ASSERT_TRUE(response
->headers
.get() != NULL
);
3277 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3279 std::string response_data
;
3280 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3281 EXPECT_EQ(kUploadData
, response_data
);
3284 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3285 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3286 HttpRequestInfo request
;
3287 request
.method
= "GET";
3288 request
.url
= GURL("https://www.google.com/");
3289 request
.load_flags
= 0;
3291 // Configure against https proxy server "proxy:70".
3292 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3293 "https://proxy:70"));
3294 CapturingBoundNetLog log
;
3295 session_deps_
.net_log
= log
.bound().net_log();
3296 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3298 scoped_ptr
<HttpTransaction
> trans(
3299 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3301 // CONNECT to www.google.com:443 via SPDY
3302 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3304 scoped_ptr
<SpdyFrame
> get(
3305 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3307 MockWrite spdy_writes
[] = {
3308 CreateMockWrite(*connect
, 1),
3309 CreateMockWrite(*get
, 3),
3312 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3313 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3314 MockRead spdy_reads
[] = {
3315 CreateMockRead(*resp
, 2, ASYNC
),
3316 MockRead(ASYNC
, 0, 4),
3319 OrderedSocketData
spdy_data(
3320 spdy_reads
, arraysize(spdy_reads
),
3321 spdy_writes
, arraysize(spdy_writes
));
3322 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3324 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3325 ssl
.SetNextProto(GetParam());
3326 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3327 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3328 ssl2
.SetNextProto(GetParam());
3329 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3331 TestCompletionCallback callback1
;
3333 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3336 rv
= callback1
.WaitForResult();
3337 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3339 // TODO(ttuttle): Anything else to check here?
3342 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3343 // HTTPS Proxy to different servers.
3344 TEST_P(HttpNetworkTransactionTest
,
3345 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3346 // Configure against https proxy server "proxy:70".
3347 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3348 "https://proxy:70"));
3349 CapturingBoundNetLog log
;
3350 session_deps_
.net_log
= log
.bound().net_log();
3351 scoped_refptr
<HttpNetworkSession
> session(
3352 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3354 HttpRequestInfo request1
;
3355 request1
.method
= "GET";
3356 request1
.url
= GURL("https://www.google.com/");
3357 request1
.load_flags
= 0;
3359 HttpRequestInfo request2
;
3360 request2
.method
= "GET";
3361 request2
.url
= GURL("https://news.google.com/");
3362 request2
.load_flags
= 0;
3364 // CONNECT to www.google.com:443 via SPDY.
3365 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3367 scoped_ptr
<SpdyFrame
> conn_resp1(
3368 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3370 // Fetch https://www.google.com/ via HTTP.
3371 const char get1
[] = "GET / HTTP/1.1\r\n"
3372 "Host: www.google.com\r\n"
3373 "Connection: keep-alive\r\n\r\n";
3374 scoped_ptr
<SpdyFrame
> wrapped_get1(
3375 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3376 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3377 "Content-Length: 1\r\n\r\n";
3378 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3379 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3380 scoped_ptr
<SpdyFrame
> wrapped_body1(
3381 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3382 scoped_ptr
<SpdyFrame
> window_update(
3383 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3385 // CONNECT to news.google.com:443 via SPDY.
3386 SpdySynStreamIR
connect2_ir(3);
3387 spdy_util_
.SetPriority(LOWEST
, &connect2_ir
);
3388 connect2_ir
.SetHeader(spdy_util_
.GetMethodKey(), "CONNECT");
3389 connect2_ir
.SetHeader(spdy_util_
.GetPathKey(), "news.google.com:443");
3390 connect2_ir
.SetHeader(spdy_util_
.GetHostKey(), "news.google.com");
3391 spdy_util_
.MaybeAddVersionHeader(&connect2_ir
);
3392 scoped_ptr
<SpdyFrame
> connect2(
3393 spdy_util_
.CreateFramer(false)->SerializeFrame(connect2_ir
));
3395 scoped_ptr
<SpdyFrame
> conn_resp2(
3396 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3398 // Fetch https://news.google.com/ via HTTP.
3399 const char get2
[] = "GET / HTTP/1.1\r\n"
3400 "Host: news.google.com\r\n"
3401 "Connection: keep-alive\r\n\r\n";
3402 scoped_ptr
<SpdyFrame
> wrapped_get2(
3403 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3404 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3405 "Content-Length: 2\r\n\r\n";
3406 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3407 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3408 scoped_ptr
<SpdyFrame
> wrapped_body2(
3409 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3411 MockWrite spdy_writes
[] = {
3412 CreateMockWrite(*connect1
, 0),
3413 CreateMockWrite(*wrapped_get1
, 2),
3414 CreateMockWrite(*connect2
, 5),
3415 CreateMockWrite(*wrapped_get2
, 7),
3418 MockRead spdy_reads
[] = {
3419 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3420 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3421 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3422 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3423 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3424 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3425 MockRead(ASYNC
, 0, 10),
3428 DeterministicSocketData
spdy_data(
3429 spdy_reads
, arraysize(spdy_reads
),
3430 spdy_writes
, arraysize(spdy_writes
));
3431 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3433 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3434 ssl
.SetNextProto(GetParam());
3435 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3436 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3437 ssl2
.was_npn_negotiated
= false;
3438 ssl2
.protocol_negotiated
= kProtoUnknown
;
3439 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3440 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3441 ssl3
.was_npn_negotiated
= false;
3442 ssl3
.protocol_negotiated
= kProtoUnknown
;
3443 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3445 TestCompletionCallback callback
;
3447 scoped_ptr
<HttpTransaction
> trans(
3448 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3449 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3450 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3451 // The first connect and request, each of their responses, and the body.
3452 spdy_data
.RunFor(5);
3454 rv
= callback
.WaitForResult();
3457 LoadTimingInfo load_timing_info
;
3458 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3459 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3461 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3462 ASSERT_TRUE(response
!= NULL
);
3463 ASSERT_TRUE(response
->headers
.get() != NULL
);
3464 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3466 std::string response_data
;
3467 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3468 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3470 scoped_ptr
<HttpTransaction
> trans2(
3471 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3472 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3473 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3475 // The second connect and request, each of their responses, and the body.
3476 spdy_data
.RunFor(5);
3477 rv
= callback
.WaitForResult();
3480 LoadTimingInfo load_timing_info2
;
3481 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3482 // Even though the SPDY connection is reused, a new tunnelled connection has
3483 // to be created, so the socket's load timing looks like a fresh connection.
3484 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3486 // The requests should have different IDs, since they each are using their own
3488 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3490 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3493 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3494 // HTTPS Proxy to the same server.
3495 TEST_P(HttpNetworkTransactionTest
,
3496 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3497 // Configure against https proxy server "proxy:70".
3498 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3499 "https://proxy:70"));
3500 CapturingBoundNetLog log
;
3501 session_deps_
.net_log
= log
.bound().net_log();
3502 scoped_refptr
<HttpNetworkSession
> session(
3503 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3505 HttpRequestInfo request1
;
3506 request1
.method
= "GET";
3507 request1
.url
= GURL("https://www.google.com/");
3508 request1
.load_flags
= 0;
3510 HttpRequestInfo request2
;
3511 request2
.method
= "GET";
3512 request2
.url
= GURL("https://www.google.com/2");
3513 request2
.load_flags
= 0;
3515 // CONNECT to www.google.com:443 via SPDY.
3516 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3518 scoped_ptr
<SpdyFrame
> conn_resp1(
3519 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3521 // Fetch https://www.google.com/ via HTTP.
3522 const char get1
[] = "GET / HTTP/1.1\r\n"
3523 "Host: www.google.com\r\n"
3524 "Connection: keep-alive\r\n\r\n";
3525 scoped_ptr
<SpdyFrame
> wrapped_get1(
3526 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3527 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3528 "Content-Length: 1\r\n\r\n";
3529 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3530 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3531 scoped_ptr
<SpdyFrame
> wrapped_body1(
3532 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3533 scoped_ptr
<SpdyFrame
> window_update(
3534 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3536 // Fetch https://www.google.com/2 via HTTP.
3537 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3538 "Host: www.google.com\r\n"
3539 "Connection: keep-alive\r\n\r\n";
3540 scoped_ptr
<SpdyFrame
> wrapped_get2(
3541 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3542 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3543 "Content-Length: 2\r\n\r\n";
3544 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3545 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3546 scoped_ptr
<SpdyFrame
> wrapped_body2(
3547 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3549 MockWrite spdy_writes
[] = {
3550 CreateMockWrite(*connect1
, 0),
3551 CreateMockWrite(*wrapped_get1
, 2),
3552 CreateMockWrite(*wrapped_get2
, 5),
3555 MockRead spdy_reads
[] = {
3556 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3557 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3558 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3559 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3560 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3561 MockRead(ASYNC
, 0, 8),
3564 DeterministicSocketData
spdy_data(
3565 spdy_reads
, arraysize(spdy_reads
),
3566 spdy_writes
, arraysize(spdy_writes
));
3567 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3569 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3570 ssl
.SetNextProto(GetParam());
3571 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3572 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3573 ssl2
.was_npn_negotiated
= false;
3574 ssl2
.protocol_negotiated
= kProtoUnknown
;
3575 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3577 TestCompletionCallback callback
;
3579 scoped_ptr
<HttpTransaction
> trans(
3580 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3581 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3583 // The first connect and request, each of their responses, and the body.
3584 spdy_data
.RunFor(5);
3586 rv
= callback
.WaitForResult();
3589 LoadTimingInfo load_timing_info
;
3590 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3591 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3593 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3594 ASSERT_TRUE(response
!= NULL
);
3595 ASSERT_TRUE(response
->headers
.get() != NULL
);
3596 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3598 std::string response_data
;
3599 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3600 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3603 scoped_ptr
<HttpTransaction
> trans2(
3604 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3605 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3608 // The second request, response, and body. There should not be a second
3610 spdy_data
.RunFor(3);
3611 rv
= callback
.WaitForResult();
3614 LoadTimingInfo load_timing_info2
;
3615 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3616 TestLoadTimingReused(load_timing_info2
);
3618 // The requests should have the same ID.
3619 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3621 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3624 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3625 // Proxy to different servers.
3626 TEST_P(HttpNetworkTransactionTest
,
3627 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3628 // Configure against https proxy server "proxy:70".
3629 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3630 "https://proxy:70"));
3631 CapturingBoundNetLog log
;
3632 session_deps_
.net_log
= log
.bound().net_log();
3633 scoped_refptr
<HttpNetworkSession
> session(
3634 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3636 HttpRequestInfo request1
;
3637 request1
.method
= "GET";
3638 request1
.url
= GURL("http://www.google.com/");
3639 request1
.load_flags
= 0;
3641 HttpRequestInfo request2
;
3642 request2
.method
= "GET";
3643 request2
.url
= GURL("http://news.google.com/");
3644 request2
.load_flags
= 0;
3646 // http://www.google.com/
3647 scoped_ptr
<SpdyHeaderBlock
> headers(
3648 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3649 scoped_ptr
<SpdyFrame
> get1(spdy_util_
.ConstructSpdyControlFrame(
3650 headers
.Pass(), false, 1, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
3651 scoped_ptr
<SpdyFrame
> get_resp1(
3652 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3653 scoped_ptr
<SpdyFrame
> body1(
3654 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3656 // http://news.google.com/
3657 scoped_ptr
<SpdyHeaderBlock
> headers2(
3658 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3659 scoped_ptr
<SpdyFrame
> get2(spdy_util_
.ConstructSpdyControlFrame(
3660 headers2
.Pass(), false, 3, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
3661 scoped_ptr
<SpdyFrame
> get_resp2(
3662 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3663 scoped_ptr
<SpdyFrame
> body2(
3664 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3666 MockWrite spdy_writes
[] = {
3667 CreateMockWrite(*get1
, 0),
3668 CreateMockWrite(*get2
, 3),
3671 MockRead spdy_reads
[] = {
3672 CreateMockRead(*get_resp1
, 1, ASYNC
),
3673 CreateMockRead(*body1
, 2, ASYNC
),
3674 CreateMockRead(*get_resp2
, 4, ASYNC
),
3675 CreateMockRead(*body2
, 5, ASYNC
),
3676 MockRead(ASYNC
, 0, 6),
3679 DeterministicSocketData
spdy_data(
3680 spdy_reads
, arraysize(spdy_reads
),
3681 spdy_writes
, arraysize(spdy_writes
));
3682 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3684 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3685 ssl
.SetNextProto(GetParam());
3686 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3688 TestCompletionCallback callback
;
3690 scoped_ptr
<HttpTransaction
> trans(
3691 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3692 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3693 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3694 spdy_data
.RunFor(2);
3696 rv
= callback
.WaitForResult();
3699 LoadTimingInfo load_timing_info
;
3700 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3701 TestLoadTimingNotReused(load_timing_info
,
3702 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3704 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3705 ASSERT_TRUE(response
!= NULL
);
3706 ASSERT_TRUE(response
->headers
.get() != NULL
);
3707 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3709 std::string response_data
;
3710 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3711 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3712 spdy_data
.RunFor(1);
3713 EXPECT_EQ(1, callback
.WaitForResult());
3714 // Delete the first request, so the second one can reuse the socket.
3717 scoped_ptr
<HttpTransaction
> trans2(
3718 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3719 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3720 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3722 spdy_data
.RunFor(2);
3723 rv
= callback
.WaitForResult();
3726 LoadTimingInfo load_timing_info2
;
3727 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3728 TestLoadTimingReused(load_timing_info2
);
3730 // The requests should have the same ID.
3731 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3733 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3734 spdy_data
.RunFor(1);
3735 EXPECT_EQ(2, callback
.WaitForResult());
3738 // Test the challenge-response-retry sequence through an HTTPS Proxy
3739 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3740 HttpRequestInfo request
;
3741 request
.method
= "GET";
3742 request
.url
= GURL("http://www.google.com/");
3743 // when the no authentication data flag is set.
3744 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3746 // Configure against https proxy server "myproxy:70".
3747 session_deps_
.proxy_service
.reset(
3748 ProxyService::CreateFixed("https://myproxy:70"));
3749 CapturingBoundNetLog log
;
3750 session_deps_
.net_log
= log
.bound().net_log();
3751 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3753 // Since we have proxy, should use full url
3754 MockWrite data_writes1
[] = {
3755 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3756 "Host: www.google.com\r\n"
3757 "Proxy-Connection: keep-alive\r\n\r\n"),
3759 // After calling trans->RestartWithAuth(), this is the request we should
3760 // be issuing -- the final header line contains the credentials.
3761 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3762 "Host: www.google.com\r\n"
3763 "Proxy-Connection: keep-alive\r\n"
3764 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3767 // The proxy responds to the GET with a 407, using a persistent
3769 MockRead data_reads1
[] = {
3771 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3772 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3773 MockRead("Proxy-Connection: keep-alive\r\n"),
3774 MockRead("Content-Length: 0\r\n\r\n"),
3776 MockRead("HTTP/1.1 200 OK\r\n"),
3777 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3778 MockRead("Content-Length: 100\r\n\r\n"),
3779 MockRead(SYNCHRONOUS
, OK
),
3782 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3783 data_writes1
, arraysize(data_writes1
));
3784 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3785 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3786 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3788 TestCompletionCallback callback1
;
3790 scoped_ptr
<HttpTransaction
> trans(
3791 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3793 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3794 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3796 rv
= callback1
.WaitForResult();
3799 LoadTimingInfo load_timing_info
;
3800 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3801 TestLoadTimingNotReused(load_timing_info
,
3802 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3804 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3805 ASSERT_TRUE(response
!= NULL
);
3806 ASSERT_FALSE(response
->headers
.get() == NULL
);
3807 EXPECT_EQ(407, response
->headers
->response_code());
3808 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3809 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3811 TestCompletionCallback callback2
;
3813 rv
= trans
->RestartWithAuth(
3814 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3815 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3817 rv
= callback2
.WaitForResult();
3820 load_timing_info
= LoadTimingInfo();
3821 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3822 // Retrying with HTTP AUTH is considered to be reusing a socket.
3823 TestLoadTimingReused(load_timing_info
);
3825 response
= trans
->GetResponseInfo();
3826 ASSERT_TRUE(response
!= NULL
);
3828 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3829 EXPECT_EQ(200, response
->headers
->response_code());
3830 EXPECT_EQ(100, response
->headers
->GetContentLength());
3831 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3833 // The password prompt info should not be set.
3834 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3837 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3838 const MockRead
& status
, int expected_status
) {
3839 HttpRequestInfo request
;
3840 request
.method
= "GET";
3841 request
.url
= GURL("https://www.google.com/");
3842 request
.load_flags
= 0;
3844 // Configure against proxy server "myproxy:70".
3845 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3846 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3848 // Since we have proxy, should try to establish tunnel.
3849 MockWrite data_writes
[] = {
3850 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3851 "Host: www.google.com\r\n"
3852 "Proxy-Connection: keep-alive\r\n\r\n"),
3855 MockRead data_reads
[] = {
3857 MockRead("Content-Length: 10\r\n\r\n"),
3858 // No response body because the test stops reading here.
3859 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3862 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3863 data_writes
, arraysize(data_writes
));
3864 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3866 TestCompletionCallback callback
;
3868 scoped_ptr
<HttpTransaction
> trans(
3869 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3871 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3872 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3874 rv
= callback
.WaitForResult();
3875 EXPECT_EQ(expected_status
, rv
);
3878 void HttpNetworkTransactionTest::ConnectStatusHelper(
3879 const MockRead
& status
) {
3880 ConnectStatusHelperWithExpectedStatus(
3881 status
, ERR_TUNNEL_CONNECTION_FAILED
);
3884 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
3885 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3888 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
3889 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3892 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
3893 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3896 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
3897 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3900 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
3901 ConnectStatusHelper(
3902 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3905 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
3906 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3909 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
3910 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3913 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
3914 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3917 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
3918 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3921 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
3922 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3925 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
3926 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3929 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
3930 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3933 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
3934 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3937 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
3938 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3941 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
3942 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3945 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
3946 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3949 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
3950 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
3953 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
3954 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3957 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
3958 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3961 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
3962 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3965 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
3966 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3969 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
3970 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3973 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
3974 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3977 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
3978 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3981 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
3982 ConnectStatusHelperWithExpectedStatus(
3983 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3984 ERR_PROXY_AUTH_UNSUPPORTED
);
3987 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
3988 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3991 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
3992 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3995 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
3996 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
3999 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4000 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4003 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4004 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4007 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4008 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4011 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4012 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4015 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4016 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4019 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4020 ConnectStatusHelper(
4021 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4024 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4025 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4028 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4029 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4032 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4033 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4036 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4037 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4040 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4041 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4044 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4045 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4048 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4049 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4052 // Test the flow when both the proxy server AND origin server require
4053 // authentication. Again, this uses basic auth for both since that is
4054 // the simplest to mock.
4055 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4056 HttpRequestInfo request
;
4057 request
.method
= "GET";
4058 request
.url
= GURL("http://www.google.com/");
4059 request
.load_flags
= 0;
4061 // Configure against proxy server "myproxy:70".
4062 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4065 scoped_ptr
<HttpTransaction
> trans(
4066 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4068 MockWrite data_writes1
[] = {
4069 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4070 "Host: www.google.com\r\n"
4071 "Proxy-Connection: keep-alive\r\n\r\n"),
4074 MockRead data_reads1
[] = {
4075 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4076 // Give a couple authenticate options (only the middle one is actually
4078 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4079 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4080 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4081 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4082 // Large content-length -- won't matter, as connection will be reset.
4083 MockRead("Content-Length: 10000\r\n\r\n"),
4084 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4087 // After calling trans->RestartWithAuth() the first time, this is the
4088 // request we should be issuing -- the final header line contains the
4089 // proxy's credentials.
4090 MockWrite data_writes2
[] = {
4091 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4092 "Host: www.google.com\r\n"
4093 "Proxy-Connection: keep-alive\r\n"
4094 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4097 // Now the proxy server lets the request pass through to origin server.
4098 // The origin server responds with a 401.
4099 MockRead data_reads2
[] = {
4100 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4101 // Note: We are using the same realm-name as the proxy server. This is
4102 // completely valid, as realms are unique across hosts.
4103 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4105 MockRead("Content-Length: 2000\r\n\r\n"),
4106 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4109 // After calling trans->RestartWithAuth() the second time, we should send
4110 // the credentials for both the proxy and origin server.
4111 MockWrite data_writes3
[] = {
4112 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4113 "Host: www.google.com\r\n"
4114 "Proxy-Connection: keep-alive\r\n"
4115 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4116 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4119 // Lastly we get the desired content.
4120 MockRead data_reads3
[] = {
4121 MockRead("HTTP/1.0 200 OK\r\n"),
4122 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4123 MockRead("Content-Length: 100\r\n\r\n"),
4124 MockRead(SYNCHRONOUS
, OK
),
4127 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4128 data_writes1
, arraysize(data_writes1
));
4129 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4130 data_writes2
, arraysize(data_writes2
));
4131 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4132 data_writes3
, arraysize(data_writes3
));
4133 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4134 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4135 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4137 TestCompletionCallback callback1
;
4139 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4140 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4142 rv
= callback1
.WaitForResult();
4145 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4146 ASSERT_TRUE(response
!= NULL
);
4147 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4149 TestCompletionCallback callback2
;
4151 rv
= trans
->RestartWithAuth(
4152 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4153 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4155 rv
= callback2
.WaitForResult();
4158 response
= trans
->GetResponseInfo();
4159 ASSERT_TRUE(response
!= NULL
);
4160 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4162 TestCompletionCallback callback3
;
4164 rv
= trans
->RestartWithAuth(
4165 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4168 rv
= callback3
.WaitForResult();
4171 response
= trans
->GetResponseInfo();
4172 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4173 EXPECT_EQ(100, response
->headers
->GetContentLength());
4176 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4177 // can't hook into its internals to cause it to generate predictable NTLM
4178 // authorization headers.
4179 #if defined(NTLM_PORTABLE)
4180 // The NTLM authentication unit tests were generated by capturing the HTTP
4181 // requests and responses using Fiddler 2 and inspecting the generated random
4182 // bytes in the debugger.
4184 // Enter the correct password and authenticate successfully.
4185 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4186 HttpRequestInfo request
;
4187 request
.method
= "GET";
4188 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4190 // Ensure load is not disrupted by flags which suppress behaviour specific
4191 // to other auth schemes.
4192 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4194 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4198 MockWrite data_writes1
[] = {
4199 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4200 "Host: 172.22.68.17\r\n"
4201 "Connection: keep-alive\r\n\r\n"),
4204 MockRead data_reads1
[] = {
4205 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4206 // Negotiate and NTLM are often requested together. However, we only want
4207 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4208 // the header that requests Negotiate for this test.
4209 MockRead("WWW-Authenticate: NTLM\r\n"),
4210 MockRead("Connection: close\r\n"),
4211 MockRead("Content-Length: 42\r\n"),
4212 MockRead("Content-Type: text/html\r\n\r\n"),
4213 // Missing content -- won't matter, as connection will be reset.
4214 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4217 MockWrite data_writes2
[] = {
4218 // After restarting with a null identity, this is the
4219 // request we should be issuing -- the final header line contains a Type
4221 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4222 "Host: 172.22.68.17\r\n"
4223 "Connection: keep-alive\r\n"
4224 "Authorization: NTLM "
4225 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4227 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4228 // (the credentials for the origin server). The second request continues
4229 // on the same connection.
4230 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4231 "Host: 172.22.68.17\r\n"
4232 "Connection: keep-alive\r\n"
4233 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4234 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4235 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4236 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4237 "ahlhx5I=\r\n\r\n"),
4240 MockRead data_reads2
[] = {
4241 // The origin server responds with a Type 2 message.
4242 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4243 MockRead("WWW-Authenticate: NTLM "
4244 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4245 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4246 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4247 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4248 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4249 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4251 MockRead("Content-Length: 42\r\n"),
4252 MockRead("Content-Type: text/html\r\n\r\n"),
4253 MockRead("You are not authorized to view this page\r\n"),
4255 // Lastly we get the desired content.
4256 MockRead("HTTP/1.1 200 OK\r\n"),
4257 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4258 MockRead("Content-Length: 13\r\n\r\n"),
4259 MockRead("Please Login\r\n"),
4260 MockRead(SYNCHRONOUS
, OK
),
4263 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4264 data_writes1
, arraysize(data_writes1
));
4265 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4266 data_writes2
, arraysize(data_writes2
));
4267 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4268 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4270 TestCompletionCallback callback1
;
4272 scoped_ptr
<HttpTransaction
> trans(
4273 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4275 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4276 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4278 rv
= callback1
.WaitForResult();
4281 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4283 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4284 ASSERT_FALSE(response
== NULL
);
4285 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4287 TestCompletionCallback callback2
;
4289 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4290 callback2
.callback());
4291 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4293 rv
= callback2
.WaitForResult();
4296 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4298 response
= trans
->GetResponseInfo();
4299 ASSERT_TRUE(response
!= NULL
);
4300 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4302 TestCompletionCallback callback3
;
4304 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4307 rv
= callback3
.WaitForResult();
4310 response
= trans
->GetResponseInfo();
4311 ASSERT_TRUE(response
!= NULL
);
4312 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4313 EXPECT_EQ(13, response
->headers
->GetContentLength());
4316 // Enter a wrong password, and then the correct one.
4317 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4318 HttpRequestInfo request
;
4319 request
.method
= "GET";
4320 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4321 request
.load_flags
= 0;
4323 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4325 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4327 MockWrite data_writes1
[] = {
4328 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4329 "Host: 172.22.68.17\r\n"
4330 "Connection: keep-alive\r\n\r\n"),
4333 MockRead data_reads1
[] = {
4334 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4335 // Negotiate and NTLM are often requested together. However, we only want
4336 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4337 // the header that requests Negotiate for this test.
4338 MockRead("WWW-Authenticate: NTLM\r\n"),
4339 MockRead("Connection: close\r\n"),
4340 MockRead("Content-Length: 42\r\n"),
4341 MockRead("Content-Type: text/html\r\n\r\n"),
4342 // Missing content -- won't matter, as connection will be reset.
4343 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4346 MockWrite data_writes2
[] = {
4347 // After restarting with a null identity, this is the
4348 // request we should be issuing -- the final header line contains a Type
4350 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4351 "Host: 172.22.68.17\r\n"
4352 "Connection: keep-alive\r\n"
4353 "Authorization: NTLM "
4354 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4356 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4357 // (the credentials for the origin server). The second request continues
4358 // on the same connection.
4359 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4360 "Host: 172.22.68.17\r\n"
4361 "Connection: keep-alive\r\n"
4362 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4363 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4364 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4365 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4366 "4Ww7b7E=\r\n\r\n"),
4369 MockRead data_reads2
[] = {
4370 // The origin server responds with a Type 2 message.
4371 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4372 MockRead("WWW-Authenticate: NTLM "
4373 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4374 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4375 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4376 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4377 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4378 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4380 MockRead("Content-Length: 42\r\n"),
4381 MockRead("Content-Type: text/html\r\n\r\n"),
4382 MockRead("You are not authorized to view this page\r\n"),
4385 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4386 MockRead("WWW-Authenticate: NTLM\r\n"),
4387 MockRead("Connection: close\r\n"),
4388 MockRead("Content-Length: 42\r\n"),
4389 MockRead("Content-Type: text/html\r\n\r\n"),
4390 // Missing content -- won't matter, as connection will be reset.
4391 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4394 MockWrite data_writes3
[] = {
4395 // After restarting with a null identity, this is the
4396 // request we should be issuing -- the final header line contains a Type
4398 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4399 "Host: 172.22.68.17\r\n"
4400 "Connection: keep-alive\r\n"
4401 "Authorization: NTLM "
4402 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4404 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4405 // (the credentials for the origin server). The second request continues
4406 // on the same connection.
4407 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4408 "Host: 172.22.68.17\r\n"
4409 "Connection: keep-alive\r\n"
4410 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4411 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4412 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4413 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4414 "+4MUm7c=\r\n\r\n"),
4417 MockRead data_reads3
[] = {
4418 // The origin server responds with a Type 2 message.
4419 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4420 MockRead("WWW-Authenticate: NTLM "
4421 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4422 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4423 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4424 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4425 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4426 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4428 MockRead("Content-Length: 42\r\n"),
4429 MockRead("Content-Type: text/html\r\n\r\n"),
4430 MockRead("You are not authorized to view this page\r\n"),
4432 // Lastly we get the desired content.
4433 MockRead("HTTP/1.1 200 OK\r\n"),
4434 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4435 MockRead("Content-Length: 13\r\n\r\n"),
4436 MockRead("Please Login\r\n"),
4437 MockRead(SYNCHRONOUS
, OK
),
4440 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4441 data_writes1
, arraysize(data_writes1
));
4442 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4443 data_writes2
, arraysize(data_writes2
));
4444 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4445 data_writes3
, arraysize(data_writes3
));
4446 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4447 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4448 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4450 TestCompletionCallback callback1
;
4452 scoped_ptr
<HttpTransaction
> trans(
4453 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4455 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4456 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4458 rv
= callback1
.WaitForResult();
4461 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4463 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4464 ASSERT_TRUE(response
!= NULL
);
4465 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4467 TestCompletionCallback callback2
;
4469 // Enter the wrong password.
4470 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4471 callback2
.callback());
4472 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4474 rv
= callback2
.WaitForResult();
4477 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4478 TestCompletionCallback callback3
;
4479 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4480 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4481 rv
= callback3
.WaitForResult();
4483 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4485 response
= trans
->GetResponseInfo();
4486 ASSERT_FALSE(response
== NULL
);
4487 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4489 TestCompletionCallback callback4
;
4491 // Now enter the right password.
4492 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4493 callback4
.callback());
4494 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4496 rv
= callback4
.WaitForResult();
4499 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4501 TestCompletionCallback callback5
;
4503 // One more roundtrip
4504 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4507 rv
= callback5
.WaitForResult();
4510 response
= trans
->GetResponseInfo();
4511 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4512 EXPECT_EQ(13, response
->headers
->GetContentLength());
4514 #endif // NTLM_PORTABLE
4516 // Test reading a server response which has only headers, and no body.
4517 // After some maximum number of bytes is consumed, the transaction should
4518 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4519 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4520 HttpRequestInfo request
;
4521 request
.method
= "GET";
4522 request
.url
= GURL("http://www.google.com/");
4523 request
.load_flags
= 0;
4525 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4526 scoped_ptr
<HttpTransaction
> trans(
4527 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4529 // Respond with 300 kb of headers (we should fail after 256 kb).
4530 std::string large_headers_string
;
4531 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4533 MockRead data_reads
[] = {
4534 MockRead("HTTP/1.0 200 OK\r\n"),
4535 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4536 MockRead("\r\nBODY"),
4537 MockRead(SYNCHRONOUS
, OK
),
4539 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4540 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4542 TestCompletionCallback callback
;
4544 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4545 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4547 rv
= callback
.WaitForResult();
4548 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4550 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4551 EXPECT_TRUE(response
== NULL
);
4554 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4555 // establish tunnel.
4556 // http://code.google.com/p/chromium/issues/detail?id=3772
4557 TEST_P(HttpNetworkTransactionTest
,
4558 DontRecycleTransportSocketForSSLTunnel
) {
4559 HttpRequestInfo request
;
4560 request
.method
= "GET";
4561 request
.url
= GURL("https://www.google.com/");
4562 request
.load_flags
= 0;
4564 // Configure against proxy server "myproxy:70".
4565 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4567 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4569 scoped_ptr
<HttpTransaction
> trans(
4570 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4572 // Since we have proxy, should try to establish tunnel.
4573 MockWrite data_writes1
[] = {
4574 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4575 "Host: www.google.com\r\n"
4576 "Proxy-Connection: keep-alive\r\n\r\n"),
4579 // The proxy responds to the connect with a 404, using a persistent
4580 // connection. Usually a proxy would return 501 (not implemented),
4581 // or 200 (tunnel established).
4582 MockRead data_reads1
[] = {
4583 MockRead("HTTP/1.1 404 Not Found\r\n"),
4584 MockRead("Content-Length: 10\r\n\r\n"),
4585 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4588 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4589 data_writes1
, arraysize(data_writes1
));
4590 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4592 TestCompletionCallback callback1
;
4594 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4595 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4597 rv
= callback1
.WaitForResult();
4598 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4600 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4601 EXPECT_TRUE(response
== NULL
);
4603 // Empty the current queue. This is necessary because idle sockets are
4604 // added to the connection pool asynchronously with a PostTask.
4605 base::MessageLoop::current()->RunUntilIdle();
4607 // We now check to make sure the TCPClientSocket was not added back to
4609 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4611 base::MessageLoop::current()->RunUntilIdle();
4612 // Make sure that the socket didn't get recycled after calling the destructor.
4613 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4616 // Make sure that we recycle a socket after reading all of the response body.
4617 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4618 HttpRequestInfo request
;
4619 request
.method
= "GET";
4620 request
.url
= GURL("http://www.google.com/");
4621 request
.load_flags
= 0;
4623 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4625 scoped_ptr
<HttpTransaction
> trans(
4626 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4628 MockRead data_reads
[] = {
4629 // A part of the response body is received with the response headers.
4630 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4631 // The rest of the response body is received in two parts.
4634 MockRead("junk"), // Should not be read!!
4635 MockRead(SYNCHRONOUS
, OK
),
4638 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4639 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4641 TestCompletionCallback callback
;
4643 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4644 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4646 rv
= callback
.WaitForResult();
4649 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4650 ASSERT_TRUE(response
!= NULL
);
4652 EXPECT_TRUE(response
->headers
.get() != NULL
);
4653 std::string status_line
= response
->headers
->GetStatusLine();
4654 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4656 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4658 std::string response_data
;
4659 rv
= ReadTransaction(trans
.get(), &response_data
);
4661 EXPECT_EQ("hello world", response_data
);
4663 // Empty the current queue. This is necessary because idle sockets are
4664 // added to the connection pool asynchronously with a PostTask.
4665 base::MessageLoop::current()->RunUntilIdle();
4667 // We now check to make sure the socket was added back to the pool.
4668 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4671 // Make sure that we recycle a SSL socket after reading all of the response
4673 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4674 HttpRequestInfo request
;
4675 request
.method
= "GET";
4676 request
.url
= GURL("https://www.google.com/");
4677 request
.load_flags
= 0;
4679 MockWrite data_writes
[] = {
4680 MockWrite("GET / HTTP/1.1\r\n"
4681 "Host: www.google.com\r\n"
4682 "Connection: keep-alive\r\n\r\n"),
4685 MockRead data_reads
[] = {
4686 MockRead("HTTP/1.1 200 OK\r\n"),
4687 MockRead("Content-Length: 11\r\n\r\n"),
4688 MockRead("hello world"),
4689 MockRead(SYNCHRONOUS
, OK
),
4692 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4693 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4695 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4696 data_writes
, arraysize(data_writes
));
4697 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4699 TestCompletionCallback callback
;
4701 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4702 scoped_ptr
<HttpTransaction
> trans(
4703 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4705 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4707 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4708 EXPECT_EQ(OK
, callback
.WaitForResult());
4710 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4711 ASSERT_TRUE(response
!= NULL
);
4712 ASSERT_TRUE(response
->headers
.get() != NULL
);
4713 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4715 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4717 std::string response_data
;
4718 rv
= ReadTransaction(trans
.get(), &response_data
);
4720 EXPECT_EQ("hello world", response_data
);
4722 // Empty the current queue. This is necessary because idle sockets are
4723 // added to the connection pool asynchronously with a PostTask.
4724 base::MessageLoop::current()->RunUntilIdle();
4726 // We now check to make sure the socket was added back to the pool.
4727 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4730 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4731 // from the pool and make sure that we recover okay.
4732 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4733 HttpRequestInfo request
;
4734 request
.method
= "GET";
4735 request
.url
= GURL("https://www.google.com/");
4736 request
.load_flags
= 0;
4738 MockWrite data_writes
[] = {
4739 MockWrite("GET / HTTP/1.1\r\n"
4740 "Host: www.google.com\r\n"
4741 "Connection: keep-alive\r\n\r\n"),
4742 MockWrite("GET / HTTP/1.1\r\n"
4743 "Host: www.google.com\r\n"
4744 "Connection: keep-alive\r\n\r\n"),
4747 MockRead data_reads
[] = {
4748 MockRead("HTTP/1.1 200 OK\r\n"),
4749 MockRead("Content-Length: 11\r\n\r\n"),
4750 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4751 MockRead("hello world"),
4752 MockRead(ASYNC
, 0, 0) // EOF
4755 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4756 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4757 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4758 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4760 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4761 data_writes
, arraysize(data_writes
));
4762 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4763 data_writes
, arraysize(data_writes
));
4764 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4765 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4767 TestCompletionCallback callback
;
4769 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4770 scoped_ptr
<HttpTransaction
> trans(
4771 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4773 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4776 EXPECT_EQ(OK
, callback
.WaitForResult());
4778 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4779 ASSERT_TRUE(response
!= NULL
);
4780 ASSERT_TRUE(response
->headers
.get() != NULL
);
4781 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4783 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4785 std::string response_data
;
4786 rv
= ReadTransaction(trans
.get(), &response_data
);
4788 EXPECT_EQ("hello world", response_data
);
4790 // Empty the current queue. This is necessary because idle sockets are
4791 // added to the connection pool asynchronously with a PostTask.
4792 base::MessageLoop::current()->RunUntilIdle();
4794 // We now check to make sure the socket was added back to the pool.
4795 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4797 // Now start the second transaction, which should reuse the previous socket.
4799 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4801 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4803 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4804 EXPECT_EQ(OK
, callback
.WaitForResult());
4806 response
= trans
->GetResponseInfo();
4807 ASSERT_TRUE(response
!= NULL
);
4808 ASSERT_TRUE(response
->headers
.get() != NULL
);
4809 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4811 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4813 rv
= ReadTransaction(trans
.get(), &response_data
);
4815 EXPECT_EQ("hello world", response_data
);
4817 // Empty the current queue. This is necessary because idle sockets are
4818 // added to the connection pool asynchronously with a PostTask.
4819 base::MessageLoop::current()->RunUntilIdle();
4821 // We now check to make sure the socket was added back to the pool.
4822 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4825 // Make sure that we recycle a socket after a zero-length response.
4826 // http://crbug.com/9880
4827 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4828 HttpRequestInfo request
;
4829 request
.method
= "GET";
4830 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4831 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4832 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4833 "rt=prt.2642,ol.2649,xjs.2951");
4834 request
.load_flags
= 0;
4836 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4838 scoped_ptr
<HttpTransaction
> trans(
4839 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4841 MockRead data_reads
[] = {
4842 MockRead("HTTP/1.1 204 No Content\r\n"
4843 "Content-Length: 0\r\n"
4844 "Content-Type: text/html\r\n\r\n"),
4845 MockRead("junk"), // Should not be read!!
4846 MockRead(SYNCHRONOUS
, OK
),
4849 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4850 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4852 TestCompletionCallback callback
;
4854 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4855 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4857 rv
= callback
.WaitForResult();
4860 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4861 ASSERT_TRUE(response
!= NULL
);
4863 EXPECT_TRUE(response
->headers
.get() != NULL
);
4864 std::string status_line
= response
->headers
->GetStatusLine();
4865 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
4867 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4869 std::string response_data
;
4870 rv
= ReadTransaction(trans
.get(), &response_data
);
4872 EXPECT_EQ("", response_data
);
4874 // Empty the current queue. This is necessary because idle sockets are
4875 // added to the connection pool asynchronously with a PostTask.
4876 base::MessageLoop::current()->RunUntilIdle();
4878 // We now check to make sure the socket was added back to the pool.
4879 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4882 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
4883 ScopedVector
<UploadElementReader
> element_readers
;
4884 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
4885 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
4887 HttpRequestInfo request
[2];
4888 // Transaction 1: a GET request that succeeds. The socket is recycled
4890 request
[0].method
= "GET";
4891 request
[0].url
= GURL("http://www.google.com/");
4892 request
[0].load_flags
= 0;
4893 // Transaction 2: a POST request. Reuses the socket kept alive from
4894 // transaction 1. The first attempts fails when writing the POST data.
4895 // This causes the transaction to retry with a new socket. The second
4896 // attempt succeeds.
4897 request
[1].method
= "POST";
4898 request
[1].url
= GURL("http://www.google.com/login.cgi");
4899 request
[1].upload_data_stream
= &upload_data_stream
;
4900 request
[1].load_flags
= 0;
4902 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4904 // The first socket is used for transaction 1 and the first attempt of
4907 // The response of transaction 1.
4908 MockRead data_reads1
[] = {
4909 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4910 MockRead("hello world"),
4911 MockRead(SYNCHRONOUS
, OK
),
4913 // The mock write results of transaction 1 and the first attempt of
4915 MockWrite data_writes1
[] = {
4916 MockWrite(SYNCHRONOUS
, 64), // GET
4917 MockWrite(SYNCHRONOUS
, 93), // POST
4918 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
4920 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4921 data_writes1
, arraysize(data_writes1
));
4923 // The second socket is used for the second attempt of transaction 2.
4925 // The response of transaction 2.
4926 MockRead data_reads2
[] = {
4927 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4928 MockRead("welcome"),
4929 MockRead(SYNCHRONOUS
, OK
),
4931 // The mock write results of the second attempt of transaction 2.
4932 MockWrite data_writes2
[] = {
4933 MockWrite(SYNCHRONOUS
, 93), // POST
4934 MockWrite(SYNCHRONOUS
, 3), // POST data
4936 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4937 data_writes2
, arraysize(data_writes2
));
4939 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4940 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4942 const char* kExpectedResponseData
[] = {
4943 "hello world", "welcome"
4946 for (int i
= 0; i
< 2; ++i
) {
4947 scoped_ptr
<HttpTransaction
> trans(
4948 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4950 TestCompletionCallback callback
;
4952 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
4953 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4955 rv
= callback
.WaitForResult();
4958 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4959 ASSERT_TRUE(response
!= NULL
);
4961 EXPECT_TRUE(response
->headers
.get() != NULL
);
4962 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4964 std::string response_data
;
4965 rv
= ReadTransaction(trans
.get(), &response_data
);
4967 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
4971 // Test the request-challenge-retry sequence for basic auth when there is
4972 // an identity in the URL. The request should be sent as normal, but when
4973 // it fails the identity from the URL is used to answer the challenge.
4974 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
4975 HttpRequestInfo request
;
4976 request
.method
= "GET";
4977 request
.url
= GURL("http://foo:b@r@www.google.com/");
4978 request
.load_flags
= LOAD_NORMAL
;
4980 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4981 scoped_ptr
<HttpTransaction
> trans(
4982 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4984 // The password contains an escaped character -- for this test to pass it
4985 // will need to be unescaped by HttpNetworkTransaction.
4986 EXPECT_EQ("b%40r", request
.url
.password());
4988 MockWrite data_writes1
[] = {
4989 MockWrite("GET / HTTP/1.1\r\n"
4990 "Host: www.google.com\r\n"
4991 "Connection: keep-alive\r\n\r\n"),
4994 MockRead data_reads1
[] = {
4995 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4996 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4997 MockRead("Content-Length: 10\r\n\r\n"),
4998 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5001 // After the challenge above, the transaction will be restarted using the
5002 // identity from the url (foo, b@r) to answer the challenge.
5003 MockWrite data_writes2
[] = {
5004 MockWrite("GET / HTTP/1.1\r\n"
5005 "Host: www.google.com\r\n"
5006 "Connection: keep-alive\r\n"
5007 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5010 MockRead data_reads2
[] = {
5011 MockRead("HTTP/1.0 200 OK\r\n"),
5012 MockRead("Content-Length: 100\r\n\r\n"),
5013 MockRead(SYNCHRONOUS
, OK
),
5016 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5017 data_writes1
, arraysize(data_writes1
));
5018 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5019 data_writes2
, arraysize(data_writes2
));
5020 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5021 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5023 TestCompletionCallback callback1
;
5024 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5025 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5026 rv
= callback1
.WaitForResult();
5028 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5030 TestCompletionCallback callback2
;
5031 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5033 rv
= callback2
.WaitForResult();
5035 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5037 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5038 ASSERT_TRUE(response
!= NULL
);
5040 // There is no challenge info, since the identity in URL worked.
5041 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5043 EXPECT_EQ(100, response
->headers
->GetContentLength());
5045 // Empty the current queue.
5046 base::MessageLoop::current()->RunUntilIdle();
5049 // Test the request-challenge-retry sequence for basic auth when there is an
5050 // incorrect identity in the URL. The identity from the URL should be used only
5052 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5053 HttpRequestInfo request
;
5054 request
.method
= "GET";
5055 // Note: the URL has a username:password in it. The password "baz" is
5056 // wrong (should be "bar").
5057 request
.url
= GURL("http://foo:baz@www.google.com/");
5059 request
.load_flags
= LOAD_NORMAL
;
5061 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5062 scoped_ptr
<HttpTransaction
> trans(
5063 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5065 MockWrite data_writes1
[] = {
5066 MockWrite("GET / HTTP/1.1\r\n"
5067 "Host: www.google.com\r\n"
5068 "Connection: keep-alive\r\n\r\n"),
5071 MockRead data_reads1
[] = {
5072 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5073 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5074 MockRead("Content-Length: 10\r\n\r\n"),
5075 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5078 // After the challenge above, the transaction will be restarted using the
5079 // identity from the url (foo, baz) to answer the challenge.
5080 MockWrite data_writes2
[] = {
5081 MockWrite("GET / HTTP/1.1\r\n"
5082 "Host: www.google.com\r\n"
5083 "Connection: keep-alive\r\n"
5084 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5087 MockRead data_reads2
[] = {
5088 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5089 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5090 MockRead("Content-Length: 10\r\n\r\n"),
5091 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5094 // After the challenge above, the transaction will be restarted using the
5095 // identity supplied by the user (foo, bar) to answer the challenge.
5096 MockWrite data_writes3
[] = {
5097 MockWrite("GET / HTTP/1.1\r\n"
5098 "Host: www.google.com\r\n"
5099 "Connection: keep-alive\r\n"
5100 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5103 MockRead data_reads3
[] = {
5104 MockRead("HTTP/1.0 200 OK\r\n"),
5105 MockRead("Content-Length: 100\r\n\r\n"),
5106 MockRead(SYNCHRONOUS
, OK
),
5109 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5110 data_writes1
, arraysize(data_writes1
));
5111 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5112 data_writes2
, arraysize(data_writes2
));
5113 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5114 data_writes3
, arraysize(data_writes3
));
5115 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5116 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5117 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5119 TestCompletionCallback callback1
;
5121 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5122 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5124 rv
= callback1
.WaitForResult();
5127 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5128 TestCompletionCallback callback2
;
5129 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5130 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5131 rv
= callback2
.WaitForResult();
5133 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5135 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5136 ASSERT_TRUE(response
!= NULL
);
5137 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5139 TestCompletionCallback callback3
;
5140 rv
= trans
->RestartWithAuth(
5141 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5142 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5143 rv
= callback3
.WaitForResult();
5145 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5147 response
= trans
->GetResponseInfo();
5148 ASSERT_TRUE(response
!= NULL
);
5150 // There is no challenge info, since the identity worked.
5151 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5153 EXPECT_EQ(100, response
->headers
->GetContentLength());
5155 // Empty the current queue.
5156 base::MessageLoop::current()->RunUntilIdle();
5160 // Test the request-challenge-retry sequence for basic auth when there is a
5161 // correct identity in the URL, but its use is being suppressed. The identity
5162 // from the URL should never be used.
5163 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5164 HttpRequestInfo request
;
5165 request
.method
= "GET";
5166 request
.url
= GURL("http://foo:bar@www.google.com/");
5167 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5169 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5170 scoped_ptr
<HttpTransaction
> trans(
5171 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5173 MockWrite data_writes1
[] = {
5174 MockWrite("GET / HTTP/1.1\r\n"
5175 "Host: www.google.com\r\n"
5176 "Connection: keep-alive\r\n\r\n"),
5179 MockRead data_reads1
[] = {
5180 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5181 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5182 MockRead("Content-Length: 10\r\n\r\n"),
5183 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5186 // After the challenge above, the transaction will be restarted using the
5187 // identity supplied by the user, not the one in the URL, to answer the
5189 MockWrite data_writes3
[] = {
5190 MockWrite("GET / HTTP/1.1\r\n"
5191 "Host: www.google.com\r\n"
5192 "Connection: keep-alive\r\n"
5193 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5196 MockRead data_reads3
[] = {
5197 MockRead("HTTP/1.0 200 OK\r\n"),
5198 MockRead("Content-Length: 100\r\n\r\n"),
5199 MockRead(SYNCHRONOUS
, OK
),
5202 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5203 data_writes1
, arraysize(data_writes1
));
5204 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5205 data_writes3
, arraysize(data_writes3
));
5206 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5207 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5209 TestCompletionCallback callback1
;
5210 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5211 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5212 rv
= callback1
.WaitForResult();
5214 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5216 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5217 ASSERT_TRUE(response
!= NULL
);
5218 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5220 TestCompletionCallback callback3
;
5221 rv
= trans
->RestartWithAuth(
5222 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5223 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5224 rv
= callback3
.WaitForResult();
5226 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5228 response
= trans
->GetResponseInfo();
5229 ASSERT_TRUE(response
!= NULL
);
5231 // There is no challenge info, since the identity worked.
5232 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5233 EXPECT_EQ(100, response
->headers
->GetContentLength());
5235 // Empty the current queue.
5236 base::MessageLoop::current()->RunUntilIdle();
5239 // Test that previously tried username/passwords for a realm get re-used.
5240 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5241 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5243 // Transaction 1: authenticate (foo, bar) on MyRealm1
5245 HttpRequestInfo request
;
5246 request
.method
= "GET";
5247 request
.url
= GURL("http://www.google.com/x/y/z");
5248 request
.load_flags
= 0;
5250 scoped_ptr
<HttpTransaction
> trans(
5251 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5253 MockWrite data_writes1
[] = {
5254 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5255 "Host: www.google.com\r\n"
5256 "Connection: keep-alive\r\n\r\n"),
5259 MockRead data_reads1
[] = {
5260 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5261 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5262 MockRead("Content-Length: 10000\r\n\r\n"),
5263 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5266 // Resend with authorization (username=foo, password=bar)
5267 MockWrite data_writes2
[] = {
5268 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5269 "Host: www.google.com\r\n"
5270 "Connection: keep-alive\r\n"
5271 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5274 // Sever accepts the authorization.
5275 MockRead data_reads2
[] = {
5276 MockRead("HTTP/1.0 200 OK\r\n"),
5277 MockRead("Content-Length: 100\r\n\r\n"),
5278 MockRead(SYNCHRONOUS
, OK
),
5281 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5282 data_writes1
, arraysize(data_writes1
));
5283 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5284 data_writes2
, arraysize(data_writes2
));
5285 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5286 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5288 TestCompletionCallback callback1
;
5290 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5291 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5293 rv
= callback1
.WaitForResult();
5296 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5297 ASSERT_TRUE(response
!= NULL
);
5298 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5300 TestCompletionCallback callback2
;
5302 rv
= trans
->RestartWithAuth(
5303 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5304 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5306 rv
= callback2
.WaitForResult();
5309 response
= trans
->GetResponseInfo();
5310 ASSERT_TRUE(response
!= NULL
);
5311 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5312 EXPECT_EQ(100, response
->headers
->GetContentLength());
5315 // ------------------------------------------------------------------------
5317 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5319 HttpRequestInfo request
;
5320 request
.method
= "GET";
5321 // Note that Transaction 1 was at /x/y/z, so this is in the same
5322 // protection space as MyRealm1.
5323 request
.url
= GURL("http://www.google.com/x/y/a/b");
5324 request
.load_flags
= 0;
5326 scoped_ptr
<HttpTransaction
> trans(
5327 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5329 MockWrite data_writes1
[] = {
5330 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5331 "Host: www.google.com\r\n"
5332 "Connection: keep-alive\r\n"
5333 // Send preemptive authorization for MyRealm1
5334 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5337 // The server didn't like the preemptive authorization, and
5338 // challenges us for a different realm (MyRealm2).
5339 MockRead data_reads1
[] = {
5340 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5341 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5342 MockRead("Content-Length: 10000\r\n\r\n"),
5343 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5346 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5347 MockWrite data_writes2
[] = {
5348 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5349 "Host: www.google.com\r\n"
5350 "Connection: keep-alive\r\n"
5351 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5354 // Sever accepts the authorization.
5355 MockRead data_reads2
[] = {
5356 MockRead("HTTP/1.0 200 OK\r\n"),
5357 MockRead("Content-Length: 100\r\n\r\n"),
5358 MockRead(SYNCHRONOUS
, OK
),
5361 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5362 data_writes1
, arraysize(data_writes1
));
5363 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5364 data_writes2
, arraysize(data_writes2
));
5365 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5366 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5368 TestCompletionCallback callback1
;
5370 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5371 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5373 rv
= callback1
.WaitForResult();
5376 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5377 ASSERT_TRUE(response
!= NULL
);
5378 ASSERT_TRUE(response
->auth_challenge
.get());
5379 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5380 EXPECT_EQ("www.google.com:80",
5381 response
->auth_challenge
->challenger
.ToString());
5382 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5383 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5385 TestCompletionCallback callback2
;
5387 rv
= trans
->RestartWithAuth(
5388 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5389 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5391 rv
= callback2
.WaitForResult();
5394 response
= trans
->GetResponseInfo();
5395 ASSERT_TRUE(response
!= NULL
);
5396 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5397 EXPECT_EQ(100, response
->headers
->GetContentLength());
5400 // ------------------------------------------------------------------------
5402 // Transaction 3: Resend a request in MyRealm's protection space --
5403 // succeed with preemptive authorization.
5405 HttpRequestInfo request
;
5406 request
.method
= "GET";
5407 request
.url
= GURL("http://www.google.com/x/y/z2");
5408 request
.load_flags
= 0;
5410 scoped_ptr
<HttpTransaction
> trans(
5411 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5413 MockWrite data_writes1
[] = {
5414 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5415 "Host: www.google.com\r\n"
5416 "Connection: keep-alive\r\n"
5417 // The authorization for MyRealm1 gets sent preemptively
5418 // (since the url is in the same protection space)
5419 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5422 // Sever accepts the preemptive authorization
5423 MockRead data_reads1
[] = {
5424 MockRead("HTTP/1.0 200 OK\r\n"),
5425 MockRead("Content-Length: 100\r\n\r\n"),
5426 MockRead(SYNCHRONOUS
, OK
),
5429 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5430 data_writes1
, arraysize(data_writes1
));
5431 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5433 TestCompletionCallback callback1
;
5435 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5438 rv
= callback1
.WaitForResult();
5441 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5442 ASSERT_TRUE(response
!= NULL
);
5444 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5445 EXPECT_EQ(100, response
->headers
->GetContentLength());
5448 // ------------------------------------------------------------------------
5450 // Transaction 4: request another URL in MyRealm (however the
5451 // url is not known to belong to the protection space, so no pre-auth).
5453 HttpRequestInfo request
;
5454 request
.method
= "GET";
5455 request
.url
= GURL("http://www.google.com/x/1");
5456 request
.load_flags
= 0;
5458 scoped_ptr
<HttpTransaction
> trans(
5459 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5461 MockWrite data_writes1
[] = {
5462 MockWrite("GET /x/1 HTTP/1.1\r\n"
5463 "Host: www.google.com\r\n"
5464 "Connection: keep-alive\r\n\r\n"),
5467 MockRead data_reads1
[] = {
5468 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5469 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5470 MockRead("Content-Length: 10000\r\n\r\n"),
5471 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5474 // Resend with authorization from MyRealm's cache.
5475 MockWrite data_writes2
[] = {
5476 MockWrite("GET /x/1 HTTP/1.1\r\n"
5477 "Host: www.google.com\r\n"
5478 "Connection: keep-alive\r\n"
5479 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5482 // Sever accepts the authorization.
5483 MockRead data_reads2
[] = {
5484 MockRead("HTTP/1.0 200 OK\r\n"),
5485 MockRead("Content-Length: 100\r\n\r\n"),
5486 MockRead(SYNCHRONOUS
, OK
),
5489 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5490 data_writes1
, arraysize(data_writes1
));
5491 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5492 data_writes2
, arraysize(data_writes2
));
5493 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5494 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5496 TestCompletionCallback callback1
;
5498 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5499 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5501 rv
= callback1
.WaitForResult();
5504 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5505 TestCompletionCallback callback2
;
5506 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5507 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5508 rv
= callback2
.WaitForResult();
5510 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5512 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5513 ASSERT_TRUE(response
!= NULL
);
5514 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5515 EXPECT_EQ(100, response
->headers
->GetContentLength());
5518 // ------------------------------------------------------------------------
5520 // Transaction 5: request a URL in MyRealm, but the server rejects the
5521 // cached identity. Should invalidate and re-prompt.
5523 HttpRequestInfo request
;
5524 request
.method
= "GET";
5525 request
.url
= GURL("http://www.google.com/p/q/t");
5526 request
.load_flags
= 0;
5528 scoped_ptr
<HttpTransaction
> trans(
5529 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5531 MockWrite data_writes1
[] = {
5532 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5533 "Host: www.google.com\r\n"
5534 "Connection: keep-alive\r\n\r\n"),
5537 MockRead data_reads1
[] = {
5538 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5539 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5540 MockRead("Content-Length: 10000\r\n\r\n"),
5541 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5544 // Resend with authorization from cache for MyRealm.
5545 MockWrite data_writes2
[] = {
5546 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5547 "Host: www.google.com\r\n"
5548 "Connection: keep-alive\r\n"
5549 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5552 // Sever rejects the authorization.
5553 MockRead data_reads2
[] = {
5554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5556 MockRead("Content-Length: 10000\r\n\r\n"),
5557 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5560 // At this point we should prompt for new credentials for MyRealm.
5561 // Restart with username=foo3, password=foo4.
5562 MockWrite data_writes3
[] = {
5563 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5564 "Host: www.google.com\r\n"
5565 "Connection: keep-alive\r\n"
5566 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5569 // Sever accepts the authorization.
5570 MockRead data_reads3
[] = {
5571 MockRead("HTTP/1.0 200 OK\r\n"),
5572 MockRead("Content-Length: 100\r\n\r\n"),
5573 MockRead(SYNCHRONOUS
, OK
),
5576 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5577 data_writes1
, arraysize(data_writes1
));
5578 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5579 data_writes2
, arraysize(data_writes2
));
5580 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5581 data_writes3
, arraysize(data_writes3
));
5582 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5583 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5584 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5586 TestCompletionCallback callback1
;
5588 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5591 rv
= callback1
.WaitForResult();
5594 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5595 TestCompletionCallback callback2
;
5596 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5597 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5598 rv
= callback2
.WaitForResult();
5600 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5602 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5603 ASSERT_TRUE(response
!= NULL
);
5604 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5606 TestCompletionCallback callback3
;
5608 rv
= trans
->RestartWithAuth(
5609 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5610 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5612 rv
= callback3
.WaitForResult();
5615 response
= trans
->GetResponseInfo();
5616 ASSERT_TRUE(response
!= NULL
);
5617 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5618 EXPECT_EQ(100, response
->headers
->GetContentLength());
5622 // Tests that nonce count increments when multiple auth attempts
5623 // are started with the same nonce.
5624 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5625 HttpAuthHandlerDigest::Factory
* digest_factory
=
5626 new HttpAuthHandlerDigest::Factory();
5627 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5628 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5629 digest_factory
->set_nonce_generator(nonce_generator
);
5630 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5631 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5633 // Transaction 1: authenticate (foo, bar) on MyRealm1
5635 HttpRequestInfo request
;
5636 request
.method
= "GET";
5637 request
.url
= GURL("http://www.google.com/x/y/z");
5638 request
.load_flags
= 0;
5640 scoped_ptr
<HttpTransaction
> trans(
5641 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5643 MockWrite data_writes1
[] = {
5644 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5645 "Host: www.google.com\r\n"
5646 "Connection: keep-alive\r\n\r\n"),
5649 MockRead data_reads1
[] = {
5650 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5651 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5652 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5653 MockRead(SYNCHRONOUS
, OK
),
5656 // Resend with authorization (username=foo, password=bar)
5657 MockWrite data_writes2
[] = {
5658 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5659 "Host: www.google.com\r\n"
5660 "Connection: keep-alive\r\n"
5661 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5662 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5663 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5664 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5667 // Sever accepts the authorization.
5668 MockRead data_reads2
[] = {
5669 MockRead("HTTP/1.0 200 OK\r\n"),
5670 MockRead(SYNCHRONOUS
, OK
),
5673 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5674 data_writes1
, arraysize(data_writes1
));
5675 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5676 data_writes2
, arraysize(data_writes2
));
5677 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5678 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5680 TestCompletionCallback callback1
;
5682 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5683 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5685 rv
= callback1
.WaitForResult();
5688 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5689 ASSERT_TRUE(response
!= NULL
);
5690 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5692 TestCompletionCallback callback2
;
5694 rv
= trans
->RestartWithAuth(
5695 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5696 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5698 rv
= callback2
.WaitForResult();
5701 response
= trans
->GetResponseInfo();
5702 ASSERT_TRUE(response
!= NULL
);
5703 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5706 // ------------------------------------------------------------------------
5708 // Transaction 2: Request another resource in digestive's protection space.
5709 // This will preemptively add an Authorization header which should have an
5710 // "nc" value of 2 (as compared to 1 in the first use.
5712 HttpRequestInfo request
;
5713 request
.method
= "GET";
5714 // Note that Transaction 1 was at /x/y/z, so this is in the same
5715 // protection space as digest.
5716 request
.url
= GURL("http://www.google.com/x/y/a/b");
5717 request
.load_flags
= 0;
5719 scoped_ptr
<HttpTransaction
> trans(
5720 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5722 MockWrite data_writes1
[] = {
5723 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5724 "Host: www.google.com\r\n"
5725 "Connection: keep-alive\r\n"
5726 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5727 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5728 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5729 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5732 // Sever accepts the authorization.
5733 MockRead data_reads1
[] = {
5734 MockRead("HTTP/1.0 200 OK\r\n"),
5735 MockRead("Content-Length: 100\r\n\r\n"),
5736 MockRead(SYNCHRONOUS
, OK
),
5739 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5740 data_writes1
, arraysize(data_writes1
));
5741 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5743 TestCompletionCallback callback1
;
5745 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5746 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5748 rv
= callback1
.WaitForResult();
5751 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5752 ASSERT_TRUE(response
!= NULL
);
5753 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5757 // Test the ResetStateForRestart() private method.
5758 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5759 // Create a transaction (the dependencies aren't important).
5760 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5761 scoped_ptr
<HttpNetworkTransaction
> trans(
5762 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5764 // Setup some state (which we expect ResetStateForRestart() will clear).
5765 trans
->read_buf_
= new IOBuffer(15);
5766 trans
->read_buf_len_
= 15;
5767 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5769 // Setup state in response_
5770 HttpResponseInfo
* response
= &trans
->response_
;
5771 response
->auth_challenge
= new AuthChallengeInfo();
5772 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5773 response
->response_time
= base::Time::Now();
5774 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5776 { // Setup state for response_.vary_data
5777 HttpRequestInfo request
;
5778 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5779 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5780 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5781 request
.extra_headers
.SetHeader("Foo", "1");
5782 request
.extra_headers
.SetHeader("bar", "23");
5783 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5786 // Cause the above state to be reset.
5787 trans
->ResetStateForRestart();
5789 // Verify that the state that needed to be reset, has been reset.
5790 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5791 EXPECT_EQ(0, trans
->read_buf_len_
);
5792 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5793 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5794 EXPECT_TRUE(response
->headers
.get() == NULL
);
5795 EXPECT_FALSE(response
->was_cached
);
5796 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5797 EXPECT_FALSE(response
->vary_data
.is_valid());
5800 // Test HTTPS connections to a site with a bad certificate
5801 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5802 HttpRequestInfo request
;
5803 request
.method
= "GET";
5804 request
.url
= GURL("https://www.google.com/");
5805 request
.load_flags
= 0;
5807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5808 scoped_ptr
<HttpTransaction
> trans(
5809 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5811 MockWrite data_writes
[] = {
5812 MockWrite("GET / HTTP/1.1\r\n"
5813 "Host: www.google.com\r\n"
5814 "Connection: keep-alive\r\n\r\n"),
5817 MockRead data_reads
[] = {
5818 MockRead("HTTP/1.0 200 OK\r\n"),
5819 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5820 MockRead("Content-Length: 100\r\n\r\n"),
5821 MockRead(SYNCHRONOUS
, OK
),
5824 StaticSocketDataProvider ssl_bad_certificate
;
5825 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5826 data_writes
, arraysize(data_writes
));
5827 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5828 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5830 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5831 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5832 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5833 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5835 TestCompletionCallback callback
;
5837 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5838 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5840 rv
= callback
.WaitForResult();
5841 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5843 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5844 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5846 rv
= callback
.WaitForResult();
5849 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5851 ASSERT_TRUE(response
!= NULL
);
5852 EXPECT_EQ(100, response
->headers
->GetContentLength());
5855 // Test HTTPS connections to a site with a bad certificate, going through a
5857 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5858 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5860 HttpRequestInfo request
;
5861 request
.method
= "GET";
5862 request
.url
= GURL("https://www.google.com/");
5863 request
.load_flags
= 0;
5865 MockWrite proxy_writes
[] = {
5866 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5867 "Host: www.google.com\r\n"
5868 "Proxy-Connection: keep-alive\r\n\r\n"),
5871 MockRead proxy_reads
[] = {
5872 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5873 MockRead(SYNCHRONOUS
, OK
)
5876 MockWrite data_writes
[] = {
5877 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5878 "Host: www.google.com\r\n"
5879 "Proxy-Connection: keep-alive\r\n\r\n"),
5880 MockWrite("GET / HTTP/1.1\r\n"
5881 "Host: www.google.com\r\n"
5882 "Connection: keep-alive\r\n\r\n"),
5885 MockRead data_reads
[] = {
5886 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5887 MockRead("HTTP/1.0 200 OK\r\n"),
5888 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5889 MockRead("Content-Length: 100\r\n\r\n"),
5890 MockRead(SYNCHRONOUS
, OK
),
5893 StaticSocketDataProvider
ssl_bad_certificate(
5894 proxy_reads
, arraysize(proxy_reads
),
5895 proxy_writes
, arraysize(proxy_writes
));
5896 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5897 data_writes
, arraysize(data_writes
));
5898 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5899 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5901 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5902 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5903 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5904 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5906 TestCompletionCallback callback
;
5908 for (int i
= 0; i
< 2; i
++) {
5909 session_deps_
.socket_factory
->ResetNextMockIndexes();
5911 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5912 scoped_ptr
<HttpTransaction
> trans(
5913 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5915 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5916 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5918 rv
= callback
.WaitForResult();
5919 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5921 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5922 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5924 rv
= callback
.WaitForResult();
5927 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5929 ASSERT_TRUE(response
!= NULL
);
5930 EXPECT_EQ(100, response
->headers
->GetContentLength());
5935 // Test HTTPS connections to a site, going through an HTTPS proxy
5936 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
5937 session_deps_
.proxy_service
.reset(
5938 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5939 CapturingNetLog net_log
;
5940 session_deps_
.net_log
= &net_log
;
5942 HttpRequestInfo request
;
5943 request
.method
= "GET";
5944 request
.url
= GURL("https://www.google.com/");
5945 request
.load_flags
= 0;
5947 MockWrite data_writes
[] = {
5948 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5949 "Host: www.google.com\r\n"
5950 "Proxy-Connection: keep-alive\r\n\r\n"),
5951 MockWrite("GET / HTTP/1.1\r\n"
5952 "Host: www.google.com\r\n"
5953 "Connection: keep-alive\r\n\r\n"),
5956 MockRead data_reads
[] = {
5957 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5958 MockRead("HTTP/1.1 200 OK\r\n"),
5959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5960 MockRead("Content-Length: 100\r\n\r\n"),
5961 MockRead(SYNCHRONOUS
, OK
),
5964 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5965 data_writes
, arraysize(data_writes
));
5966 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5967 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
5969 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5970 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5971 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
5973 TestCompletionCallback callback
;
5975 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5976 scoped_ptr
<HttpTransaction
> trans(
5977 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5979 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5980 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5982 rv
= callback
.WaitForResult();
5984 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5986 ASSERT_TRUE(response
!= NULL
);
5988 EXPECT_TRUE(response
->headers
->IsKeepAlive());
5989 EXPECT_EQ(200, response
->headers
->response_code());
5990 EXPECT_EQ(100, response
->headers
->GetContentLength());
5991 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
5993 LoadTimingInfo load_timing_info
;
5994 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
5995 TestLoadTimingNotReusedWithPac(load_timing_info
,
5996 CONNECT_TIMING_HAS_SSL_TIMES
);
5999 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6000 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6001 session_deps_
.proxy_service
.reset(
6002 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6003 CapturingNetLog net_log
;
6004 session_deps_
.net_log
= &net_log
;
6006 HttpRequestInfo request
;
6007 request
.method
= "GET";
6008 request
.url
= GURL("https://www.google.com/");
6009 request
.load_flags
= 0;
6011 MockWrite data_writes
[] = {
6012 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6013 "Host: www.google.com\r\n"
6014 "Proxy-Connection: keep-alive\r\n\r\n"),
6017 MockRead data_reads
[] = {
6018 MockRead("HTTP/1.1 302 Redirect\r\n"),
6019 MockRead("Location: http://login.example.com/\r\n"),
6020 MockRead("Content-Length: 0\r\n\r\n"),
6021 MockRead(SYNCHRONOUS
, OK
),
6024 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6025 data_writes
, arraysize(data_writes
));
6026 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6028 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6029 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6031 TestCompletionCallback callback
;
6033 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6034 scoped_ptr
<HttpTransaction
> trans(
6035 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6037 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6038 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6040 rv
= callback
.WaitForResult();
6042 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6044 ASSERT_TRUE(response
!= NULL
);
6046 EXPECT_EQ(302, response
->headers
->response_code());
6048 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6049 EXPECT_EQ("http://login.example.com/", url
);
6051 // In the case of redirects from proxies, HttpNetworkTransaction returns
6052 // timing for the proxy connection instead of the connection to the host,
6053 // and no send / receive times.
6054 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6055 LoadTimingInfo load_timing_info
;
6056 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6058 EXPECT_FALSE(load_timing_info
.socket_reused
);
6059 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6061 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6062 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6063 load_timing_info
.proxy_resolve_end
);
6064 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6065 load_timing_info
.connect_timing
.connect_start
);
6066 ExpectConnectTimingHasTimes(
6067 load_timing_info
.connect_timing
,
6068 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6070 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6071 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6072 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6075 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6076 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6077 session_deps_
.proxy_service
.reset(
6078 ProxyService::CreateFixed("https://proxy:70"));
6080 HttpRequestInfo request
;
6081 request
.method
= "GET";
6082 request
.url
= GURL("https://www.google.com/");
6083 request
.load_flags
= 0;
6085 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6087 scoped_ptr
<SpdyFrame
> goaway(
6088 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6089 MockWrite data_writes
[] = {
6090 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6091 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6094 static const char* const kExtraHeaders
[] = {
6096 "http://login.example.com/",
6098 scoped_ptr
<SpdyFrame
> resp(
6099 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6100 arraysize(kExtraHeaders
)/2, 1));
6101 MockRead data_reads
[] = {
6102 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6103 MockRead(ASYNC
, 0, 2), // EOF
6106 DelayedSocketData
data(
6107 1, // wait for one write to finish before reading.
6108 data_reads
, arraysize(data_reads
),
6109 data_writes
, arraysize(data_writes
));
6110 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6111 proxy_ssl
.SetNextProto(GetParam());
6113 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6114 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6116 TestCompletionCallback callback
;
6118 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6119 scoped_ptr
<HttpTransaction
> trans(
6120 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6122 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6125 rv
= callback
.WaitForResult();
6127 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6129 ASSERT_TRUE(response
!= NULL
);
6131 EXPECT_EQ(302, response
->headers
->response_code());
6133 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6134 EXPECT_EQ("http://login.example.com/", url
);
6137 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6138 TEST_P(HttpNetworkTransactionTest
,
6139 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6140 session_deps_
.proxy_service
.reset(
6141 ProxyService::CreateFixed("https://proxy:70"));
6143 HttpRequestInfo request
;
6144 request
.method
= "GET";
6145 request
.url
= GURL("https://www.google.com/");
6146 request
.load_flags
= 0;
6148 MockWrite data_writes
[] = {
6149 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6150 "Host: www.google.com\r\n"
6151 "Proxy-Connection: keep-alive\r\n\r\n"),
6154 MockRead data_reads
[] = {
6155 MockRead("HTTP/1.1 404 Not Found\r\n"),
6156 MockRead("Content-Length: 23\r\n\r\n"),
6157 MockRead("The host does not exist"),
6158 MockRead(SYNCHRONOUS
, OK
),
6161 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6162 data_writes
, arraysize(data_writes
));
6163 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6165 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6166 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6168 TestCompletionCallback callback
;
6170 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6171 scoped_ptr
<HttpTransaction
> trans(
6172 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6174 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6175 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6177 rv
= callback
.WaitForResult();
6178 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6180 // TODO(ttuttle): Anything else to check here?
6183 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6184 TEST_P(HttpNetworkTransactionTest
,
6185 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6186 session_deps_
.proxy_service
.reset(
6187 ProxyService::CreateFixed("https://proxy:70"));
6189 HttpRequestInfo request
;
6190 request
.method
= "GET";
6191 request
.url
= GURL("https://www.google.com/");
6192 request
.load_flags
= 0;
6194 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6196 scoped_ptr
<SpdyFrame
> rst(
6197 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6198 MockWrite data_writes
[] = {
6199 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6200 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6203 static const char* const kExtraHeaders
[] = {
6205 "http://login.example.com/",
6207 scoped_ptr
<SpdyFrame
> resp(
6208 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6209 arraysize(kExtraHeaders
)/2, 1));
6210 scoped_ptr
<SpdyFrame
> body(
6211 spdy_util_
.ConstructSpdyBodyFrame(
6212 1, "The host does not exist", 23, true));
6213 MockRead data_reads
[] = {
6214 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6215 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6216 MockRead(ASYNC
, 0, 4), // EOF
6219 DelayedSocketData
data(
6220 1, // wait for one write to finish before reading.
6221 data_reads
, arraysize(data_reads
),
6222 data_writes
, arraysize(data_writes
));
6223 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6224 proxy_ssl
.SetNextProto(GetParam());
6226 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6227 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6229 TestCompletionCallback callback
;
6231 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6232 scoped_ptr
<HttpTransaction
> trans(
6233 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6235 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6236 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6238 rv
= callback
.WaitForResult();
6239 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6241 // TODO(ttuttle): Anything else to check here?
6244 // Test the request-challenge-retry sequence for basic auth, through
6245 // a SPDY proxy over a single SPDY session.
6246 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6247 HttpRequestInfo request
;
6248 request
.method
= "GET";
6249 request
.url
= GURL("https://www.google.com/");
6250 // when the no authentication data flag is set.
6251 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6253 // Configure against https proxy server "myproxy:70".
6254 session_deps_
.proxy_service
.reset(
6255 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6256 CapturingBoundNetLog log
;
6257 session_deps_
.net_log
= log
.bound().net_log();
6258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6260 // Since we have proxy, should try to establish tunnel.
6261 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6263 scoped_ptr
<SpdyFrame
> rst(
6264 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6266 // After calling trans->RestartWithAuth(), this is the request we should
6267 // be issuing -- the final header line contains the credentials.
6268 const char* const kAuthCredentials
[] = {
6269 "proxy-authorization", "Basic Zm9vOmJhcg==",
6271 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6272 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
));
6273 // fetch https://www.google.com/ via HTTP
6274 const char get
[] = "GET / HTTP/1.1\r\n"
6275 "Host: www.google.com\r\n"
6276 "Connection: keep-alive\r\n\r\n";
6277 scoped_ptr
<SpdyFrame
> wrapped_get(
6278 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6280 MockWrite spdy_writes
[] = {
6281 CreateMockWrite(*req
, 1, ASYNC
),
6282 CreateMockWrite(*rst
, 4, ASYNC
),
6283 CreateMockWrite(*connect2
, 5),
6284 CreateMockWrite(*wrapped_get
, 8),
6287 // The proxy responds to the connect with a 407, using a persistent
6289 const char* const kAuthChallenge
[] = {
6290 spdy_util_
.GetStatusKey(), "407 Proxy Authentication Required",
6291 spdy_util_
.GetVersionKey(), "HTTP/1.1",
6292 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6295 scoped_ptr
<SpdyFrame
> conn_auth_resp(
6296 spdy_util_
.ConstructSpdyControlFrame(NULL
,
6304 arraysize(kAuthChallenge
),
6307 scoped_ptr
<SpdyFrame
> conn_resp(
6308 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6309 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6310 "Content-Length: 5\r\n\r\n";
6312 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6313 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6314 scoped_ptr
<SpdyFrame
> wrapped_body(
6315 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6316 MockRead spdy_reads
[] = {
6317 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6318 CreateMockRead(*conn_resp
, 6, ASYNC
),
6319 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6320 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6321 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6324 OrderedSocketData
spdy_data(
6325 spdy_reads
, arraysize(spdy_reads
),
6326 spdy_writes
, arraysize(spdy_writes
));
6327 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6328 // Negotiate SPDY to the proxy
6329 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6330 proxy
.SetNextProto(GetParam());
6331 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6332 // Vanilla SSL to the server
6333 SSLSocketDataProvider
server(ASYNC
, OK
);
6334 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6336 TestCompletionCallback callback1
;
6338 scoped_ptr
<HttpTransaction
> trans(
6339 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6341 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6342 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6344 rv
= callback1
.WaitForResult();
6346 net::CapturingNetLog::CapturedEntryList entries
;
6347 log
.GetEntries(&entries
);
6348 size_t pos
= ExpectLogContainsSomewhere(
6349 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6350 NetLog::PHASE_NONE
);
6351 ExpectLogContainsSomewhere(
6353 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6354 NetLog::PHASE_NONE
);
6356 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6357 ASSERT_TRUE(response
!= NULL
);
6358 ASSERT_FALSE(response
->headers
.get() == NULL
);
6359 EXPECT_EQ(407, response
->headers
->response_code());
6360 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6361 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6362 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6364 TestCompletionCallback callback2
;
6366 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6367 callback2
.callback());
6368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6370 rv
= callback2
.WaitForResult();
6373 response
= trans
->GetResponseInfo();
6374 ASSERT_TRUE(response
!= NULL
);
6376 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6377 EXPECT_EQ(200, response
->headers
->response_code());
6378 EXPECT_EQ(5, response
->headers
->GetContentLength());
6379 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6381 // The password prompt info should not be set.
6382 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6384 LoadTimingInfo load_timing_info
;
6385 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6386 TestLoadTimingNotReusedWithPac(load_timing_info
,
6387 CONNECT_TIMING_HAS_SSL_TIMES
);
6390 session
->CloseAllConnections();
6393 // Test that an explicitly trusted SPDY proxy can push a resource from an
6394 // origin that is different from that of its associated resource.
6395 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6396 HttpRequestInfo request
;
6397 HttpRequestInfo push_request
;
6399 request
.method
= "GET";
6400 request
.url
= GURL("http://www.google.com/");
6401 push_request
.method
= "GET";
6402 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6404 // Configure against https proxy server "myproxy:70".
6405 session_deps_
.proxy_service
.reset(
6406 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6407 CapturingBoundNetLog log
;
6408 session_deps_
.net_log
= log
.bound().net_log();
6410 // Enable cross-origin push.
6411 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6415 scoped_ptr
<SpdyFrame
> stream1_syn(
6416 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6418 MockWrite spdy_writes
[] = {
6419 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6422 scoped_ptr
<SpdyFrame
>
6423 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6425 scoped_ptr
<SpdyFrame
>
6426 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6428 scoped_ptr
<SpdyFrame
>
6429 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6433 "http://www.another-origin.com/foo.dat"));
6434 const char kPushedData
[] = "pushed";
6435 scoped_ptr
<SpdyFrame
> stream2_body(
6436 spdy_util_
.ConstructSpdyBodyFrame(
6437 2, kPushedData
, strlen(kPushedData
), true));
6439 MockRead spdy_reads
[] = {
6440 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6441 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6442 CreateMockRead(*stream1_body
, 4, ASYNC
),
6443 CreateMockRead(*stream2_body
, 5, ASYNC
),
6444 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6447 OrderedSocketData
spdy_data(
6448 spdy_reads
, arraysize(spdy_reads
),
6449 spdy_writes
, arraysize(spdy_writes
));
6450 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6451 // Negotiate SPDY to the proxy
6452 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6453 proxy
.SetNextProto(GetParam());
6454 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6456 scoped_ptr
<HttpTransaction
> trans(
6457 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6458 TestCompletionCallback callback
;
6459 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6460 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6462 rv
= callback
.WaitForResult();
6464 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6466 scoped_ptr
<HttpTransaction
> push_trans(
6467 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6468 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6469 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6471 rv
= callback
.WaitForResult();
6473 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6475 ASSERT_TRUE(response
!= NULL
);
6476 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6478 EXPECT_EQ(200, response
->headers
->response_code());
6479 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6481 std::string response_data
;
6482 rv
= ReadTransaction(trans
.get(), &response_data
);
6484 EXPECT_EQ("hello!", response_data
);
6486 LoadTimingInfo load_timing_info
;
6487 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6488 TestLoadTimingNotReusedWithPac(load_timing_info
,
6489 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6491 // Verify the pushed stream.
6492 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6493 EXPECT_EQ(200, push_response
->headers
->response_code());
6495 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6497 EXPECT_EQ("pushed", response_data
);
6499 LoadTimingInfo push_load_timing_info
;
6500 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6501 TestLoadTimingReusedWithPac(push_load_timing_info
);
6502 // The transactions should share a socket ID, despite being for different
6504 EXPECT_EQ(load_timing_info
.socket_log_id
,
6505 push_load_timing_info
.socket_log_id
);
6509 session
->CloseAllConnections();
6512 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6513 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6514 HttpRequestInfo request
;
6516 request
.method
= "GET";
6517 request
.url
= GURL("http://www.google.com/");
6519 // Configure against https proxy server "myproxy:70".
6520 session_deps_
.proxy_service
.reset(
6521 ProxyService::CreateFixed("https://myproxy:70"));
6522 CapturingBoundNetLog log
;
6523 session_deps_
.net_log
= log
.bound().net_log();
6525 // Enable cross-origin push.
6526 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6528 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6530 scoped_ptr
<SpdyFrame
> stream1_syn(
6531 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6533 scoped_ptr
<SpdyFrame
> push_rst(
6534 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6536 MockWrite spdy_writes
[] = {
6537 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6538 CreateMockWrite(*push_rst
, 4),
6541 scoped_ptr
<SpdyFrame
>
6542 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6544 scoped_ptr
<SpdyFrame
>
6545 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6547 scoped_ptr
<SpdyFrame
>
6548 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6552 "https://www.another-origin.com/foo.dat"));
6554 MockRead spdy_reads
[] = {
6555 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6556 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6557 CreateMockRead(*stream1_body
, 5, ASYNC
),
6558 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6561 OrderedSocketData
spdy_data(
6562 spdy_reads
, arraysize(spdy_reads
),
6563 spdy_writes
, arraysize(spdy_writes
));
6564 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6565 // Negotiate SPDY to the proxy
6566 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6567 proxy
.SetNextProto(GetParam());
6568 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6570 scoped_ptr
<HttpTransaction
> trans(
6571 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6572 TestCompletionCallback callback
;
6573 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6574 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6576 rv
= callback
.WaitForResult();
6578 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6580 ASSERT_TRUE(response
!= NULL
);
6581 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6583 EXPECT_EQ(200, response
->headers
->response_code());
6584 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6586 std::string response_data
;
6587 rv
= ReadTransaction(trans
.get(), &response_data
);
6589 EXPECT_EQ("hello!", response_data
);
6592 session
->CloseAllConnections();
6595 // Test HTTPS connections to a site with a bad certificate, going through an
6597 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6598 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6599 "https://proxy:70"));
6601 HttpRequestInfo request
;
6602 request
.method
= "GET";
6603 request
.url
= GURL("https://www.google.com/");
6604 request
.load_flags
= 0;
6606 // Attempt to fetch the URL from a server with a bad cert
6607 MockWrite bad_cert_writes
[] = {
6608 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6609 "Host: www.google.com\r\n"
6610 "Proxy-Connection: keep-alive\r\n\r\n"),
6613 MockRead bad_cert_reads
[] = {
6614 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6615 MockRead(SYNCHRONOUS
, OK
)
6618 // Attempt to fetch the URL with a good cert
6619 MockWrite good_data_writes
[] = {
6620 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6621 "Host: www.google.com\r\n"
6622 "Proxy-Connection: keep-alive\r\n\r\n"),
6623 MockWrite("GET / HTTP/1.1\r\n"
6624 "Host: www.google.com\r\n"
6625 "Connection: keep-alive\r\n\r\n"),
6628 MockRead good_cert_reads
[] = {
6629 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6630 MockRead("HTTP/1.0 200 OK\r\n"),
6631 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6632 MockRead("Content-Length: 100\r\n\r\n"),
6633 MockRead(SYNCHRONOUS
, OK
),
6636 StaticSocketDataProvider
ssl_bad_certificate(
6637 bad_cert_reads
, arraysize(bad_cert_reads
),
6638 bad_cert_writes
, arraysize(bad_cert_writes
));
6639 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6640 good_data_writes
, arraysize(good_data_writes
));
6641 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6642 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6644 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6645 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6646 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6647 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6649 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6650 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6651 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6652 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6654 TestCompletionCallback callback
;
6656 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6657 scoped_ptr
<HttpTransaction
> trans(
6658 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6660 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6661 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6663 rv
= callback
.WaitForResult();
6664 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6666 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6667 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6669 rv
= callback
.WaitForResult();
6672 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6674 ASSERT_TRUE(response
!= NULL
);
6675 EXPECT_EQ(100, response
->headers
->GetContentLength());
6678 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6679 HttpRequestInfo request
;
6680 request
.method
= "GET";
6681 request
.url
= GURL("http://www.google.com/");
6682 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6683 "Chromium Ultra Awesome X Edition");
6685 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6686 scoped_ptr
<HttpTransaction
> trans(
6687 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6689 MockWrite data_writes
[] = {
6690 MockWrite("GET / HTTP/1.1\r\n"
6691 "Host: www.google.com\r\n"
6692 "Connection: keep-alive\r\n"
6693 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6696 // Lastly, the server responds with the actual content.
6697 MockRead data_reads
[] = {
6698 MockRead("HTTP/1.0 200 OK\r\n"),
6699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6700 MockRead("Content-Length: 100\r\n\r\n"),
6701 MockRead(SYNCHRONOUS
, OK
),
6704 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6705 data_writes
, arraysize(data_writes
));
6706 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6708 TestCompletionCallback callback
;
6710 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6711 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6713 rv
= callback
.WaitForResult();
6717 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6718 HttpRequestInfo request
;
6719 request
.method
= "GET";
6720 request
.url
= GURL("https://www.google.com/");
6721 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6722 "Chromium Ultra Awesome X Edition");
6724 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6725 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6726 scoped_ptr
<HttpTransaction
> trans(
6727 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6729 MockWrite data_writes
[] = {
6730 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6731 "Host: www.google.com\r\n"
6732 "Proxy-Connection: keep-alive\r\n"
6733 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6735 MockRead data_reads
[] = {
6736 // Return an error, so the transaction stops here (this test isn't
6737 // interested in the rest).
6738 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6739 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6740 MockRead("Proxy-Connection: close\r\n\r\n"),
6743 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6744 data_writes
, arraysize(data_writes
));
6745 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6747 TestCompletionCallback callback
;
6749 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6750 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6752 rv
= callback
.WaitForResult();
6756 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6757 HttpRequestInfo request
;
6758 request
.method
= "GET";
6759 request
.url
= GURL("http://www.google.com/");
6760 request
.load_flags
= 0;
6761 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6762 "http://the.previous.site.com/");
6764 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6765 scoped_ptr
<HttpTransaction
> trans(
6766 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6768 MockWrite data_writes
[] = {
6769 MockWrite("GET / HTTP/1.1\r\n"
6770 "Host: www.google.com\r\n"
6771 "Connection: keep-alive\r\n"
6772 "Referer: http://the.previous.site.com/\r\n\r\n"),
6775 // Lastly, the server responds with the actual content.
6776 MockRead data_reads
[] = {
6777 MockRead("HTTP/1.0 200 OK\r\n"),
6778 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6779 MockRead("Content-Length: 100\r\n\r\n"),
6780 MockRead(SYNCHRONOUS
, OK
),
6783 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6784 data_writes
, arraysize(data_writes
));
6785 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6787 TestCompletionCallback callback
;
6789 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6790 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6792 rv
= callback
.WaitForResult();
6796 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6797 HttpRequestInfo request
;
6798 request
.method
= "POST";
6799 request
.url
= GURL("http://www.google.com/");
6801 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6802 scoped_ptr
<HttpTransaction
> trans(
6803 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6805 MockWrite data_writes
[] = {
6806 MockWrite("POST / HTTP/1.1\r\n"
6807 "Host: www.google.com\r\n"
6808 "Connection: keep-alive\r\n"
6809 "Content-Length: 0\r\n\r\n"),
6812 // Lastly, the server responds with the actual content.
6813 MockRead data_reads
[] = {
6814 MockRead("HTTP/1.0 200 OK\r\n"),
6815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6816 MockRead("Content-Length: 100\r\n\r\n"),
6817 MockRead(SYNCHRONOUS
, OK
),
6820 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6821 data_writes
, arraysize(data_writes
));
6822 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6824 TestCompletionCallback callback
;
6826 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6827 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6829 rv
= callback
.WaitForResult();
6833 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6834 HttpRequestInfo request
;
6835 request
.method
= "PUT";
6836 request
.url
= GURL("http://www.google.com/");
6838 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6839 scoped_ptr
<HttpTransaction
> trans(
6840 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6842 MockWrite data_writes
[] = {
6843 MockWrite("PUT / HTTP/1.1\r\n"
6844 "Host: www.google.com\r\n"
6845 "Connection: keep-alive\r\n"
6846 "Content-Length: 0\r\n\r\n"),
6849 // Lastly, the server responds with the actual content.
6850 MockRead data_reads
[] = {
6851 MockRead("HTTP/1.0 200 OK\r\n"),
6852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6853 MockRead("Content-Length: 100\r\n\r\n"),
6854 MockRead(SYNCHRONOUS
, OK
),
6857 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6858 data_writes
, arraysize(data_writes
));
6859 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6861 TestCompletionCallback callback
;
6863 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6864 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6866 rv
= callback
.WaitForResult();
6870 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6871 HttpRequestInfo request
;
6872 request
.method
= "HEAD";
6873 request
.url
= GURL("http://www.google.com/");
6875 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6876 scoped_ptr
<HttpTransaction
> trans(
6877 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6879 MockWrite data_writes
[] = {
6880 MockWrite("HEAD / HTTP/1.1\r\n"
6881 "Host: www.google.com\r\n"
6882 "Connection: keep-alive\r\n"
6883 "Content-Length: 0\r\n\r\n"),
6886 // Lastly, the server responds with the actual content.
6887 MockRead data_reads
[] = {
6888 MockRead("HTTP/1.0 200 OK\r\n"),
6889 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6890 MockRead("Content-Length: 100\r\n\r\n"),
6891 MockRead(SYNCHRONOUS
, OK
),
6894 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6895 data_writes
, arraysize(data_writes
));
6896 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6898 TestCompletionCallback callback
;
6900 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6901 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6903 rv
= callback
.WaitForResult();
6907 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
6908 HttpRequestInfo request
;
6909 request
.method
= "GET";
6910 request
.url
= GURL("http://www.google.com/");
6911 request
.load_flags
= LOAD_BYPASS_CACHE
;
6913 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6914 scoped_ptr
<HttpTransaction
> trans(
6915 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6917 MockWrite data_writes
[] = {
6918 MockWrite("GET / HTTP/1.1\r\n"
6919 "Host: www.google.com\r\n"
6920 "Connection: keep-alive\r\n"
6921 "Pragma: no-cache\r\n"
6922 "Cache-Control: no-cache\r\n\r\n"),
6925 // Lastly, the server responds with the actual content.
6926 MockRead data_reads
[] = {
6927 MockRead("HTTP/1.0 200 OK\r\n"),
6928 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6929 MockRead("Content-Length: 100\r\n\r\n"),
6930 MockRead(SYNCHRONOUS
, OK
),
6933 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6934 data_writes
, arraysize(data_writes
));
6935 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6937 TestCompletionCallback callback
;
6939 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6940 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6942 rv
= callback
.WaitForResult();
6946 TEST_P(HttpNetworkTransactionTest
,
6947 BuildRequest_CacheControlValidateCache
) {
6948 HttpRequestInfo request
;
6949 request
.method
= "GET";
6950 request
.url
= GURL("http://www.google.com/");
6951 request
.load_flags
= LOAD_VALIDATE_CACHE
;
6953 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6954 scoped_ptr
<HttpTransaction
> trans(
6955 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6957 MockWrite data_writes
[] = {
6958 MockWrite("GET / HTTP/1.1\r\n"
6959 "Host: www.google.com\r\n"
6960 "Connection: keep-alive\r\n"
6961 "Cache-Control: max-age=0\r\n\r\n"),
6964 // Lastly, the server responds with the actual content.
6965 MockRead data_reads
[] = {
6966 MockRead("HTTP/1.0 200 OK\r\n"),
6967 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6968 MockRead("Content-Length: 100\r\n\r\n"),
6969 MockRead(SYNCHRONOUS
, OK
),
6972 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6973 data_writes
, arraysize(data_writes
));
6974 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6976 TestCompletionCallback callback
;
6978 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6981 rv
= callback
.WaitForResult();
6985 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
6986 HttpRequestInfo request
;
6987 request
.method
= "GET";
6988 request
.url
= GURL("http://www.google.com/");
6989 request
.extra_headers
.SetHeader("FooHeader", "Bar");
6991 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6992 scoped_ptr
<HttpTransaction
> trans(
6993 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6995 MockWrite data_writes
[] = {
6996 MockWrite("GET / HTTP/1.1\r\n"
6997 "Host: www.google.com\r\n"
6998 "Connection: keep-alive\r\n"
6999 "FooHeader: Bar\r\n\r\n"),
7002 // Lastly, the server responds with the actual content.
7003 MockRead data_reads
[] = {
7004 MockRead("HTTP/1.0 200 OK\r\n"),
7005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7006 MockRead("Content-Length: 100\r\n\r\n"),
7007 MockRead(SYNCHRONOUS
, OK
),
7010 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7011 data_writes
, arraysize(data_writes
));
7012 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7014 TestCompletionCallback callback
;
7016 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7017 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7019 rv
= callback
.WaitForResult();
7023 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7024 HttpRequestInfo request
;
7025 request
.method
= "GET";
7026 request
.url
= GURL("http://www.google.com/");
7027 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7028 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7029 request
.extra_headers
.SetHeader("FoO", "bar");
7031 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7032 scoped_ptr
<HttpTransaction
> trans(
7033 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7035 MockWrite data_writes
[] = {
7036 MockWrite("GET / HTTP/1.1\r\n"
7037 "Host: www.google.com\r\n"
7038 "Connection: keep-alive\r\n"
7039 "referer: www.foo.com\r\n"
7041 "FoO: bar\r\n\r\n"),
7044 // Lastly, the server responds with the actual content.
7045 MockRead data_reads
[] = {
7046 MockRead("HTTP/1.0 200 OK\r\n"),
7047 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7048 MockRead("Content-Length: 100\r\n\r\n"),
7049 MockRead(SYNCHRONOUS
, OK
),
7052 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7053 data_writes
, arraysize(data_writes
));
7054 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7056 TestCompletionCallback callback
;
7058 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7059 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7061 rv
= callback
.WaitForResult();
7065 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7066 HttpRequestInfo request
;
7067 request
.method
= "GET";
7068 request
.url
= GURL("http://www.google.com/");
7069 request
.load_flags
= 0;
7071 session_deps_
.proxy_service
.reset(
7072 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7073 CapturingNetLog net_log
;
7074 session_deps_
.net_log
= &net_log
;
7076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7077 scoped_ptr
<HttpTransaction
> trans(
7078 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7080 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7081 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7083 MockWrite data_writes
[] = {
7084 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7085 MockWrite("GET / HTTP/1.1\r\n"
7086 "Host: www.google.com\r\n"
7087 "Connection: keep-alive\r\n\r\n")
7090 MockRead data_reads
[] = {
7091 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7092 MockRead("HTTP/1.0 200 OK\r\n"),
7093 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7094 MockRead("Payload"),
7095 MockRead(SYNCHRONOUS
, OK
)
7098 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7099 data_writes
, arraysize(data_writes
));
7100 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7102 TestCompletionCallback callback
;
7104 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7105 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7107 rv
= callback
.WaitForResult();
7110 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7111 ASSERT_TRUE(response
!= NULL
);
7113 LoadTimingInfo load_timing_info
;
7114 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7115 TestLoadTimingNotReusedWithPac(load_timing_info
,
7116 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7118 std::string response_text
;
7119 rv
= ReadTransaction(trans
.get(), &response_text
);
7121 EXPECT_EQ("Payload", response_text
);
7124 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7125 HttpRequestInfo request
;
7126 request
.method
= "GET";
7127 request
.url
= GURL("https://www.google.com/");
7128 request
.load_flags
= 0;
7130 session_deps_
.proxy_service
.reset(
7131 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7132 CapturingNetLog net_log
;
7133 session_deps_
.net_log
= &net_log
;
7135 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7136 scoped_ptr
<HttpTransaction
> trans(
7137 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7139 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7140 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7142 MockWrite data_writes
[] = {
7143 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7144 arraysize(write_buffer
)),
7145 MockWrite("GET / HTTP/1.1\r\n"
7146 "Host: www.google.com\r\n"
7147 "Connection: keep-alive\r\n\r\n")
7150 MockRead data_reads
[] = {
7151 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7152 arraysize(read_buffer
)),
7153 MockRead("HTTP/1.0 200 OK\r\n"),
7154 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7155 MockRead("Payload"),
7156 MockRead(SYNCHRONOUS
, OK
)
7159 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7160 data_writes
, arraysize(data_writes
));
7161 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7163 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7164 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7166 TestCompletionCallback callback
;
7168 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7169 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7171 rv
= callback
.WaitForResult();
7174 LoadTimingInfo load_timing_info
;
7175 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7176 TestLoadTimingNotReusedWithPac(load_timing_info
,
7177 CONNECT_TIMING_HAS_SSL_TIMES
);
7179 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7180 ASSERT_TRUE(response
!= NULL
);
7182 std::string response_text
;
7183 rv
= ReadTransaction(trans
.get(), &response_text
);
7185 EXPECT_EQ("Payload", response_text
);
7188 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7189 HttpRequestInfo request
;
7190 request
.method
= "GET";
7191 request
.url
= GURL("http://www.google.com/");
7192 request
.load_flags
= 0;
7194 session_deps_
.proxy_service
.reset(
7195 ProxyService::CreateFixed("socks4://myproxy:1080"));
7196 CapturingNetLog net_log
;
7197 session_deps_
.net_log
= &net_log
;
7199 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7200 scoped_ptr
<HttpTransaction
> trans(
7201 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7203 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7204 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7206 MockWrite data_writes
[] = {
7207 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7208 MockWrite("GET / HTTP/1.1\r\n"
7209 "Host: www.google.com\r\n"
7210 "Connection: keep-alive\r\n\r\n")
7213 MockRead data_reads
[] = {
7214 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7215 MockRead("HTTP/1.0 200 OK\r\n"),
7216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7217 MockRead("Payload"),
7218 MockRead(SYNCHRONOUS
, OK
)
7221 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7222 data_writes
, arraysize(data_writes
));
7223 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7225 TestCompletionCallback callback
;
7227 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7228 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7230 rv
= callback
.WaitForResult();
7233 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7234 ASSERT_TRUE(response
!= NULL
);
7236 LoadTimingInfo load_timing_info
;
7237 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7238 TestLoadTimingNotReused(load_timing_info
,
7239 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7241 std::string response_text
;
7242 rv
= ReadTransaction(trans
.get(), &response_text
);
7244 EXPECT_EQ("Payload", response_text
);
7247 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7248 HttpRequestInfo request
;
7249 request
.method
= "GET";
7250 request
.url
= GURL("http://www.google.com/");
7251 request
.load_flags
= 0;
7253 session_deps_
.proxy_service
.reset(
7254 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7255 CapturingNetLog net_log
;
7256 session_deps_
.net_log
= &net_log
;
7258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7259 scoped_ptr
<HttpTransaction
> trans(
7260 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7262 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7263 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7264 const char kSOCKS5OkRequest
[] = {
7266 0x01, // Command (CONNECT)
7268 0x03, // Address type (DOMAINNAME).
7269 0x0E, // Length of domain (14)
7271 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7272 0x00, 0x50, // 16-bit port (80)
7274 const char kSOCKS5OkResponse
[] =
7275 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7277 MockWrite data_writes
[] = {
7278 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7279 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7280 MockWrite("GET / HTTP/1.1\r\n"
7281 "Host: www.google.com\r\n"
7282 "Connection: keep-alive\r\n\r\n")
7285 MockRead data_reads
[] = {
7286 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7287 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7288 MockRead("HTTP/1.0 200 OK\r\n"),
7289 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7290 MockRead("Payload"),
7291 MockRead(SYNCHRONOUS
, OK
)
7294 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7295 data_writes
, arraysize(data_writes
));
7296 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7298 TestCompletionCallback callback
;
7300 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7301 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7303 rv
= callback
.WaitForResult();
7306 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7307 ASSERT_TRUE(response
!= NULL
);
7309 LoadTimingInfo load_timing_info
;
7310 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7311 TestLoadTimingNotReusedWithPac(load_timing_info
,
7312 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7314 std::string response_text
;
7315 rv
= ReadTransaction(trans
.get(), &response_text
);
7317 EXPECT_EQ("Payload", response_text
);
7320 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7321 HttpRequestInfo request
;
7322 request
.method
= "GET";
7323 request
.url
= GURL("https://www.google.com/");
7324 request
.load_flags
= 0;
7326 session_deps_
.proxy_service
.reset(
7327 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7328 CapturingNetLog net_log
;
7329 session_deps_
.net_log
= &net_log
;
7331 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7332 scoped_ptr
<HttpTransaction
> trans(
7333 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7335 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7336 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7337 const unsigned char kSOCKS5OkRequest
[] = {
7339 0x01, // Command (CONNECT)
7341 0x03, // Address type (DOMAINNAME).
7342 0x0E, // Length of domain (14)
7344 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7345 0x01, 0xBB, // 16-bit port (443)
7348 const char kSOCKS5OkResponse
[] =
7349 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7351 MockWrite data_writes
[] = {
7352 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7353 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7354 arraysize(kSOCKS5OkRequest
)),
7355 MockWrite("GET / HTTP/1.1\r\n"
7356 "Host: www.google.com\r\n"
7357 "Connection: keep-alive\r\n\r\n")
7360 MockRead data_reads
[] = {
7361 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7362 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7363 MockRead("HTTP/1.0 200 OK\r\n"),
7364 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7365 MockRead("Payload"),
7366 MockRead(SYNCHRONOUS
, OK
)
7369 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7370 data_writes
, arraysize(data_writes
));
7371 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7373 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7374 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7376 TestCompletionCallback callback
;
7378 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7379 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7381 rv
= callback
.WaitForResult();
7384 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7385 ASSERT_TRUE(response
!= NULL
);
7387 LoadTimingInfo load_timing_info
;
7388 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7389 TestLoadTimingNotReusedWithPac(load_timing_info
,
7390 CONNECT_TIMING_HAS_SSL_TIMES
);
7392 std::string response_text
;
7393 rv
= ReadTransaction(trans
.get(), &response_text
);
7395 EXPECT_EQ("Payload", response_text
);
7400 // Tests that for connection endpoints the group names are correctly set.
7402 struct GroupNameTest
{
7403 std::string proxy_server
;
7405 std::string expected_group_name
;
7409 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7410 NextProto next_proto
,
7411 SpdySessionDependencies
* session_deps_
) {
7412 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7414 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7415 session
->http_server_properties();
7416 http_server_properties
->SetAlternateProtocol(
7417 HostPortPair("host.with.alternate", 80), 443,
7418 AlternateProtocolFromNextProto(next_proto
));
7423 int GroupNameTransactionHelper(
7424 const std::string
& url
,
7425 const scoped_refptr
<HttpNetworkSession
>& session
) {
7426 HttpRequestInfo request
;
7427 request
.method
= "GET";
7428 request
.url
= GURL(url
);
7429 request
.load_flags
= 0;
7431 scoped_ptr
<HttpTransaction
> trans(
7432 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7434 TestCompletionCallback callback
;
7436 // We do not complete this request, the dtor will clean the transaction up.
7437 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7442 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7443 const GroupNameTest tests
[] = {
7446 "http://www.google.com/direct",
7447 "www.google.com:80",
7452 "http://[2001:1418:13:1::25]/direct",
7453 "[2001:1418:13:1::25]:80",
7460 "https://www.google.com/direct_ssl",
7461 "ssl/www.google.com:443",
7466 "https://[2001:1418:13:1::25]/direct",
7467 "ssl/[2001:1418:13:1::25]:443",
7472 "http://host.with.alternate/direct",
7473 "ssl/host.with.alternate:443",
7478 session_deps_
.use_alternate_protocols
= true;
7480 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7481 session_deps_
.proxy_service
.reset(
7482 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7483 scoped_refptr
<HttpNetworkSession
> session(
7484 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7486 HttpNetworkSessionPeer
peer(session
);
7487 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7488 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7489 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7490 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7491 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7492 new MockClientSocketPoolManager
);
7493 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7494 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7495 peer
.SetClientSocketPoolManager(
7496 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7498 EXPECT_EQ(ERR_IO_PENDING
,
7499 GroupNameTransactionHelper(tests
[i
].url
, session
));
7501 EXPECT_EQ(tests
[i
].expected_group_name
,
7502 ssl_conn_pool
->last_group_name_received());
7504 EXPECT_EQ(tests
[i
].expected_group_name
,
7505 transport_conn_pool
->last_group_name_received());
7510 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7511 const GroupNameTest tests
[] = {
7514 "http://www.google.com/http_proxy_normal",
7515 "www.google.com:80",
7522 "https://www.google.com/http_connect_ssl",
7523 "ssl/www.google.com:443",
7529 "http://host.with.alternate/direct",
7530 "ssl/host.with.alternate:443",
7536 "ftp://ftp.google.com/http_proxy_normal",
7537 "ftp/ftp.google.com:21",
7542 session_deps_
.use_alternate_protocols
= true;
7544 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7545 session_deps_
.proxy_service
.reset(
7546 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7547 scoped_refptr
<HttpNetworkSession
> session(
7548 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7550 HttpNetworkSessionPeer
peer(session
);
7552 HostPortPair
proxy_host("http_proxy", 80);
7553 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7554 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7555 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7556 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7558 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7559 new MockClientSocketPoolManager
);
7560 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7561 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7562 peer
.SetClientSocketPoolManager(
7563 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7565 EXPECT_EQ(ERR_IO_PENDING
,
7566 GroupNameTransactionHelper(tests
[i
].url
, session
));
7568 EXPECT_EQ(tests
[i
].expected_group_name
,
7569 ssl_conn_pool
->last_group_name_received());
7571 EXPECT_EQ(tests
[i
].expected_group_name
,
7572 http_proxy_pool
->last_group_name_received());
7576 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7577 const GroupNameTest tests
[] = {
7579 "socks4://socks_proxy:1080",
7580 "http://www.google.com/socks4_direct",
7581 "socks4/www.google.com:80",
7585 "socks5://socks_proxy:1080",
7586 "http://www.google.com/socks5_direct",
7587 "socks5/www.google.com:80",
7593 "socks4://socks_proxy:1080",
7594 "https://www.google.com/socks4_ssl",
7595 "socks4/ssl/www.google.com:443",
7599 "socks5://socks_proxy:1080",
7600 "https://www.google.com/socks5_ssl",
7601 "socks5/ssl/www.google.com:443",
7606 "socks4://socks_proxy:1080",
7607 "http://host.with.alternate/direct",
7608 "socks4/ssl/host.with.alternate:443",
7613 session_deps_
.use_alternate_protocols
= true;
7615 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7616 session_deps_
.proxy_service
.reset(
7617 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7618 scoped_refptr
<HttpNetworkSession
> session(
7619 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7621 HttpNetworkSessionPeer
peer(session
);
7623 HostPortPair
proxy_host("socks_proxy", 1080);
7624 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7625 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7626 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7627 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7629 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7630 new MockClientSocketPoolManager
);
7631 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7632 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7633 peer
.SetClientSocketPoolManager(
7634 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7636 scoped_ptr
<HttpTransaction
> trans(
7637 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7639 EXPECT_EQ(ERR_IO_PENDING
,
7640 GroupNameTransactionHelper(tests
[i
].url
, session
));
7642 EXPECT_EQ(tests
[i
].expected_group_name
,
7643 ssl_conn_pool
->last_group_name_received());
7645 EXPECT_EQ(tests
[i
].expected_group_name
,
7646 socks_conn_pool
->last_group_name_received());
7650 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
7651 HttpRequestInfo request
;
7652 request
.method
= "GET";
7653 request
.url
= GURL("http://www.google.com/");
7655 session_deps_
.proxy_service
.reset(
7656 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7658 // This simulates failure resolving all hostnames; that means we will fail
7659 // connecting to both proxies (myproxy:70 and foobar:80).
7660 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
7662 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7663 scoped_ptr
<HttpTransaction
> trans(
7664 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7666 TestCompletionCallback callback
;
7668 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7669 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7671 rv
= callback
.WaitForResult();
7672 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
7675 // Base test to make sure that when the load flags for a request specify to
7676 // bypass the cache, the DNS cache is not used.
7677 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7679 // Issue a request, asking to bypass the cache(s).
7680 HttpRequestInfo request
;
7681 request
.method
= "GET";
7682 request
.load_flags
= load_flags
;
7683 request
.url
= GURL("http://www.google.com/");
7685 // Select a host resolver that does caching.
7686 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
7688 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7689 scoped_ptr
<HttpTransaction
> trans(
7690 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7692 // Warm up the host cache so it has an entry for "www.google.com".
7693 AddressList addrlist
;
7694 TestCompletionCallback callback
;
7695 int rv
= session_deps_
.host_resolver
->Resolve(
7696 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7699 callback
.callback(),
7702 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7703 rv
= callback
.WaitForResult();
7706 // Verify that it was added to host cache, by doing a subsequent async lookup
7707 // and confirming it completes synchronously.
7708 rv
= session_deps_
.host_resolver
->Resolve(
7709 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7712 callback
.callback(),
7717 // Inject a failure the next time that "www.google.com" is resolved. This way
7718 // we can tell if the next lookup hit the cache, or the "network".
7719 // (cache --> success, "network" --> failure).
7720 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
7722 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7723 // first read -- this won't be reached as the host resolution will fail first.
7724 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
7725 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7726 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7729 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7730 ASSERT_EQ(ERR_IO_PENDING
, rv
);
7731 rv
= callback
.WaitForResult();
7733 // If we bypassed the cache, we would have gotten a failure while resolving
7734 // "www.google.com".
7735 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
7738 // There are multiple load flags that should trigger the host cache bypass.
7739 // Test each in isolation:
7740 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
7741 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
7744 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
7745 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
7748 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
7749 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
7752 // Make sure we can handle an error when writing the request.
7753 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
7754 HttpRequestInfo request
;
7755 request
.method
= "GET";
7756 request
.url
= GURL("http://www.foo.com/");
7757 request
.load_flags
= 0;
7759 MockWrite write_failure
[] = {
7760 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
7762 StaticSocketDataProvider
data(NULL
, 0,
7763 write_failure
, arraysize(write_failure
));
7764 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7765 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7767 TestCompletionCallback callback
;
7769 scoped_ptr
<HttpTransaction
> trans(
7770 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7772 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7773 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7775 rv
= callback
.WaitForResult();
7776 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
7779 // Check that a connection closed after the start of the headers finishes ok.
7780 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
7781 HttpRequestInfo request
;
7782 request
.method
= "GET";
7783 request
.url
= GURL("http://www.foo.com/");
7784 request
.load_flags
= 0;
7786 MockRead data_reads
[] = {
7787 MockRead("HTTP/1."),
7788 MockRead(SYNCHRONOUS
, OK
),
7791 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7792 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7793 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7795 TestCompletionCallback callback
;
7797 scoped_ptr
<HttpTransaction
> trans(
7798 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7800 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7801 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7803 rv
= callback
.WaitForResult();
7806 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7807 ASSERT_TRUE(response
!= NULL
);
7809 EXPECT_TRUE(response
->headers
.get() != NULL
);
7810 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7812 std::string response_data
;
7813 rv
= ReadTransaction(trans
.get(), &response_data
);
7815 EXPECT_EQ("", response_data
);
7818 // Make sure that a dropped connection while draining the body for auth
7819 // restart does the right thing.
7820 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
7821 HttpRequestInfo request
;
7822 request
.method
= "GET";
7823 request
.url
= GURL("http://www.google.com/");
7824 request
.load_flags
= 0;
7826 MockWrite data_writes1
[] = {
7827 MockWrite("GET / HTTP/1.1\r\n"
7828 "Host: www.google.com\r\n"
7829 "Connection: keep-alive\r\n\r\n"),
7832 MockRead data_reads1
[] = {
7833 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7834 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7835 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7836 MockRead("Content-Length: 14\r\n\r\n"),
7838 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
7841 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7842 data_writes1
, arraysize(data_writes1
));
7843 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7845 // After calling trans->RestartWithAuth(), this is the request we should
7846 // be issuing -- the final header line contains the credentials.
7847 MockWrite data_writes2
[] = {
7848 MockWrite("GET / HTTP/1.1\r\n"
7849 "Host: www.google.com\r\n"
7850 "Connection: keep-alive\r\n"
7851 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7854 // Lastly, the server responds with the actual content.
7855 MockRead data_reads2
[] = {
7856 MockRead("HTTP/1.1 200 OK\r\n"),
7857 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7858 MockRead("Content-Length: 100\r\n\r\n"),
7859 MockRead(SYNCHRONOUS
, OK
),
7862 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7863 data_writes2
, arraysize(data_writes2
));
7864 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7865 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7867 TestCompletionCallback callback1
;
7869 scoped_ptr
<HttpTransaction
> trans(
7870 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7872 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7873 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7875 rv
= callback1
.WaitForResult();
7878 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7879 ASSERT_TRUE(response
!= NULL
);
7880 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
7882 TestCompletionCallback callback2
;
7884 rv
= trans
->RestartWithAuth(
7885 AuthCredentials(kFoo
, kBar
), callback2
.callback());
7886 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7888 rv
= callback2
.WaitForResult();
7891 response
= trans
->GetResponseInfo();
7892 ASSERT_TRUE(response
!= NULL
);
7893 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
7894 EXPECT_EQ(100, response
->headers
->GetContentLength());
7897 // Test HTTPS connections going through a proxy that sends extra data.
7898 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
7899 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7901 HttpRequestInfo request
;
7902 request
.method
= "GET";
7903 request
.url
= GURL("https://www.google.com/");
7904 request
.load_flags
= 0;
7906 MockRead proxy_reads
[] = {
7907 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7908 MockRead(SYNCHRONOUS
, OK
)
7911 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
7912 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7914 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7915 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7917 TestCompletionCallback callback
;
7919 session_deps_
.socket_factory
->ResetNextMockIndexes();
7921 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7922 scoped_ptr
<HttpTransaction
> trans(
7923 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7925 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7928 rv
= callback
.WaitForResult();
7929 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
7932 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
7933 HttpRequestInfo request
;
7934 request
.method
= "GET";
7935 request
.url
= GURL("http://www.google.com/");
7936 request
.load_flags
= 0;
7938 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7939 scoped_ptr
<HttpTransaction
> trans(
7940 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7942 MockRead data_reads
[] = {
7943 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7944 MockRead(SYNCHRONOUS
, OK
),
7947 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7948 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7950 TestCompletionCallback callback
;
7952 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7953 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7955 EXPECT_EQ(OK
, callback
.WaitForResult());
7957 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7958 ASSERT_TRUE(response
!= NULL
);
7960 EXPECT_TRUE(response
->headers
.get() != NULL
);
7961 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7963 std::string response_data
;
7964 rv
= ReadTransaction(trans
.get(), &response_data
);
7965 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
7968 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
7969 base::FilePath temp_file_path
;
7970 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
7971 const uint64 kFakeSize
= 100000; // file is actually blank
7972 UploadFileElementReader::ScopedOverridingContentLengthForTests
7973 overriding_content_length(kFakeSize
);
7975 ScopedVector
<UploadElementReader
> element_readers
;
7976 element_readers
.push_back(
7977 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7982 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
7984 HttpRequestInfo request
;
7985 request
.method
= "POST";
7986 request
.url
= GURL("http://www.google.com/upload");
7987 request
.upload_data_stream
= &upload_data_stream
;
7988 request
.load_flags
= 0;
7990 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7991 scoped_ptr
<HttpTransaction
> trans(
7992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7994 MockRead data_reads
[] = {
7995 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7996 MockRead("hello world"),
7997 MockRead(SYNCHRONOUS
, OK
),
7999 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8000 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8002 TestCompletionCallback callback
;
8004 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8005 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8007 rv
= callback
.WaitForResult();
8010 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8011 ASSERT_TRUE(response
!= NULL
);
8013 EXPECT_TRUE(response
->headers
.get() != NULL
);
8014 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8016 std::string response_data
;
8017 rv
= ReadTransaction(trans
.get(), &response_data
);
8019 EXPECT_EQ("hello world", response_data
);
8021 base::DeleteFile(temp_file_path
, false);
8024 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8025 base::FilePath temp_file
;
8026 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8027 std::string
temp_file_content("Unreadable file.");
8028 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8029 temp_file_content
.length()));
8030 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file
));
8032 ScopedVector
<UploadElementReader
> element_readers
;
8033 element_readers
.push_back(
8034 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8039 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8041 HttpRequestInfo request
;
8042 request
.method
= "POST";
8043 request
.url
= GURL("http://www.google.com/upload");
8044 request
.upload_data_stream
= &upload_data_stream
;
8045 request
.load_flags
= 0;
8047 // If we try to upload an unreadable file, the transaction should fail.
8048 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8049 scoped_ptr
<HttpTransaction
> trans(
8050 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8052 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8053 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8055 TestCompletionCallback callback
;
8057 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8058 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8060 rv
= callback
.WaitForResult();
8061 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8063 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8064 EXPECT_FALSE(response
);
8066 base::DeleteFile(temp_file
, false);
8069 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8070 class FakeUploadElementReader
: public UploadElementReader
{
8072 FakeUploadElementReader() {}
8073 virtual ~FakeUploadElementReader() {}
8075 const CompletionCallback
& callback() const { return callback_
; }
8077 // UploadElementReader overrides:
8078 virtual int Init(const CompletionCallback
& callback
) OVERRIDE
{
8079 callback_
= callback
;
8080 return ERR_IO_PENDING
;
8082 virtual uint64
GetContentLength() const OVERRIDE
{ return 0; }
8083 virtual uint64
BytesRemaining() const OVERRIDE
{ return 0; }
8084 virtual int Read(IOBuffer
* buf
,
8086 const CompletionCallback
& callback
) OVERRIDE
{
8091 CompletionCallback callback_
;
8094 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8095 ScopedVector
<UploadElementReader
> element_readers
;
8096 element_readers
.push_back(fake_reader
);
8097 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8099 HttpRequestInfo request
;
8100 request
.method
= "POST";
8101 request
.url
= GURL("http://www.google.com/upload");
8102 request
.upload_data_stream
= &upload_data_stream
;
8103 request
.load_flags
= 0;
8105 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8106 scoped_ptr
<HttpTransaction
> trans(
8107 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8109 StaticSocketDataProvider data
;
8110 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8112 TestCompletionCallback callback
;
8113 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8115 base::MessageLoop::current()->RunUntilIdle();
8117 // Transaction is pending on request body initialization.
8118 ASSERT_FALSE(fake_reader
->callback().is_null());
8120 // Return Init()'s result after the transaction gets destroyed.
8122 fake_reader
->callback().Run(OK
); // Should not crash.
8125 // Tests that changes to Auth realms are treated like auth rejections.
8126 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8128 HttpRequestInfo request
;
8129 request
.method
= "GET";
8130 request
.url
= GURL("http://www.google.com/");
8131 request
.load_flags
= 0;
8133 // First transaction will request a resource and receive a Basic challenge
8134 // with realm="first_realm".
8135 MockWrite data_writes1
[] = {
8136 MockWrite("GET / HTTP/1.1\r\n"
8137 "Host: www.google.com\r\n"
8138 "Connection: keep-alive\r\n"
8141 MockRead data_reads1
[] = {
8142 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8143 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8147 // After calling trans->RestartWithAuth(), provide an Authentication header
8148 // for first_realm. The server will reject and provide a challenge with
8150 MockWrite data_writes2
[] = {
8151 MockWrite("GET / HTTP/1.1\r\n"
8152 "Host: www.google.com\r\n"
8153 "Connection: keep-alive\r\n"
8154 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8157 MockRead data_reads2
[] = {
8158 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8159 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8163 // This again fails, and goes back to first_realm. Make sure that the
8164 // entry is removed from cache.
8165 MockWrite data_writes3
[] = {
8166 MockWrite("GET / HTTP/1.1\r\n"
8167 "Host: www.google.com\r\n"
8168 "Connection: keep-alive\r\n"
8169 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8172 MockRead data_reads3
[] = {
8173 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8174 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8178 // Try one last time (with the correct password) and get the resource.
8179 MockWrite data_writes4
[] = {
8180 MockWrite("GET / HTTP/1.1\r\n"
8181 "Host: www.google.com\r\n"
8182 "Connection: keep-alive\r\n"
8183 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8186 MockRead data_reads4
[] = {
8187 MockRead("HTTP/1.1 200 OK\r\n"
8188 "Content-Type: text/html; charset=iso-8859-1\r\n"
8189 "Content-Length: 5\r\n"
8194 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8195 data_writes1
, arraysize(data_writes1
));
8196 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8197 data_writes2
, arraysize(data_writes2
));
8198 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8199 data_writes3
, arraysize(data_writes3
));
8200 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8201 data_writes4
, arraysize(data_writes4
));
8202 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8203 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8204 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8205 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8207 TestCompletionCallback callback1
;
8209 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8210 scoped_ptr
<HttpTransaction
> trans(
8211 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8213 // Issue the first request with Authorize headers. There should be a
8214 // password prompt for first_realm waiting to be filled in after the
8215 // transaction completes.
8216 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8217 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8218 rv
= callback1
.WaitForResult();
8220 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8221 ASSERT_TRUE(response
!= NULL
);
8222 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8223 ASSERT_FALSE(challenge
== NULL
);
8224 EXPECT_FALSE(challenge
->is_proxy
);
8225 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8226 EXPECT_EQ("first_realm", challenge
->realm
);
8227 EXPECT_EQ("basic", challenge
->scheme
);
8229 // Issue the second request with an incorrect password. There should be a
8230 // password prompt for second_realm waiting to be filled in after the
8231 // transaction completes.
8232 TestCompletionCallback callback2
;
8233 rv
= trans
->RestartWithAuth(
8234 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8235 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8236 rv
= callback2
.WaitForResult();
8238 response
= trans
->GetResponseInfo();
8239 ASSERT_TRUE(response
!= NULL
);
8240 challenge
= response
->auth_challenge
.get();
8241 ASSERT_FALSE(challenge
== NULL
);
8242 EXPECT_FALSE(challenge
->is_proxy
);
8243 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8244 EXPECT_EQ("second_realm", challenge
->realm
);
8245 EXPECT_EQ("basic", challenge
->scheme
);
8247 // Issue the third request with another incorrect password. There should be
8248 // a password prompt for first_realm waiting to be filled in. If the password
8249 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8250 // first_realm was not correctly removed.
8251 TestCompletionCallback callback3
;
8252 rv
= trans
->RestartWithAuth(
8253 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8255 rv
= callback3
.WaitForResult();
8257 response
= trans
->GetResponseInfo();
8258 ASSERT_TRUE(response
!= NULL
);
8259 challenge
= response
->auth_challenge
.get();
8260 ASSERT_FALSE(challenge
== NULL
);
8261 EXPECT_FALSE(challenge
->is_proxy
);
8262 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8263 EXPECT_EQ("first_realm", challenge
->realm
);
8264 EXPECT_EQ("basic", challenge
->scheme
);
8266 // Issue the fourth request with the correct password and username.
8267 TestCompletionCallback callback4
;
8268 rv
= trans
->RestartWithAuth(
8269 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8270 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8271 rv
= callback4
.WaitForResult();
8273 response
= trans
->GetResponseInfo();
8274 ASSERT_TRUE(response
!= NULL
);
8275 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8278 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8279 session_deps_
.next_protos
= SpdyNextProtos();
8280 session_deps_
.use_alternate_protocols
= true;
8282 std::string alternate_protocol_http_header
=
8283 GetAlternateProtocolHttpHeader();
8285 MockRead data_reads
[] = {
8286 MockRead("HTTP/1.1 200 OK\r\n"),
8287 MockRead(alternate_protocol_http_header
.c_str()),
8288 MockRead("hello world"),
8289 MockRead(SYNCHRONOUS
, OK
),
8292 HttpRequestInfo request
;
8293 request
.method
= "GET";
8294 request
.url
= GURL("http://www.google.com/");
8295 request
.load_flags
= 0;
8297 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8299 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8301 TestCompletionCallback callback
;
8303 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8304 scoped_ptr
<HttpTransaction
> trans(
8305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8307 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8308 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8310 HostPortPair
http_host_port_pair("www.google.com", 80);
8311 HttpServerProperties
& http_server_properties
=
8312 *session
->http_server_properties();
8314 http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8316 EXPECT_EQ(OK
, callback
.WaitForResult());
8318 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8319 ASSERT_TRUE(response
!= NULL
);
8320 ASSERT_TRUE(response
->headers
.get() != NULL
);
8321 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8322 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8323 EXPECT_FALSE(response
->was_npn_negotiated
);
8325 std::string response_data
;
8326 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8327 EXPECT_EQ("hello world", response_data
);
8329 ASSERT_TRUE(http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8330 const PortAlternateProtocolPair alternate
=
8331 http_server_properties
.GetAlternateProtocol(http_host_port_pair
);
8332 PortAlternateProtocolPair expected_alternate
;
8333 expected_alternate
.port
= 443;
8334 expected_alternate
.protocol
= AlternateProtocolFromNextProto(GetParam());
8335 EXPECT_TRUE(expected_alternate
.Equals(alternate
));
8338 TEST_P(HttpNetworkTransactionTest
,
8339 MarkBrokenAlternateProtocolAndFallback
) {
8340 session_deps_
.use_alternate_protocols
= true;
8342 HttpRequestInfo request
;
8343 request
.method
= "GET";
8344 request
.url
= GURL("http://www.google.com/");
8345 request
.load_flags
= 0;
8347 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8348 StaticSocketDataProvider first_data
;
8349 first_data
.set_connect_data(mock_connect
);
8350 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8352 MockRead data_reads
[] = {
8353 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8354 MockRead("hello world"),
8355 MockRead(ASYNC
, OK
),
8357 StaticSocketDataProvider
second_data(
8358 data_reads
, arraysize(data_reads
), NULL
, 0);
8359 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8361 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8363 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8364 session
->http_server_properties();
8365 // Port must be < 1024, or the header will be ignored (since initial port was
8366 // port 80 (another restricted port).
8367 http_server_properties
->SetAlternateProtocol(
8368 HostPortPair::FromURL(request
.url
),
8369 666 /* port is ignored by MockConnect anyway */,
8370 AlternateProtocolFromNextProto(GetParam()));
8372 scoped_ptr
<HttpTransaction
> trans(
8373 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8374 TestCompletionCallback callback
;
8376 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8377 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8378 EXPECT_EQ(OK
, callback
.WaitForResult());
8380 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8381 ASSERT_TRUE(response
!= NULL
);
8382 ASSERT_TRUE(response
->headers
.get() != NULL
);
8383 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8385 std::string response_data
;
8386 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8387 EXPECT_EQ("hello world", response_data
);
8389 ASSERT_TRUE(http_server_properties
->HasAlternateProtocol(
8390 HostPortPair::FromURL(request
.url
)));
8391 const PortAlternateProtocolPair alternate
=
8392 http_server_properties
->GetAlternateProtocol(
8393 HostPortPair::FromURL(request
.url
));
8394 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN
, alternate
.protocol
);
8397 TEST_P(HttpNetworkTransactionTest
,
8398 AlternateProtocolPortRestrictedBlocked
) {
8399 // Ensure that we're not allowed to redirect traffic via an alternate
8400 // protocol to an unrestricted (port >= 1024) when the original traffic was
8401 // on a restricted port (port < 1024). Ensure that we can redirect in all
8403 session_deps_
.use_alternate_protocols
= true;
8405 HttpRequestInfo restricted_port_request
;
8406 restricted_port_request
.method
= "GET";
8407 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8408 restricted_port_request
.load_flags
= 0;
8410 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8411 StaticSocketDataProvider first_data
;
8412 first_data
.set_connect_data(mock_connect
);
8413 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8415 MockRead data_reads
[] = {
8416 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8417 MockRead("hello world"),
8418 MockRead(ASYNC
, OK
),
8420 StaticSocketDataProvider
second_data(
8421 data_reads
, arraysize(data_reads
), NULL
, 0);
8422 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8424 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8426 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8427 session
->http_server_properties();
8428 const int kUnrestrictedAlternatePort
= 1024;
8429 http_server_properties
->SetAlternateProtocol(
8430 HostPortPair::FromURL(restricted_port_request
.url
),
8431 kUnrestrictedAlternatePort
,
8432 AlternateProtocolFromNextProto(GetParam()));
8434 scoped_ptr
<HttpTransaction
> trans(
8435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8436 TestCompletionCallback callback
;
8438 int rv
= trans
->Start(
8439 &restricted_port_request
,
8440 callback
.callback(), BoundNetLog());
8441 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8442 // Invalid change to unrestricted port should fail.
8443 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8446 TEST_P(HttpNetworkTransactionTest
,
8447 AlternateProtocolPortRestrictedPermitted
) {
8448 // Ensure that we're allowed to redirect traffic via an alternate
8449 // protocol to an unrestricted (port >= 1024) when the original traffic was
8450 // on a restricted port (port < 1024) if we set
8451 // enable_user_alternate_protocol_ports.
8453 session_deps_
.use_alternate_protocols
= true;
8454 session_deps_
.enable_user_alternate_protocol_ports
= true;
8456 HttpRequestInfo restricted_port_request
;
8457 restricted_port_request
.method
= "GET";
8458 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8459 restricted_port_request
.load_flags
= 0;
8461 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8462 StaticSocketDataProvider first_data
;
8463 first_data
.set_connect_data(mock_connect
);
8464 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8466 MockRead data_reads
[] = {
8467 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8468 MockRead("hello world"),
8469 MockRead(ASYNC
, OK
),
8471 StaticSocketDataProvider
second_data(
8472 data_reads
, arraysize(data_reads
), NULL
, 0);
8473 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8475 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8477 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8478 session
->http_server_properties();
8479 const int kUnrestrictedAlternatePort
= 1024;
8480 http_server_properties
->SetAlternateProtocol(
8481 HostPortPair::FromURL(restricted_port_request
.url
),
8482 kUnrestrictedAlternatePort
,
8483 AlternateProtocolFromNextProto(GetParam()));
8485 scoped_ptr
<HttpTransaction
> trans(
8486 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8487 TestCompletionCallback callback
;
8489 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8490 &restricted_port_request
,
8491 callback
.callback(), BoundNetLog()));
8492 // Change to unrestricted port should succeed.
8493 EXPECT_EQ(OK
, callback
.WaitForResult());
8496 TEST_P(HttpNetworkTransactionTest
,
8497 AlternateProtocolPortRestrictedAllowed
) {
8498 // Ensure that we're not allowed to redirect traffic via an alternate
8499 // protocol to an unrestricted (port >= 1024) when the original traffic was
8500 // on a restricted port (port < 1024). Ensure that we can redirect in all
8502 session_deps_
.use_alternate_protocols
= true;
8504 HttpRequestInfo restricted_port_request
;
8505 restricted_port_request
.method
= "GET";
8506 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8507 restricted_port_request
.load_flags
= 0;
8509 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8510 StaticSocketDataProvider first_data
;
8511 first_data
.set_connect_data(mock_connect
);
8512 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8514 MockRead data_reads
[] = {
8515 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8516 MockRead("hello world"),
8517 MockRead(ASYNC
, OK
),
8519 StaticSocketDataProvider
second_data(
8520 data_reads
, arraysize(data_reads
), NULL
, 0);
8521 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8523 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8525 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8526 session
->http_server_properties();
8527 const int kRestrictedAlternatePort
= 80;
8528 http_server_properties
->SetAlternateProtocol(
8529 HostPortPair::FromURL(restricted_port_request
.url
),
8530 kRestrictedAlternatePort
,
8531 AlternateProtocolFromNextProto(GetParam()));
8533 scoped_ptr
<HttpTransaction
> trans(
8534 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8535 TestCompletionCallback callback
;
8537 int rv
= trans
->Start(
8538 &restricted_port_request
,
8539 callback
.callback(), BoundNetLog());
8540 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8541 // Valid change to restricted port should pass.
8542 EXPECT_EQ(OK
, callback
.WaitForResult());
8545 TEST_P(HttpNetworkTransactionTest
,
8546 AlternateProtocolPortUnrestrictedAllowed1
) {
8547 // Ensure that we're not allowed to redirect traffic via an alternate
8548 // protocol to an unrestricted (port >= 1024) when the original traffic was
8549 // on a restricted port (port < 1024). Ensure that we can redirect in all
8551 session_deps_
.use_alternate_protocols
= true;
8553 HttpRequestInfo unrestricted_port_request
;
8554 unrestricted_port_request
.method
= "GET";
8555 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8556 unrestricted_port_request
.load_flags
= 0;
8558 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8559 StaticSocketDataProvider first_data
;
8560 first_data
.set_connect_data(mock_connect
);
8561 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8563 MockRead data_reads
[] = {
8564 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8565 MockRead("hello world"),
8566 MockRead(ASYNC
, OK
),
8568 StaticSocketDataProvider
second_data(
8569 data_reads
, arraysize(data_reads
), NULL
, 0);
8570 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8572 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8574 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8575 session
->http_server_properties();
8576 const int kRestrictedAlternatePort
= 80;
8577 http_server_properties
->SetAlternateProtocol(
8578 HostPortPair::FromURL(unrestricted_port_request
.url
),
8579 kRestrictedAlternatePort
,
8580 AlternateProtocolFromNextProto(GetParam()));
8582 scoped_ptr
<HttpTransaction
> trans(
8583 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8584 TestCompletionCallback callback
;
8586 int rv
= trans
->Start(
8587 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8588 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8589 // Valid change to restricted port should pass.
8590 EXPECT_EQ(OK
, callback
.WaitForResult());
8593 TEST_P(HttpNetworkTransactionTest
,
8594 AlternateProtocolPortUnrestrictedAllowed2
) {
8595 // Ensure that we're not allowed to redirect traffic via an alternate
8596 // protocol to an unrestricted (port >= 1024) when the original traffic was
8597 // on a restricted port (port < 1024). Ensure that we can redirect in all
8599 session_deps_
.use_alternate_protocols
= true;
8601 HttpRequestInfo unrestricted_port_request
;
8602 unrestricted_port_request
.method
= "GET";
8603 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8604 unrestricted_port_request
.load_flags
= 0;
8606 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8607 StaticSocketDataProvider first_data
;
8608 first_data
.set_connect_data(mock_connect
);
8609 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8611 MockRead data_reads
[] = {
8612 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8613 MockRead("hello world"),
8614 MockRead(ASYNC
, OK
),
8616 StaticSocketDataProvider
second_data(
8617 data_reads
, arraysize(data_reads
), NULL
, 0);
8618 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8620 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8622 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8623 session
->http_server_properties();
8624 const int kUnrestrictedAlternatePort
= 1024;
8625 http_server_properties
->SetAlternateProtocol(
8626 HostPortPair::FromURL(unrestricted_port_request
.url
),
8627 kUnrestrictedAlternatePort
,
8628 AlternateProtocolFromNextProto(GetParam()));
8630 scoped_ptr
<HttpTransaction
> trans(
8631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8632 TestCompletionCallback callback
;
8634 int rv
= trans
->Start(
8635 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8636 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8637 // Valid change to an unrestricted port should pass.
8638 EXPECT_EQ(OK
, callback
.WaitForResult());
8641 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
8642 // Ensure that we're not allowed to redirect traffic via an alternate
8643 // protocol to an unsafe port, and that we resume the second
8644 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8645 session_deps_
.use_alternate_protocols
= true;
8647 HttpRequestInfo request
;
8648 request
.method
= "GET";
8649 request
.url
= GURL("http://www.google.com/");
8650 request
.load_flags
= 0;
8652 // The alternate protocol request will error out before we attempt to connect,
8653 // so only the standard HTTP request will try to connect.
8654 MockRead data_reads
[] = {
8655 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8656 MockRead("hello world"),
8657 MockRead(ASYNC
, OK
),
8659 StaticSocketDataProvider
data(
8660 data_reads
, arraysize(data_reads
), NULL
, 0);
8661 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8663 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8665 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8666 session
->http_server_properties();
8667 const int kUnsafePort
= 7;
8668 http_server_properties
->SetAlternateProtocol(
8669 HostPortPair::FromURL(request
.url
),
8671 AlternateProtocolFromNextProto(GetParam()));
8673 scoped_ptr
<HttpTransaction
> trans(
8674 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8675 TestCompletionCallback callback
;
8677 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8678 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8679 // The HTTP request should succeed.
8680 EXPECT_EQ(OK
, callback
.WaitForResult());
8682 // Disable alternate protocol before the asserts.
8683 // HttpStreamFactory::set_use_alternate_protocols(false);
8685 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8686 ASSERT_TRUE(response
!= NULL
);
8687 ASSERT_TRUE(response
->headers
.get() != NULL
);
8688 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8690 std::string response_data
;
8691 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8692 EXPECT_EQ("hello world", response_data
);
8695 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
8696 session_deps_
.use_alternate_protocols
= true;
8697 session_deps_
.next_protos
= SpdyNextProtos();
8699 HttpRequestInfo request
;
8700 request
.method
= "GET";
8701 request
.url
= GURL("http://www.google.com/");
8702 request
.load_flags
= 0;
8704 std::string alternate_protocol_http_header
=
8705 GetAlternateProtocolHttpHeader();
8707 MockRead data_reads
[] = {
8708 MockRead("HTTP/1.1 200 OK\r\n"),
8709 MockRead(alternate_protocol_http_header
.c_str()),
8710 MockRead("hello world"),
8711 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8715 StaticSocketDataProvider
first_transaction(
8716 data_reads
, arraysize(data_reads
), NULL
, 0);
8717 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8719 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8720 ssl
.SetNextProto(GetParam());
8721 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8723 scoped_ptr
<SpdyFrame
> req(
8724 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8725 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8727 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8728 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8729 MockRead spdy_reads
[] = {
8730 CreateMockRead(*resp
),
8731 CreateMockRead(*data
),
8732 MockRead(ASYNC
, 0, 0),
8735 DelayedSocketData
spdy_data(
8736 1, // wait for one write to finish before reading.
8737 spdy_reads
, arraysize(spdy_reads
),
8738 spdy_writes
, arraysize(spdy_writes
));
8739 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8741 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8742 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8744 hanging_non_alternate_protocol_socket
.set_connect_data(
8745 never_finishing_connect
);
8746 session_deps_
.socket_factory
->AddSocketDataProvider(
8747 &hanging_non_alternate_protocol_socket
);
8749 TestCompletionCallback callback
;
8751 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8752 scoped_ptr
<HttpTransaction
> trans(
8753 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8755 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8757 EXPECT_EQ(OK
, callback
.WaitForResult());
8759 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8760 ASSERT_TRUE(response
!= NULL
);
8761 ASSERT_TRUE(response
->headers
.get() != NULL
);
8762 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8764 std::string response_data
;
8765 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8766 EXPECT_EQ("hello world", response_data
);
8768 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8770 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8771 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8772 EXPECT_EQ(OK
, callback
.WaitForResult());
8774 response
= trans
->GetResponseInfo();
8775 ASSERT_TRUE(response
!= NULL
);
8776 ASSERT_TRUE(response
->headers
.get() != NULL
);
8777 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8778 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8779 EXPECT_TRUE(response
->was_npn_negotiated
);
8781 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8782 EXPECT_EQ("hello!", response_data
);
8785 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
8786 session_deps_
.use_alternate_protocols
= true;
8787 session_deps_
.next_protos
= SpdyNextProtos();
8789 HttpRequestInfo request
;
8790 request
.method
= "GET";
8791 request
.url
= GURL("http://www.google.com/");
8792 request
.load_flags
= 0;
8794 std::string alternate_protocol_http_header
=
8795 GetAlternateProtocolHttpHeader();
8797 MockRead data_reads
[] = {
8798 MockRead("HTTP/1.1 200 OK\r\n"),
8799 MockRead(alternate_protocol_http_header
.c_str()),
8800 MockRead("hello world"),
8801 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8802 MockRead(ASYNC
, OK
),
8805 StaticSocketDataProvider
first_transaction(
8806 data_reads
, arraysize(data_reads
), NULL
, 0);
8807 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8808 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8810 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8811 StaticSocketDataProvider
hanging_socket(
8813 hanging_socket
.set_connect_data(never_finishing_connect
);
8814 // Socket 2 and 3 are the hanging Alternate-Protocol and
8815 // non-Alternate-Protocol jobs from the 2nd transaction.
8816 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8817 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8819 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8820 ssl
.SetNextProto(GetParam());
8821 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8823 scoped_ptr
<SpdyFrame
> req1(
8824 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8825 scoped_ptr
<SpdyFrame
> req2(
8826 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
8827 MockWrite spdy_writes
[] = {
8828 CreateMockWrite(*req1
),
8829 CreateMockWrite(*req2
),
8831 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8832 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8833 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
8834 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
8835 MockRead spdy_reads
[] = {
8836 CreateMockRead(*resp1
),
8837 CreateMockRead(*data1
),
8838 CreateMockRead(*resp2
),
8839 CreateMockRead(*data2
),
8840 MockRead(ASYNC
, 0, 0),
8843 DelayedSocketData
spdy_data(
8844 2, // wait for writes to finish before reading.
8845 spdy_reads
, arraysize(spdy_reads
),
8846 spdy_writes
, arraysize(spdy_writes
));
8847 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8848 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8850 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8851 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8853 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8854 TestCompletionCallback callback1
;
8855 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
8857 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
8858 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8859 EXPECT_EQ(OK
, callback1
.WaitForResult());
8861 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
8862 ASSERT_TRUE(response
!= NULL
);
8863 ASSERT_TRUE(response
->headers
.get() != NULL
);
8864 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8866 std::string response_data
;
8867 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
8868 EXPECT_EQ("hello world", response_data
);
8870 TestCompletionCallback callback2
;
8871 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
8872 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
8873 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8875 TestCompletionCallback callback3
;
8876 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
8877 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8880 EXPECT_EQ(OK
, callback2
.WaitForResult());
8881 EXPECT_EQ(OK
, callback3
.WaitForResult());
8883 response
= trans2
.GetResponseInfo();
8884 ASSERT_TRUE(response
!= NULL
);
8885 ASSERT_TRUE(response
->headers
.get() != NULL
);
8886 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8887 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8888 EXPECT_TRUE(response
->was_npn_negotiated
);
8889 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
8890 EXPECT_EQ("hello!", response_data
);
8892 response
= trans3
.GetResponseInfo();
8893 ASSERT_TRUE(response
!= NULL
);
8894 ASSERT_TRUE(response
->headers
.get() != NULL
);
8895 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8896 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8897 EXPECT_TRUE(response
->was_npn_negotiated
);
8898 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
8899 EXPECT_EQ("hello!", response_data
);
8902 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
8903 session_deps_
.use_alternate_protocols
= true;
8904 session_deps_
.next_protos
= SpdyNextProtos();
8906 HttpRequestInfo request
;
8907 request
.method
= "GET";
8908 request
.url
= GURL("http://www.google.com/");
8909 request
.load_flags
= 0;
8911 std::string alternate_protocol_http_header
=
8912 GetAlternateProtocolHttpHeader();
8914 MockRead data_reads
[] = {
8915 MockRead("HTTP/1.1 200 OK\r\n"),
8916 MockRead(alternate_protocol_http_header
.c_str()),
8917 MockRead("hello world"),
8918 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8919 MockRead(ASYNC
, OK
),
8922 StaticSocketDataProvider
first_transaction(
8923 data_reads
, arraysize(data_reads
), NULL
, 0);
8924 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8926 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8927 ssl
.SetNextProto(GetParam());
8928 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8930 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8931 StaticSocketDataProvider
hanging_alternate_protocol_socket(
8933 hanging_alternate_protocol_socket
.set_connect_data(
8934 never_finishing_connect
);
8935 session_deps_
.socket_factory
->AddSocketDataProvider(
8936 &hanging_alternate_protocol_socket
);
8938 // 2nd request is just a copy of the first one, over HTTP again.
8939 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8941 TestCompletionCallback callback
;
8943 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8944 scoped_ptr
<HttpTransaction
> trans(
8945 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8947 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8948 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8949 EXPECT_EQ(OK
, callback
.WaitForResult());
8951 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8952 ASSERT_TRUE(response
!= NULL
);
8953 ASSERT_TRUE(response
->headers
.get() != NULL
);
8954 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8956 std::string response_data
;
8957 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8958 EXPECT_EQ("hello world", response_data
);
8960 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8962 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8963 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8964 EXPECT_EQ(OK
, callback
.WaitForResult());
8966 response
= trans
->GetResponseInfo();
8967 ASSERT_TRUE(response
!= NULL
);
8968 ASSERT_TRUE(response
->headers
.get() != NULL
);
8969 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8970 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8971 EXPECT_FALSE(response
->was_npn_negotiated
);
8973 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8974 EXPECT_EQ("hello world", response_data
);
8977 class CapturingProxyResolver
: public ProxyResolver
{
8979 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8980 virtual ~CapturingProxyResolver() {}
8982 virtual int GetProxyForURL(const GURL
& url
,
8984 const CompletionCallback
& callback
,
8985 RequestHandle
* request
,
8986 const BoundNetLog
& net_log
) OVERRIDE
{
8987 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
8988 HostPortPair("myproxy", 80));
8989 results
->UseProxyServer(proxy_server
);
8990 resolved_
.push_back(url
);
8994 virtual void CancelRequest(RequestHandle request
) OVERRIDE
{
8998 virtual LoadState
GetLoadState(RequestHandle request
) const OVERRIDE
{
9000 return LOAD_STATE_IDLE
;
9003 virtual void CancelSetPacScript() OVERRIDE
{
9007 virtual int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9008 const CompletionCallback
& /*callback*/) OVERRIDE
{
9012 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9015 std::vector
<GURL
> resolved_
;
9017 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9020 TEST_P(HttpNetworkTransactionTest
,
9021 UseAlternateProtocolForTunneledNpnSpdy
) {
9022 session_deps_
.use_alternate_protocols
= true;
9023 session_deps_
.next_protos
= SpdyNextProtos();
9025 ProxyConfig proxy_config
;
9026 proxy_config
.set_auto_detect(true);
9027 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9029 CapturingProxyResolver
* capturing_proxy_resolver
=
9030 new CapturingProxyResolver();
9031 session_deps_
.proxy_service
.reset(new ProxyService(
9032 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
9034 CapturingNetLog net_log
;
9035 session_deps_
.net_log
= &net_log
;
9037 HttpRequestInfo request
;
9038 request
.method
= "GET";
9039 request
.url
= GURL("http://www.google.com/");
9040 request
.load_flags
= 0;
9042 std::string alternate_protocol_http_header
=
9043 GetAlternateProtocolHttpHeader();
9045 MockRead data_reads
[] = {
9046 MockRead("HTTP/1.1 200 OK\r\n"),
9047 MockRead(alternate_protocol_http_header
.c_str()),
9048 MockRead("hello world"),
9049 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9050 MockRead(ASYNC
, OK
),
9053 StaticSocketDataProvider
first_transaction(
9054 data_reads
, arraysize(data_reads
), NULL
, 0);
9055 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9057 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9058 ssl
.SetNextProto(GetParam());
9059 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9061 scoped_ptr
<SpdyFrame
> req(
9062 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9063 MockWrite spdy_writes
[] = {
9064 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9065 "Host: www.google.com\r\n"
9066 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9067 CreateMockWrite(*req
), // 3
9070 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9072 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9073 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9074 MockRead spdy_reads
[] = {
9075 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9076 CreateMockRead(*resp
.get(), 4), // 2, 4
9077 CreateMockRead(*data
.get(), 4), // 5
9078 MockRead(ASYNC
, 0, 0, 4), // 6
9081 OrderedSocketData
spdy_data(
9082 spdy_reads
, arraysize(spdy_reads
),
9083 spdy_writes
, arraysize(spdy_writes
));
9084 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9086 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9087 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9089 hanging_non_alternate_protocol_socket
.set_connect_data(
9090 never_finishing_connect
);
9091 session_deps_
.socket_factory
->AddSocketDataProvider(
9092 &hanging_non_alternate_protocol_socket
);
9094 TestCompletionCallback callback
;
9096 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9097 scoped_ptr
<HttpTransaction
> trans(
9098 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9100 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9101 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9102 EXPECT_EQ(OK
, callback
.WaitForResult());
9104 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9105 ASSERT_TRUE(response
!= NULL
);
9106 ASSERT_TRUE(response
->headers
.get() != NULL
);
9107 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9108 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9109 EXPECT_FALSE(response
->was_npn_negotiated
);
9111 std::string response_data
;
9112 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9113 EXPECT_EQ("hello world", response_data
);
9115 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9117 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9118 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9119 EXPECT_EQ(OK
, callback
.WaitForResult());
9121 response
= trans
->GetResponseInfo();
9122 ASSERT_TRUE(response
!= NULL
);
9123 ASSERT_TRUE(response
->headers
.get() != NULL
);
9124 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9125 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9126 EXPECT_TRUE(response
->was_npn_negotiated
);
9128 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9129 EXPECT_EQ("hello!", response_data
);
9130 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
9131 EXPECT_EQ("http://www.google.com/",
9132 capturing_proxy_resolver
->resolved()[0].spec());
9133 EXPECT_EQ("https://www.google.com/",
9134 capturing_proxy_resolver
->resolved()[1].spec());
9136 LoadTimingInfo load_timing_info
;
9137 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9138 TestLoadTimingNotReusedWithPac(load_timing_info
,
9139 CONNECT_TIMING_HAS_SSL_TIMES
);
9142 TEST_P(HttpNetworkTransactionTest
,
9143 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9144 session_deps_
.use_alternate_protocols
= true;
9145 session_deps_
.next_protos
= SpdyNextProtos();
9147 HttpRequestInfo request
;
9148 request
.method
= "GET";
9149 request
.url
= GURL("http://www.google.com/");
9150 request
.load_flags
= 0;
9152 std::string alternate_protocol_http_header
=
9153 GetAlternateProtocolHttpHeader();
9155 MockRead data_reads
[] = {
9156 MockRead("HTTP/1.1 200 OK\r\n"),
9157 MockRead(alternate_protocol_http_header
.c_str()),
9158 MockRead("hello world"),
9159 MockRead(ASYNC
, OK
),
9162 StaticSocketDataProvider
first_transaction(
9163 data_reads
, arraysize(data_reads
), NULL
, 0);
9164 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9166 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9167 ssl
.SetNextProto(GetParam());
9168 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9170 scoped_ptr
<SpdyFrame
> req(
9171 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9172 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9174 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9175 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9176 MockRead spdy_reads
[] = {
9177 CreateMockRead(*resp
),
9178 CreateMockRead(*data
),
9179 MockRead(ASYNC
, 0, 0),
9182 DelayedSocketData
spdy_data(
9183 1, // wait for one write to finish before reading.
9184 spdy_reads
, arraysize(spdy_reads
),
9185 spdy_writes
, arraysize(spdy_writes
));
9186 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9188 TestCompletionCallback callback
;
9190 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9192 scoped_ptr
<HttpTransaction
> trans(
9193 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9195 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9196 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9197 EXPECT_EQ(OK
, callback
.WaitForResult());
9199 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9200 ASSERT_TRUE(response
!= NULL
);
9201 ASSERT_TRUE(response
->headers
.get() != NULL
);
9202 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9204 std::string response_data
;
9205 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9206 EXPECT_EQ("hello world", response_data
);
9208 // Set up an initial SpdySession in the pool to reuse.
9209 HostPortPair
host_port_pair("www.google.com", 443);
9210 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9211 PRIVACY_MODE_DISABLED
);
9212 base::WeakPtr
<SpdySession
> spdy_session
=
9213 CreateSecureSpdySession(session
, key
, BoundNetLog());
9215 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9217 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9218 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9219 EXPECT_EQ(OK
, callback
.WaitForResult());
9221 response
= trans
->GetResponseInfo();
9222 ASSERT_TRUE(response
!= NULL
);
9223 ASSERT_TRUE(response
->headers
.get() != NULL
);
9224 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9225 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9226 EXPECT_TRUE(response
->was_npn_negotiated
);
9228 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9229 EXPECT_EQ("hello!", response_data
);
9232 // GenerateAuthToken is a mighty big test.
9233 // It tests all permutation of GenerateAuthToken behavior:
9234 // - Synchronous and Asynchronous completion.
9235 // - OK or error on completion.
9236 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9237 // - HTTP or HTTPS backend (to include proxy tunneling).
9238 // - Non-authenticating and authenticating backend.
9240 // In all, there are 44 reasonable permuations (for example, if there are
9241 // problems generating an auth token for an authenticating proxy, we don't
9242 // need to test all permutations of the backend server).
9244 // The test proceeds by going over each of the configuration cases, and
9245 // potentially running up to three rounds in each of the tests. The TestConfig
9246 // specifies both the configuration for the test as well as the expectations
9248 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9249 static const char kServer
[] = "http://www.example.com";
9250 static const char kSecureServer
[] = "https://www.example.com";
9251 static const char kProxy
[] = "myproxy:70";
9252 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9260 const MockWrite
kGet(
9261 "GET / HTTP/1.1\r\n"
9262 "Host: www.example.com\r\n"
9263 "Connection: keep-alive\r\n\r\n");
9264 const MockWrite
kGetProxy(
9265 "GET http://www.example.com/ HTTP/1.1\r\n"
9266 "Host: www.example.com\r\n"
9267 "Proxy-Connection: keep-alive\r\n\r\n");
9268 const MockWrite
kGetAuth(
9269 "GET / HTTP/1.1\r\n"
9270 "Host: www.example.com\r\n"
9271 "Connection: keep-alive\r\n"
9272 "Authorization: auth_token\r\n\r\n");
9273 const MockWrite
kGetProxyAuth(
9274 "GET http://www.example.com/ HTTP/1.1\r\n"
9275 "Host: www.example.com\r\n"
9276 "Proxy-Connection: keep-alive\r\n"
9277 "Proxy-Authorization: auth_token\r\n\r\n");
9278 const MockWrite
kGetAuthThroughProxy(
9279 "GET http://www.example.com/ HTTP/1.1\r\n"
9280 "Host: www.example.com\r\n"
9281 "Proxy-Connection: keep-alive\r\n"
9282 "Authorization: auth_token\r\n\r\n");
9283 const MockWrite
kGetAuthWithProxyAuth(
9284 "GET http://www.example.com/ HTTP/1.1\r\n"
9285 "Host: www.example.com\r\n"
9286 "Proxy-Connection: keep-alive\r\n"
9287 "Proxy-Authorization: auth_token\r\n"
9288 "Authorization: auth_token\r\n\r\n");
9289 const MockWrite
kConnect(
9290 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9291 "Host: www.example.com\r\n"
9292 "Proxy-Connection: keep-alive\r\n\r\n");
9293 const MockWrite
kConnectProxyAuth(
9294 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9295 "Host: www.example.com\r\n"
9296 "Proxy-Connection: keep-alive\r\n"
9297 "Proxy-Authorization: auth_token\r\n\r\n");
9299 const MockRead
kSuccess(
9300 "HTTP/1.1 200 OK\r\n"
9301 "Content-Type: text/html; charset=iso-8859-1\r\n"
9302 "Content-Length: 3\r\n\r\n"
9304 const MockRead
kFailure(
9305 "Should not be called.");
9306 const MockRead
kServerChallenge(
9307 "HTTP/1.1 401 Unauthorized\r\n"
9308 "WWW-Authenticate: Mock realm=server\r\n"
9309 "Content-Type: text/html; charset=iso-8859-1\r\n"
9310 "Content-Length: 14\r\n\r\n"
9311 "Unauthorized\r\n");
9312 const MockRead
kProxyChallenge(
9313 "HTTP/1.1 407 Unauthorized\r\n"
9314 "Proxy-Authenticate: Mock realm=proxy\r\n"
9315 "Proxy-Connection: close\r\n"
9316 "Content-Type: text/html; charset=iso-8859-1\r\n"
9317 "Content-Length: 14\r\n\r\n"
9318 "Unauthorized\r\n");
9319 const MockRead
kProxyConnected(
9320 "HTTP/1.1 200 Connection Established\r\n\r\n");
9322 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9323 // no constructors, but the C++ compiler on Windows warns about
9324 // unspecified data in compound literals. So, moved to using constructors,
9325 // and TestRound's created with the default constructor should not be used.
9328 : expected_rv(ERR_UNEXPECTED
),
9332 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9333 int expected_rv_arg
)
9336 expected_rv(expected_rv_arg
),
9340 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9341 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9342 const MockRead
* extra_read_arg
)
9345 expected_rv(expected_rv_arg
),
9346 extra_write(extra_write_arg
),
9347 extra_read(extra_read_arg
) {
9352 const MockWrite
* extra_write
;
9353 const MockRead
* extra_read
;
9356 static const int kNoSSL
= 500;
9359 const char* proxy_url
;
9360 AuthTiming proxy_auth_timing
;
9362 const char* server_url
;
9363 AuthTiming server_auth_timing
;
9365 int num_auth_rounds
;
9366 int first_ssl_round
;
9367 TestRound rounds
[3];
9368 } test_configs
[] = {
9369 // Non-authenticating HTTP server with a direct connection.
9370 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9371 { TestRound(kGet
, kSuccess
, OK
)}},
9372 // Authenticating HTTP server with a direct connection.
9373 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9374 { TestRound(kGet
, kServerChallenge
, OK
),
9375 TestRound(kGetAuth
, kSuccess
, OK
)}},
9376 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9377 { TestRound(kGet
, kServerChallenge
, OK
),
9378 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9379 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9380 { TestRound(kGet
, kServerChallenge
, OK
),
9381 TestRound(kGetAuth
, kSuccess
, OK
)}},
9382 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9383 { TestRound(kGet
, kServerChallenge
, OK
),
9384 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9385 // Non-authenticating HTTP server through a non-authenticating proxy.
9386 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9387 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9388 // Authenticating HTTP server through a non-authenticating proxy.
9389 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9390 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9391 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9392 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9393 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9394 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9395 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9396 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9397 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9398 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9399 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9400 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9401 // Non-authenticating HTTP server through an authenticating proxy.
9402 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9403 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9404 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9405 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9406 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9407 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9408 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9409 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9410 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9411 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9412 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9413 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9414 // Authenticating HTTP server through an authenticating proxy.
9415 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9416 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9417 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9418 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9419 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9420 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9421 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9422 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9423 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9424 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9425 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9426 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9427 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9428 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9429 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9430 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9431 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9432 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9433 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9434 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9435 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9436 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9437 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9438 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9439 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9440 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9441 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9442 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9443 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9444 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9445 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9446 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9447 // Non-authenticating HTTPS server with a direct connection.
9448 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9449 { TestRound(kGet
, kSuccess
, OK
)}},
9450 // Authenticating HTTPS server with a direct connection.
9451 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9452 { TestRound(kGet
, kServerChallenge
, OK
),
9453 TestRound(kGetAuth
, kSuccess
, OK
)}},
9454 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9455 { TestRound(kGet
, kServerChallenge
, OK
),
9456 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9457 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9458 { TestRound(kGet
, kServerChallenge
, OK
),
9459 TestRound(kGetAuth
, kSuccess
, OK
)}},
9460 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9461 { TestRound(kGet
, kServerChallenge
, OK
),
9462 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9463 // Non-authenticating HTTPS server with a non-authenticating proxy.
9464 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9465 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9466 // Authenticating HTTPS server through a non-authenticating proxy.
9467 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9468 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9469 TestRound(kGetAuth
, kSuccess
, OK
)}},
9470 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9471 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9472 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9473 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9474 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9475 TestRound(kGetAuth
, kSuccess
, OK
)}},
9476 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9477 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9478 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9479 // Non-Authenticating HTTPS server through an authenticating proxy.
9480 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9481 { TestRound(kConnect
, kProxyChallenge
, OK
),
9482 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9483 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9484 { TestRound(kConnect
, kProxyChallenge
, OK
),
9485 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9486 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9487 { TestRound(kConnect
, kProxyChallenge
, OK
),
9488 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9489 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9490 { TestRound(kConnect
, kProxyChallenge
, OK
),
9491 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9492 // Authenticating HTTPS server through an authenticating proxy.
9493 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9494 { TestRound(kConnect
, kProxyChallenge
, OK
),
9495 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9496 &kGet
, &kServerChallenge
),
9497 TestRound(kGetAuth
, kSuccess
, OK
)}},
9498 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9499 { TestRound(kConnect
, kProxyChallenge
, OK
),
9500 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9501 &kGet
, &kServerChallenge
),
9502 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9503 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9504 { TestRound(kConnect
, kProxyChallenge
, OK
),
9505 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9506 &kGet
, &kServerChallenge
),
9507 TestRound(kGetAuth
, kSuccess
, OK
)}},
9508 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9509 { TestRound(kConnect
, kProxyChallenge
, OK
),
9510 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9511 &kGet
, &kServerChallenge
),
9512 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9513 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9514 { TestRound(kConnect
, kProxyChallenge
, OK
),
9515 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9516 &kGet
, &kServerChallenge
),
9517 TestRound(kGetAuth
, kSuccess
, OK
)}},
9518 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9519 { TestRound(kConnect
, kProxyChallenge
, OK
),
9520 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9521 &kGet
, &kServerChallenge
),
9522 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9523 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9524 { TestRound(kConnect
, kProxyChallenge
, OK
),
9525 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9526 &kGet
, &kServerChallenge
),
9527 TestRound(kGetAuth
, kSuccess
, OK
)}},
9528 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9529 { TestRound(kConnect
, kProxyChallenge
, OK
),
9530 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9531 &kGet
, &kServerChallenge
),
9532 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9535 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_configs
); ++i
) {
9536 HttpAuthHandlerMock::Factory
* auth_factory(
9537 new HttpAuthHandlerMock::Factory());
9538 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9539 const TestConfig
& test_config
= test_configs
[i
];
9541 // Set up authentication handlers as necessary.
9542 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9543 for (int n
= 0; n
< 2; n
++) {
9544 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9545 std::string auth_challenge
= "Mock realm=proxy";
9546 GURL
origin(test_config
.proxy_url
);
9547 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9548 auth_challenge
.end());
9549 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9550 origin
, BoundNetLog());
9551 auth_handler
->SetGenerateExpectation(
9552 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9553 test_config
.proxy_auth_rv
);
9554 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9557 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9558 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9559 std::string auth_challenge
= "Mock realm=server";
9560 GURL
origin(test_config
.server_url
);
9561 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9562 auth_challenge
.end());
9563 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9564 origin
, BoundNetLog());
9565 auth_handler
->SetGenerateExpectation(
9566 test_config
.server_auth_timing
== AUTH_ASYNC
,
9567 test_config
.server_auth_rv
);
9568 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9570 if (test_config
.proxy_url
) {
9571 session_deps_
.proxy_service
.reset(
9572 ProxyService::CreateFixed(test_config
.proxy_url
));
9574 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9577 HttpRequestInfo request
;
9578 request
.method
= "GET";
9579 request
.url
= GURL(test_config
.server_url
);
9580 request
.load_flags
= 0;
9582 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9583 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
9585 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9586 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9588 // Set up expected reads and writes.
9590 reads
[0] = read_write_round
.read
;
9591 size_t length_reads
= 1;
9592 if (read_write_round
.extra_read
) {
9593 reads
[1] = *read_write_round
.extra_read
;
9597 MockWrite writes
[2];
9598 writes
[0] = read_write_round
.write
;
9599 size_t length_writes
= 1;
9600 if (read_write_round
.extra_write
) {
9601 writes
[1] = *read_write_round
.extra_write
;
9604 StaticSocketDataProvider
data_provider(
9605 reads
, length_reads
, writes
, length_writes
);
9606 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9608 // Add an SSL sequence if necessary.
9609 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9610 if (round
>= test_config
.first_ssl_round
)
9611 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9612 &ssl_socket_data_provider
);
9614 // Start or restart the transaction.
9615 TestCompletionCallback callback
;
9618 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9620 rv
= trans
.RestartWithAuth(
9621 AuthCredentials(kFoo
, kBar
), callback
.callback());
9623 if (rv
== ERR_IO_PENDING
)
9624 rv
= callback
.WaitForResult();
9626 // Compare results with expected data.
9627 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9628 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9629 if (read_write_round
.expected_rv
== OK
) {
9630 ASSERT_TRUE(response
!= NULL
);
9632 EXPECT_TRUE(response
== NULL
);
9633 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9636 if (round
+ 1 < test_config
.num_auth_rounds
) {
9637 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9639 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9645 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9646 // Do multi-round authentication and make sure it works correctly.
9647 HttpAuthHandlerMock::Factory
* auth_factory(
9648 new HttpAuthHandlerMock::Factory());
9649 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9650 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9651 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9652 session_deps_
.host_resolver
->set_synchronous_mode(true);
9654 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9655 auth_handler
->set_connection_based(true);
9656 std::string auth_challenge
= "Mock realm=server";
9657 GURL
origin("http://www.example.com");
9658 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9659 auth_challenge
.end());
9660 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9661 origin
, BoundNetLog());
9662 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9665 const HttpResponseInfo
* response
= NULL
;
9666 HttpRequestInfo request
;
9667 request
.method
= "GET";
9668 request
.url
= origin
;
9669 request
.load_flags
= 0;
9671 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9673 // Use a TCP Socket Pool with only one connection per group. This is used
9674 // to validate that the TCP socket is not released to the pool between
9675 // each round of multi-round authentication.
9676 HttpNetworkSessionPeer
session_peer(session
);
9677 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9678 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9679 50, // Max sockets for pool
9680 1, // Max sockets per group
9681 &transport_pool_histograms
,
9682 session_deps_
.host_resolver
.get(),
9683 session_deps_
.socket_factory
.get(),
9684 session_deps_
.net_log
);
9685 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
9686 new MockClientSocketPoolManager
);
9687 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9688 session_peer
.SetClientSocketPoolManager(
9689 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
9691 scoped_ptr
<HttpTransaction
> trans(
9692 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9693 TestCompletionCallback callback
;
9695 const MockWrite
kGet(
9696 "GET / HTTP/1.1\r\n"
9697 "Host: www.example.com\r\n"
9698 "Connection: keep-alive\r\n\r\n");
9699 const MockWrite
kGetAuth(
9700 "GET / HTTP/1.1\r\n"
9701 "Host: www.example.com\r\n"
9702 "Connection: keep-alive\r\n"
9703 "Authorization: auth_token\r\n\r\n");
9705 const MockRead
kServerChallenge(
9706 "HTTP/1.1 401 Unauthorized\r\n"
9707 "WWW-Authenticate: Mock realm=server\r\n"
9708 "Content-Type: text/html; charset=iso-8859-1\r\n"
9709 "Content-Length: 14\r\n\r\n"
9710 "Unauthorized\r\n");
9711 const MockRead
kSuccess(
9712 "HTTP/1.1 200 OK\r\n"
9713 "Content-Type: text/html; charset=iso-8859-1\r\n"
9714 "Content-Length: 3\r\n\r\n"
9717 MockWrite writes
[] = {
9726 // Competing request
9729 MockRead reads
[] = {
9738 // Competing response
9741 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9742 writes
, arraysize(writes
));
9743 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9745 const char* const kSocketGroup
= "www.example.com:80";
9747 // First round of authentication.
9748 auth_handler
->SetGenerateExpectation(false, OK
);
9749 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9750 if (rv
== ERR_IO_PENDING
)
9751 rv
= callback
.WaitForResult();
9753 response
= trans
->GetResponseInfo();
9754 ASSERT_TRUE(response
!= NULL
);
9755 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9756 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9758 // In between rounds, another request comes in for the same domain.
9759 // It should not be able to grab the TCP socket that trans has already
9761 scoped_ptr
<HttpTransaction
> trans_compete(
9762 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9763 TestCompletionCallback callback_compete
;
9764 rv
= trans_compete
->Start(
9765 &request
, callback_compete
.callback(), BoundNetLog());
9766 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9767 // callback_compete.WaitForResult at this point would stall forever,
9768 // since the HttpNetworkTransaction does not release the request back to
9769 // the pool until after authentication completes.
9771 // Second round of authentication.
9772 auth_handler
->SetGenerateExpectation(false, OK
);
9773 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9774 if (rv
== ERR_IO_PENDING
)
9775 rv
= callback
.WaitForResult();
9777 response
= trans
->GetResponseInfo();
9778 ASSERT_TRUE(response
!= NULL
);
9779 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9780 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9782 // Third round of authentication.
9783 auth_handler
->SetGenerateExpectation(false, OK
);
9784 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9785 if (rv
== ERR_IO_PENDING
)
9786 rv
= callback
.WaitForResult();
9788 response
= trans
->GetResponseInfo();
9789 ASSERT_TRUE(response
!= NULL
);
9790 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9791 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9793 // Fourth round of authentication, which completes successfully.
9794 auth_handler
->SetGenerateExpectation(false, OK
);
9795 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9796 if (rv
== ERR_IO_PENDING
)
9797 rv
= callback
.WaitForResult();
9799 response
= trans
->GetResponseInfo();
9800 ASSERT_TRUE(response
!= NULL
);
9801 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9802 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9804 // Read the body since the fourth round was successful. This will also
9805 // release the socket back to the pool.
9806 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9807 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9808 if (rv
== ERR_IO_PENDING
)
9809 rv
= callback
.WaitForResult();
9811 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9813 // There are still 0 idle sockets, since the trans_compete transaction
9814 // will be handed it immediately after trans releases it to the group.
9815 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9817 // The competing request can now finish. Wait for the headers and then
9819 rv
= callback_compete
.WaitForResult();
9821 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9822 if (rv
== ERR_IO_PENDING
)
9823 rv
= callback
.WaitForResult();
9825 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9828 // Finally, the socket is released to the group.
9829 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9832 // This tests the case that a request is issued via http instead of spdy after
9833 // npn is negotiated.
9834 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9835 session_deps_
.use_alternate_protocols
= true;
9836 NextProtoVector next_protos
;
9837 next_protos
.push_back(kProtoHTTP11
);
9838 session_deps_
.next_protos
= next_protos
;
9840 HttpRequestInfo request
;
9841 request
.method
= "GET";
9842 request
.url
= GURL("https://www.google.com/");
9843 request
.load_flags
= 0;
9845 MockWrite data_writes
[] = {
9846 MockWrite("GET / HTTP/1.1\r\n"
9847 "Host: www.google.com\r\n"
9848 "Connection: keep-alive\r\n\r\n"),
9851 std::string alternate_protocol_http_header
=
9852 GetAlternateProtocolHttpHeader();
9854 MockRead data_reads
[] = {
9855 MockRead("HTTP/1.1 200 OK\r\n"),
9856 MockRead(alternate_protocol_http_header
.c_str()),
9857 MockRead("hello world"),
9858 MockRead(SYNCHRONOUS
, OK
),
9861 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9862 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9863 ssl
.next_proto
= "http/1.1";
9864 ssl
.protocol_negotiated
= kProtoHTTP11
;
9866 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9868 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9869 data_writes
, arraysize(data_writes
));
9870 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9872 TestCompletionCallback callback
;
9874 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9875 scoped_ptr
<HttpTransaction
> trans(
9876 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9878 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9880 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9881 EXPECT_EQ(OK
, callback
.WaitForResult());
9883 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9884 ASSERT_TRUE(response
!= NULL
);
9885 ASSERT_TRUE(response
->headers
.get() != NULL
);
9886 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9888 std::string response_data
;
9889 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9890 EXPECT_EQ("hello world", response_data
);
9892 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9893 EXPECT_TRUE(response
->was_npn_negotiated
);
9896 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
9897 // Simulate the SSL handshake completing with an NPN negotiation
9898 // followed by an immediate server closing of the socket.
9899 // Fix crash: http://crbug.com/46369
9900 session_deps_
.use_alternate_protocols
= true;
9901 session_deps_
.next_protos
= SpdyNextProtos();
9903 HttpRequestInfo request
;
9904 request
.method
= "GET";
9905 request
.url
= GURL("https://www.google.com/");
9906 request
.load_flags
= 0;
9908 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9909 ssl
.SetNextProto(GetParam());
9910 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9912 scoped_ptr
<SpdyFrame
> req(
9913 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9914 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9916 MockRead spdy_reads
[] = {
9917 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
9920 DelayedSocketData
spdy_data(
9921 0, // don't wait in this case, immediate hangup.
9922 spdy_reads
, arraysize(spdy_reads
),
9923 spdy_writes
, arraysize(spdy_writes
));
9924 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9926 TestCompletionCallback callback
;
9928 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9929 scoped_ptr
<HttpTransaction
> trans(
9930 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9932 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9933 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9934 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
9937 // A subclass of HttpAuthHandlerMock that records the request URL when
9938 // it gets it. This is needed since the auth handler may get destroyed
9939 // before we get a chance to query it.
9940 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
9942 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
9944 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9947 virtual int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
9948 const HttpRequestInfo
* request
,
9949 const CompletionCallback
& callback
,
9950 std::string
* auth_token
) OVERRIDE
{
9951 *url_
= request
->url
;
9952 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9953 credentials
, request
, callback
, auth_token
);
9960 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
9961 // This test ensures that the URL passed into the proxy is upgraded
9962 // to https when doing an Alternate Protocol upgrade.
9963 session_deps_
.use_alternate_protocols
= true;
9964 session_deps_
.next_protos
= SpdyNextProtos();
9966 session_deps_
.proxy_service
.reset(
9967 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9968 CapturingNetLog net_log
;
9969 session_deps_
.net_log
= &net_log
;
9972 HttpAuthHandlerMock::Factory
* auth_factory
=
9973 new HttpAuthHandlerMock::Factory();
9974 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
9975 new UrlRecordingHttpAuthHandlerMock(&request_url
);
9976 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9977 auth_factory
->set_do_init_from_challenge(true);
9978 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9981 HttpRequestInfo request
;
9982 request
.method
= "GET";
9983 request
.url
= GURL("http://www.google.com");
9984 request
.load_flags
= 0;
9986 // First round goes unauthenticated through the proxy.
9987 MockWrite data_writes_1
[] = {
9988 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9989 "Host: www.google.com\r\n"
9990 "Proxy-Connection: keep-alive\r\n"
9993 MockRead data_reads_1
[] = {
9994 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9995 MockRead("HTTP/1.1 200 OK\r\n"
9996 "Alternate-Protocol: 443:npn-spdy/2\r\n"
9997 "Proxy-Connection: close\r\n"
10000 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10001 data_writes_1
, arraysize(data_writes_1
));
10003 // Second round tries to tunnel to www.google.com due to the
10004 // Alternate-Protocol announcement in the first round. It fails due
10005 // to a proxy authentication challenge.
10006 // After the failure, a tunnel is established to www.google.com using
10007 // Proxy-Authorization headers. There is then a SPDY request round.
10009 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10010 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10011 // does a Disconnect and Connect on the same socket, rather than trying
10012 // to obtain a new one.
10014 // NOTE: Originally, the proxy response to the second CONNECT request
10015 // simply returned another 407 so the unit test could skip the SSL connection
10016 // establishment and SPDY framing issues. Alas, the
10017 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10018 // complicated to set up expectations for than the SPDY session.
10020 scoped_ptr
<SpdyFrame
> req(
10021 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10022 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10023 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10025 MockWrite data_writes_2
[] = {
10026 // First connection attempt without Proxy-Authorization.
10027 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10028 "Host: www.google.com\r\n"
10029 "Proxy-Connection: keep-alive\r\n"
10032 // Second connection attempt with Proxy-Authorization.
10033 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10034 "Host: www.google.com\r\n"
10035 "Proxy-Connection: keep-alive\r\n"
10036 "Proxy-Authorization: auth_token\r\n"
10040 CreateMockWrite(*req
),
10042 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10043 "Proxy-Authenticate: Mock\r\n"
10044 "Proxy-Connection: close\r\n"
10046 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10047 MockRead data_reads_2
[] = {
10048 // First connection attempt fails
10049 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10050 MockRead(ASYNC
, kRejectConnectResponse
,
10051 arraysize(kRejectConnectResponse
) - 1, 1),
10053 // Second connection attempt passes
10054 MockRead(ASYNC
, kAcceptConnectResponse
,
10055 arraysize(kAcceptConnectResponse
) -1, 4),
10058 CreateMockRead(*resp
.get(), 6),
10059 CreateMockRead(*data
.get(), 6),
10060 MockRead(ASYNC
, 0, 0, 6),
10062 OrderedSocketData
data_2(
10063 data_reads_2
, arraysize(data_reads_2
),
10064 data_writes_2
, arraysize(data_writes_2
));
10066 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10067 ssl
.SetNextProto(GetParam());
10069 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10070 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10072 hanging_non_alternate_protocol_socket
.set_connect_data(
10073 never_finishing_connect
);
10075 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10076 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10077 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10078 session_deps_
.socket_factory
->AddSocketDataProvider(
10079 &hanging_non_alternate_protocol_socket
);
10080 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10082 // First round should work and provide the Alternate-Protocol state.
10083 TestCompletionCallback callback_1
;
10084 scoped_ptr
<HttpTransaction
> trans_1(
10085 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10086 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10088 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10090 // Second round should attempt a tunnel connect and get an auth challenge.
10091 TestCompletionCallback callback_2
;
10092 scoped_ptr
<HttpTransaction
> trans_2(
10093 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10094 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10096 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10097 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10098 ASSERT_TRUE(response
!= NULL
);
10099 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10101 // Restart with auth. Tunnel should work and response received.
10102 TestCompletionCallback callback_3
;
10103 rv
= trans_2
->RestartWithAuth(
10104 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10105 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10106 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10108 // After all that work, these two lines (or actually, just the scheme) are
10109 // what this test is all about. Make sure it happens correctly.
10110 EXPECT_EQ("https", request_url
.scheme());
10111 EXPECT_EQ("www.google.com", request_url
.host());
10113 LoadTimingInfo load_timing_info
;
10114 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10115 TestLoadTimingNotReusedWithPac(load_timing_info
,
10116 CONNECT_TIMING_HAS_SSL_TIMES
);
10119 // Test that if we cancel the transaction as the connection is completing, that
10120 // everything tears down correctly.
10121 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10122 // Setup everything about the connection to complete synchronously, so that
10123 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10124 // for is the callback from the HttpStreamRequest.
10125 // Then cancel the transaction.
10126 // Verify that we don't crash.
10127 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10128 MockRead data_reads
[] = {
10129 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10130 MockRead(SYNCHRONOUS
, "hello world"),
10131 MockRead(SYNCHRONOUS
, OK
),
10134 HttpRequestInfo request
;
10135 request
.method
= "GET";
10136 request
.url
= GURL("http://www.google.com/");
10137 request
.load_flags
= 0;
10139 session_deps_
.host_resolver
->set_synchronous_mode(true);
10140 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10141 scoped_ptr
<HttpTransaction
> trans(
10142 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
10144 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10145 data
.set_connect_data(mock_connect
);
10146 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10148 TestCompletionCallback callback
;
10150 CapturingBoundNetLog log
;
10151 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10152 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10153 trans
.reset(); // Cancel the transaction here.
10155 base::MessageLoop::current()->RunUntilIdle();
10158 // Test that if a transaction is cancelled after receiving the headers, the
10159 // stream is drained properly and added back to the socket pool. The main
10160 // purpose of this test is to make sure that an HttpStreamParser can be read
10161 // from after the HttpNetworkTransaction and the objects it owns have been
10163 // See http://crbug.com/368418
10164 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10165 MockRead data_reads
[] = {
10166 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10167 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10168 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10169 MockRead(ASYNC
, "1"),
10170 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10171 // HttpNetworkTransaction has been deleted.
10172 MockRead(ASYNC
, "2"),
10173 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10175 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10176 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10178 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10181 HttpRequestInfo request
;
10182 request
.method
= "GET";
10183 request
.url
= GURL("http://www.google.com/");
10184 request
.load_flags
= 0;
10186 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
10187 TestCompletionCallback callback
;
10189 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10190 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10191 callback
.WaitForResult();
10193 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10194 ASSERT_TRUE(response
!= NULL
);
10195 EXPECT_TRUE(response
->headers
.get() != NULL
);
10196 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10198 // The transaction and HttpRequestInfo are deleted.
10201 // Let the HttpResponseBodyDrainer drain the socket.
10202 base::MessageLoop::current()->RunUntilIdle();
10204 // Socket should now be idle, waiting to be reused.
10205 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
10208 // Test a basic GET request through a proxy.
10209 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10210 session_deps_
.proxy_service
.reset(
10211 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10212 CapturingBoundNetLog log
;
10213 session_deps_
.net_log
= log
.bound().net_log();
10214 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10216 HttpRequestInfo request
;
10217 request
.method
= "GET";
10218 request
.url
= GURL("http://www.google.com/");
10220 MockWrite data_writes1
[] = {
10221 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10222 "Host: www.google.com\r\n"
10223 "Proxy-Connection: keep-alive\r\n\r\n"),
10226 MockRead data_reads1
[] = {
10227 MockRead("HTTP/1.1 200 OK\r\n"),
10228 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10229 MockRead("Content-Length: 100\r\n\r\n"),
10230 MockRead(SYNCHRONOUS
, OK
),
10233 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10234 data_writes1
, arraysize(data_writes1
));
10235 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10237 TestCompletionCallback callback1
;
10239 scoped_ptr
<HttpTransaction
> trans(
10240 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10242 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10245 rv
= callback1
.WaitForResult();
10248 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10249 ASSERT_TRUE(response
!= NULL
);
10251 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10252 EXPECT_EQ(200, response
->headers
->response_code());
10253 EXPECT_EQ(100, response
->headers
->GetContentLength());
10254 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10255 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10257 LoadTimingInfo load_timing_info
;
10258 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10259 TestLoadTimingNotReusedWithPac(load_timing_info
,
10260 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10263 // Test a basic HTTPS GET request through a proxy.
10264 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10265 session_deps_
.proxy_service
.reset(
10266 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10267 CapturingBoundNetLog log
;
10268 session_deps_
.net_log
= log
.bound().net_log();
10269 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10271 HttpRequestInfo request
;
10272 request
.method
= "GET";
10273 request
.url
= GURL("https://www.google.com/");
10275 // Since we have proxy, should try to establish tunnel.
10276 MockWrite data_writes1
[] = {
10277 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10278 "Host: www.google.com\r\n"
10279 "Proxy-Connection: keep-alive\r\n\r\n"),
10281 MockWrite("GET / HTTP/1.1\r\n"
10282 "Host: www.google.com\r\n"
10283 "Connection: keep-alive\r\n\r\n"),
10286 MockRead data_reads1
[] = {
10287 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10289 MockRead("HTTP/1.1 200 OK\r\n"),
10290 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10291 MockRead("Content-Length: 100\r\n\r\n"),
10292 MockRead(SYNCHRONOUS
, OK
),
10295 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10296 data_writes1
, arraysize(data_writes1
));
10297 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10298 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10299 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10301 TestCompletionCallback callback1
;
10303 scoped_ptr
<HttpTransaction
> trans(
10304 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10306 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10307 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10309 rv
= callback1
.WaitForResult();
10311 net::CapturingNetLog::CapturedEntryList entries
;
10312 log
.GetEntries(&entries
);
10313 size_t pos
= ExpectLogContainsSomewhere(
10314 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10315 NetLog::PHASE_NONE
);
10316 ExpectLogContainsSomewhere(
10318 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10319 NetLog::PHASE_NONE
);
10321 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10322 ASSERT_TRUE(response
!= NULL
);
10324 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10325 EXPECT_EQ(200, response
->headers
->response_code());
10326 EXPECT_EQ(100, response
->headers
->GetContentLength());
10327 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10328 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10330 LoadTimingInfo load_timing_info
;
10331 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10332 TestLoadTimingNotReusedWithPac(load_timing_info
,
10333 CONNECT_TIMING_HAS_SSL_TIMES
);
10336 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10337 // while establishing the tunnel.
10338 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10339 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10340 CapturingBoundNetLog log
;
10341 session_deps_
.net_log
= log
.bound().net_log();
10342 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10344 HttpRequestInfo request
;
10345 request
.method
= "GET";
10346 request
.url
= GURL("https://www.google.com/");
10348 // Since we have proxy, should try to establish tunnel.
10349 MockWrite data_writes1
[] = {
10350 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10351 "Host: www.google.com\r\n"
10352 "Proxy-Connection: keep-alive\r\n\r\n"),
10354 MockWrite("GET / HTTP/1.1\r\n"
10355 "Host: www.google.com\r\n"
10356 "Connection: keep-alive\r\n\r\n"),
10359 MockRead data_reads1
[] = {
10360 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10361 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10362 MockRead(ASYNC
, 0, 0), // EOF
10365 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10366 data_writes1
, arraysize(data_writes1
));
10367 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10368 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10369 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10371 TestCompletionCallback callback1
;
10373 scoped_ptr
<HttpTransaction
> trans(
10374 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10376 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10377 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10379 rv
= callback1
.WaitForResult();
10380 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10381 net::CapturingNetLog::CapturedEntryList entries
;
10382 log
.GetEntries(&entries
);
10383 size_t pos
= ExpectLogContainsSomewhere(
10384 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10385 NetLog::PHASE_NONE
);
10386 ExpectLogContainsSomewhere(
10388 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10389 NetLog::PHASE_NONE
);
10392 // Test for crbug.com/55424.
10393 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10394 scoped_ptr
<SpdyFrame
> req(
10395 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10396 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10398 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10399 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10400 MockRead spdy_reads
[] = {
10401 CreateMockRead(*resp
),
10402 CreateMockRead(*data
),
10403 MockRead(ASYNC
, 0, 0),
10406 DelayedSocketData
spdy_data(
10407 1, // wait for one write to finish before reading.
10408 spdy_reads
, arraysize(spdy_reads
),
10409 spdy_writes
, arraysize(spdy_writes
));
10410 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10412 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10413 ssl
.SetNextProto(GetParam());
10414 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10416 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10418 // Set up an initial SpdySession in the pool to reuse.
10419 HostPortPair
host_port_pair("www.google.com", 443);
10420 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10421 PRIVACY_MODE_DISABLED
);
10422 base::WeakPtr
<SpdySession
> spdy_session
=
10423 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10425 HttpRequestInfo request
;
10426 request
.method
= "GET";
10427 request
.url
= GURL("https://www.google.com/");
10428 request
.load_flags
= 0;
10430 // This is the important line that marks this as a preconnect.
10431 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10433 scoped_ptr
<HttpTransaction
> trans(
10434 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10436 TestCompletionCallback callback
;
10437 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10439 EXPECT_EQ(OK
, callback
.WaitForResult());
10442 // Given a net error, cause that error to be returned from the first Write()
10443 // call and verify that the HttpTransaction fails with that error.
10444 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10445 int error
, IoMode mode
) {
10446 net::HttpRequestInfo request_info
;
10447 request_info
.url
= GURL("https://www.example.com/");
10448 request_info
.method
= "GET";
10449 request_info
.load_flags
= net::LOAD_NORMAL
;
10451 SSLSocketDataProvider
ssl_data(mode
, OK
);
10452 net::MockWrite data_writes
[] = {
10453 net::MockWrite(mode
, error
),
10455 net::StaticSocketDataProvider
data(NULL
, 0,
10456 data_writes
, arraysize(data_writes
));
10457 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10458 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10460 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10461 scoped_ptr
<HttpTransaction
> trans(
10462 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10464 TestCompletionCallback callback
;
10465 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10466 if (rv
== net::ERR_IO_PENDING
)
10467 rv
= callback
.WaitForResult();
10468 ASSERT_EQ(error
, rv
);
10471 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10472 // Just check a grab bag of cert errors.
10473 static const int kErrors
[] = {
10474 ERR_CERT_COMMON_NAME_INVALID
,
10475 ERR_CERT_AUTHORITY_INVALID
,
10476 ERR_CERT_DATE_INVALID
,
10478 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10479 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10480 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10484 // Ensure that a client certificate is removed from the SSL client auth
10486 // 1) No proxy is involved.
10487 // 2) TLS False Start is disabled.
10488 // 3) The initial TLS handshake requests a client certificate.
10489 // 4) The client supplies an invalid/unacceptable certificate.
10490 TEST_P(HttpNetworkTransactionTest
,
10491 ClientAuthCertCache_Direct_NoFalseStart
) {
10492 net::HttpRequestInfo request_info
;
10493 request_info
.url
= GURL("https://www.example.com/");
10494 request_info
.method
= "GET";
10495 request_info
.load_flags
= net::LOAD_NORMAL
;
10497 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10498 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10500 // [ssl_]data1 contains the data for the first SSL handshake. When a
10501 // CertificateRequest is received for the first time, the handshake will
10502 // be aborted to allow the caller to provide a certificate.
10503 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10504 ssl_data1
.cert_request_info
= cert_request
.get();
10505 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10506 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10507 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10509 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10510 // False Start is not being used, the result of the SSL handshake will be
10511 // returned as part of the SSLClientSocket::Connect() call. This test
10512 // matches the result of a server sending a handshake_failure alert,
10513 // rather than a Finished message, because it requires a client
10514 // certificate and none was supplied.
10515 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10516 ssl_data2
.cert_request_info
= cert_request
.get();
10517 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10518 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10519 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10521 // [ssl_]data3 contains the data for the third SSL handshake. When a
10522 // connection to a server fails during an SSL handshake,
10523 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10524 // connection was attempted with TLSv1.1. This is transparent to the caller
10525 // of the HttpNetworkTransaction. Because this test failure is due to
10526 // requiring a client certificate, this fallback handshake should also
10528 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10529 ssl_data3
.cert_request_info
= cert_request
.get();
10530 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10531 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10532 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10534 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10535 // connection to a server fails during an SSL handshake,
10536 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10537 // connection was attempted with TLSv1. This is transparent to the caller
10538 // of the HttpNetworkTransaction. Because this test failure is due to
10539 // requiring a client certificate, this fallback handshake should also
10541 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10542 ssl_data4
.cert_request_info
= cert_request
.get();
10543 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10544 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10545 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10547 // Need one more if TLSv1.2 is enabled.
10548 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10549 ssl_data5
.cert_request_info
= cert_request
.get();
10550 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10551 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10552 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10554 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10555 scoped_ptr
<HttpTransaction
> trans(
10556 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10558 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10559 TestCompletionCallback callback
;
10560 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10561 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10563 // Complete the SSL handshake, which should abort due to requiring a
10564 // client certificate.
10565 rv
= callback
.WaitForResult();
10566 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10568 // Indicate that no certificate should be supplied. From the perspective
10569 // of SSLClientCertCache, NULL is just as meaningful as a real
10570 // certificate, so this is the same as supply a
10571 // legitimate-but-unacceptable certificate.
10572 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10573 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10575 // Ensure the certificate was added to the client auth cache before
10576 // allowing the connection to continue restarting.
10577 scoped_refptr
<X509Certificate
> client_cert
;
10578 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10579 HostPortPair("www.example.com", 443), &client_cert
));
10580 ASSERT_EQ(NULL
, client_cert
.get());
10582 // Restart the handshake. This will consume ssl_data2, which fails, and
10583 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10584 // The result code is checked against what ssl_data4 should return.
10585 rv
= callback
.WaitForResult();
10586 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10588 // Ensure that the client certificate is removed from the cache on a
10589 // handshake failure.
10590 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10591 HostPortPair("www.example.com", 443), &client_cert
));
10594 // Ensure that a client certificate is removed from the SSL client auth
10596 // 1) No proxy is involved.
10597 // 2) TLS False Start is enabled.
10598 // 3) The initial TLS handshake requests a client certificate.
10599 // 4) The client supplies an invalid/unacceptable certificate.
10600 TEST_P(HttpNetworkTransactionTest
,
10601 ClientAuthCertCache_Direct_FalseStart
) {
10602 net::HttpRequestInfo request_info
;
10603 request_info
.url
= GURL("https://www.example.com/");
10604 request_info
.method
= "GET";
10605 request_info
.load_flags
= net::LOAD_NORMAL
;
10607 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10608 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10610 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10611 // return successfully after reading up to the peer's Certificate message.
10612 // This is to allow the caller to call SSLClientSocket::Write(), which can
10613 // enqueue application data to be sent in the same packet as the
10614 // ChangeCipherSpec and Finished messages.
10615 // The actual handshake will be finished when SSLClientSocket::Read() is
10616 // called, which expects to process the peer's ChangeCipherSpec and
10617 // Finished messages. If there was an error negotiating with the peer,
10618 // such as due to the peer requiring a client certificate when none was
10619 // supplied, the alert sent by the peer won't be processed until Read() is
10622 // Like the non-False Start case, when a client certificate is requested by
10623 // the peer, the handshake is aborted during the Connect() call.
10624 // [ssl_]data1 represents the initial SSL handshake with the peer.
10625 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10626 ssl_data1
.cert_request_info
= cert_request
.get();
10627 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10628 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10629 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10631 // When a client certificate is supplied, Connect() will not be aborted
10632 // when the peer requests the certificate. Instead, the handshake will
10633 // artificially succeed, allowing the caller to write the HTTP request to
10634 // the socket. The handshake messages are not processed until Read() is
10635 // called, which then detects that the handshake was aborted, due to the
10636 // peer sending a handshake_failure because it requires a client
10638 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10639 ssl_data2
.cert_request_info
= cert_request
.get();
10640 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10641 net::MockRead data2_reads
[] = {
10642 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10644 net::StaticSocketDataProvider
data2(
10645 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10646 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10648 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10649 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10650 // TLSv1. It has the same behaviour as [ssl_]data2.
10651 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10652 ssl_data3
.cert_request_info
= cert_request
.get();
10653 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10654 net::StaticSocketDataProvider
data3(
10655 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10656 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10658 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10659 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10660 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10661 ssl_data4
.cert_request_info
= cert_request
.get();
10662 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10663 net::StaticSocketDataProvider
data4(
10664 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10665 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10667 // Need one more if TLSv1.2 is enabled.
10668 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10669 ssl_data5
.cert_request_info
= cert_request
.get();
10670 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10671 net::StaticSocketDataProvider
data5(
10672 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10673 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10675 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10676 scoped_ptr
<HttpTransaction
> trans(
10677 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10679 // Begin the initial SSL handshake.
10680 TestCompletionCallback callback
;
10681 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10682 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10684 // Complete the SSL handshake, which should abort due to requiring a
10685 // client certificate.
10686 rv
= callback
.WaitForResult();
10687 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10689 // Indicate that no certificate should be supplied. From the perspective
10690 // of SSLClientCertCache, NULL is just as meaningful as a real
10691 // certificate, so this is the same as supply a
10692 // legitimate-but-unacceptable certificate.
10693 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10694 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10696 // Ensure the certificate was added to the client auth cache before
10697 // allowing the connection to continue restarting.
10698 scoped_refptr
<X509Certificate
> client_cert
;
10699 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10700 HostPortPair("www.example.com", 443), &client_cert
));
10701 ASSERT_EQ(NULL
, client_cert
.get());
10703 // Restart the handshake. This will consume ssl_data2, which fails, and
10704 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10705 // The result code is checked against what ssl_data4 should return.
10706 rv
= callback
.WaitForResult();
10707 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10709 // Ensure that the client certificate is removed from the cache on a
10710 // handshake failure.
10711 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10712 HostPortPair("www.example.com", 443), &client_cert
));
10715 // Ensure that a client certificate is removed from the SSL client auth
10717 // 1) An HTTPS proxy is involved.
10718 // 3) The HTTPS proxy requests a client certificate.
10719 // 4) The client supplies an invalid/unacceptable certificate for the
10721 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10722 // then for connecting to an HTTP endpoint.
10723 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10724 session_deps_
.proxy_service
.reset(
10725 ProxyService::CreateFixed("https://proxy:70"));
10726 CapturingBoundNetLog log
;
10727 session_deps_
.net_log
= log
.bound().net_log();
10729 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10730 cert_request
->host_and_port
= HostPortPair("proxy", 70);
10732 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10733 // [ssl_]data[1-3]. Rather than represending the endpoint
10734 // (www.example.com:443), they represent failures with the HTTPS proxy
10736 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10737 ssl_data1
.cert_request_info
= cert_request
.get();
10738 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10739 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10740 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10742 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10743 ssl_data2
.cert_request_info
= cert_request
.get();
10744 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10745 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10746 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10748 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10750 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10751 ssl_data3
.cert_request_info
= cert_request
.get();
10752 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10753 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10754 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10757 net::HttpRequestInfo requests
[2];
10758 requests
[0].url
= GURL("https://www.example.com/");
10759 requests
[0].method
= "GET";
10760 requests
[0].load_flags
= net::LOAD_NORMAL
;
10762 requests
[1].url
= GURL("http://www.example.com/");
10763 requests
[1].method
= "GET";
10764 requests
[1].load_flags
= net::LOAD_NORMAL
;
10766 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10767 session_deps_
.socket_factory
->ResetNextMockIndexes();
10768 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10769 scoped_ptr
<HttpNetworkTransaction
> trans(
10770 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10772 // Begin the SSL handshake with the proxy.
10773 TestCompletionCallback callback
;
10774 int rv
= trans
->Start(
10775 &requests
[i
], callback
.callback(), net::BoundNetLog());
10776 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10778 // Complete the SSL handshake, which should abort due to requiring a
10779 // client certificate.
10780 rv
= callback
.WaitForResult();
10781 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10783 // Indicate that no certificate should be supplied. From the perspective
10784 // of SSLClientCertCache, NULL is just as meaningful as a real
10785 // certificate, so this is the same as supply a
10786 // legitimate-but-unacceptable certificate.
10787 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10788 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10790 // Ensure the certificate was added to the client auth cache before
10791 // allowing the connection to continue restarting.
10792 scoped_refptr
<X509Certificate
> client_cert
;
10793 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10794 HostPortPair("proxy", 70), &client_cert
));
10795 ASSERT_EQ(NULL
, client_cert
.get());
10796 // Ensure the certificate was NOT cached for the endpoint. This only
10797 // applies to HTTPS requests, but is fine to check for HTTP requests.
10798 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10799 HostPortPair("www.example.com", 443), &client_cert
));
10801 // Restart the handshake. This will consume ssl_data2, which fails, and
10802 // then consume ssl_data3, which should also fail. The result code is
10803 // checked against what ssl_data3 should return.
10804 rv
= callback
.WaitForResult();
10805 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10807 // Now that the new handshake has failed, ensure that the client
10808 // certificate was removed from the client auth cache.
10809 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10810 HostPortPair("proxy", 70), &client_cert
));
10811 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10812 HostPortPair("www.example.com", 443), &client_cert
));
10816 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10817 // TEST_P is a macro that expands directly to code that stringizes the
10818 // arguments. As a result, macros passed as parameters (such as prefix
10819 // or test_case_name) will not be expanded by the preprocessor. To
10820 // work around this, indirect the macro for TEST_P, so that the
10821 // pre-processor will expand macros such as MAYBE_test_name before
10822 // instantiating the test.
10823 #define WRAPPED_TEST_P(test_case_name, test_name) \
10824 TEST_P(test_case_name, test_name)
10826 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10827 #if defined(OS_WIN)
10828 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10830 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10832 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10833 session_deps_
.use_alternate_protocols
= true;
10834 session_deps_
.next_protos
= SpdyNextProtos();
10836 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10837 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10838 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10839 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10840 pool_peer
.DisableDomainAuthenticationVerification();
10842 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10843 ssl
.SetNextProto(GetParam());
10844 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10846 scoped_ptr
<SpdyFrame
> host1_req(
10847 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10848 scoped_ptr
<SpdyFrame
> host2_req(
10849 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10850 MockWrite spdy_writes
[] = {
10851 CreateMockWrite(*host1_req
, 1),
10852 CreateMockWrite(*host2_req
, 4),
10854 scoped_ptr
<SpdyFrame
> host1_resp(
10855 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10856 scoped_ptr
<SpdyFrame
> host1_resp_body(
10857 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10858 scoped_ptr
<SpdyFrame
> host2_resp(
10859 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10860 scoped_ptr
<SpdyFrame
> host2_resp_body(
10861 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10862 MockRead spdy_reads
[] = {
10863 CreateMockRead(*host1_resp
, 2),
10864 CreateMockRead(*host1_resp_body
, 3),
10865 CreateMockRead(*host2_resp
, 5),
10866 CreateMockRead(*host2_resp_body
, 6),
10867 MockRead(ASYNC
, 0, 7),
10870 IPAddressNumber ip
;
10871 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10872 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10873 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10874 OrderedSocketData
spdy_data(
10876 spdy_reads
, arraysize(spdy_reads
),
10877 spdy_writes
, arraysize(spdy_writes
));
10878 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10880 TestCompletionCallback callback
;
10881 HttpRequestInfo request1
;
10882 request1
.method
= "GET";
10883 request1
.url
= GURL("https://www.google.com/");
10884 request1
.load_flags
= 0;
10885 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10887 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10888 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10889 EXPECT_EQ(OK
, callback
.WaitForResult());
10891 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10892 ASSERT_TRUE(response
!= NULL
);
10893 ASSERT_TRUE(response
->headers
.get() != NULL
);
10894 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10896 std::string response_data
;
10897 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
10898 EXPECT_EQ("hello!", response_data
);
10900 // Preload www.gmail.com into HostCache.
10901 HostPortPair
host_port("www.gmail.com", 443);
10902 HostResolver::RequestInfo
resolve_info(host_port
);
10903 AddressList ignored
;
10904 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
10907 callback
.callback(),
10910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10911 rv
= callback
.WaitForResult();
10914 HttpRequestInfo request2
;
10915 request2
.method
= "GET";
10916 request2
.url
= GURL("https://www.gmail.com/");
10917 request2
.load_flags
= 0;
10918 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
10920 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
10921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10922 EXPECT_EQ(OK
, callback
.WaitForResult());
10924 response
= trans2
.GetResponseInfo();
10925 ASSERT_TRUE(response
!= NULL
);
10926 ASSERT_TRUE(response
->headers
.get() != NULL
);
10927 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10928 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10929 EXPECT_TRUE(response
->was_npn_negotiated
);
10930 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
10931 EXPECT_EQ("hello!", response_data
);
10933 #undef MAYBE_UseIPConnectionPooling
10935 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
10936 session_deps_
.use_alternate_protocols
= true;
10937 session_deps_
.next_protos
= SpdyNextProtos();
10939 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10940 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10941 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10942 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10943 pool_peer
.DisableDomainAuthenticationVerification();
10945 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10946 ssl
.SetNextProto(GetParam());
10947 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10949 scoped_ptr
<SpdyFrame
> host1_req(
10950 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10951 scoped_ptr
<SpdyFrame
> host2_req(
10952 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10953 MockWrite spdy_writes
[] = {
10954 CreateMockWrite(*host1_req
, 1),
10955 CreateMockWrite(*host2_req
, 4),
10957 scoped_ptr
<SpdyFrame
> host1_resp(
10958 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10959 scoped_ptr
<SpdyFrame
> host1_resp_body(
10960 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10961 scoped_ptr
<SpdyFrame
> host2_resp(
10962 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10963 scoped_ptr
<SpdyFrame
> host2_resp_body(
10964 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10965 MockRead spdy_reads
[] = {
10966 CreateMockRead(*host1_resp
, 2),
10967 CreateMockRead(*host1_resp_body
, 3),
10968 CreateMockRead(*host2_resp
, 5),
10969 CreateMockRead(*host2_resp_body
, 6),
10970 MockRead(ASYNC
, 0, 7),
10973 IPAddressNumber ip
;
10974 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10975 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10976 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10977 OrderedSocketData
spdy_data(
10979 spdy_reads
, arraysize(spdy_reads
),
10980 spdy_writes
, arraysize(spdy_writes
));
10981 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10983 TestCompletionCallback callback
;
10984 HttpRequestInfo request1
;
10985 request1
.method
= "GET";
10986 request1
.url
= GURL("https://www.google.com/");
10987 request1
.load_flags
= 0;
10988 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10990 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10991 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10992 EXPECT_EQ(OK
, callback
.WaitForResult());
10994 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10995 ASSERT_TRUE(response
!= NULL
);
10996 ASSERT_TRUE(response
->headers
.get() != NULL
);
10997 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10999 std::string response_data
;
11000 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11001 EXPECT_EQ("hello!", response_data
);
11003 HttpRequestInfo request2
;
11004 request2
.method
= "GET";
11005 request2
.url
= GURL("https://www.gmail.com/");
11006 request2
.load_flags
= 0;
11007 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11009 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11010 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11011 EXPECT_EQ(OK
, callback
.WaitForResult());
11013 response
= trans2
.GetResponseInfo();
11014 ASSERT_TRUE(response
!= NULL
);
11015 ASSERT_TRUE(response
->headers
.get() != NULL
);
11016 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11017 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11018 EXPECT_TRUE(response
->was_npn_negotiated
);
11019 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11020 EXPECT_EQ("hello!", response_data
);
11023 class OneTimeCachingHostResolver
: public net::HostResolver
{
11025 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11026 : host_port_(host_port
) {}
11027 virtual ~OneTimeCachingHostResolver() {}
11029 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11031 // HostResolver methods:
11032 virtual int Resolve(const RequestInfo
& info
,
11033 RequestPriority priority
,
11034 AddressList
* addresses
,
11035 const CompletionCallback
& callback
,
11036 RequestHandle
* out_req
,
11037 const BoundNetLog
& net_log
) OVERRIDE
{
11038 return host_resolver_
.Resolve(
11039 info
, priority
, addresses
, callback
, out_req
, net_log
);
11042 virtual int ResolveFromCache(const RequestInfo
& info
,
11043 AddressList
* addresses
,
11044 const BoundNetLog
& net_log
) OVERRIDE
{
11045 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11046 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11047 host_resolver_
.GetHostCache()->clear();
11051 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
11052 host_resolver_
.CancelRequest(req
);
11055 MockCachingHostResolver
* GetMockHostResolver() {
11056 return &host_resolver_
;
11060 MockCachingHostResolver host_resolver_
;
11061 const HostPortPair host_port_
;
11064 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11065 #if defined(OS_WIN)
11066 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11067 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11069 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11070 UseIPConnectionPoolingWithHostCacheExpiration
11072 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11073 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11074 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11075 // prefix doesn't work with parametrized tests).
11076 #if defined(OS_WIN)
11079 session_deps_
.use_alternate_protocols
= true;
11080 session_deps_
.next_protos
= SpdyNextProtos();
11082 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11083 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11084 HttpNetworkSession::Params params
=
11085 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11086 params
.host_resolver
= &host_resolver
;
11087 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11088 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11089 pool_peer
.DisableDomainAuthenticationVerification();
11091 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11092 ssl
.SetNextProto(GetParam());
11093 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11095 scoped_ptr
<SpdyFrame
> host1_req(
11096 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11097 scoped_ptr
<SpdyFrame
> host2_req(
11098 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11099 MockWrite spdy_writes
[] = {
11100 CreateMockWrite(*host1_req
, 1),
11101 CreateMockWrite(*host2_req
, 4),
11103 scoped_ptr
<SpdyFrame
> host1_resp(
11104 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11105 scoped_ptr
<SpdyFrame
> host1_resp_body(
11106 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11107 scoped_ptr
<SpdyFrame
> host2_resp(
11108 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11109 scoped_ptr
<SpdyFrame
> host2_resp_body(
11110 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11111 MockRead spdy_reads
[] = {
11112 CreateMockRead(*host1_resp
, 2),
11113 CreateMockRead(*host1_resp_body
, 3),
11114 CreateMockRead(*host2_resp
, 5),
11115 CreateMockRead(*host2_resp_body
, 6),
11116 MockRead(ASYNC
, 0, 7),
11119 IPAddressNumber ip
;
11120 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11121 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11122 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11123 OrderedSocketData
spdy_data(
11125 spdy_reads
, arraysize(spdy_reads
),
11126 spdy_writes
, arraysize(spdy_writes
));
11127 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11129 TestCompletionCallback callback
;
11130 HttpRequestInfo request1
;
11131 request1
.method
= "GET";
11132 request1
.url
= GURL("https://www.google.com/");
11133 request1
.load_flags
= 0;
11134 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11136 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11137 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11138 EXPECT_EQ(OK
, callback
.WaitForResult());
11140 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11141 ASSERT_TRUE(response
!= NULL
);
11142 ASSERT_TRUE(response
->headers
.get() != NULL
);
11143 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11145 std::string response_data
;
11146 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11147 EXPECT_EQ("hello!", response_data
);
11149 // Preload cache entries into HostCache.
11150 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11151 AddressList ignored
;
11152 rv
= host_resolver
.Resolve(resolve_info
,
11155 callback
.callback(),
11158 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11159 rv
= callback
.WaitForResult();
11162 HttpRequestInfo request2
;
11163 request2
.method
= "GET";
11164 request2
.url
= GURL("https://www.gmail.com/");
11165 request2
.load_flags
= 0;
11166 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11168 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11169 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11170 EXPECT_EQ(OK
, callback
.WaitForResult());
11172 response
= trans2
.GetResponseInfo();
11173 ASSERT_TRUE(response
!= NULL
);
11174 ASSERT_TRUE(response
->headers
.get() != NULL
);
11175 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11176 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11177 EXPECT_TRUE(response
->was_npn_negotiated
);
11178 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11179 EXPECT_EQ("hello!", response_data
);
11182 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11184 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11185 const std::string https_url
= "https://www.google.com/";
11186 const std::string http_url
= "http://www.google.com:443/";
11188 // SPDY GET for HTTPS URL
11189 scoped_ptr
<SpdyFrame
> req1(
11190 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11192 MockWrite writes1
[] = {
11193 CreateMockWrite(*req1
, 0),
11196 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11197 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11198 MockRead reads1
[] = {
11199 CreateMockRead(*resp1
, 1),
11200 CreateMockRead(*body1
, 2),
11201 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11204 DelayedSocketData
data1(
11205 1, reads1
, arraysize(reads1
),
11206 writes1
, arraysize(writes1
));
11207 MockConnect
connect_data1(ASYNC
, OK
);
11208 data1
.set_connect_data(connect_data1
);
11210 // HTTP GET for the HTTP URL
11211 MockWrite writes2
[] = {
11212 MockWrite(ASYNC
, 4,
11213 "GET / HTTP/1.1\r\n"
11214 "Host: www.google.com:443\r\n"
11215 "Connection: keep-alive\r\n\r\n"),
11218 MockRead reads2
[] = {
11219 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11220 MockRead(ASYNC
, 6, "hello"),
11221 MockRead(ASYNC
, 7, OK
),
11224 DelayedSocketData
data2(
11225 1, reads2
, arraysize(reads2
),
11226 writes2
, arraysize(writes2
));
11228 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11229 ssl
.SetNextProto(GetParam());
11230 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11231 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11232 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11234 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11236 // Start the first transaction to set up the SpdySession
11237 HttpRequestInfo request1
;
11238 request1
.method
= "GET";
11239 request1
.url
= GURL(https_url
);
11240 request1
.load_flags
= 0;
11241 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11242 TestCompletionCallback callback1
;
11243 EXPECT_EQ(ERR_IO_PENDING
,
11244 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11245 base::MessageLoop::current()->RunUntilIdle();
11247 EXPECT_EQ(OK
, callback1
.WaitForResult());
11248 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11250 // Now, start the HTTP request
11251 HttpRequestInfo request2
;
11252 request2
.method
= "GET";
11253 request2
.url
= GURL(http_url
);
11254 request2
.load_flags
= 0;
11255 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11256 TestCompletionCallback callback2
;
11257 EXPECT_EQ(ERR_IO_PENDING
,
11258 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11259 base::MessageLoop::current()->RunUntilIdle();
11261 EXPECT_EQ(OK
, callback2
.WaitForResult());
11262 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11265 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11266 const std::string https_url
= "https://www.google.com/";
11267 const std::string http_url
= "http://www.google.com:443/";
11269 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11270 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
11272 scoped_ptr
<SpdyFrame
> req1(
11273 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11274 scoped_ptr
<SpdyFrame
> wrapped_req1(
11275 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11277 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11278 SpdySynStreamIR
req2_ir(3);
11279 spdy_util_
.SetPriority(MEDIUM
, &req2_ir
);
11280 req2_ir
.set_fin(true);
11281 req2_ir
.SetHeader(spdy_util_
.GetMethodKey(), "GET");
11282 req2_ir
.SetHeader(spdy_util_
.GetPathKey(),
11283 spdy_util_
.is_spdy2() ? http_url
.c_str() : "/");
11284 req2_ir
.SetHeader(spdy_util_
.GetHostKey(), "www.google.com:443");
11285 req2_ir
.SetHeader(spdy_util_
.GetSchemeKey(), "http");
11286 spdy_util_
.MaybeAddVersionHeader(&req2_ir
);
11287 scoped_ptr
<SpdyFrame
> req2(
11288 spdy_util_
.CreateFramer(false)->SerializeFrame(req2_ir
));
11290 MockWrite writes1
[] = {
11291 CreateMockWrite(*connect
, 0),
11292 CreateMockWrite(*wrapped_req1
, 2),
11293 CreateMockWrite(*req2
, 5),
11296 scoped_ptr
<SpdyFrame
> conn_resp(
11297 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11298 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11299 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11300 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11301 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11302 scoped_ptr
<SpdyFrame
> wrapped_body1(
11303 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11304 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11305 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11306 MockRead reads1
[] = {
11307 CreateMockRead(*conn_resp
, 1),
11308 CreateMockRead(*wrapped_resp1
, 3),
11309 CreateMockRead(*wrapped_body1
, 4),
11310 CreateMockRead(*resp2
, 6),
11311 CreateMockRead(*body2
, 7),
11312 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11315 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11316 writes1
, arraysize(writes1
));
11317 MockConnect
connect_data1(ASYNC
, OK
);
11318 data1
.set_connect_data(connect_data1
);
11320 session_deps_
.proxy_service
.reset(
11321 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11322 CapturingNetLog log
;
11323 session_deps_
.net_log
= &log
;
11324 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11325 ssl1
.SetNextProto(GetParam());
11326 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11327 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11328 ssl2
.SetNextProto(GetParam());
11329 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11330 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11332 scoped_refptr
<HttpNetworkSession
> session(
11333 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11335 // Start the first transaction to set up the SpdySession
11336 HttpRequestInfo request1
;
11337 request1
.method
= "GET";
11338 request1
.url
= GURL(https_url
);
11339 request1
.load_flags
= 0;
11340 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11341 TestCompletionCallback callback1
;
11342 EXPECT_EQ(ERR_IO_PENDING
,
11343 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11344 base::MessageLoop::current()->RunUntilIdle();
11347 EXPECT_EQ(OK
, callback1
.WaitForResult());
11348 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11350 LoadTimingInfo load_timing_info1
;
11351 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11352 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11353 CONNECT_TIMING_HAS_SSL_TIMES
);
11355 // Now, start the HTTP request
11356 HttpRequestInfo request2
;
11357 request2
.method
= "GET";
11358 request2
.url
= GURL(http_url
);
11359 request2
.load_flags
= 0;
11360 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11361 TestCompletionCallback callback2
;
11362 EXPECT_EQ(ERR_IO_PENDING
,
11363 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11364 base::MessageLoop::current()->RunUntilIdle();
11367 EXPECT_EQ(OK
, callback2
.WaitForResult());
11368 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11370 LoadTimingInfo load_timing_info2
;
11371 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11372 // The established SPDY sessions is considered reused by the HTTP request.
11373 TestLoadTimingReusedWithPac(load_timing_info2
);
11374 // HTTP requests over a SPDY session should have a different connection
11375 // socket_log_id than requests over a tunnel.
11376 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11379 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11380 session_deps_
.force_spdy_always
= true;
11381 const std::string https_url
= "https://www.google.com/";
11382 const std::string http_url
= "http://www.google.com:443/";
11384 // SPDY GET for HTTPS URL
11385 scoped_ptr
<SpdyFrame
> req1(
11386 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11387 // SPDY GET for the HTTP URL
11388 scoped_ptr
<SpdyFrame
> req2(
11389 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11391 MockWrite writes
[] = {
11392 CreateMockWrite(*req1
, 1),
11393 CreateMockWrite(*req2
, 4),
11396 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11397 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11398 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11399 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11400 MockRead reads
[] = {
11401 CreateMockRead(*resp1
, 2),
11402 CreateMockRead(*body1
, 3),
11403 CreateMockRead(*resp2
, 5),
11404 CreateMockRead(*body2
, 6),
11405 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11408 OrderedSocketData
data(reads
, arraysize(reads
),
11409 writes
, arraysize(writes
));
11411 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11412 ssl
.SetNextProto(GetParam());
11413 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11414 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11416 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11418 // Start the first transaction to set up the SpdySession
11419 HttpRequestInfo request1
;
11420 request1
.method
= "GET";
11421 request1
.url
= GURL(https_url
);
11422 request1
.load_flags
= 0;
11423 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11424 TestCompletionCallback callback1
;
11425 EXPECT_EQ(ERR_IO_PENDING
,
11426 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11427 base::MessageLoop::current()->RunUntilIdle();
11429 EXPECT_EQ(OK
, callback1
.WaitForResult());
11430 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11432 // Now, start the HTTP request
11433 HttpRequestInfo request2
;
11434 request2
.method
= "GET";
11435 request2
.url
= GURL(http_url
);
11436 request2
.load_flags
= 0;
11437 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11438 TestCompletionCallback callback2
;
11439 EXPECT_EQ(ERR_IO_PENDING
,
11440 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11441 base::MessageLoop::current()->RunUntilIdle();
11443 EXPECT_EQ(OK
, callback2
.WaitForResult());
11444 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11447 // Test that in the case where we have a SPDY session to a SPDY proxy
11448 // that we do not pool other origins that resolve to the same IP when
11449 // the certificate does not match the new origin.
11450 // http://crbug.com/134690
11451 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11452 const std::string url1
= "http://www.google.com/";
11453 const std::string url2
= "https://mail.google.com/";
11454 const std::string ip_addr
= "1.2.3.4";
11456 // SPDY GET for HTTP URL (through SPDY proxy)
11457 scoped_ptr
<SpdyHeaderBlock
> headers(
11458 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11459 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyControlFrame(
11460 headers
.Pass(), false, 1, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
11462 MockWrite writes1
[] = {
11463 CreateMockWrite(*req1
, 0),
11466 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11467 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11468 MockRead reads1
[] = {
11469 CreateMockRead(*resp1
, 1),
11470 CreateMockRead(*body1
, 2),
11471 MockRead(ASYNC
, OK
, 3) // EOF
11474 scoped_ptr
<DeterministicSocketData
> data1(
11475 new DeterministicSocketData(reads1
, arraysize(reads1
),
11476 writes1
, arraysize(writes1
)));
11477 IPAddressNumber ip
;
11478 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11479 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11480 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11481 data1
->set_connect_data(connect_data1
);
11483 // SPDY GET for HTTPS URL (direct)
11484 scoped_ptr
<SpdyFrame
> req2(
11485 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11487 MockWrite writes2
[] = {
11488 CreateMockWrite(*req2
, 0),
11491 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11492 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11493 MockRead reads2
[] = {
11494 CreateMockRead(*resp2
, 1),
11495 CreateMockRead(*body2
, 2),
11496 MockRead(ASYNC
, OK
, 3) // EOF
11499 scoped_ptr
<DeterministicSocketData
> data2(
11500 new DeterministicSocketData(reads2
, arraysize(reads2
),
11501 writes2
, arraysize(writes2
)));
11502 MockConnect
connect_data2(ASYNC
, OK
);
11503 data2
->set_connect_data(connect_data2
);
11505 // Set up a proxy config that sends HTTP requests to a proxy, and
11506 // all others direct.
11507 ProxyConfig proxy_config
;
11508 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11509 CapturingProxyResolver
* capturing_proxy_resolver
=
11510 new CapturingProxyResolver();
11511 session_deps_
.proxy_service
.reset(new ProxyService(
11512 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11515 // Load a valid cert. Note, that this does not need to
11516 // be valid for proxy because the MockSSLClientSocket does
11517 // not actually verify it. But SpdySession will use this
11518 // to see if it is valid for the new origin
11519 base::FilePath certs_dir
= GetTestCertsDirectory();
11520 scoped_refptr
<X509Certificate
> server_cert(
11521 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11522 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
);
11524 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11525 ssl1
.SetNextProto(GetParam());
11526 ssl1
.cert
= server_cert
;
11527 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11528 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11531 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11532 ssl2
.SetNextProto(GetParam());
11533 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11534 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11537 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11538 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11539 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11541 scoped_refptr
<HttpNetworkSession
> session(
11542 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11544 // Start the first transaction to set up the SpdySession
11545 HttpRequestInfo request1
;
11546 request1
.method
= "GET";
11547 request1
.url
= GURL(url1
);
11548 request1
.load_flags
= 0;
11549 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11550 TestCompletionCallback callback1
;
11551 ASSERT_EQ(ERR_IO_PENDING
,
11552 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11555 ASSERT_TRUE(callback1
.have_result());
11556 EXPECT_EQ(OK
, callback1
.WaitForResult());
11557 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11559 // Now, start the HTTP request
11560 HttpRequestInfo request2
;
11561 request2
.method
= "GET";
11562 request2
.url
= GURL(url2
);
11563 request2
.load_flags
= 0;
11564 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11565 TestCompletionCallback callback2
;
11566 EXPECT_EQ(ERR_IO_PENDING
,
11567 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11568 base::MessageLoop::current()->RunUntilIdle();
11571 ASSERT_TRUE(callback2
.have_result());
11572 EXPECT_EQ(OK
, callback2
.WaitForResult());
11573 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11576 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11577 // error) in SPDY session, removes the socket from pool and closes the SPDY
11578 // session. Verify that new url's from the same HttpNetworkSession (and a new
11579 // SpdySession) do work. http://crbug.com/224701
11580 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11581 const std::string https_url
= "https://www.google.com/";
11583 MockRead reads1
[] = {
11584 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11587 scoped_ptr
<DeterministicSocketData
> data1(
11588 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11591 scoped_ptr
<SpdyFrame
> req2(
11592 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11593 MockWrite writes2
[] = {
11594 CreateMockWrite(*req2
, 0),
11597 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11598 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11599 MockRead reads2
[] = {
11600 CreateMockRead(*resp2
, 1),
11601 CreateMockRead(*body2
, 2),
11602 MockRead(ASYNC
, OK
, 3) // EOF
11605 scoped_ptr
<DeterministicSocketData
> data2(
11606 new DeterministicSocketData(reads2
, arraysize(reads2
),
11607 writes2
, arraysize(writes2
)));
11609 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11610 ssl1
.SetNextProto(GetParam());
11611 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11612 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11615 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11616 ssl2
.SetNextProto(GetParam());
11617 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11618 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11621 scoped_refptr
<HttpNetworkSession
> session(
11622 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11624 // Start the first transaction to set up the SpdySession and verify that
11625 // connection was closed.
11626 HttpRequestInfo request1
;
11627 request1
.method
= "GET";
11628 request1
.url
= GURL(https_url
);
11629 request1
.load_flags
= 0;
11630 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11631 TestCompletionCallback callback1
;
11632 EXPECT_EQ(ERR_IO_PENDING
,
11633 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11634 base::MessageLoop::current()->RunUntilIdle();
11635 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11637 // Now, start the second request and make sure it succeeds.
11638 HttpRequestInfo request2
;
11639 request2
.method
= "GET";
11640 request2
.url
= GURL(https_url
);
11641 request2
.load_flags
= 0;
11642 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11643 TestCompletionCallback callback2
;
11644 EXPECT_EQ(ERR_IO_PENDING
,
11645 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11646 base::MessageLoop::current()->RunUntilIdle();
11649 ASSERT_TRUE(callback2
.have_result());
11650 EXPECT_EQ(OK
, callback2
.WaitForResult());
11651 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11654 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11655 session_deps_
.next_protos
= SpdyNextProtos();
11656 ClientSocketPoolManager::set_max_sockets_per_group(
11657 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11658 ClientSocketPoolManager::set_max_sockets_per_pool(
11659 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11661 // Use two different hosts with different IPs so they don't get pooled.
11662 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11663 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11664 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11666 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11667 ssl1
.SetNextProto(GetParam());
11668 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11669 ssl2
.SetNextProto(GetParam());
11670 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11671 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11673 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11674 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11675 MockWrite spdy1_writes
[] = {
11676 CreateMockWrite(*host1_req
, 1),
11678 scoped_ptr
<SpdyFrame
> host1_resp(
11679 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11680 scoped_ptr
<SpdyFrame
> host1_resp_body(
11681 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11682 MockRead spdy1_reads
[] = {
11683 CreateMockRead(*host1_resp
, 2),
11684 CreateMockRead(*host1_resp_body
, 3),
11685 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11688 scoped_ptr
<OrderedSocketData
> spdy1_data(
11689 new OrderedSocketData(
11690 spdy1_reads
, arraysize(spdy1_reads
),
11691 spdy1_writes
, arraysize(spdy1_writes
)));
11692 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11694 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11695 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11696 MockWrite spdy2_writes
[] = {
11697 CreateMockWrite(*host2_req
, 1),
11699 scoped_ptr
<SpdyFrame
> host2_resp(
11700 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11701 scoped_ptr
<SpdyFrame
> host2_resp_body(
11702 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11703 MockRead spdy2_reads
[] = {
11704 CreateMockRead(*host2_resp
, 2),
11705 CreateMockRead(*host2_resp_body
, 3),
11706 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11709 scoped_ptr
<OrderedSocketData
> spdy2_data(
11710 new OrderedSocketData(
11711 spdy2_reads
, arraysize(spdy2_reads
),
11712 spdy2_writes
, arraysize(spdy2_writes
)));
11713 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11715 MockWrite http_write
[] = {
11716 MockWrite("GET / HTTP/1.1\r\n"
11717 "Host: www.a.com\r\n"
11718 "Connection: keep-alive\r\n\r\n"),
11721 MockRead http_read
[] = {
11722 MockRead("HTTP/1.1 200 OK\r\n"),
11723 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11724 MockRead("Content-Length: 6\r\n\r\n"),
11725 MockRead("hello!"),
11727 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11728 http_write
, arraysize(http_write
));
11729 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11731 HostPortPair
host_port_pair_a("www.a.com", 443);
11732 SpdySessionKey
spdy_session_key_a(
11733 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11735 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11737 TestCompletionCallback callback
;
11738 HttpRequestInfo request1
;
11739 request1
.method
= "GET";
11740 request1
.url
= GURL("https://www.a.com/");
11741 request1
.load_flags
= 0;
11742 scoped_ptr
<HttpNetworkTransaction
> trans(
11743 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11745 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11746 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11747 EXPECT_EQ(OK
, callback
.WaitForResult());
11749 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11750 ASSERT_TRUE(response
!= NULL
);
11751 ASSERT_TRUE(response
->headers
.get() != NULL
);
11752 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11753 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11754 EXPECT_TRUE(response
->was_npn_negotiated
);
11756 std::string response_data
;
11757 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11758 EXPECT_EQ("hello!", response_data
);
11761 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11763 HostPortPair
host_port_pair_b("www.b.com", 443);
11764 SpdySessionKey
spdy_session_key_b(
11765 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11767 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11768 HttpRequestInfo request2
;
11769 request2
.method
= "GET";
11770 request2
.url
= GURL("https://www.b.com/");
11771 request2
.load_flags
= 0;
11772 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11774 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11776 EXPECT_EQ(OK
, callback
.WaitForResult());
11778 response
= trans
->GetResponseInfo();
11779 ASSERT_TRUE(response
!= NULL
);
11780 ASSERT_TRUE(response
->headers
.get() != NULL
);
11781 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11782 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11783 EXPECT_TRUE(response
->was_npn_negotiated
);
11784 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11785 EXPECT_EQ("hello!", response_data
);
11787 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11789 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11791 HostPortPair
host_port_pair_a1("www.a.com", 80);
11792 SpdySessionKey
spdy_session_key_a1(
11793 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11795 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11796 HttpRequestInfo request3
;
11797 request3
.method
= "GET";
11798 request3
.url
= GURL("http://www.a.com/");
11799 request3
.load_flags
= 0;
11800 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11802 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11803 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11804 EXPECT_EQ(OK
, callback
.WaitForResult());
11806 response
= trans
->GetResponseInfo();
11807 ASSERT_TRUE(response
!= NULL
);
11808 ASSERT_TRUE(response
->headers
.get() != NULL
);
11809 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11810 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11811 EXPECT_FALSE(response
->was_npn_negotiated
);
11812 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11813 EXPECT_EQ("hello!", response_data
);
11815 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11817 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11820 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11821 HttpRequestInfo request
;
11822 request
.method
= "GET";
11823 request
.url
= GURL("http://www.google.com/");
11824 request
.load_flags
= 0;
11826 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11827 scoped_ptr
<HttpTransaction
> trans(
11828 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11830 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11831 StaticSocketDataProvider data
;
11832 data
.set_connect_data(mock_connect
);
11833 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11835 TestCompletionCallback callback
;
11837 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11838 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11840 rv
= callback
.WaitForResult();
11841 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11843 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11845 // We don't care whether this succeeds or fails, but it shouldn't crash.
11846 HttpRequestHeaders request_headers
;
11847 trans
->GetFullRequestHeaders(&request_headers
);
11850 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11851 HttpRequestInfo request
;
11852 request
.method
= "GET";
11853 request
.url
= GURL("http://www.google.com/");
11854 request
.load_flags
= 0;
11856 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11857 scoped_ptr
<HttpTransaction
> trans(
11858 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11860 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11861 StaticSocketDataProvider data
;
11862 data
.set_connect_data(mock_connect
);
11863 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11865 TestCompletionCallback callback
;
11867 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11868 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11870 rv
= callback
.WaitForResult();
11871 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11873 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11875 // We don't care whether this succeeds or fails, but it shouldn't crash.
11876 HttpRequestHeaders request_headers
;
11877 trans
->GetFullRequestHeaders(&request_headers
);
11880 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
11881 HttpRequestInfo request
;
11882 request
.method
= "GET";
11883 request
.url
= GURL("http://www.google.com/");
11884 request
.load_flags
= 0;
11886 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11887 scoped_ptr
<HttpTransaction
> trans(
11888 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11890 MockWrite data_writes
[] = {
11891 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
11893 MockRead data_reads
[] = {
11894 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
11897 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11898 data_writes
, arraysize(data_writes
));
11899 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11901 TestCompletionCallback callback
;
11903 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11904 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11906 rv
= callback
.WaitForResult();
11907 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11909 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11911 HttpRequestHeaders request_headers
;
11912 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11913 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11916 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
11917 HttpRequestInfo request
;
11918 request
.method
= "GET";
11919 request
.url
= GURL("http://www.google.com/");
11920 request
.load_flags
= 0;
11922 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11923 scoped_ptr
<HttpTransaction
> trans(
11924 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11926 MockWrite data_writes
[] = {
11927 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
11929 MockRead data_reads
[] = {
11930 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
11933 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11934 data_writes
, arraysize(data_writes
));
11935 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11937 TestCompletionCallback callback
;
11939 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11940 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11942 rv
= callback
.WaitForResult();
11943 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11945 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11947 HttpRequestHeaders request_headers
;
11948 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11949 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11952 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
11953 HttpRequestInfo request
;
11954 request
.method
= "GET";
11955 request
.url
= GURL("http://www.google.com/");
11956 request
.load_flags
= 0;
11958 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11959 scoped_ptr
<HttpTransaction
> trans(
11960 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11962 MockWrite data_writes
[] = {
11963 MockWrite("GET / HTTP/1.1\r\n"
11964 "Host: www.google.com\r\n"
11965 "Connection: keep-alive\r\n\r\n"),
11967 MockRead data_reads
[] = {
11968 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
11971 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11972 data_writes
, arraysize(data_writes
));
11973 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11975 TestCompletionCallback callback
;
11977 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11980 rv
= callback
.WaitForResult();
11981 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11983 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11985 HttpRequestHeaders request_headers
;
11986 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11987 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11990 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
11991 HttpRequestInfo request
;
11992 request
.method
= "GET";
11993 request
.url
= GURL("http://www.google.com/");
11994 request
.load_flags
= 0;
11996 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11997 scoped_ptr
<HttpTransaction
> trans(
11998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12000 MockWrite data_writes
[] = {
12001 MockWrite("GET / HTTP/1.1\r\n"
12002 "Host: www.google.com\r\n"
12003 "Connection: keep-alive\r\n\r\n"),
12005 MockRead data_reads
[] = {
12006 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12009 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12010 data_writes
, arraysize(data_writes
));
12011 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12013 TestCompletionCallback callback
;
12015 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12016 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12018 rv
= callback
.WaitForResult();
12019 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12021 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12023 HttpRequestHeaders request_headers
;
12024 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12025 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12028 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12029 HttpRequestInfo request
;
12030 request
.method
= "GET";
12031 request
.url
= GURL("http://www.google.com/");
12032 request
.load_flags
= 0;
12033 request
.extra_headers
.SetHeader("X-Foo", "bar");
12035 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12036 scoped_ptr
<HttpTransaction
> trans(
12037 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12039 MockWrite data_writes
[] = {
12040 MockWrite("GET / HTTP/1.1\r\n"
12041 "Host: www.google.com\r\n"
12042 "Connection: keep-alive\r\n"
12043 "X-Foo: bar\r\n\r\n"),
12045 MockRead data_reads
[] = {
12046 MockRead("HTTP/1.1 200 OK\r\n"
12047 "Content-Length: 5\r\n\r\n"
12049 MockRead(ASYNC
, ERR_UNEXPECTED
),
12052 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12053 data_writes
, arraysize(data_writes
));
12054 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12056 TestCompletionCallback callback
;
12058 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12059 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12061 rv
= callback
.WaitForResult();
12064 HttpRequestHeaders request_headers
;
12065 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12067 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12068 EXPECT_EQ("bar", foo
);
12073 // Fake HttpStreamBase that simply records calls to SetPriority().
12074 class FakeStream
: public HttpStreamBase
,
12075 public base::SupportsWeakPtr
<FakeStream
> {
12077 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12078 virtual ~FakeStream() {}
12080 RequestPriority
priority() const { return priority_
; }
12082 virtual int InitializeStream(const HttpRequestInfo
* request_info
,
12083 RequestPriority priority
,
12084 const BoundNetLog
& net_log
,
12085 const CompletionCallback
& callback
) OVERRIDE
{
12086 return ERR_IO_PENDING
;
12089 virtual int SendRequest(const HttpRequestHeaders
& request_headers
,
12090 HttpResponseInfo
* response
,
12091 const CompletionCallback
& callback
) OVERRIDE
{
12093 return ERR_UNEXPECTED
;
12096 virtual int ReadResponseHeaders(const CompletionCallback
& callback
) OVERRIDE
{
12098 return ERR_UNEXPECTED
;
12101 virtual int ReadResponseBody(IOBuffer
* buf
, int buf_len
,
12102 const CompletionCallback
& callback
) OVERRIDE
{
12104 return ERR_UNEXPECTED
;
12107 virtual void Close(bool not_reusable
) OVERRIDE
{}
12109 virtual bool IsResponseBodyComplete() const OVERRIDE
{
12114 virtual bool CanFindEndOfResponse() const OVERRIDE
{
12118 virtual bool IsConnectionReused() const OVERRIDE
{
12123 virtual void SetConnectionReused() OVERRIDE
{
12127 virtual bool IsConnectionReusable() const OVERRIDE
{
12132 virtual int64
GetTotalReceivedBytes() const OVERRIDE
{
12137 virtual bool GetLoadTimingInfo(
12138 LoadTimingInfo
* load_timing_info
) const OVERRIDE
{
12143 virtual void GetSSLInfo(SSLInfo
* ssl_info
) OVERRIDE
{
12147 virtual void GetSSLCertRequestInfo(
12148 SSLCertRequestInfo
* cert_request_info
) OVERRIDE
{
12152 virtual bool IsSpdyHttpStream() const OVERRIDE
{
12157 virtual void Drain(HttpNetworkSession
* session
) OVERRIDE
{
12161 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12162 priority_
= priority
;
12166 RequestPriority priority_
;
12168 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12171 // Fake HttpStreamRequest that simply records calls to SetPriority()
12172 // and vends FakeStreams with its current priority.
12173 class FakeStreamRequest
: public HttpStreamRequest
,
12174 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12176 FakeStreamRequest(RequestPriority priority
,
12177 HttpStreamRequest::Delegate
* delegate
)
12178 : priority_(priority
),
12179 delegate_(delegate
),
12180 websocket_stream_create_helper_(NULL
) {}
12182 FakeStreamRequest(RequestPriority priority
,
12183 HttpStreamRequest::Delegate
* delegate
,
12184 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12185 : priority_(priority
),
12186 delegate_(delegate
),
12187 websocket_stream_create_helper_(create_helper
) {}
12189 virtual ~FakeStreamRequest() {}
12191 RequestPriority
priority() const { return priority_
; }
12193 const WebSocketHandshakeStreamBase::CreateHelper
*
12194 websocket_stream_create_helper() const {
12195 return websocket_stream_create_helper_
;
12198 // Create a new FakeStream and pass it to the request's
12199 // delegate. Returns a weak pointer to the FakeStream.
12200 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12201 FakeStream
* fake_stream
= new FakeStream(priority_
);
12202 // Do this before calling OnStreamReady() as OnStreamReady() may
12203 // immediately delete |fake_stream|.
12204 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12205 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12206 return weak_stream
;
12209 virtual int RestartTunnelWithProxyAuth(
12210 const AuthCredentials
& credentials
) OVERRIDE
{
12212 return ERR_UNEXPECTED
;
12215 virtual LoadState
GetLoadState() const OVERRIDE
{
12217 return LoadState();
12220 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12221 priority_
= priority
;
12224 virtual bool was_npn_negotiated() const OVERRIDE
{
12228 virtual NextProto
protocol_negotiated() const OVERRIDE
{
12229 return kProtoUnknown
;
12232 virtual bool using_spdy() const OVERRIDE
{
12237 RequestPriority priority_
;
12238 HttpStreamRequest::Delegate
* const delegate_
;
12239 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12241 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12244 // Fake HttpStreamFactory that vends FakeStreamRequests.
12245 class FakeStreamFactory
: public HttpStreamFactory
{
12247 FakeStreamFactory() {}
12248 virtual ~FakeStreamFactory() {}
12250 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12251 // RequestStream() (which may be NULL if it was destroyed already).
12252 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12253 return last_stream_request_
;
12256 virtual HttpStreamRequest
* RequestStream(
12257 const HttpRequestInfo
& info
,
12258 RequestPriority priority
,
12259 const SSLConfig
& server_ssl_config
,
12260 const SSLConfig
& proxy_ssl_config
,
12261 HttpStreamRequest::Delegate
* delegate
,
12262 const BoundNetLog
& net_log
) OVERRIDE
{
12263 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12264 last_stream_request_
= fake_request
->AsWeakPtr();
12265 return fake_request
;
12268 virtual HttpStreamRequest
* RequestWebSocketHandshakeStream(
12269 const HttpRequestInfo
& info
,
12270 RequestPriority priority
,
12271 const SSLConfig
& server_ssl_config
,
12272 const SSLConfig
& proxy_ssl_config
,
12273 HttpStreamRequest::Delegate
* delegate
,
12274 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12275 const BoundNetLog
& net_log
) OVERRIDE
{
12276 FakeStreamRequest
* fake_request
=
12277 new FakeStreamRequest(priority
, delegate
, create_helper
);
12278 last_stream_request_
= fake_request
->AsWeakPtr();
12279 return fake_request
;
12282 virtual void PreconnectStreams(int num_streams
,
12283 const HttpRequestInfo
& info
,
12284 RequestPriority priority
,
12285 const SSLConfig
& server_ssl_config
,
12286 const SSLConfig
& proxy_ssl_config
) OVERRIDE
{
12290 virtual const HostMappingRules
* GetHostMappingRules() const OVERRIDE
{
12296 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12298 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12301 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12303 class FakeWebSocketStreamCreateHelper
:
12304 public WebSocketHandshakeStreamBase::CreateHelper
{
12306 virtual WebSocketHandshakeStreamBase
* CreateBasicStream(
12307 scoped_ptr
<ClientSocketHandle
> connection
,
12308 bool using_proxy
) OVERRIDE
{
12313 virtual WebSocketHandshakeStreamBase
* CreateSpdyStream(
12314 const base::WeakPtr
<SpdySession
>& session
,
12315 bool use_relative_url
) OVERRIDE
{
12320 virtual ~FakeWebSocketStreamCreateHelper() {}
12322 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12324 return scoped_ptr
<WebSocketStream
>();
12330 // Make sure that HttpNetworkTransaction passes on its priority to its
12331 // stream request on start.
12332 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12333 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12334 HttpNetworkSessionPeer
peer(session
);
12335 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12336 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12338 HttpNetworkTransaction
trans(LOW
, session
);
12340 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12342 HttpRequestInfo request
;
12343 TestCompletionCallback callback
;
12344 EXPECT_EQ(ERR_IO_PENDING
,
12345 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12347 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12348 fake_factory
->last_stream_request();
12349 ASSERT_TRUE(fake_request
!= NULL
);
12350 EXPECT_EQ(LOW
, fake_request
->priority());
12353 // Make sure that HttpNetworkTransaction passes on its priority
12354 // updates to its stream request.
12355 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12356 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12357 HttpNetworkSessionPeer
peer(session
);
12358 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12359 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12361 HttpNetworkTransaction
trans(LOW
, session
);
12363 HttpRequestInfo request
;
12364 TestCompletionCallback callback
;
12365 EXPECT_EQ(ERR_IO_PENDING
,
12366 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12368 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12369 fake_factory
->last_stream_request();
12370 ASSERT_TRUE(fake_request
!= NULL
);
12371 EXPECT_EQ(LOW
, fake_request
->priority());
12373 trans
.SetPriority(LOWEST
);
12374 ASSERT_TRUE(fake_request
!= NULL
);
12375 EXPECT_EQ(LOWEST
, fake_request
->priority());
12378 // Make sure that HttpNetworkTransaction passes on its priority
12379 // updates to its stream.
12380 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12381 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12382 HttpNetworkSessionPeer
peer(session
);
12383 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12384 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12386 HttpNetworkTransaction
trans(LOW
, session
);
12388 HttpRequestInfo request
;
12389 TestCompletionCallback callback
;
12390 EXPECT_EQ(ERR_IO_PENDING
,
12391 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12393 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12394 fake_factory
->last_stream_request();
12395 ASSERT_TRUE(fake_request
!= NULL
);
12396 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12397 ASSERT_TRUE(fake_stream
!= NULL
);
12398 EXPECT_EQ(LOW
, fake_stream
->priority());
12400 trans
.SetPriority(LOWEST
);
12401 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12404 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12405 // The same logic needs to be tested for both ws: and wss: schemes, but this
12406 // test is already parameterised on NextProto, so it uses a loop to verify
12407 // that the different schemes work.
12408 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
12409 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
12410 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12411 HttpNetworkSessionPeer
peer(session
);
12412 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12413 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
12414 peer
.SetHttpStreamFactoryForWebSocket(
12415 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12417 HttpNetworkTransaction
trans(LOW
, session
);
12418 trans
.SetWebSocketHandshakeStreamCreateHelper(
12419 &websocket_stream_create_helper
);
12421 HttpRequestInfo request
;
12422 TestCompletionCallback callback
;
12423 request
.method
= "GET";
12424 request
.url
= GURL(test_cases
[i
]);
12426 EXPECT_EQ(ERR_IO_PENDING
,
12427 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12429 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12430 fake_factory
->last_stream_request();
12431 ASSERT_TRUE(fake_request
!= NULL
);
12432 EXPECT_EQ(&websocket_stream_create_helper
,
12433 fake_request
->websocket_stream_create_helper());
12437 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12438 // if the transport socket pool is stalled on the global socket limit.
12439 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
12440 ClientSocketPoolManager::set_max_sockets_per_group(
12441 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12442 ClientSocketPoolManager::set_max_sockets_per_pool(
12443 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12445 // Set up SSL request.
12447 HttpRequestInfo ssl_request
;
12448 ssl_request
.method
= "GET";
12449 ssl_request
.url
= GURL("https://www.google.com/");
12451 MockWrite ssl_writes
[] = {
12452 MockWrite("GET / HTTP/1.1\r\n"
12453 "Host: www.google.com\r\n"
12454 "Connection: keep-alive\r\n\r\n"),
12456 MockRead ssl_reads
[] = {
12457 MockRead("HTTP/1.1 200 OK\r\n"),
12458 MockRead("Content-Length: 11\r\n\r\n"),
12459 MockRead("hello world"),
12460 MockRead(SYNCHRONOUS
, OK
),
12462 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
12463 ssl_writes
, arraysize(ssl_writes
));
12464 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12466 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12467 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12469 // Set up HTTP request.
12471 HttpRequestInfo http_request
;
12472 http_request
.method
= "GET";
12473 http_request
.url
= GURL("http://www.google.com/");
12475 MockWrite http_writes
[] = {
12476 MockWrite("GET / HTTP/1.1\r\n"
12477 "Host: www.google.com\r\n"
12478 "Connection: keep-alive\r\n\r\n"),
12480 MockRead http_reads
[] = {
12481 MockRead("HTTP/1.1 200 OK\r\n"),
12482 MockRead("Content-Length: 7\r\n\r\n"),
12483 MockRead("falafel"),
12484 MockRead(SYNCHRONOUS
, OK
),
12486 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12487 http_writes
, arraysize(http_writes
));
12488 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12492 // Start the SSL request.
12493 TestCompletionCallback ssl_callback
;
12494 scoped_ptr
<HttpTransaction
> ssl_trans(
12495 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12496 ASSERT_EQ(ERR_IO_PENDING
,
12497 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
12500 // Start the HTTP request. Pool should stall.
12501 TestCompletionCallback http_callback
;
12502 scoped_ptr
<HttpTransaction
> http_trans(
12503 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12504 ASSERT_EQ(ERR_IO_PENDING
,
12505 http_trans
->Start(&http_request
, http_callback
.callback(),
12507 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12509 // Wait for response from SSL request.
12510 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
12511 std::string response_data
;
12512 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
12513 EXPECT_EQ("hello world", response_data
);
12515 // The SSL socket should automatically be closed, so the HTTP request can
12517 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12518 ASSERT_FALSE(IsTransportSocketPoolStalled(session
));
12520 // The HTTP request can now complete.
12521 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12522 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12523 EXPECT_EQ("falafel", response_data
);
12525 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12528 // Tests that when a SSL connection is established but there's no corresponding
12529 // request that needs it, the new socket is closed if the transport socket pool
12530 // is stalled on the global socket limit.
12531 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
12532 ClientSocketPoolManager::set_max_sockets_per_group(
12533 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12534 ClientSocketPoolManager::set_max_sockets_per_pool(
12535 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12537 // Set up an ssl request.
12539 HttpRequestInfo ssl_request
;
12540 ssl_request
.method
= "GET";
12541 ssl_request
.url
= GURL("https://www.foopy.com/");
12543 // No data will be sent on the SSL socket.
12544 StaticSocketDataProvider ssl_data
;
12545 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12547 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12548 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12550 // Set up HTTP request.
12552 HttpRequestInfo http_request
;
12553 http_request
.method
= "GET";
12554 http_request
.url
= GURL("http://www.google.com/");
12556 MockWrite http_writes
[] = {
12557 MockWrite("GET / HTTP/1.1\r\n"
12558 "Host: www.google.com\r\n"
12559 "Connection: keep-alive\r\n\r\n"),
12561 MockRead http_reads
[] = {
12562 MockRead("HTTP/1.1 200 OK\r\n"),
12563 MockRead("Content-Length: 7\r\n\r\n"),
12564 MockRead("falafel"),
12565 MockRead(SYNCHRONOUS
, OK
),
12567 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12568 http_writes
, arraysize(http_writes
));
12569 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12571 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12573 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12574 // cancelled when a normal transaction is cancelled.
12575 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
12576 net::SSLConfig ssl_config
;
12577 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
12578 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
12579 ssl_config
, ssl_config
);
12580 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12582 // Start the HTTP request. Pool should stall.
12583 TestCompletionCallback http_callback
;
12584 scoped_ptr
<HttpTransaction
> http_trans(
12585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12586 ASSERT_EQ(ERR_IO_PENDING
,
12587 http_trans
->Start(&http_request
, http_callback
.callback(),
12589 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12591 // The SSL connection will automatically be closed once the connection is
12592 // established, to let the HTTP request start.
12593 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12594 std::string response_data
;
12595 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12596 EXPECT_EQ("falafel", response_data
);
12598 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12601 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
12602 ScopedVector
<UploadElementReader
> element_readers
;
12603 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12604 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12606 HttpRequestInfo request
;
12607 request
.method
= "POST";
12608 request
.url
= GURL("http://www.foo.com/");
12609 request
.upload_data_stream
= &upload_data_stream
;
12610 request
.load_flags
= 0;
12612 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12613 scoped_ptr
<HttpTransaction
> trans(
12614 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12615 // Send headers successfully, but get an error while sending the body.
12616 MockWrite data_writes
[] = {
12617 MockWrite("POST / HTTP/1.1\r\n"
12618 "Host: www.foo.com\r\n"
12619 "Connection: keep-alive\r\n"
12620 "Content-Length: 3\r\n\r\n"),
12621 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12624 MockRead data_reads
[] = {
12625 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12626 MockRead("hello world"),
12627 MockRead(SYNCHRONOUS
, OK
),
12629 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12630 arraysize(data_writes
));
12631 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12633 TestCompletionCallback callback
;
12635 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12636 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12638 rv
= callback
.WaitForResult();
12641 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12642 ASSERT_TRUE(response
!= NULL
);
12644 EXPECT_TRUE(response
->headers
.get() != NULL
);
12645 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12647 std::string response_data
;
12648 rv
= ReadTransaction(trans
.get(), &response_data
);
12650 EXPECT_EQ("hello world", response_data
);
12653 // This test makes sure the retry logic doesn't trigger when reading an error
12654 // response from a server that rejected a POST with a CONNECTION_RESET.
12655 TEST_P(HttpNetworkTransactionTest
,
12656 PostReadsErrorResponseAfterResetOnReusedSocket
) {
12657 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12658 MockWrite data_writes
[] = {
12659 MockWrite("GET / HTTP/1.1\r\n"
12660 "Host: www.foo.com\r\n"
12661 "Connection: keep-alive\r\n\r\n"),
12662 MockWrite("POST / HTTP/1.1\r\n"
12663 "Host: www.foo.com\r\n"
12664 "Connection: keep-alive\r\n"
12665 "Content-Length: 3\r\n\r\n"),
12666 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12669 MockRead data_reads
[] = {
12670 MockRead("HTTP/1.1 200 Peachy\r\n"
12671 "Content-Length: 14\r\n\r\n"),
12672 MockRead("first response"),
12673 MockRead("HTTP/1.1 400 Not OK\r\n"
12674 "Content-Length: 15\r\n\r\n"),
12675 MockRead("second response"),
12676 MockRead(SYNCHRONOUS
, OK
),
12678 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12679 arraysize(data_writes
));
12680 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12682 TestCompletionCallback callback
;
12683 HttpRequestInfo request1
;
12684 request1
.method
= "GET";
12685 request1
.url
= GURL("http://www.foo.com/");
12686 request1
.load_flags
= 0;
12688 scoped_ptr
<HttpTransaction
> trans1(
12689 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12690 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
12691 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12693 rv
= callback
.WaitForResult();
12696 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12697 ASSERT_TRUE(response1
!= NULL
);
12699 EXPECT_TRUE(response1
->headers
.get() != NULL
);
12700 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
12702 std::string response_data1
;
12703 rv
= ReadTransaction(trans1
.get(), &response_data1
);
12705 EXPECT_EQ("first response", response_data1
);
12706 // Delete the transaction to release the socket back into the socket pool.
12709 ScopedVector
<UploadElementReader
> element_readers
;
12710 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12711 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12713 HttpRequestInfo request2
;
12714 request2
.method
= "POST";
12715 request2
.url
= GURL("http://www.foo.com/");
12716 request2
.upload_data_stream
= &upload_data_stream
;
12717 request2
.load_flags
= 0;
12719 scoped_ptr
<HttpTransaction
> trans2(
12720 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12721 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
12722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12724 rv
= callback
.WaitForResult();
12727 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
12728 ASSERT_TRUE(response2
!= NULL
);
12730 EXPECT_TRUE(response2
->headers
.get() != NULL
);
12731 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
12733 std::string response_data2
;
12734 rv
= ReadTransaction(trans2
.get(), &response_data2
);
12736 EXPECT_EQ("second response", response_data2
);
12739 TEST_P(HttpNetworkTransactionTest
,
12740 PostReadsErrorResponseAfterResetPartialBodySent
) {
12741 ScopedVector
<UploadElementReader
> element_readers
;
12742 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12743 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12745 HttpRequestInfo request
;
12746 request
.method
= "POST";
12747 request
.url
= GURL("http://www.foo.com/");
12748 request
.upload_data_stream
= &upload_data_stream
;
12749 request
.load_flags
= 0;
12751 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12752 scoped_ptr
<HttpTransaction
> trans(
12753 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12754 // Send headers successfully, but get an error while sending the body.
12755 MockWrite data_writes
[] = {
12756 MockWrite("POST / HTTP/1.1\r\n"
12757 "Host: www.foo.com\r\n"
12758 "Connection: keep-alive\r\n"
12759 "Content-Length: 3\r\n\r\n"
12761 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12764 MockRead data_reads
[] = {
12765 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12766 MockRead("hello world"),
12767 MockRead(SYNCHRONOUS
, OK
),
12769 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12770 arraysize(data_writes
));
12771 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12773 TestCompletionCallback callback
;
12775 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12778 rv
= callback
.WaitForResult();
12781 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12782 ASSERT_TRUE(response
!= NULL
);
12784 EXPECT_TRUE(response
->headers
.get() != NULL
);
12785 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12787 std::string response_data
;
12788 rv
= ReadTransaction(trans
.get(), &response_data
);
12790 EXPECT_EQ("hello world", response_data
);
12793 // This tests the more common case than the previous test, where headers and
12794 // body are not merged into a single request.
12795 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
12796 ScopedVector
<UploadElementReader
> element_readers
;
12797 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12798 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
12800 HttpRequestInfo request
;
12801 request
.method
= "POST";
12802 request
.url
= GURL("http://www.foo.com/");
12803 request
.upload_data_stream
= &upload_data_stream
;
12804 request
.load_flags
= 0;
12806 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12807 scoped_ptr
<HttpTransaction
> trans(
12808 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12809 // Send headers successfully, but get an error while sending the body.
12810 MockWrite data_writes
[] = {
12811 MockWrite("POST / HTTP/1.1\r\n"
12812 "Host: www.foo.com\r\n"
12813 "Connection: keep-alive\r\n"
12814 "Transfer-Encoding: chunked\r\n\r\n"),
12815 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12818 MockRead data_reads
[] = {
12819 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12820 MockRead("hello world"),
12821 MockRead(SYNCHRONOUS
, OK
),
12823 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12824 arraysize(data_writes
));
12825 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12827 TestCompletionCallback callback
;
12829 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12830 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12831 // Make sure the headers are sent before adding a chunk. This ensures that
12832 // they can't be merged with the body in a single send. Not currently
12833 // necessary since a chunked body is never merged with headers, but this makes
12834 // the test more future proof.
12835 base::RunLoop().RunUntilIdle();
12837 upload_data_stream
.AppendChunk("last chunk", 10, true);
12839 rv
= callback
.WaitForResult();
12842 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12843 ASSERT_TRUE(response
!= NULL
);
12845 EXPECT_TRUE(response
->headers
.get() != NULL
);
12846 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12848 std::string response_data
;
12849 rv
= ReadTransaction(trans
.get(), &response_data
);
12851 EXPECT_EQ("hello world", response_data
);
12854 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
12855 ScopedVector
<UploadElementReader
> element_readers
;
12856 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12857 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12859 HttpRequestInfo request
;
12860 request
.method
= "POST";
12861 request
.url
= GURL("http://www.foo.com/");
12862 request
.upload_data_stream
= &upload_data_stream
;
12863 request
.load_flags
= 0;
12865 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12866 scoped_ptr
<HttpTransaction
> trans(
12867 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12869 MockWrite data_writes
[] = {
12870 MockWrite("POST / HTTP/1.1\r\n"
12871 "Host: www.foo.com\r\n"
12872 "Connection: keep-alive\r\n"
12873 "Content-Length: 3\r\n\r\n"),
12874 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12877 MockRead data_reads
[] = {
12878 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12879 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12880 MockRead("hello world"),
12881 MockRead(SYNCHRONOUS
, OK
),
12883 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12884 arraysize(data_writes
));
12885 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12887 TestCompletionCallback callback
;
12889 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12890 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12892 rv
= callback
.WaitForResult();
12895 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12896 ASSERT_TRUE(response
!= NULL
);
12898 EXPECT_TRUE(response
->headers
.get() != NULL
);
12899 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12901 std::string response_data
;
12902 rv
= ReadTransaction(trans
.get(), &response_data
);
12904 EXPECT_EQ("hello world", response_data
);
12907 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
12908 ScopedVector
<UploadElementReader
> element_readers
;
12909 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12910 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12912 HttpRequestInfo request
;
12913 request
.method
= "POST";
12914 request
.url
= GURL("http://www.foo.com/");
12915 request
.upload_data_stream
= &upload_data_stream
;
12916 request
.load_flags
= 0;
12918 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12919 scoped_ptr
<HttpTransaction
> trans(
12920 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12921 // Send headers successfully, but get an error while sending the body.
12922 MockWrite data_writes
[] = {
12923 MockWrite("POST / HTTP/1.1\r\n"
12924 "Host: www.foo.com\r\n"
12925 "Connection: keep-alive\r\n"
12926 "Content-Length: 3\r\n\r\n"),
12927 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12930 MockRead data_reads
[] = {
12931 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
12932 MockRead("hello world"),
12933 MockRead(SYNCHRONOUS
, OK
),
12935 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12936 arraysize(data_writes
));
12937 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12939 TestCompletionCallback callback
;
12941 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12944 rv
= callback
.WaitForResult();
12945 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12947 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12948 EXPECT_TRUE(response
== NULL
);
12951 TEST_P(HttpNetworkTransactionTest
,
12952 PostIgnoresNonErrorResponseAfterResetAnd100
) {
12953 ScopedVector
<UploadElementReader
> element_readers
;
12954 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12955 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12957 HttpRequestInfo request
;
12958 request
.method
= "POST";
12959 request
.url
= GURL("http://www.foo.com/");
12960 request
.upload_data_stream
= &upload_data_stream
;
12961 request
.load_flags
= 0;
12963 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12964 scoped_ptr
<HttpTransaction
> trans(
12965 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12966 // Send headers successfully, but get an error while sending the body.
12967 MockWrite data_writes
[] = {
12968 MockWrite("POST / HTTP/1.1\r\n"
12969 "Host: www.foo.com\r\n"
12970 "Connection: keep-alive\r\n"
12971 "Content-Length: 3\r\n\r\n"),
12972 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12975 MockRead data_reads
[] = {
12976 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12977 MockRead("HTTP/1.0 302 Redirect\r\n"),
12978 MockRead("Location: http://somewhere-else.com/\r\n"),
12979 MockRead("Content-Length: 0\r\n\r\n"),
12980 MockRead(SYNCHRONOUS
, OK
),
12982 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12983 arraysize(data_writes
));
12984 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12986 TestCompletionCallback callback
;
12988 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12989 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12991 rv
= callback
.WaitForResult();
12992 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12994 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12995 EXPECT_TRUE(response
== NULL
);
12998 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
12999 ScopedVector
<UploadElementReader
> element_readers
;
13000 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13001 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13003 HttpRequestInfo request
;
13004 request
.method
= "POST";
13005 request
.url
= GURL("http://www.foo.com/");
13006 request
.upload_data_stream
= &upload_data_stream
;
13007 request
.load_flags
= 0;
13009 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13010 scoped_ptr
<HttpTransaction
> trans(
13011 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13012 // Send headers successfully, but get an error while sending the body.
13013 MockWrite data_writes
[] = {
13014 MockWrite("POST / HTTP/1.1\r\n"
13015 "Host: www.foo.com\r\n"
13016 "Connection: keep-alive\r\n"
13017 "Content-Length: 3\r\n\r\n"),
13018 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13021 MockRead data_reads
[] = {
13022 MockRead("HTTP 0.9 rocks!"),
13023 MockRead(SYNCHRONOUS
, OK
),
13025 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13026 arraysize(data_writes
));
13027 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13029 TestCompletionCallback callback
;
13031 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13034 rv
= callback
.WaitForResult();
13035 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13037 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13038 EXPECT_TRUE(response
== NULL
);
13041 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13042 ScopedVector
<UploadElementReader
> element_readers
;
13043 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13044 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13046 HttpRequestInfo request
;
13047 request
.method
= "POST";
13048 request
.url
= GURL("http://www.foo.com/");
13049 request
.upload_data_stream
= &upload_data_stream
;
13050 request
.load_flags
= 0;
13052 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13053 scoped_ptr
<HttpTransaction
> trans(
13054 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13055 // Send headers successfully, but get an error while sending the body.
13056 MockWrite data_writes
[] = {
13057 MockWrite("POST / HTTP/1.1\r\n"
13058 "Host: www.foo.com\r\n"
13059 "Connection: keep-alive\r\n"
13060 "Content-Length: 3\r\n\r\n"),
13061 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13064 MockRead data_reads
[] = {
13065 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13066 MockRead(SYNCHRONOUS
, OK
),
13068 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13069 arraysize(data_writes
));
13070 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13072 TestCompletionCallback callback
;
13074 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13075 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13077 rv
= callback
.WaitForResult();
13078 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13080 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13081 EXPECT_TRUE(response
== NULL
);