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_unittest.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();
268 HttpStreamFactory::set_use_alternate_protocols(false);
269 HttpStreamFactory::SetNextProtos(std::vector
<NextProto
>());
272 // This is the expected return from a current server advertising SPDY.
273 std::string
GetAlternateProtocolHttpHeader() {
275 std::string("Alternate-Protocol: 443:") +
276 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())) +
280 // Either |write_failure| specifies a write failure or |read_failure|
281 // specifies a read failure when using a reused socket. In either case, the
282 // failure should cause the network transaction to resend the request, and the
283 // other argument should be NULL.
284 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
285 const MockRead
* read_failure
);
287 // Either |write_failure| specifies a write failure or |read_failure|
288 // specifies a read failure when using a reused socket. In either case, the
289 // failure should cause the network transaction to resend the request, and the
290 // other argument should be NULL.
291 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
292 const MockRead
* read_failure
,
295 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
297 SimpleGetHelperResult out
;
299 HttpRequestInfo request
;
300 request
.method
= "GET";
301 request
.url
= GURL("http://www.google.com/");
302 request
.load_flags
= 0;
304 CapturingBoundNetLog log
;
305 session_deps_
.net_log
= log
.bound().net_log();
306 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
307 scoped_ptr
<HttpTransaction
> trans(
308 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
310 for (size_t i
= 0; i
< data_count
; ++i
) {
311 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
314 TestCompletionCallback callback
;
316 EXPECT_TRUE(log
.bound().IsLogging());
317 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
318 EXPECT_EQ(ERR_IO_PENDING
, rv
);
320 out
.rv
= callback
.WaitForResult();
322 // Even in the failure cases that use this function, connections are always
323 // successfully established before the error.
324 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
325 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
330 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
331 // Can't use ASSERT_* inside helper functions like this, so
333 if (response
== NULL
|| response
->headers
.get() == NULL
) {
334 out
.rv
= ERR_UNEXPECTED
;
337 out
.status_line
= response
->headers
->GetStatusLine();
339 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
340 EXPECT_EQ(80, response
->socket_address
.port());
342 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
345 net::CapturingNetLog::CapturedEntryList entries
;
346 log
.GetEntries(&entries
);
347 size_t pos
= ExpectLogContainsSomewhere(
348 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
350 ExpectLogContainsSomewhere(
352 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
356 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
357 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
359 HttpRequestHeaders request_headers
;
360 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
362 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
363 EXPECT_EQ("www.google.com", value
);
364 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
365 EXPECT_EQ("keep-alive", value
);
367 std::string response_headers
;
368 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
369 EXPECT_EQ("['Host: www.google.com','Connection: keep-alive']",
372 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
376 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
377 size_t reads_count
) {
378 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
379 StaticSocketDataProvider
* data
[] = { &reads
};
380 return SimpleGetHelperForData(data
, 1);
383 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
385 for (size_t i
= 0; i
< reads_count
; ++i
)
386 size
+= data_reads
[i
].data_len
;
390 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
391 int expected_status
);
393 void ConnectStatusHelper(const MockRead
& status
);
395 void BypassHostCacheOnRefreshHelper(int load_flags
);
397 void CheckErrorIsPassedBack(int error
, IoMode mode
);
399 SpdyTestUtil spdy_util_
;
400 SpdySessionDependencies session_deps_
;
402 // Original socket limits. Some tests set these. Safest to always restore
403 // them once each test has been run.
404 int old_max_group_sockets_
;
405 int old_max_pool_sockets_
;
408 INSTANTIATE_TEST_CASE_P(
410 HttpNetworkTransactionTest
,
411 testing::Values(kProtoDeprecatedSPDY2
,
412 kProtoSPDY3
, kProtoSPDY31
, kProtoSPDY4
));
416 class BeforeNetworkStartHandler
{
418 explicit BeforeNetworkStartHandler(bool defer
)
419 : defer_on_before_network_start_(defer
),
420 observed_before_network_start_(false) {}
422 void OnBeforeNetworkStart(bool* defer
) {
423 *defer
= defer_on_before_network_start_
;
424 observed_before_network_start_
= true;
427 bool observed_before_network_start() const {
428 return observed_before_network_start_
;
432 const bool defer_on_before_network_start_
;
433 bool observed_before_network_start_
;
435 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
438 // Fill |str| with a long header list that consumes >= |size| bytes.
439 void FillLargeHeadersString(std::string
* str
, int size
) {
441 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
442 const int sizeof_row
= strlen(row
);
443 const int num_rows
= static_cast<int>(
444 ceil(static_cast<float>(size
) / sizeof_row
));
445 const int sizeof_data
= num_rows
* sizeof_row
;
446 DCHECK(sizeof_data
>= size
);
447 str
->reserve(sizeof_data
);
449 for (int i
= 0; i
< num_rows
; ++i
)
450 str
->append(row
, sizeof_row
);
453 // Alternative functions that eliminate randomness and dependency on the local
454 // host name so that the generated NTLM messages are reproducible.
455 void MockGenerateRandom1(uint8
* output
, size_t n
) {
456 static const uint8 bytes
[] = {
457 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
459 static size_t current_byte
= 0;
460 for (size_t i
= 0; i
< n
; ++i
) {
461 output
[i
] = bytes
[current_byte
++];
462 current_byte
%= arraysize(bytes
);
466 void MockGenerateRandom2(uint8
* output
, size_t n
) {
467 static const uint8 bytes
[] = {
468 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
469 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
471 static size_t current_byte
= 0;
472 for (size_t i
= 0; i
< n
; ++i
) {
473 output
[i
] = bytes
[current_byte
++];
474 current_byte
%= arraysize(bytes
);
478 std::string
MockGetHostName() {
482 template<typename ParentPool
>
483 class CaptureGroupNameSocketPool
: public ParentPool
{
485 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
486 CertVerifier
* cert_verifier
);
488 const std::string
last_group_name_received() const {
489 return last_group_name_
;
492 virtual int RequestSocket(const std::string
& group_name
,
493 const void* socket_params
,
494 RequestPriority priority
,
495 ClientSocketHandle
* handle
,
496 const CompletionCallback
& callback
,
497 const BoundNetLog
& net_log
) {
498 last_group_name_
= group_name
;
499 return ERR_IO_PENDING
;
501 virtual void CancelRequest(const std::string
& group_name
,
502 ClientSocketHandle
* handle
) {}
503 virtual void ReleaseSocket(const std::string
& group_name
,
504 scoped_ptr
<StreamSocket
> socket
,
506 virtual void CloseIdleSockets() {}
507 virtual int IdleSocketCount() const {
510 virtual int IdleSocketCountInGroup(const std::string
& group_name
) const {
513 virtual LoadState
GetLoadState(const std::string
& group_name
,
514 const ClientSocketHandle
* handle
) const {
515 return LOAD_STATE_IDLE
;
517 virtual base::TimeDelta
ConnectionTimeout() const {
518 return base::TimeDelta();
522 std::string last_group_name_
;
525 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
526 CaptureGroupNameTransportSocketPool
;
527 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
528 CaptureGroupNameHttpProxySocketPool
;
529 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
530 CaptureGroupNameSOCKSSocketPool
;
531 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
532 CaptureGroupNameSSLSocketPool
;
534 template<typename ParentPool
>
535 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
536 HostResolver
* host_resolver
,
537 CertVerifier
* /* cert_verifier */)
538 : ParentPool(0, 0, NULL
, host_resolver
, NULL
, NULL
) {}
541 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
542 HostResolver
* host_resolver
,
543 CertVerifier
* /* cert_verifier */)
544 : HttpProxyClientSocketPool(0, 0, NULL
, host_resolver
, NULL
, NULL
, NULL
) {}
547 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
548 HostResolver
* host_resolver
,
549 CertVerifier
* cert_verifier
)
550 : SSLClientSocketPool(0,
566 //-----------------------------------------------------------------------------
568 // Helper functions for validating that AuthChallengeInfo's are correctly
569 // configured for common cases.
570 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
573 EXPECT_FALSE(auth_challenge
->is_proxy
);
574 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
575 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
576 EXPECT_EQ("basic", auth_challenge
->scheme
);
580 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
583 EXPECT_TRUE(auth_challenge
->is_proxy
);
584 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
585 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
586 EXPECT_EQ("basic", auth_challenge
->scheme
);
590 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
593 EXPECT_FALSE(auth_challenge
->is_proxy
);
594 EXPECT_EQ("www.google.com:80", auth_challenge
->challenger
.ToString());
595 EXPECT_EQ("digestive", auth_challenge
->realm
);
596 EXPECT_EQ("digest", auth_challenge
->scheme
);
600 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
603 EXPECT_FALSE(auth_challenge
->is_proxy
);
604 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
605 EXPECT_EQ(std::string(), auth_challenge
->realm
);
606 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
612 TEST_P(HttpNetworkTransactionTest
, Basic
) {
613 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
614 scoped_ptr
<HttpTransaction
> trans(
615 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
618 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
619 MockRead data_reads
[] = {
620 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
621 MockRead("hello world"),
622 MockRead(SYNCHRONOUS
, OK
),
624 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
625 arraysize(data_reads
));
626 EXPECT_EQ(OK
, out
.rv
);
627 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
628 EXPECT_EQ("hello world", out
.response_data
);
629 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
630 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
633 // Response with no status line.
634 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
635 MockRead data_reads
[] = {
636 MockRead("hello world"),
637 MockRead(SYNCHRONOUS
, OK
),
639 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
640 arraysize(data_reads
));
641 EXPECT_EQ(OK
, out
.rv
);
642 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
643 EXPECT_EQ("hello world", out
.response_data
);
644 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
645 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
648 // Allow up to 4 bytes of junk to precede status line.
649 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
650 MockRead data_reads
[] = {
651 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
652 MockRead(SYNCHRONOUS
, OK
),
654 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
655 arraysize(data_reads
));
656 EXPECT_EQ(OK
, out
.rv
);
657 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
658 EXPECT_EQ("DATA", out
.response_data
);
659 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
660 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
663 // Allow up to 4 bytes of junk to precede status line.
664 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
665 MockRead data_reads
[] = {
666 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
667 MockRead(SYNCHRONOUS
, OK
),
669 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
670 arraysize(data_reads
));
671 EXPECT_EQ(OK
, out
.rv
);
672 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
673 EXPECT_EQ("DATA", out
.response_data
);
674 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
675 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
678 // Beyond 4 bytes of slop and it should fail to find a status line.
679 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
680 MockRead data_reads
[] = {
681 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
682 MockRead(SYNCHRONOUS
, OK
),
684 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
685 arraysize(data_reads
));
686 EXPECT_EQ(OK
, out
.rv
);
687 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
688 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
689 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
690 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
693 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
694 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
695 MockRead data_reads
[] = {
700 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
701 MockRead(SYNCHRONOUS
, OK
),
703 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
704 arraysize(data_reads
));
705 EXPECT_EQ(OK
, out
.rv
);
706 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
707 EXPECT_EQ("DATA", out
.response_data
);
708 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
709 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
712 // Close the connection before enough bytes to have a status line.
713 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
714 MockRead data_reads
[] = {
716 MockRead(SYNCHRONOUS
, OK
),
718 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
719 arraysize(data_reads
));
720 EXPECT_EQ(OK
, out
.rv
);
721 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
722 EXPECT_EQ("HTT", out
.response_data
);
723 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
724 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
727 // Simulate a 204 response, lacking a Content-Length header, sent over a
728 // persistent connection. The response should still terminate since a 204
729 // cannot have a response body.
730 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
731 char junk
[] = "junk";
732 MockRead data_reads
[] = {
733 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
734 MockRead(junk
), // Should not be read!!
735 MockRead(SYNCHRONOUS
, OK
),
737 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
738 arraysize(data_reads
));
739 EXPECT_EQ(OK
, out
.rv
);
740 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
741 EXPECT_EQ("", out
.response_data
);
742 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
743 int64 response_size
= reads_size
- strlen(junk
);
744 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
747 // A simple request using chunked encoding with some extra data after.
748 // (Like might be seen in a pipelined response.)
749 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
750 std::string final_chunk
= "0\r\n\r\n";
751 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
752 std::string last_read
= final_chunk
+ extra_data
;
753 MockRead data_reads
[] = {
754 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
755 MockRead("5\r\nHello\r\n"),
758 MockRead("5\r\nworld\r\n"),
759 MockRead(last_read
.data()),
760 MockRead(SYNCHRONOUS
, OK
),
762 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
763 arraysize(data_reads
));
764 EXPECT_EQ(OK
, out
.rv
);
765 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
766 EXPECT_EQ("Hello world", out
.response_data
);
767 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
768 int64 response_size
= reads_size
- extra_data
.size();
769 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
772 // Next tests deal with http://crbug.com/56344.
774 TEST_P(HttpNetworkTransactionTest
,
775 MultipleContentLengthHeadersNoTransferEncoding
) {
776 MockRead data_reads
[] = {
777 MockRead("HTTP/1.1 200 OK\r\n"),
778 MockRead("Content-Length: 10\r\n"),
779 MockRead("Content-Length: 5\r\n\r\n"),
781 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
782 arraysize(data_reads
));
783 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
786 TEST_P(HttpNetworkTransactionTest
,
787 DuplicateContentLengthHeadersNoTransferEncoding
) {
788 MockRead data_reads
[] = {
789 MockRead("HTTP/1.1 200 OK\r\n"),
790 MockRead("Content-Length: 5\r\n"),
791 MockRead("Content-Length: 5\r\n\r\n"),
794 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
795 arraysize(data_reads
));
796 EXPECT_EQ(OK
, out
.rv
);
797 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
798 EXPECT_EQ("Hello", out
.response_data
);
801 TEST_P(HttpNetworkTransactionTest
,
802 ComplexContentLengthHeadersNoTransferEncoding
) {
803 // More than 2 dupes.
805 MockRead data_reads
[] = {
806 MockRead("HTTP/1.1 200 OK\r\n"),
807 MockRead("Content-Length: 5\r\n"),
808 MockRead("Content-Length: 5\r\n"),
809 MockRead("Content-Length: 5\r\n\r\n"),
812 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
813 arraysize(data_reads
));
814 EXPECT_EQ(OK
, out
.rv
);
815 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
816 EXPECT_EQ("Hello", out
.response_data
);
820 MockRead data_reads
[] = {
821 MockRead("HTTP/1.0 200 OK\r\n"),
822 MockRead("Content-Length: 5\r\n"),
823 MockRead("Content-Length: 5\r\n"),
824 MockRead("Content-Length: 5\r\n\r\n"),
827 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
828 arraysize(data_reads
));
829 EXPECT_EQ(OK
, out
.rv
);
830 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
831 EXPECT_EQ("Hello", out
.response_data
);
833 // 2 dupes and one mismatched.
835 MockRead data_reads
[] = {
836 MockRead("HTTP/1.1 200 OK\r\n"),
837 MockRead("Content-Length: 10\r\n"),
838 MockRead("Content-Length: 10\r\n"),
839 MockRead("Content-Length: 5\r\n\r\n"),
841 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
842 arraysize(data_reads
));
843 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
847 TEST_P(HttpNetworkTransactionTest
,
848 MultipleContentLengthHeadersTransferEncoding
) {
849 MockRead data_reads
[] = {
850 MockRead("HTTP/1.1 200 OK\r\n"),
851 MockRead("Content-Length: 666\r\n"),
852 MockRead("Content-Length: 1337\r\n"),
853 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
854 MockRead("5\r\nHello\r\n"),
857 MockRead("5\r\nworld\r\n"),
858 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
859 MockRead(SYNCHRONOUS
, OK
),
861 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
862 arraysize(data_reads
));
863 EXPECT_EQ(OK
, out
.rv
);
864 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
865 EXPECT_EQ("Hello world", out
.response_data
);
868 // Next tests deal with http://crbug.com/98895.
870 // Checks that a single Content-Disposition header results in no error.
871 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
872 MockRead data_reads
[] = {
873 MockRead("HTTP/1.1 200 OK\r\n"),
874 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
875 MockRead("Content-Length: 5\r\n\r\n"),
878 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
879 arraysize(data_reads
));
880 EXPECT_EQ(OK
, out
.rv
);
881 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
882 EXPECT_EQ("Hello", out
.response_data
);
885 // Checks that two identical Content-Disposition headers result in no error.
886 TEST_P(HttpNetworkTransactionTest
,
887 TwoIdenticalContentDispositionHeaders
) {
888 MockRead data_reads
[] = {
889 MockRead("HTTP/1.1 200 OK\r\n"),
890 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
891 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
892 MockRead("Content-Length: 5\r\n\r\n"),
895 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
896 arraysize(data_reads
));
897 EXPECT_EQ(OK
, out
.rv
);
898 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
899 EXPECT_EQ("Hello", out
.response_data
);
902 // Checks that two distinct Content-Disposition headers result in an error.
903 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
904 MockRead data_reads
[] = {
905 MockRead("HTTP/1.1 200 OK\r\n"),
906 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
907 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
908 MockRead("Content-Length: 5\r\n\r\n"),
911 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
912 arraysize(data_reads
));
913 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
916 // Checks that two identical Location headers result in no error.
917 // Also tests Location header behavior.
918 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
919 MockRead data_reads
[] = {
920 MockRead("HTTP/1.1 302 Redirect\r\n"),
921 MockRead("Location: http://good.com/\r\n"),
922 MockRead("Location: http://good.com/\r\n"),
923 MockRead("Content-Length: 0\r\n\r\n"),
924 MockRead(SYNCHRONOUS
, OK
),
927 HttpRequestInfo request
;
928 request
.method
= "GET";
929 request
.url
= GURL("http://redirect.com/");
930 request
.load_flags
= 0;
932 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
933 scoped_ptr
<HttpTransaction
> trans(
934 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
936 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
937 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
939 TestCompletionCallback callback
;
941 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
944 EXPECT_EQ(OK
, callback
.WaitForResult());
946 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
947 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
948 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
950 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
951 EXPECT_EQ("http://good.com/", url
);
954 // Checks that two distinct Location headers result in an error.
955 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
956 MockRead data_reads
[] = {
957 MockRead("HTTP/1.1 302 Redirect\r\n"),
958 MockRead("Location: http://good.com/\r\n"),
959 MockRead("Location: http://evil.com/\r\n"),
960 MockRead("Content-Length: 0\r\n\r\n"),
961 MockRead(SYNCHRONOUS
, OK
),
963 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
964 arraysize(data_reads
));
965 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
968 // Do a request using the HEAD method. Verify that we don't try to read the
969 // message body (since HEAD has none).
970 TEST_P(HttpNetworkTransactionTest
, Head
) {
971 HttpRequestInfo request
;
972 request
.method
= "HEAD";
973 request
.url
= GURL("http://www.google.com/");
974 request
.load_flags
= 0;
976 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
977 scoped_ptr
<HttpTransaction
> trans(
978 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
980 MockWrite data_writes1
[] = {
981 MockWrite("HEAD / HTTP/1.1\r\n"
982 "Host: www.google.com\r\n"
983 "Connection: keep-alive\r\n"
984 "Content-Length: 0\r\n\r\n"),
986 MockRead data_reads1
[] = {
987 MockRead("HTTP/1.1 404 Not Found\r\n"),
988 MockRead("Server: Blah\r\n"),
989 MockRead("Content-Length: 1234\r\n\r\n"),
991 // No response body because the test stops reading here.
992 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
995 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
996 data_writes1
, arraysize(data_writes1
));
997 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
999 TestCompletionCallback callback1
;
1001 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1004 rv
= callback1
.WaitForResult();
1007 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1008 ASSERT_TRUE(response
!= NULL
);
1010 // Check that the headers got parsed.
1011 EXPECT_TRUE(response
->headers
.get() != NULL
);
1012 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1013 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1015 std::string server_header
;
1017 bool has_server_header
= response
->headers
->EnumerateHeader(
1018 &iter
, "Server", &server_header
);
1019 EXPECT_TRUE(has_server_header
);
1020 EXPECT_EQ("Blah", server_header
);
1022 // Reading should give EOF right away, since there is no message body
1023 // (despite non-zero content-length).
1024 std::string response_data
;
1025 rv
= ReadTransaction(trans
.get(), &response_data
);
1027 EXPECT_EQ("", response_data
);
1030 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1031 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1033 MockRead data_reads
[] = {
1034 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1036 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1038 MockRead(SYNCHRONOUS
, OK
),
1040 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1041 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1043 const char* const kExpectedResponseData
[] = {
1047 for (int i
= 0; i
< 2; ++i
) {
1048 HttpRequestInfo request
;
1049 request
.method
= "GET";
1050 request
.url
= GURL("http://www.google.com/");
1051 request
.load_flags
= 0;
1053 scoped_ptr
<HttpTransaction
> trans(
1054 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1056 TestCompletionCallback callback
;
1058 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1059 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1061 rv
= callback
.WaitForResult();
1064 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1065 ASSERT_TRUE(response
!= NULL
);
1067 EXPECT_TRUE(response
->headers
.get() != NULL
);
1068 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1070 std::string response_data
;
1071 rv
= ReadTransaction(trans
.get(), &response_data
);
1073 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1077 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1078 ScopedVector
<UploadElementReader
> element_readers
;
1079 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1080 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1082 HttpRequestInfo request
;
1083 request
.method
= "POST";
1084 request
.url
= GURL("http://www.foo.com/");
1085 request
.upload_data_stream
= &upload_data_stream
;
1086 request
.load_flags
= 0;
1088 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1089 scoped_ptr
<HttpTransaction
> trans(
1090 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1092 MockRead data_reads
[] = {
1093 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1094 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1095 MockRead("hello world"),
1096 MockRead(SYNCHRONOUS
, OK
),
1098 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1099 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1101 TestCompletionCallback callback
;
1103 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1104 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1106 rv
= callback
.WaitForResult();
1109 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1110 ASSERT_TRUE(response
!= NULL
);
1112 EXPECT_TRUE(response
->headers
.get() != NULL
);
1113 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1115 std::string response_data
;
1116 rv
= ReadTransaction(trans
.get(), &response_data
);
1118 EXPECT_EQ("hello world", response_data
);
1121 // This test is almost the same as Ignores100 above, but the response contains
1122 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1123 // HTTP/1.1 and the two status headers are read in one read.
1124 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1125 HttpRequestInfo request
;
1126 request
.method
= "GET";
1127 request
.url
= GURL("http://www.foo.com/");
1128 request
.load_flags
= 0;
1130 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1131 scoped_ptr
<HttpTransaction
> trans(
1132 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1134 MockRead data_reads
[] = {
1135 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1136 "HTTP/1.1 200 OK\r\n\r\n"),
1137 MockRead("hello world"),
1138 MockRead(SYNCHRONOUS
, OK
),
1140 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1141 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1143 TestCompletionCallback callback
;
1145 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1148 rv
= callback
.WaitForResult();
1151 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1152 ASSERT_TRUE(response
!= NULL
);
1154 EXPECT_TRUE(response
->headers
.get() != NULL
);
1155 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1157 std::string response_data
;
1158 rv
= ReadTransaction(trans
.get(), &response_data
);
1160 EXPECT_EQ("hello world", response_data
);
1163 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1164 HttpRequestInfo request
;
1165 request
.method
= "POST";
1166 request
.url
= GURL("http://www.foo.com/");
1167 request
.load_flags
= 0;
1169 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1170 scoped_ptr
<HttpTransaction
> trans(
1171 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1173 MockRead data_reads
[] = {
1174 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1177 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1178 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1180 TestCompletionCallback callback
;
1182 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1185 rv
= callback
.WaitForResult();
1188 std::string response_data
;
1189 rv
= ReadTransaction(trans
.get(), &response_data
);
1191 EXPECT_EQ("", response_data
);
1194 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1195 HttpRequestInfo request
;
1196 request
.method
= "POST";
1197 request
.url
= GURL("http://www.foo.com/");
1198 request
.load_flags
= 0;
1200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1201 scoped_ptr
<HttpTransaction
> trans(
1202 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1205 MockRead data_reads
[] = {
1208 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1209 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1211 TestCompletionCallback callback
;
1213 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1214 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1216 rv
= callback
.WaitForResult();
1217 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1220 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1221 const MockWrite
* write_failure
,
1222 const MockRead
* read_failure
) {
1223 HttpRequestInfo request
;
1224 request
.method
= "GET";
1225 request
.url
= GURL("http://www.foo.com/");
1226 request
.load_flags
= 0;
1228 CapturingNetLog net_log
;
1229 session_deps_
.net_log
= &net_log
;
1230 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1232 // Written data for successfully sending both requests.
1233 MockWrite data1_writes
[] = {
1234 MockWrite("GET / HTTP/1.1\r\n"
1235 "Host: www.foo.com\r\n"
1236 "Connection: keep-alive\r\n\r\n"),
1237 MockWrite("GET / HTTP/1.1\r\n"
1238 "Host: www.foo.com\r\n"
1239 "Connection: keep-alive\r\n\r\n")
1242 // Read results for the first request.
1243 MockRead data1_reads
[] = {
1244 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1246 MockRead(ASYNC
, OK
),
1249 if (write_failure
) {
1250 ASSERT_FALSE(read_failure
);
1251 data1_writes
[1] = *write_failure
;
1253 ASSERT_TRUE(read_failure
);
1254 data1_reads
[2] = *read_failure
;
1257 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1258 data1_writes
, arraysize(data1_writes
));
1259 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1261 MockRead data2_reads
[] = {
1262 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1264 MockRead(ASYNC
, OK
),
1266 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1267 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1269 const char* kExpectedResponseData
[] = {
1273 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1274 for (int i
= 0; i
< 2; ++i
) {
1275 TestCompletionCallback callback
;
1277 scoped_ptr
<HttpTransaction
> trans(
1278 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1280 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1281 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1283 rv
= callback
.WaitForResult();
1286 LoadTimingInfo load_timing_info
;
1287 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1288 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1290 first_socket_log_id
= load_timing_info
.socket_log_id
;
1292 // The second request should be using a new socket.
1293 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1296 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1297 ASSERT_TRUE(response
!= NULL
);
1299 EXPECT_TRUE(response
->headers
.get() != NULL
);
1300 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1302 std::string response_data
;
1303 rv
= ReadTransaction(trans
.get(), &response_data
);
1305 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1309 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1310 const MockWrite
* write_failure
,
1311 const MockRead
* read_failure
,
1313 HttpRequestInfo request
;
1314 request
.method
= "GET";
1315 request
.url
= GURL("https://www.foo.com/");
1316 request
.load_flags
= 0;
1318 CapturingNetLog net_log
;
1319 session_deps_
.net_log
= &net_log
;
1320 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1322 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1323 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1325 ssl1
.SetNextProto(GetParam());
1326 ssl2
.SetNextProto(GetParam());
1328 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1329 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1331 // SPDY versions of the request and response.
1332 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1333 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1334 scoped_ptr
<SpdyFrame
> spdy_response(
1335 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1336 scoped_ptr
<SpdyFrame
> spdy_data(
1337 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1339 // HTTP/1.1 versions of the request and response.
1340 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1341 "Host: www.foo.com\r\n"
1342 "Connection: keep-alive\r\n\r\n";
1343 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1344 const char kHttpData
[] = "hello";
1346 std::vector
<MockRead
> data1_reads
;
1347 std::vector
<MockWrite
> data1_writes
;
1348 if (write_failure
) {
1349 ASSERT_FALSE(read_failure
);
1350 data1_writes
.push_back(*write_failure
);
1351 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1353 ASSERT_TRUE(read_failure
);
1355 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1357 data1_writes
.push_back(MockWrite(kHttpRequest
));
1359 data1_reads
.push_back(*read_failure
);
1362 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1363 &data1_writes
[0], data1_writes
.size());
1364 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1366 std::vector
<MockRead
> data2_reads
;
1367 std::vector
<MockWrite
> data2_writes
;
1370 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1372 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1373 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1374 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1376 data2_writes
.push_back(
1377 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1379 data2_reads
.push_back(
1380 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1381 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1382 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1384 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1385 &data2_writes
[0], data2_writes
.size());
1386 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1388 // Preconnect a socket.
1389 net::SSLConfig ssl_config
;
1390 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1391 if (session
->http_stream_factory()->has_next_protos())
1392 ssl_config
.next_protos
= session
->http_stream_factory()->next_protos();
1393 session
->http_stream_factory()->PreconnectStreams(
1394 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1395 // Wait for the preconnect to complete.
1396 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1397 base::RunLoop().RunUntilIdle();
1398 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1400 // Make the request.
1401 TestCompletionCallback callback
;
1403 scoped_ptr
<HttpTransaction
> trans(
1404 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1406 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1407 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1409 rv
= callback
.WaitForResult();
1412 LoadTimingInfo load_timing_info
;
1413 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1414 TestLoadTimingNotReused(
1416 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1418 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1419 ASSERT_TRUE(response
!= NULL
);
1421 EXPECT_TRUE(response
->headers
.get() != NULL
);
1422 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1424 std::string response_data
;
1425 rv
= ReadTransaction(trans
.get(), &response_data
);
1427 EXPECT_EQ(kHttpData
, response_data
);
1430 TEST_P(HttpNetworkTransactionTest
,
1431 KeepAliveConnectionNotConnectedOnWrite
) {
1432 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1433 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1436 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1437 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1438 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1441 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1442 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1443 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1446 TEST_P(HttpNetworkTransactionTest
,
1447 PreconnectErrorNotConnectedOnWrite
) {
1448 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1449 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1452 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1453 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1454 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1457 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1458 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1459 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1462 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1463 MockRead
read_failure(ASYNC
, OK
); // EOF
1464 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1467 TEST_P(HttpNetworkTransactionTest
,
1468 SpdyPreconnectErrorNotConnectedOnWrite
) {
1469 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1470 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1473 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1474 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1475 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1478 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1479 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1480 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1483 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1484 MockRead
read_failure(ASYNC
, OK
); // EOF
1485 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1488 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1489 HttpRequestInfo request
;
1490 request
.method
= "GET";
1491 request
.url
= GURL("http://www.google.com/");
1492 request
.load_flags
= 0;
1494 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1495 scoped_ptr
<HttpTransaction
> trans(
1496 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1498 MockRead data_reads
[] = {
1499 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1500 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1501 MockRead("hello world"),
1502 MockRead(SYNCHRONOUS
, OK
),
1504 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1505 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1507 TestCompletionCallback callback
;
1509 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1510 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1512 rv
= callback
.WaitForResult();
1513 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1515 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1516 EXPECT_TRUE(response
== NULL
);
1519 // What do various browsers do when the server closes a non-keepalive
1520 // connection without sending any response header or body?
1523 // Safari 3.1.2 (Windows): error page
1524 // Firefox 3.0.1: blank page
1525 // Opera 9.52: after five attempts, blank page
1526 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1527 // Us: error page (EMPTY_RESPONSE)
1528 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1529 MockRead data_reads
[] = {
1530 MockRead(SYNCHRONOUS
, OK
), // EOF
1531 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1532 MockRead("hello world"),
1533 MockRead(SYNCHRONOUS
, OK
),
1535 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1536 arraysize(data_reads
));
1537 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1540 // Test that network access can be deferred and resumed.
1541 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1542 HttpRequestInfo request
;
1543 request
.method
= "GET";
1544 request
.url
= GURL("http://www.google.com/");
1545 request
.load_flags
= 0;
1547 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1548 scoped_ptr
<HttpTransaction
> trans(
1549 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1551 // Defer on OnBeforeNetworkStart.
1552 BeforeNetworkStartHandler
net_start_handler(true); // defer
1553 trans
->SetBeforeNetworkStartCallback(
1554 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1555 base::Unretained(&net_start_handler
)));
1557 MockRead data_reads
[] = {
1558 MockRead("HTTP/1.0 200 OK\r\n"),
1559 MockRead("Content-Length: 5\r\n\r\n"),
1561 MockRead(SYNCHRONOUS
, 0),
1563 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1564 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1566 TestCompletionCallback callback
;
1568 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1569 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1570 base::MessageLoop::current()->RunUntilIdle();
1572 // Should have deferred for network start.
1573 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1574 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1575 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1577 trans
->ResumeNetworkStart();
1578 rv
= callback
.WaitForResult();
1580 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1582 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1583 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1584 if (rv
== ERR_IO_PENDING
)
1585 rv
= callback
.WaitForResult();
1590 // Test that network use can be deferred and canceled.
1591 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1592 HttpRequestInfo request
;
1593 request
.method
= "GET";
1594 request
.url
= GURL("http://www.google.com/");
1595 request
.load_flags
= 0;
1597 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1598 scoped_ptr
<HttpTransaction
> trans(
1599 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1601 // Defer on OnBeforeNetworkStart.
1602 BeforeNetworkStartHandler
net_start_handler(true); // defer
1603 trans
->SetBeforeNetworkStartCallback(
1604 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1605 base::Unretained(&net_start_handler
)));
1607 TestCompletionCallback callback
;
1609 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1610 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1611 base::MessageLoop::current()->RunUntilIdle();
1613 // Should have deferred for network start.
1614 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1615 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1616 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1619 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1620 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1621 // destructor in such situations.
1622 // See http://crbug.com/154712 and http://crbug.com/156609.
1623 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1624 HttpRequestInfo request
;
1625 request
.method
= "GET";
1626 request
.url
= GURL("http://www.google.com/");
1627 request
.load_flags
= 0;
1629 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1630 scoped_ptr
<HttpTransaction
> trans(
1631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1633 MockRead data_reads
[] = {
1634 MockRead("HTTP/1.0 200 OK\r\n"),
1635 MockRead("Connection: keep-alive\r\n"),
1636 MockRead("Content-Length: 100\r\n\r\n"),
1638 MockRead(SYNCHRONOUS
, 0),
1640 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1641 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1643 TestCompletionCallback callback
;
1645 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1646 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1648 rv
= callback
.WaitForResult();
1651 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1652 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1653 if (rv
== ERR_IO_PENDING
)
1654 rv
= callback
.WaitForResult();
1656 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1657 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1660 base::MessageLoop::current()->RunUntilIdle();
1661 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1664 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1665 HttpRequestInfo request
;
1666 request
.method
= "GET";
1667 request
.url
= GURL("http://www.google.com/");
1668 request
.load_flags
= 0;
1670 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1671 scoped_ptr
<HttpTransaction
> trans(
1672 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1674 MockRead data_reads
[] = {
1675 MockRead("HTTP/1.0 200 OK\r\n"),
1676 MockRead("Connection: keep-alive\r\n"),
1677 MockRead("Content-Length: 100\r\n\r\n"),
1678 MockRead(SYNCHRONOUS
, 0),
1680 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1681 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1683 TestCompletionCallback callback
;
1685 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1688 rv
= callback
.WaitForResult();
1691 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1692 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1693 if (rv
== ERR_IO_PENDING
)
1694 rv
= callback
.WaitForResult();
1695 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1698 base::MessageLoop::current()->RunUntilIdle();
1699 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1702 // Test that we correctly reuse a keep-alive connection after not explicitly
1703 // reading the body.
1704 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1705 HttpRequestInfo request
;
1706 request
.method
= "GET";
1707 request
.url
= GURL("http://www.foo.com/");
1708 request
.load_flags
= 0;
1710 CapturingNetLog net_log
;
1711 session_deps_
.net_log
= &net_log
;
1712 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1714 // Note that because all these reads happen in the same
1715 // StaticSocketDataProvider, it shows that the same socket is being reused for
1716 // all transactions.
1717 MockRead data1_reads
[] = {
1718 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1719 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1720 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1721 MockRead("HTTP/1.1 302 Found\r\n"
1722 "Content-Length: 0\r\n\r\n"),
1723 MockRead("HTTP/1.1 302 Found\r\n"
1724 "Content-Length: 5\r\n\r\n"
1726 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1727 "Content-Length: 0\r\n\r\n"),
1728 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1729 "Content-Length: 5\r\n\r\n"
1731 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1734 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1735 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1737 MockRead data2_reads
[] = {
1738 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1740 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1741 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1743 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1744 std::string response_lines
[kNumUnreadBodies
];
1746 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1747 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1748 TestCompletionCallback callback
;
1750 scoped_ptr
<HttpTransaction
> trans(
1751 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1753 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1754 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1756 rv
= callback
.WaitForResult();
1759 LoadTimingInfo load_timing_info
;
1760 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1762 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1763 first_socket_log_id
= load_timing_info
.socket_log_id
;
1765 TestLoadTimingReused(load_timing_info
);
1766 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1769 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1770 ASSERT_TRUE(response
!= NULL
);
1772 ASSERT_TRUE(response
->headers
.get() != NULL
);
1773 response_lines
[i
] = response
->headers
->GetStatusLine();
1775 // We intentionally don't read the response bodies.
1778 const char* const kStatusLines
[] = {
1779 "HTTP/1.1 204 No Content",
1780 "HTTP/1.1 205 Reset Content",
1781 "HTTP/1.1 304 Not Modified",
1782 "HTTP/1.1 302 Found",
1783 "HTTP/1.1 302 Found",
1784 "HTTP/1.1 301 Moved Permanently",
1785 "HTTP/1.1 301 Moved Permanently",
1788 COMPILE_ASSERT(kNumUnreadBodies
== arraysize(kStatusLines
),
1789 forgot_to_update_kStatusLines
);
1791 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1792 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1794 TestCompletionCallback callback
;
1795 scoped_ptr
<HttpTransaction
> trans(
1796 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1797 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1798 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1799 rv
= callback
.WaitForResult();
1801 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1802 ASSERT_TRUE(response
!= NULL
);
1803 ASSERT_TRUE(response
->headers
.get() != NULL
);
1804 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1805 std::string response_data
;
1806 rv
= ReadTransaction(trans
.get(), &response_data
);
1808 EXPECT_EQ("hello", response_data
);
1811 // Test the request-challenge-retry sequence for basic auth.
1812 // (basic auth is the easiest to mock, because it has no randomness).
1813 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1814 HttpRequestInfo request
;
1815 request
.method
= "GET";
1816 request
.url
= GURL("http://www.google.com/");
1817 request
.load_flags
= 0;
1819 CapturingNetLog log
;
1820 session_deps_
.net_log
= &log
;
1821 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1822 scoped_ptr
<HttpTransaction
> trans(
1823 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1825 MockWrite data_writes1
[] = {
1826 MockWrite("GET / HTTP/1.1\r\n"
1827 "Host: www.google.com\r\n"
1828 "Connection: keep-alive\r\n\r\n"),
1831 MockRead data_reads1
[] = {
1832 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1833 // Give a couple authenticate options (only the middle one is actually
1835 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1836 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1837 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1838 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1839 // Large content-length -- won't matter, as connection will be reset.
1840 MockRead("Content-Length: 10000\r\n\r\n"),
1841 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1844 // After calling trans->RestartWithAuth(), this is the request we should
1845 // be issuing -- the final header line contains the credentials.
1846 MockWrite data_writes2
[] = {
1847 MockWrite("GET / HTTP/1.1\r\n"
1848 "Host: www.google.com\r\n"
1849 "Connection: keep-alive\r\n"
1850 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1853 // Lastly, the server responds with the actual content.
1854 MockRead data_reads2
[] = {
1855 MockRead("HTTP/1.0 200 OK\r\n"),
1856 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1857 MockRead("Content-Length: 100\r\n\r\n"),
1858 MockRead(SYNCHRONOUS
, OK
),
1861 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1862 data_writes1
, arraysize(data_writes1
));
1863 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1864 data_writes2
, arraysize(data_writes2
));
1865 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1866 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1868 TestCompletionCallback callback1
;
1870 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1871 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1873 rv
= callback1
.WaitForResult();
1876 LoadTimingInfo load_timing_info1
;
1877 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1878 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1880 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1881 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1883 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1884 ASSERT_TRUE(response
!= NULL
);
1885 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1887 TestCompletionCallback callback2
;
1889 rv
= trans
->RestartWithAuth(
1890 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1891 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1893 rv
= callback2
.WaitForResult();
1896 LoadTimingInfo load_timing_info2
;
1897 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1898 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1899 // The load timing after restart should have a new socket ID, and times after
1900 // those of the first load timing.
1901 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1902 load_timing_info2
.connect_timing
.connect_start
);
1903 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1905 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1906 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1908 response
= trans
->GetResponseInfo();
1909 ASSERT_TRUE(response
!= NULL
);
1910 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1911 EXPECT_EQ(100, response
->headers
->GetContentLength());
1914 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1915 HttpRequestInfo request
;
1916 request
.method
= "GET";
1917 request
.url
= GURL("http://www.google.com/");
1918 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
1920 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1921 scoped_ptr
<HttpTransaction
> trans(
1922 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
1924 MockWrite data_writes
[] = {
1925 MockWrite("GET / HTTP/1.1\r\n"
1926 "Host: www.google.com\r\n"
1927 "Connection: keep-alive\r\n\r\n"),
1930 MockRead data_reads
[] = {
1931 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1932 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1933 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1934 // Large content-length -- won't matter, as connection will be reset.
1935 MockRead("Content-Length: 10000\r\n\r\n"),
1936 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1939 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
1940 data_writes
, arraysize(data_writes
));
1941 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1942 TestCompletionCallback callback
;
1944 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1947 rv
= callback
.WaitForResult();
1950 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
1951 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
1953 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1954 ASSERT_TRUE(response
!= NULL
);
1955 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1958 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
1960 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
1961 HttpRequestInfo request
;
1962 request
.method
= "GET";
1963 request
.url
= GURL("http://www.google.com/");
1964 request
.load_flags
= 0;
1966 CapturingNetLog log
;
1967 session_deps_
.net_log
= &log
;
1968 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1970 MockWrite data_writes1
[] = {
1971 MockWrite("GET / HTTP/1.1\r\n"
1972 "Host: www.google.com\r\n"
1973 "Connection: keep-alive\r\n\r\n"),
1975 // After calling trans->RestartWithAuth(), this is the request we should
1976 // be issuing -- the final header line contains the credentials.
1977 MockWrite("GET / HTTP/1.1\r\n"
1978 "Host: www.google.com\r\n"
1979 "Connection: keep-alive\r\n"
1980 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1983 MockRead data_reads1
[] = {
1984 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1985 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1986 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1987 MockRead("Content-Length: 14\r\n\r\n"),
1988 MockRead("Unauthorized\r\n"),
1990 // Lastly, the server responds with the actual content.
1991 MockRead("HTTP/1.1 200 OK\r\n"),
1992 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1993 MockRead("Content-Length: 5\r\n\r\n"),
1997 // If there is a regression where we disconnect a Keep-Alive
1998 // connection during an auth roundtrip, we'll end up reading this.
1999 MockRead data_reads2
[] = {
2000 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2003 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2004 data_writes1
, arraysize(data_writes1
));
2005 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2007 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2008 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2010 TestCompletionCallback callback1
;
2012 scoped_ptr
<HttpTransaction
> trans(
2013 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2014 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2015 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2017 rv
= callback1
.WaitForResult();
2020 LoadTimingInfo load_timing_info1
;
2021 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2022 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2024 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2025 ASSERT_TRUE(response
!= NULL
);
2026 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2028 TestCompletionCallback callback2
;
2030 rv
= trans
->RestartWithAuth(
2031 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2034 rv
= callback2
.WaitForResult();
2037 LoadTimingInfo load_timing_info2
;
2038 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2039 TestLoadTimingReused(load_timing_info2
);
2040 // The load timing after restart should have the same socket ID, and times
2041 // those of the first load timing.
2042 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2043 load_timing_info2
.send_start
);
2044 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2046 response
= trans
->GetResponseInfo();
2047 ASSERT_TRUE(response
!= NULL
);
2048 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2049 EXPECT_EQ(5, response
->headers
->GetContentLength());
2051 std::string response_data
;
2052 rv
= ReadTransaction(trans
.get(), &response_data
);
2054 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2055 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2058 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2059 // connection and with no response body to drain.
2060 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2061 HttpRequestInfo request
;
2062 request
.method
= "GET";
2063 request
.url
= GURL("http://www.google.com/");
2064 request
.load_flags
= 0;
2066 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2068 MockWrite data_writes1
[] = {
2069 MockWrite("GET / HTTP/1.1\r\n"
2070 "Host: www.google.com\r\n"
2071 "Connection: keep-alive\r\n\r\n"),
2073 // After calling trans->RestartWithAuth(), this is the request we should
2074 // be issuing -- the final header line contains the credentials.
2075 MockWrite("GET / HTTP/1.1\r\n"
2076 "Host: www.google.com\r\n"
2077 "Connection: keep-alive\r\n"
2078 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2081 MockRead data_reads1
[] = {
2082 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2083 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2084 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2086 // Lastly, the server responds with the actual content.
2087 MockRead("HTTP/1.1 200 OK\r\n"),
2088 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2089 MockRead("Content-Length: 5\r\n\r\n"),
2093 // An incorrect reconnect would cause this to be read.
2094 MockRead data_reads2
[] = {
2095 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2098 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2099 data_writes1
, arraysize(data_writes1
));
2100 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2102 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2103 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2105 TestCompletionCallback callback1
;
2107 scoped_ptr
<HttpTransaction
> trans(
2108 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2109 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2110 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2112 rv
= callback1
.WaitForResult();
2115 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2116 ASSERT_TRUE(response
!= NULL
);
2117 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2119 TestCompletionCallback callback2
;
2121 rv
= trans
->RestartWithAuth(
2122 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2125 rv
= callback2
.WaitForResult();
2128 response
= trans
->GetResponseInfo();
2129 ASSERT_TRUE(response
!= NULL
);
2130 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2131 EXPECT_EQ(5, response
->headers
->GetContentLength());
2134 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2135 // connection and with a large response body to drain.
2136 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2137 HttpRequestInfo request
;
2138 request
.method
= "GET";
2139 request
.url
= GURL("http://www.google.com/");
2140 request
.load_flags
= 0;
2142 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2144 MockWrite data_writes1
[] = {
2145 MockWrite("GET / HTTP/1.1\r\n"
2146 "Host: www.google.com\r\n"
2147 "Connection: keep-alive\r\n\r\n"),
2149 // After calling trans->RestartWithAuth(), this is the request we should
2150 // be issuing -- the final header line contains the credentials.
2151 MockWrite("GET / HTTP/1.1\r\n"
2152 "Host: www.google.com\r\n"
2153 "Connection: keep-alive\r\n"
2154 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2157 // Respond with 5 kb of response body.
2158 std::string
large_body_string("Unauthorized");
2159 large_body_string
.append(5 * 1024, ' ');
2160 large_body_string
.append("\r\n");
2162 MockRead data_reads1
[] = {
2163 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2164 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2166 // 5134 = 12 + 5 * 1024 + 2
2167 MockRead("Content-Length: 5134\r\n\r\n"),
2168 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2170 // Lastly, the server responds with the actual content.
2171 MockRead("HTTP/1.1 200 OK\r\n"),
2172 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2173 MockRead("Content-Length: 5\r\n\r\n"),
2177 // An incorrect reconnect would cause this to be read.
2178 MockRead data_reads2
[] = {
2179 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2182 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2183 data_writes1
, arraysize(data_writes1
));
2184 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2186 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2187 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2189 TestCompletionCallback callback1
;
2191 scoped_ptr
<HttpTransaction
> trans(
2192 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2193 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2194 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2196 rv
= callback1
.WaitForResult();
2199 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2200 ASSERT_TRUE(response
!= NULL
);
2201 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2203 TestCompletionCallback callback2
;
2205 rv
= trans
->RestartWithAuth(
2206 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2209 rv
= callback2
.WaitForResult();
2212 response
= trans
->GetResponseInfo();
2213 ASSERT_TRUE(response
!= NULL
);
2214 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2215 EXPECT_EQ(5, response
->headers
->GetContentLength());
2218 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2219 // connection, but the server gets impatient and closes the connection.
2220 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2221 HttpRequestInfo request
;
2222 request
.method
= "GET";
2223 request
.url
= GURL("http://www.google.com/");
2224 request
.load_flags
= 0;
2226 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2228 MockWrite data_writes1
[] = {
2229 MockWrite("GET / HTTP/1.1\r\n"
2230 "Host: www.google.com\r\n"
2231 "Connection: keep-alive\r\n\r\n"),
2232 // This simulates the seemingly successful write to a closed connection
2233 // if the bug is not fixed.
2234 MockWrite("GET / HTTP/1.1\r\n"
2235 "Host: www.google.com\r\n"
2236 "Connection: keep-alive\r\n"
2237 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2240 MockRead data_reads1
[] = {
2241 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2242 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2244 MockRead("Content-Length: 14\r\n\r\n"),
2245 // Tell MockTCPClientSocket to simulate the server closing the connection.
2246 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2247 MockRead("Unauthorized\r\n"),
2248 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2251 // After calling trans->RestartWithAuth(), this is the request we should
2252 // be issuing -- the final header line contains the credentials.
2253 MockWrite data_writes2
[] = {
2254 MockWrite("GET / HTTP/1.1\r\n"
2255 "Host: www.google.com\r\n"
2256 "Connection: keep-alive\r\n"
2257 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2260 // Lastly, the server responds with the actual content.
2261 MockRead data_reads2
[] = {
2262 MockRead("HTTP/1.1 200 OK\r\n"),
2263 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2264 MockRead("Content-Length: 5\r\n\r\n"),
2268 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2269 data_writes1
, arraysize(data_writes1
));
2270 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2271 data_writes2
, arraysize(data_writes2
));
2272 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2273 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2275 TestCompletionCallback callback1
;
2277 scoped_ptr
<HttpTransaction
> trans(
2278 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2279 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2280 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2282 rv
= callback1
.WaitForResult();
2285 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2286 ASSERT_TRUE(response
!= NULL
);
2287 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2289 TestCompletionCallback callback2
;
2291 rv
= trans
->RestartWithAuth(
2292 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2295 rv
= callback2
.WaitForResult();
2298 response
= trans
->GetResponseInfo();
2299 ASSERT_TRUE(response
!= NULL
);
2300 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2301 EXPECT_EQ(5, response
->headers
->GetContentLength());
2304 // Test the request-challenge-retry sequence for basic auth, over a connection
2305 // that requires a restart when setting up an SSL tunnel.
2306 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAlive
) {
2307 HttpRequestInfo request
;
2308 request
.method
= "GET";
2309 request
.url
= GURL("https://www.google.com/");
2310 // when the no authentication data flag is set.
2311 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2313 // Configure against proxy server "myproxy:70".
2314 session_deps_
.proxy_service
.reset(
2315 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2316 CapturingBoundNetLog log
;
2317 session_deps_
.net_log
= log
.bound().net_log();
2318 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2320 // Since we have proxy, should try to establish tunnel.
2321 MockWrite data_writes1
[] = {
2322 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2323 "Host: www.google.com\r\n"
2324 "Proxy-Connection: keep-alive\r\n\r\n"),
2326 // After calling trans->RestartWithAuth(), this is the request we should
2327 // be issuing -- the final header line contains the credentials.
2328 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2329 "Host: www.google.com\r\n"
2330 "Proxy-Connection: keep-alive\r\n"
2331 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2333 MockWrite("GET / HTTP/1.1\r\n"
2334 "Host: www.google.com\r\n"
2335 "Connection: keep-alive\r\n\r\n"),
2338 // The proxy responds to the connect with a 407, using a persistent
2340 MockRead data_reads1
[] = {
2342 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2343 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2344 MockRead("Proxy-Connection: close\r\n\r\n"),
2346 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2348 MockRead("HTTP/1.1 200 OK\r\n"),
2349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2350 MockRead("Content-Length: 5\r\n\r\n"),
2351 MockRead(SYNCHRONOUS
, "hello"),
2354 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2355 data_writes1
, arraysize(data_writes1
));
2356 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2357 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2358 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2360 TestCompletionCallback callback1
;
2362 scoped_ptr
<HttpTransaction
> trans(
2363 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2365 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2366 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2368 rv
= callback1
.WaitForResult();
2370 net::CapturingNetLog::CapturedEntryList entries
;
2371 log
.GetEntries(&entries
);
2372 size_t pos
= ExpectLogContainsSomewhere(
2373 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2374 NetLog::PHASE_NONE
);
2375 ExpectLogContainsSomewhere(
2377 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2378 NetLog::PHASE_NONE
);
2380 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2381 ASSERT_TRUE(response
!= NULL
);
2382 ASSERT_FALSE(response
->headers
.get() == NULL
);
2383 EXPECT_EQ(407, response
->headers
->response_code());
2384 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2385 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2387 LoadTimingInfo load_timing_info
;
2388 // CONNECT requests and responses are handled at the connect job level, so
2389 // the transaction does not yet have a connection.
2390 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2392 TestCompletionCallback callback2
;
2394 rv
= trans
->RestartWithAuth(
2395 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2396 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2398 rv
= callback2
.WaitForResult();
2401 response
= trans
->GetResponseInfo();
2402 ASSERT_TRUE(response
!= NULL
);
2404 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2405 EXPECT_EQ(200, response
->headers
->response_code());
2406 EXPECT_EQ(5, response
->headers
->GetContentLength());
2407 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2409 // The password prompt info should not be set.
2410 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2412 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2413 TestLoadTimingNotReusedWithPac(load_timing_info
,
2414 CONNECT_TIMING_HAS_SSL_TIMES
);
2417 session
->CloseAllConnections();
2420 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2421 // proxy connection, when setting up an SSL tunnel.
2422 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAlive
) {
2423 HttpRequestInfo request
;
2424 request
.method
= "GET";
2425 request
.url
= GURL("https://www.google.com/");
2426 // Ensure that proxy authentication is attempted even
2427 // when the no authentication data flag is set.
2428 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
2430 // Configure against proxy server "myproxy:70".
2431 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2432 CapturingBoundNetLog log
;
2433 session_deps_
.net_log
= log
.bound().net_log();
2434 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2436 scoped_ptr
<HttpTransaction
> trans(
2437 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2439 // Since we have proxy, should try to establish tunnel.
2440 MockWrite data_writes1
[] = {
2441 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2442 "Host: www.google.com\r\n"
2443 "Proxy-Connection: keep-alive\r\n\r\n"),
2445 // After calling trans->RestartWithAuth(), this is the request we should
2446 // be issuing -- the final header line contains the credentials.
2447 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2448 "Host: www.google.com\r\n"
2449 "Proxy-Connection: keep-alive\r\n"
2450 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2453 // The proxy responds to the connect with a 407, using a persistent
2455 MockRead data_reads1
[] = {
2457 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2458 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2459 MockRead("Content-Length: 10\r\n\r\n"),
2460 MockRead("0123456789"),
2462 // Wrong credentials (wrong password).
2463 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2464 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2465 MockRead("Content-Length: 10\r\n\r\n"),
2466 // No response body because the test stops reading here.
2467 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2470 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2471 data_writes1
, arraysize(data_writes1
));
2472 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2474 TestCompletionCallback callback1
;
2476 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2477 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2479 rv
= callback1
.WaitForResult();
2481 net::CapturingNetLog::CapturedEntryList entries
;
2482 log
.GetEntries(&entries
);
2483 size_t pos
= ExpectLogContainsSomewhere(
2484 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2485 NetLog::PHASE_NONE
);
2486 ExpectLogContainsSomewhere(
2488 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2489 NetLog::PHASE_NONE
);
2491 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2492 ASSERT_TRUE(response
!= NULL
);
2493 ASSERT_FALSE(response
->headers
.get() == NULL
);
2494 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2495 EXPECT_EQ(407, response
->headers
->response_code());
2496 EXPECT_EQ(10, response
->headers
->GetContentLength());
2497 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2498 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2500 TestCompletionCallback callback2
;
2502 // Wrong password (should be "bar").
2503 rv
= trans
->RestartWithAuth(
2504 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2507 rv
= callback2
.WaitForResult();
2510 response
= trans
->GetResponseInfo();
2511 ASSERT_TRUE(response
!= NULL
);
2512 ASSERT_FALSE(response
->headers
.get() == NULL
);
2513 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2514 EXPECT_EQ(407, response
->headers
->response_code());
2515 EXPECT_EQ(10, response
->headers
->GetContentLength());
2516 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2517 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2519 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2521 session
->CloseAllConnections();
2524 // Test that we don't read the response body when we fail to establish a tunnel,
2525 // even if the user cancels the proxy's auth attempt.
2526 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2527 HttpRequestInfo request
;
2528 request
.method
= "GET";
2529 request
.url
= GURL("https://www.google.com/");
2530 request
.load_flags
= 0;
2532 // Configure against proxy server "myproxy:70".
2533 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2535 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2537 scoped_ptr
<HttpTransaction
> trans(
2538 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2540 // Since we have proxy, should try to establish tunnel.
2541 MockWrite data_writes
[] = {
2542 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2543 "Host: www.google.com\r\n"
2544 "Proxy-Connection: keep-alive\r\n\r\n"),
2547 // The proxy responds to the connect with a 407.
2548 MockRead data_reads
[] = {
2549 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2550 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2551 MockRead("Content-Length: 10\r\n\r\n"),
2552 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2555 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2556 data_writes
, arraysize(data_writes
));
2557 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2559 TestCompletionCallback callback
;
2561 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2562 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2564 rv
= callback
.WaitForResult();
2567 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2568 ASSERT_TRUE(response
!= NULL
);
2570 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2571 EXPECT_EQ(407, response
->headers
->response_code());
2572 EXPECT_EQ(10, response
->headers
->GetContentLength());
2573 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2575 std::string response_data
;
2576 rv
= ReadTransaction(trans
.get(), &response_data
);
2577 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2579 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2580 session
->CloseAllConnections();
2583 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2584 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2585 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2586 HttpRequestInfo request
;
2587 request
.method
= "GET";
2588 request
.url
= GURL("http://www.google.com/");
2589 request
.load_flags
= 0;
2591 // We are using a DIRECT connection (i.e. no proxy) for this session.
2592 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2593 scoped_ptr
<HttpTransaction
> trans(
2594 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
2596 MockWrite data_writes1
[] = {
2597 MockWrite("GET / HTTP/1.1\r\n"
2598 "Host: www.google.com\r\n"
2599 "Connection: keep-alive\r\n\r\n"),
2602 MockRead data_reads1
[] = {
2603 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2604 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2605 // Large content-length -- won't matter, as connection will be reset.
2606 MockRead("Content-Length: 10000\r\n\r\n"),
2607 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2610 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2611 data_writes1
, arraysize(data_writes1
));
2612 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2614 TestCompletionCallback callback
;
2616 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2617 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2619 rv
= callback
.WaitForResult();
2620 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2623 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2624 // through a non-authenticating proxy. The request should fail with
2625 // ERR_UNEXPECTED_PROXY_AUTH.
2626 // Note that it is impossible to detect if an HTTP server returns a 407 through
2627 // a non-authenticating proxy - there is nothing to indicate whether the
2628 // response came from the proxy or the server, so it is treated as if the proxy
2629 // issued the challenge.
2630 TEST_P(HttpNetworkTransactionTest
,
2631 HttpsServerRequestsProxyAuthThroughProxy
) {
2632 HttpRequestInfo request
;
2633 request
.method
= "GET";
2634 request
.url
= GURL("https://www.google.com/");
2636 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2637 CapturingBoundNetLog log
;
2638 session_deps_
.net_log
= log
.bound().net_log();
2639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2641 // Since we have proxy, should try to establish tunnel.
2642 MockWrite data_writes1
[] = {
2643 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2644 "Host: www.google.com\r\n"
2645 "Proxy-Connection: keep-alive\r\n\r\n"),
2647 MockWrite("GET / HTTP/1.1\r\n"
2648 "Host: www.google.com\r\n"
2649 "Connection: keep-alive\r\n\r\n"),
2652 MockRead data_reads1
[] = {
2653 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2655 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2656 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2658 MockRead(SYNCHRONOUS
, OK
),
2661 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2662 data_writes1
, arraysize(data_writes1
));
2663 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2664 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2665 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2667 TestCompletionCallback callback1
;
2669 scoped_ptr
<HttpTransaction
> trans(
2670 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2672 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2675 rv
= callback1
.WaitForResult();
2676 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2677 net::CapturingNetLog::CapturedEntryList entries
;
2678 log
.GetEntries(&entries
);
2679 size_t pos
= ExpectLogContainsSomewhere(
2680 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2681 NetLog::PHASE_NONE
);
2682 ExpectLogContainsSomewhere(
2684 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2685 NetLog::PHASE_NONE
);
2688 // Test the load timing for HTTPS requests with an HTTP proxy.
2689 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
2690 HttpRequestInfo request1
;
2691 request1
.method
= "GET";
2692 request1
.url
= GURL("https://www.google.com/1");
2694 HttpRequestInfo request2
;
2695 request2
.method
= "GET";
2696 request2
.url
= GURL("https://www.google.com/2");
2698 // Configure against proxy server "myproxy:70".
2699 session_deps_
.proxy_service
.reset(
2700 ProxyService::CreateFixed("PROXY myproxy:70"));
2701 CapturingBoundNetLog log
;
2702 session_deps_
.net_log
= log
.bound().net_log();
2703 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2705 // Since we have proxy, should try to establish tunnel.
2706 MockWrite data_writes1
[] = {
2707 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2708 "Host: www.google.com\r\n"
2709 "Proxy-Connection: keep-alive\r\n\r\n"),
2711 MockWrite("GET /1 HTTP/1.1\r\n"
2712 "Host: www.google.com\r\n"
2713 "Connection: keep-alive\r\n\r\n"),
2715 MockWrite("GET /2 HTTP/1.1\r\n"
2716 "Host: www.google.com\r\n"
2717 "Connection: keep-alive\r\n\r\n"),
2720 // The proxy responds to the connect with a 407, using a persistent
2722 MockRead data_reads1
[] = {
2723 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2725 MockRead("HTTP/1.1 200 OK\r\n"),
2726 MockRead("Content-Length: 1\r\n\r\n"),
2727 MockRead(SYNCHRONOUS
, "1"),
2729 MockRead("HTTP/1.1 200 OK\r\n"),
2730 MockRead("Content-Length: 2\r\n\r\n"),
2731 MockRead(SYNCHRONOUS
, "22"),
2734 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2735 data_writes1
, arraysize(data_writes1
));
2736 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2737 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2738 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2740 TestCompletionCallback callback1
;
2741 scoped_ptr
<HttpTransaction
> trans1(
2742 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2744 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2745 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2747 rv
= callback1
.WaitForResult();
2750 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2751 ASSERT_TRUE(response1
!= NULL
);
2752 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2753 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2755 LoadTimingInfo load_timing_info1
;
2756 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2757 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
2761 TestCompletionCallback callback2
;
2762 scoped_ptr
<HttpTransaction
> trans2(
2763 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2765 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2766 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2768 rv
= callback2
.WaitForResult();
2771 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2772 ASSERT_TRUE(response2
!= NULL
);
2773 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2774 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2776 LoadTimingInfo load_timing_info2
;
2777 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2778 TestLoadTimingReused(load_timing_info2
);
2780 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2783 session
->CloseAllConnections();
2786 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
2787 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
2788 HttpRequestInfo request1
;
2789 request1
.method
= "GET";
2790 request1
.url
= GURL("https://www.google.com/1");
2792 HttpRequestInfo request2
;
2793 request2
.method
= "GET";
2794 request2
.url
= GURL("https://www.google.com/2");
2796 // Configure against proxy server "myproxy:70".
2797 session_deps_
.proxy_service
.reset(
2798 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2799 CapturingBoundNetLog log
;
2800 session_deps_
.net_log
= log
.bound().net_log();
2801 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2803 // Since we have proxy, should try to establish tunnel.
2804 MockWrite data_writes1
[] = {
2805 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2806 "Host: www.google.com\r\n"
2807 "Proxy-Connection: keep-alive\r\n\r\n"),
2809 MockWrite("GET /1 HTTP/1.1\r\n"
2810 "Host: www.google.com\r\n"
2811 "Connection: keep-alive\r\n\r\n"),
2813 MockWrite("GET /2 HTTP/1.1\r\n"
2814 "Host: www.google.com\r\n"
2815 "Connection: keep-alive\r\n\r\n"),
2818 // The proxy responds to the connect with a 407, using a persistent
2820 MockRead data_reads1
[] = {
2821 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2823 MockRead("HTTP/1.1 200 OK\r\n"),
2824 MockRead("Content-Length: 1\r\n\r\n"),
2825 MockRead(SYNCHRONOUS
, "1"),
2827 MockRead("HTTP/1.1 200 OK\r\n"),
2828 MockRead("Content-Length: 2\r\n\r\n"),
2829 MockRead(SYNCHRONOUS
, "22"),
2832 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2833 data_writes1
, arraysize(data_writes1
));
2834 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2835 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2836 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2838 TestCompletionCallback callback1
;
2839 scoped_ptr
<HttpTransaction
> trans1(
2840 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2842 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
2843 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2845 rv
= callback1
.WaitForResult();
2848 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
2849 ASSERT_TRUE(response1
!= NULL
);
2850 ASSERT_TRUE(response1
->headers
.get() != NULL
);
2851 EXPECT_EQ(1, response1
->headers
->GetContentLength());
2853 LoadTimingInfo load_timing_info1
;
2854 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
2855 TestLoadTimingNotReusedWithPac(load_timing_info1
,
2856 CONNECT_TIMING_HAS_SSL_TIMES
);
2860 TestCompletionCallback callback2
;
2861 scoped_ptr
<HttpTransaction
> trans2(
2862 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2864 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
2865 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2867 rv
= callback2
.WaitForResult();
2870 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
2871 ASSERT_TRUE(response2
!= NULL
);
2872 ASSERT_TRUE(response2
->headers
.get() != NULL
);
2873 EXPECT_EQ(2, response2
->headers
->GetContentLength());
2875 LoadTimingInfo load_timing_info2
;
2876 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
2877 TestLoadTimingReusedWithPac(load_timing_info2
);
2879 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2882 session
->CloseAllConnections();
2885 // Test a simple get through an HTTPS Proxy.
2886 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
2887 HttpRequestInfo request
;
2888 request
.method
= "GET";
2889 request
.url
= GURL("http://www.google.com/");
2891 // Configure against https proxy server "proxy:70".
2892 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2893 "https://proxy:70"));
2894 CapturingBoundNetLog log
;
2895 session_deps_
.net_log
= log
.bound().net_log();
2896 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2898 // Since we have proxy, should use full url
2899 MockWrite data_writes1
[] = {
2900 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2901 "Host: www.google.com\r\n"
2902 "Proxy-Connection: keep-alive\r\n\r\n"),
2905 MockRead data_reads1
[] = {
2906 MockRead("HTTP/1.1 200 OK\r\n"),
2907 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2908 MockRead("Content-Length: 100\r\n\r\n"),
2909 MockRead(SYNCHRONOUS
, OK
),
2912 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2913 data_writes1
, arraysize(data_writes1
));
2914 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2915 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2916 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2918 TestCompletionCallback callback1
;
2920 scoped_ptr
<HttpTransaction
> trans(
2921 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2923 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2926 rv
= callback1
.WaitForResult();
2929 LoadTimingInfo load_timing_info
;
2930 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2931 TestLoadTimingNotReused(load_timing_info
,
2932 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2934 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2935 ASSERT_TRUE(response
!= NULL
);
2937 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2938 EXPECT_EQ(200, response
->headers
->response_code());
2939 EXPECT_EQ(100, response
->headers
->GetContentLength());
2940 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2942 // The password prompt info should not be set.
2943 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2946 // Test a SPDY get through an HTTPS Proxy.
2947 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
2948 HttpRequestInfo request
;
2949 request
.method
= "GET";
2950 request
.url
= GURL("http://www.google.com/");
2951 request
.load_flags
= 0;
2953 // Configure against https proxy server "proxy:70".
2954 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
2955 "https://proxy:70"));
2956 CapturingBoundNetLog log
;
2957 session_deps_
.net_log
= log
.bound().net_log();
2958 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2960 // fetch http://www.google.com/ via SPDY
2961 scoped_ptr
<SpdyFrame
> req(
2962 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
2963 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
2965 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
2966 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
2967 MockRead spdy_reads
[] = {
2968 CreateMockRead(*resp
),
2969 CreateMockRead(*data
),
2970 MockRead(ASYNC
, 0, 0),
2973 DelayedSocketData
spdy_data(
2974 1, // wait for one write to finish before reading.
2975 spdy_reads
, arraysize(spdy_reads
),
2976 spdy_writes
, arraysize(spdy_writes
));
2977 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
2979 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2980 ssl
.SetNextProto(GetParam());
2981 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2983 TestCompletionCallback callback1
;
2985 scoped_ptr
<HttpTransaction
> trans(
2986 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2988 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2989 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2991 rv
= callback1
.WaitForResult();
2994 LoadTimingInfo load_timing_info
;
2995 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2996 TestLoadTimingNotReused(load_timing_info
,
2997 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
2999 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3000 ASSERT_TRUE(response
!= NULL
);
3001 ASSERT_TRUE(response
->headers
.get() != NULL
);
3002 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3004 std::string response_data
;
3005 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3006 EXPECT_EQ(kUploadData
, response_data
);
3009 // Test a SPDY get through an HTTPS Proxy.
3010 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3011 HttpRequestInfo request
;
3012 request
.method
= "GET";
3013 request
.url
= GURL("http://www.google.com/");
3014 request
.load_flags
= 0;
3016 // Configure against https proxy server "myproxy:70".
3017 session_deps_
.proxy_service
.reset(
3018 ProxyService::CreateFixed("https://myproxy:70"));
3019 CapturingBoundNetLog log
;
3020 session_deps_
.net_log
= log
.bound().net_log();
3021 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3023 // The first request will be a bare GET, the second request will be a
3024 // GET with a Proxy-Authorization header.
3025 scoped_ptr
<SpdyFrame
> req_get(
3026 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3027 const char* const kExtraAuthorizationHeaders
[] = {
3028 "proxy-authorization", "Basic Zm9vOmJhcg=="
3030 scoped_ptr
<SpdyFrame
> req_get_authorization(
3031 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3032 arraysize(kExtraAuthorizationHeaders
) / 2,
3037 MockWrite spdy_writes
[] = {
3038 CreateMockWrite(*req_get
, 1),
3039 CreateMockWrite(*req_get_authorization
, 4),
3042 // The first response is a 407 proxy authentication challenge, and the second
3043 // response will be a 200 response since the second request includes a valid
3044 // Authorization header.
3045 const char* const kExtraAuthenticationHeaders
[] = {
3046 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3048 scoped_ptr
<SpdyFrame
> resp_authentication(
3049 spdy_util_
.ConstructSpdySynReplyError(
3050 "407 Proxy Authentication Required",
3051 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3053 scoped_ptr
<SpdyFrame
> body_authentication(
3054 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3055 scoped_ptr
<SpdyFrame
> resp_data(
3056 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3057 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3058 MockRead spdy_reads
[] = {
3059 CreateMockRead(*resp_authentication
, 2),
3060 CreateMockRead(*body_authentication
, 3),
3061 CreateMockRead(*resp_data
, 5),
3062 CreateMockRead(*body_data
, 6),
3063 MockRead(ASYNC
, 0, 7),
3066 OrderedSocketData
data(
3067 spdy_reads
, arraysize(spdy_reads
),
3068 spdy_writes
, arraysize(spdy_writes
));
3069 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3071 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3072 ssl
.SetNextProto(GetParam());
3073 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3075 TestCompletionCallback callback1
;
3077 scoped_ptr
<HttpTransaction
> trans(
3078 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3080 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3081 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3083 rv
= callback1
.WaitForResult();
3086 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3088 ASSERT_TRUE(response
!= NULL
);
3089 ASSERT_TRUE(response
->headers
.get() != NULL
);
3090 EXPECT_EQ(407, response
->headers
->response_code());
3091 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3092 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3094 TestCompletionCallback callback2
;
3096 rv
= trans
->RestartWithAuth(
3097 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3098 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3100 rv
= callback2
.WaitForResult();
3103 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3105 ASSERT_TRUE(response_restart
!= NULL
);
3106 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3107 EXPECT_EQ(200, response_restart
->headers
->response_code());
3108 // The password prompt info should not be set.
3109 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3112 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3113 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3114 HttpRequestInfo request
;
3115 request
.method
= "GET";
3116 request
.url
= GURL("https://www.google.com/");
3117 request
.load_flags
= 0;
3119 // Configure against https proxy server "proxy:70".
3120 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3121 "https://proxy:70"));
3122 CapturingBoundNetLog log
;
3123 session_deps_
.net_log
= log
.bound().net_log();
3124 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3126 scoped_ptr
<HttpTransaction
> trans(
3127 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3129 // CONNECT to www.google.com:443 via SPDY
3130 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3132 // fetch https://www.google.com/ via HTTP
3134 const char get
[] = "GET / HTTP/1.1\r\n"
3135 "Host: www.google.com\r\n"
3136 "Connection: keep-alive\r\n\r\n";
3137 scoped_ptr
<SpdyFrame
> wrapped_get(
3138 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3139 scoped_ptr
<SpdyFrame
> conn_resp(
3140 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3141 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3142 "Content-Length: 10\r\n\r\n";
3143 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3144 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3145 scoped_ptr
<SpdyFrame
> wrapped_body(
3146 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3147 scoped_ptr
<SpdyFrame
> window_update(
3148 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3150 MockWrite spdy_writes
[] = {
3151 CreateMockWrite(*connect
, 1),
3152 CreateMockWrite(*wrapped_get
, 3),
3153 CreateMockWrite(*window_update
, 5),
3156 MockRead spdy_reads
[] = {
3157 CreateMockRead(*conn_resp
, 2, ASYNC
),
3158 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3159 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3160 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3161 MockRead(ASYNC
, 0, 8),
3164 OrderedSocketData
spdy_data(
3165 spdy_reads
, arraysize(spdy_reads
),
3166 spdy_writes
, arraysize(spdy_writes
));
3167 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3169 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3170 ssl
.SetNextProto(GetParam());
3171 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3172 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3173 ssl2
.was_npn_negotiated
= false;
3174 ssl2
.protocol_negotiated
= kProtoUnknown
;
3175 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3177 TestCompletionCallback callback1
;
3179 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3182 rv
= callback1
.WaitForResult();
3185 LoadTimingInfo load_timing_info
;
3186 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3187 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3189 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3190 ASSERT_TRUE(response
!= NULL
);
3191 ASSERT_TRUE(response
->headers
.get() != NULL
);
3192 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3194 std::string response_data
;
3195 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3196 EXPECT_EQ("1234567890", response_data
);
3199 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3200 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3201 HttpRequestInfo request
;
3202 request
.method
= "GET";
3203 request
.url
= GURL("https://www.google.com/");
3204 request
.load_flags
= 0;
3206 // Configure against https proxy server "proxy:70".
3207 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3208 "https://proxy:70"));
3209 CapturingBoundNetLog log
;
3210 session_deps_
.net_log
= log
.bound().net_log();
3211 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3213 scoped_ptr
<HttpTransaction
> trans(
3214 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3216 // CONNECT to www.google.com:443 via SPDY
3217 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3219 // fetch https://www.google.com/ via SPDY
3220 const char* const kMyUrl
= "https://www.google.com/";
3221 scoped_ptr
<SpdyFrame
> get(
3222 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3223 scoped_ptr
<SpdyFrame
> wrapped_get(
3224 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3225 scoped_ptr
<SpdyFrame
> conn_resp(
3226 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3227 scoped_ptr
<SpdyFrame
> get_resp(
3228 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3229 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3230 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3231 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3232 scoped_ptr
<SpdyFrame
> wrapped_body(
3233 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3234 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3235 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3236 scoped_ptr
<SpdyFrame
> window_update_body(
3237 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3239 MockWrite spdy_writes
[] = {
3240 CreateMockWrite(*connect
, 1),
3241 CreateMockWrite(*wrapped_get
, 3),
3242 CreateMockWrite(*window_update_get_resp
, 5),
3243 CreateMockWrite(*window_update_body
, 7),
3246 MockRead spdy_reads
[] = {
3247 CreateMockRead(*conn_resp
, 2, ASYNC
),
3248 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3249 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3250 MockRead(ASYNC
, 0, 8),
3253 OrderedSocketData
spdy_data(
3254 spdy_reads
, arraysize(spdy_reads
),
3255 spdy_writes
, arraysize(spdy_writes
));
3256 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3258 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3259 ssl
.SetNextProto(GetParam());
3260 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3261 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3262 ssl2
.SetNextProto(GetParam());
3263 ssl2
.protocol_negotiated
= GetParam();
3264 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3266 TestCompletionCallback callback1
;
3268 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3271 rv
= callback1
.WaitForResult();
3274 LoadTimingInfo load_timing_info
;
3275 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3276 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3278 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3279 ASSERT_TRUE(response
!= NULL
);
3280 ASSERT_TRUE(response
->headers
.get() != NULL
);
3281 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3283 std::string response_data
;
3284 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3285 EXPECT_EQ(kUploadData
, response_data
);
3288 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3289 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3290 HttpRequestInfo request
;
3291 request
.method
= "GET";
3292 request
.url
= GURL("https://www.google.com/");
3293 request
.load_flags
= 0;
3295 // Configure against https proxy server "proxy:70".
3296 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3297 "https://proxy:70"));
3298 CapturingBoundNetLog log
;
3299 session_deps_
.net_log
= log
.bound().net_log();
3300 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3302 scoped_ptr
<HttpTransaction
> trans(
3303 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3305 // CONNECT to www.google.com:443 via SPDY
3306 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3308 scoped_ptr
<SpdyFrame
> get(
3309 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3311 MockWrite spdy_writes
[] = {
3312 CreateMockWrite(*connect
, 1),
3313 CreateMockWrite(*get
, 3),
3316 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3317 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3318 MockRead spdy_reads
[] = {
3319 CreateMockRead(*resp
, 2, ASYNC
),
3320 MockRead(ASYNC
, 0, 4),
3323 OrderedSocketData
spdy_data(
3324 spdy_reads
, arraysize(spdy_reads
),
3325 spdy_writes
, arraysize(spdy_writes
));
3326 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3328 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3329 ssl
.SetNextProto(GetParam());
3330 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3331 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3332 ssl2
.SetNextProto(GetParam());
3333 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3335 TestCompletionCallback callback1
;
3337 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3338 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3340 rv
= callback1
.WaitForResult();
3341 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3343 // TODO(ttuttle): Anything else to check here?
3346 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3347 // HTTPS Proxy to different servers.
3348 TEST_P(HttpNetworkTransactionTest
,
3349 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3350 // Configure against https proxy server "proxy:70".
3351 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3352 "https://proxy:70"));
3353 CapturingBoundNetLog log
;
3354 session_deps_
.net_log
= log
.bound().net_log();
3355 scoped_refptr
<HttpNetworkSession
> session(
3356 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3358 HttpRequestInfo request1
;
3359 request1
.method
= "GET";
3360 request1
.url
= GURL("https://www.google.com/");
3361 request1
.load_flags
= 0;
3363 HttpRequestInfo request2
;
3364 request2
.method
= "GET";
3365 request2
.url
= GURL("https://news.google.com/");
3366 request2
.load_flags
= 0;
3368 // CONNECT to www.google.com:443 via SPDY.
3369 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3371 scoped_ptr
<SpdyFrame
> conn_resp1(
3372 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3374 // Fetch https://www.google.com/ via HTTP.
3375 const char get1
[] = "GET / HTTP/1.1\r\n"
3376 "Host: www.google.com\r\n"
3377 "Connection: keep-alive\r\n\r\n";
3378 scoped_ptr
<SpdyFrame
> wrapped_get1(
3379 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3380 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3381 "Content-Length: 1\r\n\r\n";
3382 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3383 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3384 scoped_ptr
<SpdyFrame
> wrapped_body1(
3385 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3386 scoped_ptr
<SpdyFrame
> window_update(
3387 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3389 // CONNECT to news.google.com:443 via SPDY.
3390 SpdySynStreamIR
connect2_ir(3);
3391 spdy_util_
.SetPriority(LOWEST
, &connect2_ir
);
3392 connect2_ir
.SetHeader(spdy_util_
.GetMethodKey(), "CONNECT");
3393 connect2_ir
.SetHeader(spdy_util_
.GetPathKey(), "news.google.com:443");
3394 connect2_ir
.SetHeader(spdy_util_
.GetHostKey(), "news.google.com");
3395 spdy_util_
.MaybeAddVersionHeader(&connect2_ir
);
3396 scoped_ptr
<SpdyFrame
> connect2(
3397 spdy_util_
.CreateFramer(false)->SerializeFrame(connect2_ir
));
3399 scoped_ptr
<SpdyFrame
> conn_resp2(
3400 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3402 // Fetch https://news.google.com/ via HTTP.
3403 const char get2
[] = "GET / HTTP/1.1\r\n"
3404 "Host: news.google.com\r\n"
3405 "Connection: keep-alive\r\n\r\n";
3406 scoped_ptr
<SpdyFrame
> wrapped_get2(
3407 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3408 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3409 "Content-Length: 2\r\n\r\n";
3410 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3411 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3412 scoped_ptr
<SpdyFrame
> wrapped_body2(
3413 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3415 MockWrite spdy_writes
[] = {
3416 CreateMockWrite(*connect1
, 0),
3417 CreateMockWrite(*wrapped_get1
, 2),
3418 CreateMockWrite(*connect2
, 5),
3419 CreateMockWrite(*wrapped_get2
, 7),
3422 MockRead spdy_reads
[] = {
3423 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3424 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3425 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3426 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3427 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3428 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3429 MockRead(ASYNC
, 0, 10),
3432 DeterministicSocketData
spdy_data(
3433 spdy_reads
, arraysize(spdy_reads
),
3434 spdy_writes
, arraysize(spdy_writes
));
3435 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3437 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3438 ssl
.SetNextProto(GetParam());
3439 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3440 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3441 ssl2
.was_npn_negotiated
= false;
3442 ssl2
.protocol_negotiated
= kProtoUnknown
;
3443 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3444 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3445 ssl3
.was_npn_negotiated
= false;
3446 ssl3
.protocol_negotiated
= kProtoUnknown
;
3447 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3449 TestCompletionCallback callback
;
3451 scoped_ptr
<HttpTransaction
> trans(
3452 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3453 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3455 // The first connect and request, each of their responses, and the body.
3456 spdy_data
.RunFor(5);
3458 rv
= callback
.WaitForResult();
3461 LoadTimingInfo load_timing_info
;
3462 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3463 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3465 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3466 ASSERT_TRUE(response
!= NULL
);
3467 ASSERT_TRUE(response
->headers
.get() != NULL
);
3468 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3470 std::string response_data
;
3471 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3472 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3474 scoped_ptr
<HttpTransaction
> trans2(
3475 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3476 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3477 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3479 // The second connect and request, each of their responses, and the body.
3480 spdy_data
.RunFor(5);
3481 rv
= callback
.WaitForResult();
3484 LoadTimingInfo load_timing_info2
;
3485 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3486 // Even though the SPDY connection is reused, a new tunnelled connection has
3487 // to be created, so the socket's load timing looks like a fresh connection.
3488 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3490 // The requests should have different IDs, since they each are using their own
3492 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3494 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3497 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3498 // HTTPS Proxy to the same server.
3499 TEST_P(HttpNetworkTransactionTest
,
3500 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3501 // Configure against https proxy server "proxy:70".
3502 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3503 "https://proxy:70"));
3504 CapturingBoundNetLog log
;
3505 session_deps_
.net_log
= log
.bound().net_log();
3506 scoped_refptr
<HttpNetworkSession
> session(
3507 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3509 HttpRequestInfo request1
;
3510 request1
.method
= "GET";
3511 request1
.url
= GURL("https://www.google.com/");
3512 request1
.load_flags
= 0;
3514 HttpRequestInfo request2
;
3515 request2
.method
= "GET";
3516 request2
.url
= GURL("https://www.google.com/2");
3517 request2
.load_flags
= 0;
3519 // CONNECT to www.google.com:443 via SPDY.
3520 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
3522 scoped_ptr
<SpdyFrame
> conn_resp1(
3523 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3525 // Fetch https://www.google.com/ via HTTP.
3526 const char get1
[] = "GET / HTTP/1.1\r\n"
3527 "Host: www.google.com\r\n"
3528 "Connection: keep-alive\r\n\r\n";
3529 scoped_ptr
<SpdyFrame
> wrapped_get1(
3530 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3531 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3532 "Content-Length: 1\r\n\r\n";
3533 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3534 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3535 scoped_ptr
<SpdyFrame
> wrapped_body1(
3536 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3537 scoped_ptr
<SpdyFrame
> window_update(
3538 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3540 // Fetch https://www.google.com/2 via HTTP.
3541 const char get2
[] = "GET /2 HTTP/1.1\r\n"
3542 "Host: www.google.com\r\n"
3543 "Connection: keep-alive\r\n\r\n";
3544 scoped_ptr
<SpdyFrame
> wrapped_get2(
3545 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3546 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3547 "Content-Length: 2\r\n\r\n";
3548 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3549 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3550 scoped_ptr
<SpdyFrame
> wrapped_body2(
3551 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3553 MockWrite spdy_writes
[] = {
3554 CreateMockWrite(*connect1
, 0),
3555 CreateMockWrite(*wrapped_get1
, 2),
3556 CreateMockWrite(*wrapped_get2
, 5),
3559 MockRead spdy_reads
[] = {
3560 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3561 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3562 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3563 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
3564 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
3565 MockRead(ASYNC
, 0, 8),
3568 DeterministicSocketData
spdy_data(
3569 spdy_reads
, arraysize(spdy_reads
),
3570 spdy_writes
, arraysize(spdy_writes
));
3571 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3573 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3574 ssl
.SetNextProto(GetParam());
3575 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3576 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3577 ssl2
.was_npn_negotiated
= false;
3578 ssl2
.protocol_negotiated
= kProtoUnknown
;
3579 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3581 TestCompletionCallback callback
;
3583 scoped_ptr
<HttpTransaction
> trans(
3584 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3585 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3586 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3587 // The first connect and request, each of their responses, and the body.
3588 spdy_data
.RunFor(5);
3590 rv
= callback
.WaitForResult();
3593 LoadTimingInfo load_timing_info
;
3594 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3595 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3597 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3598 ASSERT_TRUE(response
!= NULL
);
3599 ASSERT_TRUE(response
->headers
.get() != NULL
);
3600 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3602 std::string response_data
;
3603 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3604 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3607 scoped_ptr
<HttpTransaction
> trans2(
3608 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3609 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3610 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3612 // The second request, response, and body. There should not be a second
3614 spdy_data
.RunFor(3);
3615 rv
= callback
.WaitForResult();
3618 LoadTimingInfo load_timing_info2
;
3619 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3620 TestLoadTimingReused(load_timing_info2
);
3622 // The requests should have the same ID.
3623 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3625 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3628 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
3629 // Proxy to different servers.
3630 TEST_P(HttpNetworkTransactionTest
,
3631 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
3632 // Configure against https proxy server "proxy:70".
3633 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3634 "https://proxy:70"));
3635 CapturingBoundNetLog log
;
3636 session_deps_
.net_log
= log
.bound().net_log();
3637 scoped_refptr
<HttpNetworkSession
> session(
3638 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3640 HttpRequestInfo request1
;
3641 request1
.method
= "GET";
3642 request1
.url
= GURL("http://www.google.com/");
3643 request1
.load_flags
= 0;
3645 HttpRequestInfo request2
;
3646 request2
.method
= "GET";
3647 request2
.url
= GURL("http://news.google.com/");
3648 request2
.load_flags
= 0;
3650 // http://www.google.com/
3651 scoped_ptr
<SpdyHeaderBlock
> headers(
3652 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
3653 scoped_ptr
<SpdyFrame
> get1(spdy_util_
.ConstructSpdyControlFrame(
3654 headers
.Pass(), false, 1, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
3655 scoped_ptr
<SpdyFrame
> get_resp1(
3656 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3657 scoped_ptr
<SpdyFrame
> body1(
3658 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
3660 // http://news.google.com/
3661 scoped_ptr
<SpdyHeaderBlock
> headers2(
3662 spdy_util_
.ConstructGetHeaderBlockForProxy("http://news.google.com/"));
3663 scoped_ptr
<SpdyFrame
> get2(spdy_util_
.ConstructSpdyControlFrame(
3664 headers2
.Pass(), false, 3, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
3665 scoped_ptr
<SpdyFrame
> get_resp2(
3666 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3667 scoped_ptr
<SpdyFrame
> body2(
3668 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
3670 MockWrite spdy_writes
[] = {
3671 CreateMockWrite(*get1
, 0),
3672 CreateMockWrite(*get2
, 3),
3675 MockRead spdy_reads
[] = {
3676 CreateMockRead(*get_resp1
, 1, ASYNC
),
3677 CreateMockRead(*body1
, 2, ASYNC
),
3678 CreateMockRead(*get_resp2
, 4, ASYNC
),
3679 CreateMockRead(*body2
, 5, ASYNC
),
3680 MockRead(ASYNC
, 0, 6),
3683 DeterministicSocketData
spdy_data(
3684 spdy_reads
, arraysize(spdy_reads
),
3685 spdy_writes
, arraysize(spdy_writes
));
3686 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3688 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3689 ssl
.SetNextProto(GetParam());
3690 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3692 TestCompletionCallback callback
;
3694 scoped_ptr
<HttpTransaction
> trans(
3695 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3696 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3698 spdy_data
.RunFor(2);
3700 rv
= callback
.WaitForResult();
3703 LoadTimingInfo load_timing_info
;
3704 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3705 TestLoadTimingNotReused(load_timing_info
,
3706 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3708 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3709 ASSERT_TRUE(response
!= NULL
);
3710 ASSERT_TRUE(response
->headers
.get() != NULL
);
3711 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3713 std::string response_data
;
3714 scoped_refptr
<net::IOBuffer
> buf(new net::IOBuffer(256));
3715 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
3716 spdy_data
.RunFor(1);
3717 EXPECT_EQ(1, callback
.WaitForResult());
3718 // Delete the first request, so the second one can reuse the socket.
3721 scoped_ptr
<HttpTransaction
> trans2(
3722 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3723 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3724 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3726 spdy_data
.RunFor(2);
3727 rv
= callback
.WaitForResult();
3730 LoadTimingInfo load_timing_info2
;
3731 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3732 TestLoadTimingReused(load_timing_info2
);
3734 // The requests should have the same ID.
3735 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3737 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
3738 spdy_data
.RunFor(1);
3739 EXPECT_EQ(2, callback
.WaitForResult());
3742 // Test the challenge-response-retry sequence through an HTTPS Proxy
3743 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
3744 HttpRequestInfo request
;
3745 request
.method
= "GET";
3746 request
.url
= GURL("http://www.google.com/");
3747 // when the no authentication data flag is set.
3748 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
3750 // Configure against https proxy server "myproxy:70".
3751 session_deps_
.proxy_service
.reset(
3752 ProxyService::CreateFixed("https://myproxy:70"));
3753 CapturingBoundNetLog log
;
3754 session_deps_
.net_log
= log
.bound().net_log();
3755 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3757 // Since we have proxy, should use full url
3758 MockWrite data_writes1
[] = {
3759 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3760 "Host: www.google.com\r\n"
3761 "Proxy-Connection: keep-alive\r\n\r\n"),
3763 // After calling trans->RestartWithAuth(), this is the request we should
3764 // be issuing -- the final header line contains the credentials.
3765 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
3766 "Host: www.google.com\r\n"
3767 "Proxy-Connection: keep-alive\r\n"
3768 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3771 // The proxy responds to the GET with a 407, using a persistent
3773 MockRead data_reads1
[] = {
3775 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3777 MockRead("Proxy-Connection: keep-alive\r\n"),
3778 MockRead("Content-Length: 0\r\n\r\n"),
3780 MockRead("HTTP/1.1 200 OK\r\n"),
3781 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3782 MockRead("Content-Length: 100\r\n\r\n"),
3783 MockRead(SYNCHRONOUS
, OK
),
3786 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3787 data_writes1
, arraysize(data_writes1
));
3788 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3789 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3790 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3792 TestCompletionCallback callback1
;
3794 scoped_ptr
<HttpTransaction
> trans(
3795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3797 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3798 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3800 rv
= callback1
.WaitForResult();
3803 LoadTimingInfo load_timing_info
;
3804 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3805 TestLoadTimingNotReused(load_timing_info
,
3806 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3808 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3809 ASSERT_TRUE(response
!= NULL
);
3810 ASSERT_FALSE(response
->headers
.get() == NULL
);
3811 EXPECT_EQ(407, response
->headers
->response_code());
3812 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3813 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3815 TestCompletionCallback callback2
;
3817 rv
= trans
->RestartWithAuth(
3818 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3819 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3821 rv
= callback2
.WaitForResult();
3824 load_timing_info
= LoadTimingInfo();
3825 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3826 // Retrying with HTTP AUTH is considered to be reusing a socket.
3827 TestLoadTimingReused(load_timing_info
);
3829 response
= trans
->GetResponseInfo();
3830 ASSERT_TRUE(response
!= NULL
);
3832 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3833 EXPECT_EQ(200, response
->headers
->response_code());
3834 EXPECT_EQ(100, response
->headers
->GetContentLength());
3835 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3837 // The password prompt info should not be set.
3838 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3841 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
3842 const MockRead
& status
, int expected_status
) {
3843 HttpRequestInfo request
;
3844 request
.method
= "GET";
3845 request
.url
= GURL("https://www.google.com/");
3846 request
.load_flags
= 0;
3848 // Configure against proxy server "myproxy:70".
3849 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3850 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3852 // Since we have proxy, should try to establish tunnel.
3853 MockWrite data_writes
[] = {
3854 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3855 "Host: www.google.com\r\n"
3856 "Proxy-Connection: keep-alive\r\n\r\n"),
3859 MockRead data_reads
[] = {
3861 MockRead("Content-Length: 10\r\n\r\n"),
3862 // No response body because the test stops reading here.
3863 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3866 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
3867 data_writes
, arraysize(data_writes
));
3868 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3870 TestCompletionCallback callback
;
3872 scoped_ptr
<HttpTransaction
> trans(
3873 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3875 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3878 rv
= callback
.WaitForResult();
3879 EXPECT_EQ(expected_status
, rv
);
3882 void HttpNetworkTransactionTest::ConnectStatusHelper(
3883 const MockRead
& status
) {
3884 ConnectStatusHelperWithExpectedStatus(
3885 status
, ERR_TUNNEL_CONNECTION_FAILED
);
3888 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
3889 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
3892 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
3893 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
3896 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
3897 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
3900 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
3901 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
3904 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
3905 ConnectStatusHelper(
3906 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
3909 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
3910 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
3913 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
3914 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
3917 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
3918 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
3921 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
3922 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
3925 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
3926 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
3929 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
3930 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
3933 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
3934 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
3937 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
3938 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
3941 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
3942 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
3945 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
3946 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
3949 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
3950 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
3953 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
3954 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
3957 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
3958 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
3961 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
3962 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
3965 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
3966 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
3969 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
3970 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
3973 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
3974 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
3977 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
3978 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
3981 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
3982 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
3985 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
3986 ConnectStatusHelperWithExpectedStatus(
3987 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3988 ERR_PROXY_AUTH_UNSUPPORTED
);
3991 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
3992 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
3995 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
3996 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
3999 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4000 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4003 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4004 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4007 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4008 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4011 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4012 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4015 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4016 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4019 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4020 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4023 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4024 ConnectStatusHelper(
4025 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4028 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4029 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4032 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4033 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4036 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4037 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4040 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4041 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4044 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4045 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4048 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4049 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4052 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4053 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4056 // Test the flow when both the proxy server AND origin server require
4057 // authentication. Again, this uses basic auth for both since that is
4058 // the simplest to mock.
4059 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4060 HttpRequestInfo request
;
4061 request
.method
= "GET";
4062 request
.url
= GURL("http://www.google.com/");
4063 request
.load_flags
= 0;
4065 // Configure against proxy server "myproxy:70".
4066 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4067 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4069 scoped_ptr
<HttpTransaction
> trans(
4070 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4072 MockWrite data_writes1
[] = {
4073 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4074 "Host: www.google.com\r\n"
4075 "Proxy-Connection: keep-alive\r\n\r\n"),
4078 MockRead data_reads1
[] = {
4079 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4080 // Give a couple authenticate options (only the middle one is actually
4082 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4083 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4084 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4085 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4086 // Large content-length -- won't matter, as connection will be reset.
4087 MockRead("Content-Length: 10000\r\n\r\n"),
4088 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4091 // After calling trans->RestartWithAuth() the first time, this is the
4092 // request we should be issuing -- the final header line contains the
4093 // proxy's credentials.
4094 MockWrite data_writes2
[] = {
4095 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4096 "Host: www.google.com\r\n"
4097 "Proxy-Connection: keep-alive\r\n"
4098 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4101 // Now the proxy server lets the request pass through to origin server.
4102 // The origin server responds with a 401.
4103 MockRead data_reads2
[] = {
4104 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4105 // Note: We are using the same realm-name as the proxy server. This is
4106 // completely valid, as realms are unique across hosts.
4107 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4109 MockRead("Content-Length: 2000\r\n\r\n"),
4110 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4113 // After calling trans->RestartWithAuth() the second time, we should send
4114 // the credentials for both the proxy and origin server.
4115 MockWrite data_writes3
[] = {
4116 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
4117 "Host: www.google.com\r\n"
4118 "Proxy-Connection: keep-alive\r\n"
4119 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4120 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4123 // Lastly we get the desired content.
4124 MockRead data_reads3
[] = {
4125 MockRead("HTTP/1.0 200 OK\r\n"),
4126 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4127 MockRead("Content-Length: 100\r\n\r\n"),
4128 MockRead(SYNCHRONOUS
, OK
),
4131 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4132 data_writes1
, arraysize(data_writes1
));
4133 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4134 data_writes2
, arraysize(data_writes2
));
4135 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4136 data_writes3
, arraysize(data_writes3
));
4137 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4138 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4139 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4141 TestCompletionCallback callback1
;
4143 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4146 rv
= callback1
.WaitForResult();
4149 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4150 ASSERT_TRUE(response
!= NULL
);
4151 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4153 TestCompletionCallback callback2
;
4155 rv
= trans
->RestartWithAuth(
4156 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4159 rv
= callback2
.WaitForResult();
4162 response
= trans
->GetResponseInfo();
4163 ASSERT_TRUE(response
!= NULL
);
4164 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4166 TestCompletionCallback callback3
;
4168 rv
= trans
->RestartWithAuth(
4169 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4172 rv
= callback3
.WaitForResult();
4175 response
= trans
->GetResponseInfo();
4176 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4177 EXPECT_EQ(100, response
->headers
->GetContentLength());
4180 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4181 // can't hook into its internals to cause it to generate predictable NTLM
4182 // authorization headers.
4183 #if defined(NTLM_PORTABLE)
4184 // The NTLM authentication unit tests were generated by capturing the HTTP
4185 // requests and responses using Fiddler 2 and inspecting the generated random
4186 // bytes in the debugger.
4188 // Enter the correct password and authenticate successfully.
4189 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4190 HttpRequestInfo request
;
4191 request
.method
= "GET";
4192 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4194 // Ensure load is not disrupted by flags which suppress behaviour specific
4195 // to other auth schemes.
4196 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4198 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4202 MockWrite data_writes1
[] = {
4203 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4204 "Host: 172.22.68.17\r\n"
4205 "Connection: keep-alive\r\n\r\n"),
4208 MockRead data_reads1
[] = {
4209 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4210 // Negotiate and NTLM are often requested together. However, we only want
4211 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4212 // the header that requests Negotiate for this test.
4213 MockRead("WWW-Authenticate: NTLM\r\n"),
4214 MockRead("Connection: close\r\n"),
4215 MockRead("Content-Length: 42\r\n"),
4216 MockRead("Content-Type: text/html\r\n\r\n"),
4217 // Missing content -- won't matter, as connection will be reset.
4218 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4221 MockWrite data_writes2
[] = {
4222 // After restarting with a null identity, this is the
4223 // request we should be issuing -- the final header line contains a Type
4225 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4226 "Host: 172.22.68.17\r\n"
4227 "Connection: keep-alive\r\n"
4228 "Authorization: NTLM "
4229 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4231 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4232 // (the credentials for the origin server). The second request continues
4233 // on the same connection.
4234 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4235 "Host: 172.22.68.17\r\n"
4236 "Connection: keep-alive\r\n"
4237 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4238 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4239 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4240 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4241 "ahlhx5I=\r\n\r\n"),
4244 MockRead data_reads2
[] = {
4245 // The origin server responds with a Type 2 message.
4246 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4247 MockRead("WWW-Authenticate: NTLM "
4248 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4249 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4250 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4251 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4252 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4253 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4255 MockRead("Content-Length: 42\r\n"),
4256 MockRead("Content-Type: text/html\r\n\r\n"),
4257 MockRead("You are not authorized to view this page\r\n"),
4259 // Lastly we get the desired content.
4260 MockRead("HTTP/1.1 200 OK\r\n"),
4261 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4262 MockRead("Content-Length: 13\r\n\r\n"),
4263 MockRead("Please Login\r\n"),
4264 MockRead(SYNCHRONOUS
, OK
),
4267 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4268 data_writes1
, arraysize(data_writes1
));
4269 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4270 data_writes2
, arraysize(data_writes2
));
4271 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4272 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4274 TestCompletionCallback callback1
;
4276 scoped_ptr
<HttpTransaction
> trans(
4277 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4279 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4280 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4282 rv
= callback1
.WaitForResult();
4285 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4287 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4288 ASSERT_FALSE(response
== NULL
);
4289 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4291 TestCompletionCallback callback2
;
4293 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4294 callback2
.callback());
4295 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4297 rv
= callback2
.WaitForResult();
4300 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4302 response
= trans
->GetResponseInfo();
4303 ASSERT_TRUE(response
!= NULL
);
4304 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4306 TestCompletionCallback callback3
;
4308 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4311 rv
= callback3
.WaitForResult();
4314 response
= trans
->GetResponseInfo();
4315 ASSERT_TRUE(response
!= NULL
);
4316 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4317 EXPECT_EQ(13, response
->headers
->GetContentLength());
4320 // Enter a wrong password, and then the correct one.
4321 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4322 HttpRequestInfo request
;
4323 request
.method
= "GET";
4324 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4325 request
.load_flags
= 0;
4327 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4331 MockWrite data_writes1
[] = {
4332 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4333 "Host: 172.22.68.17\r\n"
4334 "Connection: keep-alive\r\n\r\n"),
4337 MockRead data_reads1
[] = {
4338 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4339 // Negotiate and NTLM are often requested together. However, we only want
4340 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4341 // the header that requests Negotiate for this test.
4342 MockRead("WWW-Authenticate: NTLM\r\n"),
4343 MockRead("Connection: close\r\n"),
4344 MockRead("Content-Length: 42\r\n"),
4345 MockRead("Content-Type: text/html\r\n\r\n"),
4346 // Missing content -- won't matter, as connection will be reset.
4347 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4350 MockWrite data_writes2
[] = {
4351 // After restarting with a null identity, this is the
4352 // request we should be issuing -- the final header line contains a Type
4354 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4355 "Host: 172.22.68.17\r\n"
4356 "Connection: keep-alive\r\n"
4357 "Authorization: NTLM "
4358 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4360 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4361 // (the credentials for the origin server). The second request continues
4362 // on the same connection.
4363 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4364 "Host: 172.22.68.17\r\n"
4365 "Connection: keep-alive\r\n"
4366 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4367 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4368 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4369 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4370 "4Ww7b7E=\r\n\r\n"),
4373 MockRead data_reads2
[] = {
4374 // The origin server responds with a Type 2 message.
4375 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4376 MockRead("WWW-Authenticate: NTLM "
4377 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4378 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4379 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4380 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4381 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4382 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4384 MockRead("Content-Length: 42\r\n"),
4385 MockRead("Content-Type: text/html\r\n\r\n"),
4386 MockRead("You are not authorized to view this page\r\n"),
4389 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4390 MockRead("WWW-Authenticate: NTLM\r\n"),
4391 MockRead("Connection: close\r\n"),
4392 MockRead("Content-Length: 42\r\n"),
4393 MockRead("Content-Type: text/html\r\n\r\n"),
4394 // Missing content -- won't matter, as connection will be reset.
4395 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4398 MockWrite data_writes3
[] = {
4399 // After restarting with a null identity, this is the
4400 // request we should be issuing -- the final header line contains a Type
4402 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4403 "Host: 172.22.68.17\r\n"
4404 "Connection: keep-alive\r\n"
4405 "Authorization: NTLM "
4406 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4408 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4409 // (the credentials for the origin server). The second request continues
4410 // on the same connection.
4411 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4412 "Host: 172.22.68.17\r\n"
4413 "Connection: keep-alive\r\n"
4414 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4415 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4416 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4417 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4418 "+4MUm7c=\r\n\r\n"),
4421 MockRead data_reads3
[] = {
4422 // The origin server responds with a Type 2 message.
4423 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4424 MockRead("WWW-Authenticate: NTLM "
4425 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4426 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4427 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4428 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4429 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4430 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4432 MockRead("Content-Length: 42\r\n"),
4433 MockRead("Content-Type: text/html\r\n\r\n"),
4434 MockRead("You are not authorized to view this page\r\n"),
4436 // Lastly we get the desired content.
4437 MockRead("HTTP/1.1 200 OK\r\n"),
4438 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4439 MockRead("Content-Length: 13\r\n\r\n"),
4440 MockRead("Please Login\r\n"),
4441 MockRead(SYNCHRONOUS
, OK
),
4444 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4445 data_writes1
, arraysize(data_writes1
));
4446 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4447 data_writes2
, arraysize(data_writes2
));
4448 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4449 data_writes3
, arraysize(data_writes3
));
4450 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4451 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4452 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4454 TestCompletionCallback callback1
;
4456 scoped_ptr
<HttpTransaction
> trans(
4457 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4459 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4460 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4462 rv
= callback1
.WaitForResult();
4465 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4467 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4468 ASSERT_TRUE(response
!= NULL
);
4469 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4471 TestCompletionCallback callback2
;
4473 // Enter the wrong password.
4474 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4475 callback2
.callback());
4476 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4478 rv
= callback2
.WaitForResult();
4481 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4482 TestCompletionCallback callback3
;
4483 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4484 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4485 rv
= callback3
.WaitForResult();
4487 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4489 response
= trans
->GetResponseInfo();
4490 ASSERT_FALSE(response
== NULL
);
4491 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4493 TestCompletionCallback callback4
;
4495 // Now enter the right password.
4496 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4497 callback4
.callback());
4498 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4500 rv
= callback4
.WaitForResult();
4503 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4505 TestCompletionCallback callback5
;
4507 // One more roundtrip
4508 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4509 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4511 rv
= callback5
.WaitForResult();
4514 response
= trans
->GetResponseInfo();
4515 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4516 EXPECT_EQ(13, response
->headers
->GetContentLength());
4518 #endif // NTLM_PORTABLE
4520 // Test reading a server response which has only headers, and no body.
4521 // After some maximum number of bytes is consumed, the transaction should
4522 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4523 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4524 HttpRequestInfo request
;
4525 request
.method
= "GET";
4526 request
.url
= GURL("http://www.google.com/");
4527 request
.load_flags
= 0;
4529 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4530 scoped_ptr
<HttpTransaction
> trans(
4531 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4533 // Respond with 300 kb of headers (we should fail after 256 kb).
4534 std::string large_headers_string
;
4535 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4537 MockRead data_reads
[] = {
4538 MockRead("HTTP/1.0 200 OK\r\n"),
4539 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4540 MockRead("\r\nBODY"),
4541 MockRead(SYNCHRONOUS
, OK
),
4543 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4544 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4546 TestCompletionCallback callback
;
4548 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4549 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4551 rv
= callback
.WaitForResult();
4552 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4554 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4555 EXPECT_TRUE(response
== NULL
);
4558 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4559 // establish tunnel.
4560 // http://code.google.com/p/chromium/issues/detail?id=3772
4561 TEST_P(HttpNetworkTransactionTest
,
4562 DontRecycleTransportSocketForSSLTunnel
) {
4563 HttpRequestInfo request
;
4564 request
.method
= "GET";
4565 request
.url
= GURL("https://www.google.com/");
4566 request
.load_flags
= 0;
4568 // Configure against proxy server "myproxy:70".
4569 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4571 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4573 scoped_ptr
<HttpTransaction
> trans(
4574 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4576 // Since we have proxy, should try to establish tunnel.
4577 MockWrite data_writes1
[] = {
4578 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4579 "Host: www.google.com\r\n"
4580 "Proxy-Connection: keep-alive\r\n\r\n"),
4583 // The proxy responds to the connect with a 404, using a persistent
4584 // connection. Usually a proxy would return 501 (not implemented),
4585 // or 200 (tunnel established).
4586 MockRead data_reads1
[] = {
4587 MockRead("HTTP/1.1 404 Not Found\r\n"),
4588 MockRead("Content-Length: 10\r\n\r\n"),
4589 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4592 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4593 data_writes1
, arraysize(data_writes1
));
4594 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4596 TestCompletionCallback callback1
;
4598 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4599 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4601 rv
= callback1
.WaitForResult();
4602 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
4604 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4605 EXPECT_TRUE(response
== NULL
);
4607 // Empty the current queue. This is necessary because idle sockets are
4608 // added to the connection pool asynchronously with a PostTask.
4609 base::MessageLoop::current()->RunUntilIdle();
4611 // We now check to make sure the TCPClientSocket was not added back to
4613 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4615 base::MessageLoop::current()->RunUntilIdle();
4616 // Make sure that the socket didn't get recycled after calling the destructor.
4617 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4620 // Make sure that we recycle a socket after reading all of the response body.
4621 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
4622 HttpRequestInfo request
;
4623 request
.method
= "GET";
4624 request
.url
= GURL("http://www.google.com/");
4625 request
.load_flags
= 0;
4627 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4629 scoped_ptr
<HttpTransaction
> trans(
4630 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4632 MockRead data_reads
[] = {
4633 // A part of the response body is received with the response headers.
4634 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
4635 // The rest of the response body is received in two parts.
4638 MockRead("junk"), // Should not be read!!
4639 MockRead(SYNCHRONOUS
, OK
),
4642 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4643 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4645 TestCompletionCallback callback
;
4647 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4648 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4650 rv
= callback
.WaitForResult();
4653 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4654 ASSERT_TRUE(response
!= NULL
);
4656 EXPECT_TRUE(response
->headers
.get() != NULL
);
4657 std::string status_line
= response
->headers
->GetStatusLine();
4658 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
4660 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4662 std::string response_data
;
4663 rv
= ReadTransaction(trans
.get(), &response_data
);
4665 EXPECT_EQ("hello world", response_data
);
4667 // Empty the current queue. This is necessary because idle sockets are
4668 // added to the connection pool asynchronously with a PostTask.
4669 base::MessageLoop::current()->RunUntilIdle();
4671 // We now check to make sure the socket was added back to the pool.
4672 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4675 // Make sure that we recycle a SSL socket after reading all of the response
4677 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
4678 HttpRequestInfo request
;
4679 request
.method
= "GET";
4680 request
.url
= GURL("https://www.google.com/");
4681 request
.load_flags
= 0;
4683 MockWrite data_writes
[] = {
4684 MockWrite("GET / HTTP/1.1\r\n"
4685 "Host: www.google.com\r\n"
4686 "Connection: keep-alive\r\n\r\n"),
4689 MockRead data_reads
[] = {
4690 MockRead("HTTP/1.1 200 OK\r\n"),
4691 MockRead("Content-Length: 11\r\n\r\n"),
4692 MockRead("hello world"),
4693 MockRead(SYNCHRONOUS
, OK
),
4696 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4697 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4699 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4700 data_writes
, arraysize(data_writes
));
4701 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4703 TestCompletionCallback callback
;
4705 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4706 scoped_ptr
<HttpTransaction
> trans(
4707 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4709 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4711 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4712 EXPECT_EQ(OK
, callback
.WaitForResult());
4714 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4715 ASSERT_TRUE(response
!= NULL
);
4716 ASSERT_TRUE(response
->headers
.get() != NULL
);
4717 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4719 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4721 std::string response_data
;
4722 rv
= ReadTransaction(trans
.get(), &response_data
);
4724 EXPECT_EQ("hello world", response_data
);
4726 // Empty the current queue. This is necessary because idle sockets are
4727 // added to the connection pool asynchronously with a PostTask.
4728 base::MessageLoop::current()->RunUntilIdle();
4730 // We now check to make sure the socket was added back to the pool.
4731 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4734 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
4735 // from the pool and make sure that we recover okay.
4736 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
4737 HttpRequestInfo request
;
4738 request
.method
= "GET";
4739 request
.url
= GURL("https://www.google.com/");
4740 request
.load_flags
= 0;
4742 MockWrite data_writes
[] = {
4743 MockWrite("GET / HTTP/1.1\r\n"
4744 "Host: www.google.com\r\n"
4745 "Connection: keep-alive\r\n\r\n"),
4746 MockWrite("GET / HTTP/1.1\r\n"
4747 "Host: www.google.com\r\n"
4748 "Connection: keep-alive\r\n\r\n"),
4751 MockRead data_reads
[] = {
4752 MockRead("HTTP/1.1 200 OK\r\n"),
4753 MockRead("Content-Length: 11\r\n\r\n"),
4754 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
4755 MockRead("hello world"),
4756 MockRead(ASYNC
, 0, 0) // EOF
4759 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4760 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4761 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4762 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4764 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4765 data_writes
, arraysize(data_writes
));
4766 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
4767 data_writes
, arraysize(data_writes
));
4768 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4769 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4771 TestCompletionCallback callback
;
4773 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4774 scoped_ptr
<HttpTransaction
> trans(
4775 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4777 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4780 EXPECT_EQ(OK
, callback
.WaitForResult());
4782 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4783 ASSERT_TRUE(response
!= NULL
);
4784 ASSERT_TRUE(response
->headers
.get() != NULL
);
4785 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4787 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4789 std::string response_data
;
4790 rv
= ReadTransaction(trans
.get(), &response_data
);
4792 EXPECT_EQ("hello world", response_data
);
4794 // Empty the current queue. This is necessary because idle sockets are
4795 // added to the connection pool asynchronously with a PostTask.
4796 base::MessageLoop::current()->RunUntilIdle();
4798 // We now check to make sure the socket was added back to the pool.
4799 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4801 // Now start the second transaction, which should reuse the previous socket.
4803 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4805 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4808 EXPECT_EQ(OK
, callback
.WaitForResult());
4810 response
= trans
->GetResponseInfo();
4811 ASSERT_TRUE(response
!= NULL
);
4812 ASSERT_TRUE(response
->headers
.get() != NULL
);
4813 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4815 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4817 rv
= ReadTransaction(trans
.get(), &response_data
);
4819 EXPECT_EQ("hello world", response_data
);
4821 // Empty the current queue. This is necessary because idle sockets are
4822 // added to the connection pool asynchronously with a PostTask.
4823 base::MessageLoop::current()->RunUntilIdle();
4825 // We now check to make sure the socket was added back to the pool.
4826 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
4829 // Make sure that we recycle a socket after a zero-length response.
4830 // http://crbug.com/9880
4831 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
4832 HttpRequestInfo request
;
4833 request
.method
= "GET";
4834 request
.url
= GURL("http://www.google.com/csi?v=3&s=web&action=&"
4835 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
4836 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
4837 "rt=prt.2642,ol.2649,xjs.2951");
4838 request
.load_flags
= 0;
4840 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4842 scoped_ptr
<HttpTransaction
> trans(
4843 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4845 MockRead data_reads
[] = {
4846 MockRead("HTTP/1.1 204 No Content\r\n"
4847 "Content-Length: 0\r\n"
4848 "Content-Type: text/html\r\n\r\n"),
4849 MockRead("junk"), // Should not be read!!
4850 MockRead(SYNCHRONOUS
, OK
),
4853 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4854 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4856 TestCompletionCallback callback
;
4858 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4861 rv
= callback
.WaitForResult();
4864 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4865 ASSERT_TRUE(response
!= NULL
);
4867 EXPECT_TRUE(response
->headers
.get() != NULL
);
4868 std::string status_line
= response
->headers
->GetStatusLine();
4869 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
4871 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
4873 std::string response_data
;
4874 rv
= ReadTransaction(trans
.get(), &response_data
);
4876 EXPECT_EQ("", response_data
);
4878 // Empty the current queue. This is necessary because idle sockets are
4879 // added to the connection pool asynchronously with a PostTask.
4880 base::MessageLoop::current()->RunUntilIdle();
4882 // We now check to make sure the socket was added back to the pool.
4883 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
4886 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
4887 ScopedVector
<UploadElementReader
> element_readers
;
4888 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
4889 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
4891 HttpRequestInfo request
[2];
4892 // Transaction 1: a GET request that succeeds. The socket is recycled
4894 request
[0].method
= "GET";
4895 request
[0].url
= GURL("http://www.google.com/");
4896 request
[0].load_flags
= 0;
4897 // Transaction 2: a POST request. Reuses the socket kept alive from
4898 // transaction 1. The first attempts fails when writing the POST data.
4899 // This causes the transaction to retry with a new socket. The second
4900 // attempt succeeds.
4901 request
[1].method
= "POST";
4902 request
[1].url
= GURL("http://www.google.com/login.cgi");
4903 request
[1].upload_data_stream
= &upload_data_stream
;
4904 request
[1].load_flags
= 0;
4906 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4908 // The first socket is used for transaction 1 and the first attempt of
4911 // The response of transaction 1.
4912 MockRead data_reads1
[] = {
4913 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
4914 MockRead("hello world"),
4915 MockRead(SYNCHRONOUS
, OK
),
4917 // The mock write results of transaction 1 and the first attempt of
4919 MockWrite data_writes1
[] = {
4920 MockWrite(SYNCHRONOUS
, 64), // GET
4921 MockWrite(SYNCHRONOUS
, 93), // POST
4922 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
4924 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4925 data_writes1
, arraysize(data_writes1
));
4927 // The second socket is used for the second attempt of transaction 2.
4929 // The response of transaction 2.
4930 MockRead data_reads2
[] = {
4931 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
4932 MockRead("welcome"),
4933 MockRead(SYNCHRONOUS
, OK
),
4935 // The mock write results of the second attempt of transaction 2.
4936 MockWrite data_writes2
[] = {
4937 MockWrite(SYNCHRONOUS
, 93), // POST
4938 MockWrite(SYNCHRONOUS
, 3), // POST data
4940 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4941 data_writes2
, arraysize(data_writes2
));
4943 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4944 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4946 const char* kExpectedResponseData
[] = {
4947 "hello world", "welcome"
4950 for (int i
= 0; i
< 2; ++i
) {
4951 scoped_ptr
<HttpTransaction
> trans(
4952 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4954 TestCompletionCallback callback
;
4956 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
4957 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4959 rv
= callback
.WaitForResult();
4962 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4963 ASSERT_TRUE(response
!= NULL
);
4965 EXPECT_TRUE(response
->headers
.get() != NULL
);
4966 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4968 std::string response_data
;
4969 rv
= ReadTransaction(trans
.get(), &response_data
);
4971 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
4975 // Test the request-challenge-retry sequence for basic auth when there is
4976 // an identity in the URL. The request should be sent as normal, but when
4977 // it fails the identity from the URL is used to answer the challenge.
4978 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
4979 HttpRequestInfo request
;
4980 request
.method
= "GET";
4981 request
.url
= GURL("http://foo:b@r@www.google.com/");
4982 request
.load_flags
= LOAD_NORMAL
;
4984 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4985 scoped_ptr
<HttpTransaction
> trans(
4986 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
4988 // The password contains an escaped character -- for this test to pass it
4989 // will need to be unescaped by HttpNetworkTransaction.
4990 EXPECT_EQ("b%40r", request
.url
.password());
4992 MockWrite data_writes1
[] = {
4993 MockWrite("GET / HTTP/1.1\r\n"
4994 "Host: www.google.com\r\n"
4995 "Connection: keep-alive\r\n\r\n"),
4998 MockRead data_reads1
[] = {
4999 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5000 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5001 MockRead("Content-Length: 10\r\n\r\n"),
5002 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5005 // After the challenge above, the transaction will be restarted using the
5006 // identity from the url (foo, b@r) to answer the challenge.
5007 MockWrite data_writes2
[] = {
5008 MockWrite("GET / HTTP/1.1\r\n"
5009 "Host: www.google.com\r\n"
5010 "Connection: keep-alive\r\n"
5011 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5014 MockRead data_reads2
[] = {
5015 MockRead("HTTP/1.0 200 OK\r\n"),
5016 MockRead("Content-Length: 100\r\n\r\n"),
5017 MockRead(SYNCHRONOUS
, OK
),
5020 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5021 data_writes1
, arraysize(data_writes1
));
5022 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5023 data_writes2
, arraysize(data_writes2
));
5024 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5025 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5027 TestCompletionCallback callback1
;
5028 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5029 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5030 rv
= callback1
.WaitForResult();
5032 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5034 TestCompletionCallback callback2
;
5035 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5036 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5037 rv
= callback2
.WaitForResult();
5039 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5041 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5042 ASSERT_TRUE(response
!= NULL
);
5044 // There is no challenge info, since the identity in URL worked.
5045 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5047 EXPECT_EQ(100, response
->headers
->GetContentLength());
5049 // Empty the current queue.
5050 base::MessageLoop::current()->RunUntilIdle();
5053 // Test the request-challenge-retry sequence for basic auth when there is an
5054 // incorrect identity in the URL. The identity from the URL should be used only
5056 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5057 HttpRequestInfo request
;
5058 request
.method
= "GET";
5059 // Note: the URL has a username:password in it. The password "baz" is
5060 // wrong (should be "bar").
5061 request
.url
= GURL("http://foo:baz@www.google.com/");
5063 request
.load_flags
= LOAD_NORMAL
;
5065 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5066 scoped_ptr
<HttpTransaction
> trans(
5067 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5069 MockWrite data_writes1
[] = {
5070 MockWrite("GET / HTTP/1.1\r\n"
5071 "Host: www.google.com\r\n"
5072 "Connection: keep-alive\r\n\r\n"),
5075 MockRead data_reads1
[] = {
5076 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5077 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5078 MockRead("Content-Length: 10\r\n\r\n"),
5079 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5082 // After the challenge above, the transaction will be restarted using the
5083 // identity from the url (foo, baz) to answer the challenge.
5084 MockWrite data_writes2
[] = {
5085 MockWrite("GET / HTTP/1.1\r\n"
5086 "Host: www.google.com\r\n"
5087 "Connection: keep-alive\r\n"
5088 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5091 MockRead data_reads2
[] = {
5092 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5093 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5094 MockRead("Content-Length: 10\r\n\r\n"),
5095 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5098 // After the challenge above, the transaction will be restarted using the
5099 // identity supplied by the user (foo, bar) to answer the challenge.
5100 MockWrite data_writes3
[] = {
5101 MockWrite("GET / HTTP/1.1\r\n"
5102 "Host: www.google.com\r\n"
5103 "Connection: keep-alive\r\n"
5104 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5107 MockRead data_reads3
[] = {
5108 MockRead("HTTP/1.0 200 OK\r\n"),
5109 MockRead("Content-Length: 100\r\n\r\n"),
5110 MockRead(SYNCHRONOUS
, OK
),
5113 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5114 data_writes1
, arraysize(data_writes1
));
5115 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5116 data_writes2
, arraysize(data_writes2
));
5117 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5118 data_writes3
, arraysize(data_writes3
));
5119 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5120 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5121 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5123 TestCompletionCallback callback1
;
5125 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5126 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5128 rv
= callback1
.WaitForResult();
5131 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5132 TestCompletionCallback callback2
;
5133 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5134 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5135 rv
= callback2
.WaitForResult();
5137 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5139 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5140 ASSERT_TRUE(response
!= NULL
);
5141 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5143 TestCompletionCallback callback3
;
5144 rv
= trans
->RestartWithAuth(
5145 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5147 rv
= callback3
.WaitForResult();
5149 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5151 response
= trans
->GetResponseInfo();
5152 ASSERT_TRUE(response
!= NULL
);
5154 // There is no challenge info, since the identity worked.
5155 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5157 EXPECT_EQ(100, response
->headers
->GetContentLength());
5159 // Empty the current queue.
5160 base::MessageLoop::current()->RunUntilIdle();
5164 // Test the request-challenge-retry sequence for basic auth when there is a
5165 // correct identity in the URL, but its use is being suppressed. The identity
5166 // from the URL should never be used.
5167 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5168 HttpRequestInfo request
;
5169 request
.method
= "GET";
5170 request
.url
= GURL("http://foo:bar@www.google.com/");
5171 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5173 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5174 scoped_ptr
<HttpTransaction
> trans(
5175 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5177 MockWrite data_writes1
[] = {
5178 MockWrite("GET / HTTP/1.1\r\n"
5179 "Host: www.google.com\r\n"
5180 "Connection: keep-alive\r\n\r\n"),
5183 MockRead data_reads1
[] = {
5184 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5185 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5186 MockRead("Content-Length: 10\r\n\r\n"),
5187 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5190 // After the challenge above, the transaction will be restarted using the
5191 // identity supplied by the user, not the one in the URL, to answer the
5193 MockWrite data_writes3
[] = {
5194 MockWrite("GET / HTTP/1.1\r\n"
5195 "Host: www.google.com\r\n"
5196 "Connection: keep-alive\r\n"
5197 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5200 MockRead data_reads3
[] = {
5201 MockRead("HTTP/1.0 200 OK\r\n"),
5202 MockRead("Content-Length: 100\r\n\r\n"),
5203 MockRead(SYNCHRONOUS
, OK
),
5206 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5207 data_writes1
, arraysize(data_writes1
));
5208 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5209 data_writes3
, arraysize(data_writes3
));
5210 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5211 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5213 TestCompletionCallback callback1
;
5214 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5215 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5216 rv
= callback1
.WaitForResult();
5218 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5220 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5221 ASSERT_TRUE(response
!= NULL
);
5222 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5224 TestCompletionCallback callback3
;
5225 rv
= trans
->RestartWithAuth(
5226 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5228 rv
= callback3
.WaitForResult();
5230 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5232 response
= trans
->GetResponseInfo();
5233 ASSERT_TRUE(response
!= NULL
);
5235 // There is no challenge info, since the identity worked.
5236 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5237 EXPECT_EQ(100, response
->headers
->GetContentLength());
5239 // Empty the current queue.
5240 base::MessageLoop::current()->RunUntilIdle();
5243 // Test that previously tried username/passwords for a realm get re-used.
5244 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5245 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5247 // Transaction 1: authenticate (foo, bar) on MyRealm1
5249 HttpRequestInfo request
;
5250 request
.method
= "GET";
5251 request
.url
= GURL("http://www.google.com/x/y/z");
5252 request
.load_flags
= 0;
5254 scoped_ptr
<HttpTransaction
> trans(
5255 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5257 MockWrite data_writes1
[] = {
5258 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5259 "Host: www.google.com\r\n"
5260 "Connection: keep-alive\r\n\r\n"),
5263 MockRead data_reads1
[] = {
5264 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5265 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5266 MockRead("Content-Length: 10000\r\n\r\n"),
5267 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5270 // Resend with authorization (username=foo, password=bar)
5271 MockWrite data_writes2
[] = {
5272 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5273 "Host: www.google.com\r\n"
5274 "Connection: keep-alive\r\n"
5275 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5278 // Sever accepts the authorization.
5279 MockRead data_reads2
[] = {
5280 MockRead("HTTP/1.0 200 OK\r\n"),
5281 MockRead("Content-Length: 100\r\n\r\n"),
5282 MockRead(SYNCHRONOUS
, OK
),
5285 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5286 data_writes1
, arraysize(data_writes1
));
5287 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5288 data_writes2
, arraysize(data_writes2
));
5289 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5290 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5292 TestCompletionCallback callback1
;
5294 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5295 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5297 rv
= callback1
.WaitForResult();
5300 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5301 ASSERT_TRUE(response
!= NULL
);
5302 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5304 TestCompletionCallback callback2
;
5306 rv
= trans
->RestartWithAuth(
5307 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5308 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5310 rv
= callback2
.WaitForResult();
5313 response
= trans
->GetResponseInfo();
5314 ASSERT_TRUE(response
!= NULL
);
5315 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5316 EXPECT_EQ(100, response
->headers
->GetContentLength());
5319 // ------------------------------------------------------------------------
5321 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5323 HttpRequestInfo request
;
5324 request
.method
= "GET";
5325 // Note that Transaction 1 was at /x/y/z, so this is in the same
5326 // protection space as MyRealm1.
5327 request
.url
= GURL("http://www.google.com/x/y/a/b");
5328 request
.load_flags
= 0;
5330 scoped_ptr
<HttpTransaction
> trans(
5331 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5333 MockWrite data_writes1
[] = {
5334 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5335 "Host: www.google.com\r\n"
5336 "Connection: keep-alive\r\n"
5337 // Send preemptive authorization for MyRealm1
5338 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5341 // The server didn't like the preemptive authorization, and
5342 // challenges us for a different realm (MyRealm2).
5343 MockRead data_reads1
[] = {
5344 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5345 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5346 MockRead("Content-Length: 10000\r\n\r\n"),
5347 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5350 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5351 MockWrite data_writes2
[] = {
5352 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5353 "Host: www.google.com\r\n"
5354 "Connection: keep-alive\r\n"
5355 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5358 // Sever accepts the authorization.
5359 MockRead data_reads2
[] = {
5360 MockRead("HTTP/1.0 200 OK\r\n"),
5361 MockRead("Content-Length: 100\r\n\r\n"),
5362 MockRead(SYNCHRONOUS
, OK
),
5365 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5366 data_writes1
, arraysize(data_writes1
));
5367 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5368 data_writes2
, arraysize(data_writes2
));
5369 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5370 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5372 TestCompletionCallback callback1
;
5374 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5377 rv
= callback1
.WaitForResult();
5380 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5381 ASSERT_TRUE(response
!= NULL
);
5382 ASSERT_TRUE(response
->auth_challenge
.get());
5383 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5384 EXPECT_EQ("www.google.com:80",
5385 response
->auth_challenge
->challenger
.ToString());
5386 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5387 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5389 TestCompletionCallback callback2
;
5391 rv
= trans
->RestartWithAuth(
5392 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5393 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5395 rv
= callback2
.WaitForResult();
5398 response
= trans
->GetResponseInfo();
5399 ASSERT_TRUE(response
!= NULL
);
5400 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5401 EXPECT_EQ(100, response
->headers
->GetContentLength());
5404 // ------------------------------------------------------------------------
5406 // Transaction 3: Resend a request in MyRealm's protection space --
5407 // succeed with preemptive authorization.
5409 HttpRequestInfo request
;
5410 request
.method
= "GET";
5411 request
.url
= GURL("http://www.google.com/x/y/z2");
5412 request
.load_flags
= 0;
5414 scoped_ptr
<HttpTransaction
> trans(
5415 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5417 MockWrite data_writes1
[] = {
5418 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
5419 "Host: www.google.com\r\n"
5420 "Connection: keep-alive\r\n"
5421 // The authorization for MyRealm1 gets sent preemptively
5422 // (since the url is in the same protection space)
5423 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5426 // Sever accepts the preemptive authorization
5427 MockRead data_reads1
[] = {
5428 MockRead("HTTP/1.0 200 OK\r\n"),
5429 MockRead("Content-Length: 100\r\n\r\n"),
5430 MockRead(SYNCHRONOUS
, OK
),
5433 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5434 data_writes1
, arraysize(data_writes1
));
5435 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5437 TestCompletionCallback callback1
;
5439 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5442 rv
= callback1
.WaitForResult();
5445 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5446 ASSERT_TRUE(response
!= NULL
);
5448 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5449 EXPECT_EQ(100, response
->headers
->GetContentLength());
5452 // ------------------------------------------------------------------------
5454 // Transaction 4: request another URL in MyRealm (however the
5455 // url is not known to belong to the protection space, so no pre-auth).
5457 HttpRequestInfo request
;
5458 request
.method
= "GET";
5459 request
.url
= GURL("http://www.google.com/x/1");
5460 request
.load_flags
= 0;
5462 scoped_ptr
<HttpTransaction
> trans(
5463 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5465 MockWrite data_writes1
[] = {
5466 MockWrite("GET /x/1 HTTP/1.1\r\n"
5467 "Host: www.google.com\r\n"
5468 "Connection: keep-alive\r\n\r\n"),
5471 MockRead data_reads1
[] = {
5472 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5474 MockRead("Content-Length: 10000\r\n\r\n"),
5475 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5478 // Resend with authorization from MyRealm's cache.
5479 MockWrite data_writes2
[] = {
5480 MockWrite("GET /x/1 HTTP/1.1\r\n"
5481 "Host: www.google.com\r\n"
5482 "Connection: keep-alive\r\n"
5483 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5486 // Sever accepts the authorization.
5487 MockRead data_reads2
[] = {
5488 MockRead("HTTP/1.0 200 OK\r\n"),
5489 MockRead("Content-Length: 100\r\n\r\n"),
5490 MockRead(SYNCHRONOUS
, OK
),
5493 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5494 data_writes1
, arraysize(data_writes1
));
5495 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5496 data_writes2
, arraysize(data_writes2
));
5497 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5498 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5500 TestCompletionCallback callback1
;
5502 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5505 rv
= callback1
.WaitForResult();
5508 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5509 TestCompletionCallback callback2
;
5510 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5511 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5512 rv
= callback2
.WaitForResult();
5514 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5516 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5517 ASSERT_TRUE(response
!= NULL
);
5518 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5519 EXPECT_EQ(100, response
->headers
->GetContentLength());
5522 // ------------------------------------------------------------------------
5524 // Transaction 5: request a URL in MyRealm, but the server rejects the
5525 // cached identity. Should invalidate and re-prompt.
5527 HttpRequestInfo request
;
5528 request
.method
= "GET";
5529 request
.url
= GURL("http://www.google.com/p/q/t");
5530 request
.load_flags
= 0;
5532 scoped_ptr
<HttpTransaction
> trans(
5533 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5535 MockWrite data_writes1
[] = {
5536 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5537 "Host: www.google.com\r\n"
5538 "Connection: keep-alive\r\n\r\n"),
5541 MockRead data_reads1
[] = {
5542 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5543 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5544 MockRead("Content-Length: 10000\r\n\r\n"),
5545 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5548 // Resend with authorization from cache for MyRealm.
5549 MockWrite data_writes2
[] = {
5550 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5551 "Host: www.google.com\r\n"
5552 "Connection: keep-alive\r\n"
5553 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5556 // Sever rejects the authorization.
5557 MockRead data_reads2
[] = {
5558 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5559 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5560 MockRead("Content-Length: 10000\r\n\r\n"),
5561 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5564 // At this point we should prompt for new credentials for MyRealm.
5565 // Restart with username=foo3, password=foo4.
5566 MockWrite data_writes3
[] = {
5567 MockWrite("GET /p/q/t HTTP/1.1\r\n"
5568 "Host: www.google.com\r\n"
5569 "Connection: keep-alive\r\n"
5570 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
5573 // Sever accepts the authorization.
5574 MockRead data_reads3
[] = {
5575 MockRead("HTTP/1.0 200 OK\r\n"),
5576 MockRead("Content-Length: 100\r\n\r\n"),
5577 MockRead(SYNCHRONOUS
, OK
),
5580 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5581 data_writes1
, arraysize(data_writes1
));
5582 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5583 data_writes2
, arraysize(data_writes2
));
5584 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5585 data_writes3
, arraysize(data_writes3
));
5586 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5587 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5588 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5590 TestCompletionCallback callback1
;
5592 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5593 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5595 rv
= callback1
.WaitForResult();
5598 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5599 TestCompletionCallback callback2
;
5600 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5601 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5602 rv
= callback2
.WaitForResult();
5604 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5606 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5607 ASSERT_TRUE(response
!= NULL
);
5608 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5610 TestCompletionCallback callback3
;
5612 rv
= trans
->RestartWithAuth(
5613 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
5614 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5616 rv
= callback3
.WaitForResult();
5619 response
= trans
->GetResponseInfo();
5620 ASSERT_TRUE(response
!= NULL
);
5621 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5622 EXPECT_EQ(100, response
->headers
->GetContentLength());
5626 // Tests that nonce count increments when multiple auth attempts
5627 // are started with the same nonce.
5628 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
5629 HttpAuthHandlerDigest::Factory
* digest_factory
=
5630 new HttpAuthHandlerDigest::Factory();
5631 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
5632 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
5633 digest_factory
->set_nonce_generator(nonce_generator
);
5634 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
5635 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5637 // Transaction 1: authenticate (foo, bar) on MyRealm1
5639 HttpRequestInfo request
;
5640 request
.method
= "GET";
5641 request
.url
= GURL("http://www.google.com/x/y/z");
5642 request
.load_flags
= 0;
5644 scoped_ptr
<HttpTransaction
> trans(
5645 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5647 MockWrite data_writes1
[] = {
5648 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5649 "Host: www.google.com\r\n"
5650 "Connection: keep-alive\r\n\r\n"),
5653 MockRead data_reads1
[] = {
5654 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5655 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
5656 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
5657 MockRead(SYNCHRONOUS
, OK
),
5660 // Resend with authorization (username=foo, password=bar)
5661 MockWrite data_writes2
[] = {
5662 MockWrite("GET /x/y/z HTTP/1.1\r\n"
5663 "Host: www.google.com\r\n"
5664 "Connection: keep-alive\r\n"
5665 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5666 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
5667 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
5668 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5671 // Sever accepts the authorization.
5672 MockRead data_reads2
[] = {
5673 MockRead("HTTP/1.0 200 OK\r\n"),
5674 MockRead(SYNCHRONOUS
, OK
),
5677 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5678 data_writes1
, arraysize(data_writes1
));
5679 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5680 data_writes2
, arraysize(data_writes2
));
5681 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5682 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5684 TestCompletionCallback callback1
;
5686 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5689 rv
= callback1
.WaitForResult();
5692 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5693 ASSERT_TRUE(response
!= NULL
);
5694 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
5696 TestCompletionCallback callback2
;
5698 rv
= trans
->RestartWithAuth(
5699 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5700 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5702 rv
= callback2
.WaitForResult();
5705 response
= trans
->GetResponseInfo();
5706 ASSERT_TRUE(response
!= NULL
);
5707 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5710 // ------------------------------------------------------------------------
5712 // Transaction 2: Request another resource in digestive's protection space.
5713 // This will preemptively add an Authorization header which should have an
5714 // "nc" value of 2 (as compared to 1 in the first use.
5716 HttpRequestInfo request
;
5717 request
.method
= "GET";
5718 // Note that Transaction 1 was at /x/y/z, so this is in the same
5719 // protection space as digest.
5720 request
.url
= GURL("http://www.google.com/x/y/a/b");
5721 request
.load_flags
= 0;
5723 scoped_ptr
<HttpTransaction
> trans(
5724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5726 MockWrite data_writes1
[] = {
5727 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
5728 "Host: www.google.com\r\n"
5729 "Connection: keep-alive\r\n"
5730 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
5731 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
5732 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
5733 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
5736 // Sever accepts the authorization.
5737 MockRead data_reads1
[] = {
5738 MockRead("HTTP/1.0 200 OK\r\n"),
5739 MockRead("Content-Length: 100\r\n\r\n"),
5740 MockRead(SYNCHRONOUS
, OK
),
5743 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5744 data_writes1
, arraysize(data_writes1
));
5745 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5747 TestCompletionCallback callback1
;
5749 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5750 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5752 rv
= callback1
.WaitForResult();
5755 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5756 ASSERT_TRUE(response
!= NULL
);
5757 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5761 // Test the ResetStateForRestart() private method.
5762 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
5763 // Create a transaction (the dependencies aren't important).
5764 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5765 scoped_ptr
<HttpNetworkTransaction
> trans(
5766 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5768 // Setup some state (which we expect ResetStateForRestart() will clear).
5769 trans
->read_buf_
= new IOBuffer(15);
5770 trans
->read_buf_len_
= 15;
5771 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
5773 // Setup state in response_
5774 HttpResponseInfo
* response
= &trans
->response_
;
5775 response
->auth_challenge
= new AuthChallengeInfo();
5776 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
5777 response
->response_time
= base::Time::Now();
5778 response
->was_cached
= true; // (Wouldn't ever actually be true...)
5780 { // Setup state for response_.vary_data
5781 HttpRequestInfo request
;
5782 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
5783 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
5784 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
5785 request
.extra_headers
.SetHeader("Foo", "1");
5786 request
.extra_headers
.SetHeader("bar", "23");
5787 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
5790 // Cause the above state to be reset.
5791 trans
->ResetStateForRestart();
5793 // Verify that the state that needed to be reset, has been reset.
5794 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
5795 EXPECT_EQ(0, trans
->read_buf_len_
);
5796 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
5797 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5798 EXPECT_TRUE(response
->headers
.get() == NULL
);
5799 EXPECT_FALSE(response
->was_cached
);
5800 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
5801 EXPECT_FALSE(response
->vary_data
.is_valid());
5804 // Test HTTPS connections to a site with a bad certificate
5805 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
5806 HttpRequestInfo request
;
5807 request
.method
= "GET";
5808 request
.url
= GURL("https://www.google.com/");
5809 request
.load_flags
= 0;
5811 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5812 scoped_ptr
<HttpTransaction
> trans(
5813 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5815 MockWrite data_writes
[] = {
5816 MockWrite("GET / HTTP/1.1\r\n"
5817 "Host: www.google.com\r\n"
5818 "Connection: keep-alive\r\n\r\n"),
5821 MockRead data_reads
[] = {
5822 MockRead("HTTP/1.0 200 OK\r\n"),
5823 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5824 MockRead("Content-Length: 100\r\n\r\n"),
5825 MockRead(SYNCHRONOUS
, OK
),
5828 StaticSocketDataProvider ssl_bad_certificate
;
5829 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5830 data_writes
, arraysize(data_writes
));
5831 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5832 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5834 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5835 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5836 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5837 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5839 TestCompletionCallback callback
;
5841 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5844 rv
= callback
.WaitForResult();
5845 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5847 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5848 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5850 rv
= callback
.WaitForResult();
5853 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5855 ASSERT_TRUE(response
!= NULL
);
5856 EXPECT_EQ(100, response
->headers
->GetContentLength());
5859 // Test HTTPS connections to a site with a bad certificate, going through a
5861 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
5862 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5864 HttpRequestInfo request
;
5865 request
.method
= "GET";
5866 request
.url
= GURL("https://www.google.com/");
5867 request
.load_flags
= 0;
5869 MockWrite proxy_writes
[] = {
5870 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5871 "Host: www.google.com\r\n"
5872 "Proxy-Connection: keep-alive\r\n\r\n"),
5875 MockRead proxy_reads
[] = {
5876 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5877 MockRead(SYNCHRONOUS
, OK
)
5880 MockWrite data_writes
[] = {
5881 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5882 "Host: www.google.com\r\n"
5883 "Proxy-Connection: keep-alive\r\n\r\n"),
5884 MockWrite("GET / HTTP/1.1\r\n"
5885 "Host: www.google.com\r\n"
5886 "Connection: keep-alive\r\n\r\n"),
5889 MockRead data_reads
[] = {
5890 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5891 MockRead("HTTP/1.0 200 OK\r\n"),
5892 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5893 MockRead("Content-Length: 100\r\n\r\n"),
5894 MockRead(SYNCHRONOUS
, OK
),
5897 StaticSocketDataProvider
ssl_bad_certificate(
5898 proxy_reads
, arraysize(proxy_reads
),
5899 proxy_writes
, arraysize(proxy_writes
));
5900 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5901 data_writes
, arraysize(data_writes
));
5902 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
5903 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5905 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
5906 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5907 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
5908 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5910 TestCompletionCallback callback
;
5912 for (int i
= 0; i
< 2; i
++) {
5913 session_deps_
.socket_factory
->ResetNextMockIndexes();
5915 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5916 scoped_ptr
<HttpTransaction
> trans(
5917 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5919 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5920 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5922 rv
= callback
.WaitForResult();
5923 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
5925 rv
= trans
->RestartIgnoringLastError(callback
.callback());
5926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5928 rv
= callback
.WaitForResult();
5931 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5933 ASSERT_TRUE(response
!= NULL
);
5934 EXPECT_EQ(100, response
->headers
->GetContentLength());
5939 // Test HTTPS connections to a site, going through an HTTPS proxy
5940 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
5941 session_deps_
.proxy_service
.reset(
5942 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
5943 CapturingNetLog net_log
;
5944 session_deps_
.net_log
= &net_log
;
5946 HttpRequestInfo request
;
5947 request
.method
= "GET";
5948 request
.url
= GURL("https://www.google.com/");
5949 request
.load_flags
= 0;
5951 MockWrite data_writes
[] = {
5952 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5953 "Host: www.google.com\r\n"
5954 "Proxy-Connection: keep-alive\r\n\r\n"),
5955 MockWrite("GET / HTTP/1.1\r\n"
5956 "Host: www.google.com\r\n"
5957 "Connection: keep-alive\r\n\r\n"),
5960 MockRead data_reads
[] = {
5961 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
5962 MockRead("HTTP/1.1 200 OK\r\n"),
5963 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5964 MockRead("Content-Length: 100\r\n\r\n"),
5965 MockRead(SYNCHRONOUS
, OK
),
5968 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5969 data_writes
, arraysize(data_writes
));
5970 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
5971 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
5973 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5974 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
5975 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
5977 TestCompletionCallback callback
;
5979 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5980 scoped_ptr
<HttpTransaction
> trans(
5981 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
5983 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5984 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5986 rv
= callback
.WaitForResult();
5988 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5990 ASSERT_TRUE(response
!= NULL
);
5992 EXPECT_TRUE(response
->headers
->IsKeepAlive());
5993 EXPECT_EQ(200, response
->headers
->response_code());
5994 EXPECT_EQ(100, response
->headers
->GetContentLength());
5995 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
5997 LoadTimingInfo load_timing_info
;
5998 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
5999 TestLoadTimingNotReusedWithPac(load_timing_info
,
6000 CONNECT_TIMING_HAS_SSL_TIMES
);
6003 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6004 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6005 session_deps_
.proxy_service
.reset(
6006 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6007 CapturingNetLog net_log
;
6008 session_deps_
.net_log
= &net_log
;
6010 HttpRequestInfo request
;
6011 request
.method
= "GET";
6012 request
.url
= GURL("https://www.google.com/");
6013 request
.load_flags
= 0;
6015 MockWrite data_writes
[] = {
6016 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6017 "Host: www.google.com\r\n"
6018 "Proxy-Connection: keep-alive\r\n\r\n"),
6021 MockRead data_reads
[] = {
6022 MockRead("HTTP/1.1 302 Redirect\r\n"),
6023 MockRead("Location: http://login.example.com/\r\n"),
6024 MockRead("Content-Length: 0\r\n\r\n"),
6025 MockRead(SYNCHRONOUS
, OK
),
6028 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6029 data_writes
, arraysize(data_writes
));
6030 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6032 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6033 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6035 TestCompletionCallback callback
;
6037 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6038 scoped_ptr
<HttpTransaction
> trans(
6039 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6041 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6042 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6044 rv
= callback
.WaitForResult();
6046 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6048 ASSERT_TRUE(response
!= NULL
);
6050 EXPECT_EQ(302, response
->headers
->response_code());
6052 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6053 EXPECT_EQ("http://login.example.com/", url
);
6055 // In the case of redirects from proxies, HttpNetworkTransaction returns
6056 // timing for the proxy connection instead of the connection to the host,
6057 // and no send / receive times.
6058 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6059 LoadTimingInfo load_timing_info
;
6060 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6062 EXPECT_FALSE(load_timing_info
.socket_reused
);
6063 EXPECT_NE(net::NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6065 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6066 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6067 load_timing_info
.proxy_resolve_end
);
6068 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6069 load_timing_info
.connect_timing
.connect_start
);
6070 ExpectConnectTimingHasTimes(
6071 load_timing_info
.connect_timing
,
6072 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6074 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6075 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6076 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6079 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6080 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6081 session_deps_
.proxy_service
.reset(
6082 ProxyService::CreateFixed("https://proxy:70"));
6084 HttpRequestInfo request
;
6085 request
.method
= "GET";
6086 request
.url
= GURL("https://www.google.com/");
6087 request
.load_flags
= 0;
6089 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6091 scoped_ptr
<SpdyFrame
> goaway(
6092 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6093 MockWrite data_writes
[] = {
6094 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6095 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6098 static const char* const kExtraHeaders
[] = {
6100 "http://login.example.com/",
6102 scoped_ptr
<SpdyFrame
> resp(
6103 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6104 arraysize(kExtraHeaders
)/2, 1));
6105 MockRead data_reads
[] = {
6106 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6107 MockRead(ASYNC
, 0, 2), // EOF
6110 DelayedSocketData
data(
6111 1, // wait for one write to finish before reading.
6112 data_reads
, arraysize(data_reads
),
6113 data_writes
, arraysize(data_writes
));
6114 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6115 proxy_ssl
.SetNextProto(GetParam());
6117 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6118 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6120 TestCompletionCallback callback
;
6122 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6123 scoped_ptr
<HttpTransaction
> trans(
6124 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6126 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6127 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6129 rv
= callback
.WaitForResult();
6131 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6133 ASSERT_TRUE(response
!= NULL
);
6135 EXPECT_EQ(302, response
->headers
->response_code());
6137 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6138 EXPECT_EQ("http://login.example.com/", url
);
6141 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6142 TEST_P(HttpNetworkTransactionTest
,
6143 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6144 session_deps_
.proxy_service
.reset(
6145 ProxyService::CreateFixed("https://proxy:70"));
6147 HttpRequestInfo request
;
6148 request
.method
= "GET";
6149 request
.url
= GURL("https://www.google.com/");
6150 request
.load_flags
= 0;
6152 MockWrite data_writes
[] = {
6153 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6154 "Host: www.google.com\r\n"
6155 "Proxy-Connection: keep-alive\r\n\r\n"),
6158 MockRead data_reads
[] = {
6159 MockRead("HTTP/1.1 404 Not Found\r\n"),
6160 MockRead("Content-Length: 23\r\n\r\n"),
6161 MockRead("The host does not exist"),
6162 MockRead(SYNCHRONOUS
, OK
),
6165 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6166 data_writes
, arraysize(data_writes
));
6167 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6169 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6170 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6172 TestCompletionCallback callback
;
6174 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6175 scoped_ptr
<HttpTransaction
> trans(
6176 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6178 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6181 rv
= callback
.WaitForResult();
6182 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6184 // TODO(ttuttle): Anything else to check here?
6187 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6188 TEST_P(HttpNetworkTransactionTest
,
6189 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6190 session_deps_
.proxy_service
.reset(
6191 ProxyService::CreateFixed("https://proxy:70"));
6193 HttpRequestInfo request
;
6194 request
.method
= "GET";
6195 request
.url
= GURL("https://www.google.com/");
6196 request
.load_flags
= 0;
6198 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6200 scoped_ptr
<SpdyFrame
> rst(
6201 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6202 MockWrite data_writes
[] = {
6203 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6204 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6207 static const char* const kExtraHeaders
[] = {
6209 "http://login.example.com/",
6211 scoped_ptr
<SpdyFrame
> resp(
6212 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6213 arraysize(kExtraHeaders
)/2, 1));
6214 scoped_ptr
<SpdyFrame
> body(
6215 spdy_util_
.ConstructSpdyBodyFrame(
6216 1, "The host does not exist", 23, true));
6217 MockRead data_reads
[] = {
6218 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6219 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6220 MockRead(ASYNC
, 0, 4), // EOF
6223 DelayedSocketData
data(
6224 1, // wait for one write to finish before reading.
6225 data_reads
, arraysize(data_reads
),
6226 data_writes
, arraysize(data_writes
));
6227 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6228 proxy_ssl
.SetNextProto(GetParam());
6230 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6231 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6233 TestCompletionCallback callback
;
6235 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6236 scoped_ptr
<HttpTransaction
> trans(
6237 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6239 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6240 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6242 rv
= callback
.WaitForResult();
6243 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6245 // TODO(ttuttle): Anything else to check here?
6248 // Test the request-challenge-retry sequence for basic auth, through
6249 // a SPDY proxy over a single SPDY session.
6250 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6251 HttpRequestInfo request
;
6252 request
.method
= "GET";
6253 request
.url
= GURL("https://www.google.com/");
6254 // when the no authentication data flag is set.
6255 request
.load_flags
= net::LOAD_DO_NOT_SEND_AUTH_DATA
;
6257 // Configure against https proxy server "myproxy:70".
6258 session_deps_
.proxy_service
.reset(
6259 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6260 CapturingBoundNetLog log
;
6261 session_deps_
.net_log
= log
.bound().net_log();
6262 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6264 // Since we have proxy, should try to establish tunnel.
6265 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
6267 scoped_ptr
<SpdyFrame
> rst(
6268 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6270 // After calling trans->RestartWithAuth(), this is the request we should
6271 // be issuing -- the final header line contains the credentials.
6272 const char* const kAuthCredentials
[] = {
6273 "proxy-authorization", "Basic Zm9vOmJhcg==",
6275 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6276 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
));
6277 // fetch https://www.google.com/ via HTTP
6278 const char get
[] = "GET / HTTP/1.1\r\n"
6279 "Host: www.google.com\r\n"
6280 "Connection: keep-alive\r\n\r\n";
6281 scoped_ptr
<SpdyFrame
> wrapped_get(
6282 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6284 MockWrite spdy_writes
[] = {
6285 CreateMockWrite(*req
, 1, ASYNC
),
6286 CreateMockWrite(*rst
, 4, ASYNC
),
6287 CreateMockWrite(*connect2
, 5),
6288 CreateMockWrite(*wrapped_get
, 8),
6291 // The proxy responds to the connect with a 407, using a persistent
6293 const char* const kAuthChallenge
[] = {
6294 spdy_util_
.GetStatusKey(), "407 Proxy Authentication Required",
6295 spdy_util_
.GetVersionKey(), "HTTP/1.1",
6296 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6299 scoped_ptr
<SpdyFrame
> conn_auth_resp(
6300 spdy_util_
.ConstructSpdyControlFrame(NULL
,
6308 arraysize(kAuthChallenge
),
6311 scoped_ptr
<SpdyFrame
> conn_resp(
6312 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6313 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6314 "Content-Length: 5\r\n\r\n";
6316 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6317 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6318 scoped_ptr
<SpdyFrame
> wrapped_body(
6319 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6320 MockRead spdy_reads
[] = {
6321 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6322 CreateMockRead(*conn_resp
, 6, ASYNC
),
6323 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6324 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6325 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6328 OrderedSocketData
spdy_data(
6329 spdy_reads
, arraysize(spdy_reads
),
6330 spdy_writes
, arraysize(spdy_writes
));
6331 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6332 // Negotiate SPDY to the proxy
6333 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6334 proxy
.SetNextProto(GetParam());
6335 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6336 // Vanilla SSL to the server
6337 SSLSocketDataProvider
server(ASYNC
, OK
);
6338 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6340 TestCompletionCallback callback1
;
6342 scoped_ptr
<HttpTransaction
> trans(
6343 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6345 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6346 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6348 rv
= callback1
.WaitForResult();
6350 net::CapturingNetLog::CapturedEntryList entries
;
6351 log
.GetEntries(&entries
);
6352 size_t pos
= ExpectLogContainsSomewhere(
6353 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6354 NetLog::PHASE_NONE
);
6355 ExpectLogContainsSomewhere(
6357 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6358 NetLog::PHASE_NONE
);
6360 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6361 ASSERT_TRUE(response
!= NULL
);
6362 ASSERT_FALSE(response
->headers
.get() == NULL
);
6363 EXPECT_EQ(407, response
->headers
->response_code());
6364 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6365 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6366 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6368 TestCompletionCallback callback2
;
6370 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6371 callback2
.callback());
6372 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6374 rv
= callback2
.WaitForResult();
6377 response
= trans
->GetResponseInfo();
6378 ASSERT_TRUE(response
!= NULL
);
6380 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6381 EXPECT_EQ(200, response
->headers
->response_code());
6382 EXPECT_EQ(5, response
->headers
->GetContentLength());
6383 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6385 // The password prompt info should not be set.
6386 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6388 LoadTimingInfo load_timing_info
;
6389 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6390 TestLoadTimingNotReusedWithPac(load_timing_info
,
6391 CONNECT_TIMING_HAS_SSL_TIMES
);
6394 session
->CloseAllConnections();
6397 // Test that an explicitly trusted SPDY proxy can push a resource from an
6398 // origin that is different from that of its associated resource.
6399 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6400 HttpRequestInfo request
;
6401 HttpRequestInfo push_request
;
6403 request
.method
= "GET";
6404 request
.url
= GURL("http://www.google.com/");
6405 push_request
.method
= "GET";
6406 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6408 // Configure against https proxy server "myproxy:70".
6409 session_deps_
.proxy_service
.reset(
6410 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6411 CapturingBoundNetLog log
;
6412 session_deps_
.net_log
= log
.bound().net_log();
6414 // Enable cross-origin push.
6415 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6417 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6419 scoped_ptr
<SpdyFrame
> stream1_syn(
6420 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6422 MockWrite spdy_writes
[] = {
6423 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6426 scoped_ptr
<SpdyFrame
>
6427 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6429 scoped_ptr
<SpdyFrame
>
6430 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6432 scoped_ptr
<SpdyFrame
>
6433 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6437 "http://www.another-origin.com/foo.dat"));
6438 const char kPushedData
[] = "pushed";
6439 scoped_ptr
<SpdyFrame
> stream2_body(
6440 spdy_util_
.ConstructSpdyBodyFrame(
6441 2, kPushedData
, strlen(kPushedData
), true));
6443 MockRead spdy_reads
[] = {
6444 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6445 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6446 CreateMockRead(*stream1_body
, 4, ASYNC
),
6447 CreateMockRead(*stream2_body
, 5, ASYNC
),
6448 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6451 OrderedSocketData
spdy_data(
6452 spdy_reads
, arraysize(spdy_reads
),
6453 spdy_writes
, arraysize(spdy_writes
));
6454 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6455 // Negotiate SPDY to the proxy
6456 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6457 proxy
.SetNextProto(GetParam());
6458 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6460 scoped_ptr
<HttpTransaction
> trans(
6461 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6462 TestCompletionCallback callback
;
6463 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6464 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6466 rv
= callback
.WaitForResult();
6468 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6470 scoped_ptr
<HttpTransaction
> push_trans(
6471 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6472 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6473 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6475 rv
= callback
.WaitForResult();
6477 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6479 ASSERT_TRUE(response
!= NULL
);
6480 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6482 EXPECT_EQ(200, response
->headers
->response_code());
6483 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6485 std::string response_data
;
6486 rv
= ReadTransaction(trans
.get(), &response_data
);
6488 EXPECT_EQ("hello!", response_data
);
6490 LoadTimingInfo load_timing_info
;
6491 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6492 TestLoadTimingNotReusedWithPac(load_timing_info
,
6493 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6495 // Verify the pushed stream.
6496 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6497 EXPECT_EQ(200, push_response
->headers
->response_code());
6499 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6501 EXPECT_EQ("pushed", response_data
);
6503 LoadTimingInfo push_load_timing_info
;
6504 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6505 TestLoadTimingReusedWithPac(push_load_timing_info
);
6506 // The transactions should share a socket ID, despite being for different
6508 EXPECT_EQ(load_timing_info
.socket_log_id
,
6509 push_load_timing_info
.socket_log_id
);
6513 session
->CloseAllConnections();
6516 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6517 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6518 HttpRequestInfo request
;
6520 request
.method
= "GET";
6521 request
.url
= GURL("http://www.google.com/");
6523 // Configure against https proxy server "myproxy:70".
6524 session_deps_
.proxy_service
.reset(
6525 ProxyService::CreateFixed("https://myproxy:70"));
6526 CapturingBoundNetLog log
;
6527 session_deps_
.net_log
= log
.bound().net_log();
6529 // Enable cross-origin push.
6530 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6532 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6534 scoped_ptr
<SpdyFrame
> stream1_syn(
6535 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6537 scoped_ptr
<SpdyFrame
> push_rst(
6538 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6540 MockWrite spdy_writes
[] = {
6541 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6542 CreateMockWrite(*push_rst
, 4),
6545 scoped_ptr
<SpdyFrame
>
6546 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6548 scoped_ptr
<SpdyFrame
>
6549 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6551 scoped_ptr
<SpdyFrame
>
6552 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6556 "https://www.another-origin.com/foo.dat"));
6558 MockRead spdy_reads
[] = {
6559 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6560 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6561 CreateMockRead(*stream1_body
, 5, ASYNC
),
6562 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6565 OrderedSocketData
spdy_data(
6566 spdy_reads
, arraysize(spdy_reads
),
6567 spdy_writes
, arraysize(spdy_writes
));
6568 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6569 // Negotiate SPDY to the proxy
6570 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6571 proxy
.SetNextProto(GetParam());
6572 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6574 scoped_ptr
<HttpTransaction
> trans(
6575 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6576 TestCompletionCallback callback
;
6577 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6578 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6580 rv
= callback
.WaitForResult();
6582 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6584 ASSERT_TRUE(response
!= NULL
);
6585 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6587 EXPECT_EQ(200, response
->headers
->response_code());
6588 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6590 std::string response_data
;
6591 rv
= ReadTransaction(trans
.get(), &response_data
);
6593 EXPECT_EQ("hello!", response_data
);
6596 session
->CloseAllConnections();
6599 // Test HTTPS connections to a site with a bad certificate, going through an
6601 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
6602 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
6603 "https://proxy:70"));
6605 HttpRequestInfo request
;
6606 request
.method
= "GET";
6607 request
.url
= GURL("https://www.google.com/");
6608 request
.load_flags
= 0;
6610 // Attempt to fetch the URL from a server with a bad cert
6611 MockWrite bad_cert_writes
[] = {
6612 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6613 "Host: www.google.com\r\n"
6614 "Proxy-Connection: keep-alive\r\n\r\n"),
6617 MockRead bad_cert_reads
[] = {
6618 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6619 MockRead(SYNCHRONOUS
, OK
)
6622 // Attempt to fetch the URL with a good cert
6623 MockWrite good_data_writes
[] = {
6624 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6625 "Host: www.google.com\r\n"
6626 "Proxy-Connection: keep-alive\r\n\r\n"),
6627 MockWrite("GET / HTTP/1.1\r\n"
6628 "Host: www.google.com\r\n"
6629 "Connection: keep-alive\r\n\r\n"),
6632 MockRead good_cert_reads
[] = {
6633 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6634 MockRead("HTTP/1.0 200 OK\r\n"),
6635 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6636 MockRead("Content-Length: 100\r\n\r\n"),
6637 MockRead(SYNCHRONOUS
, OK
),
6640 StaticSocketDataProvider
ssl_bad_certificate(
6641 bad_cert_reads
, arraysize(bad_cert_reads
),
6642 bad_cert_writes
, arraysize(bad_cert_writes
));
6643 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
6644 good_data_writes
, arraysize(good_data_writes
));
6645 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6646 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6648 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
6649 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6650 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6651 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6653 // SSL to the proxy, then CONNECT request, then valid SSL certificate
6654 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6655 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6656 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6658 TestCompletionCallback callback
;
6660 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6661 scoped_ptr
<HttpTransaction
> trans(
6662 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6664 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6665 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6667 rv
= callback
.WaitForResult();
6668 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6670 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6673 rv
= callback
.WaitForResult();
6676 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6678 ASSERT_TRUE(response
!= NULL
);
6679 EXPECT_EQ(100, response
->headers
->GetContentLength());
6682 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
6683 HttpRequestInfo request
;
6684 request
.method
= "GET";
6685 request
.url
= GURL("http://www.google.com/");
6686 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6687 "Chromium Ultra Awesome X Edition");
6689 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6690 scoped_ptr
<HttpTransaction
> trans(
6691 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6693 MockWrite data_writes
[] = {
6694 MockWrite("GET / HTTP/1.1\r\n"
6695 "Host: www.google.com\r\n"
6696 "Connection: keep-alive\r\n"
6697 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6700 // Lastly, the server responds with the actual content.
6701 MockRead data_reads
[] = {
6702 MockRead("HTTP/1.0 200 OK\r\n"),
6703 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6704 MockRead("Content-Length: 100\r\n\r\n"),
6705 MockRead(SYNCHRONOUS
, OK
),
6708 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6709 data_writes
, arraysize(data_writes
));
6710 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6712 TestCompletionCallback callback
;
6714 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6715 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6717 rv
= callback
.WaitForResult();
6721 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
6722 HttpRequestInfo request
;
6723 request
.method
= "GET";
6724 request
.url
= GURL("https://www.google.com/");
6725 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
6726 "Chromium Ultra Awesome X Edition");
6728 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6729 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6730 scoped_ptr
<HttpTransaction
> trans(
6731 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6733 MockWrite data_writes
[] = {
6734 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6735 "Host: www.google.com\r\n"
6736 "Proxy-Connection: keep-alive\r\n"
6737 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
6739 MockRead data_reads
[] = {
6740 // Return an error, so the transaction stops here (this test isn't
6741 // interested in the rest).
6742 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
6743 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6744 MockRead("Proxy-Connection: close\r\n\r\n"),
6747 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6748 data_writes
, arraysize(data_writes
));
6749 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6751 TestCompletionCallback callback
;
6753 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6754 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6756 rv
= callback
.WaitForResult();
6760 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
6761 HttpRequestInfo request
;
6762 request
.method
= "GET";
6763 request
.url
= GURL("http://www.google.com/");
6764 request
.load_flags
= 0;
6765 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
6766 "http://the.previous.site.com/");
6768 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6769 scoped_ptr
<HttpTransaction
> trans(
6770 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6772 MockWrite data_writes
[] = {
6773 MockWrite("GET / HTTP/1.1\r\n"
6774 "Host: www.google.com\r\n"
6775 "Connection: keep-alive\r\n"
6776 "Referer: http://the.previous.site.com/\r\n\r\n"),
6779 // Lastly, the server responds with the actual content.
6780 MockRead data_reads
[] = {
6781 MockRead("HTTP/1.0 200 OK\r\n"),
6782 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6783 MockRead("Content-Length: 100\r\n\r\n"),
6784 MockRead(SYNCHRONOUS
, OK
),
6787 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6788 data_writes
, arraysize(data_writes
));
6789 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6791 TestCompletionCallback callback
;
6793 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6794 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6796 rv
= callback
.WaitForResult();
6800 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
6801 HttpRequestInfo request
;
6802 request
.method
= "POST";
6803 request
.url
= GURL("http://www.google.com/");
6805 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6806 scoped_ptr
<HttpTransaction
> trans(
6807 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6809 MockWrite data_writes
[] = {
6810 MockWrite("POST / HTTP/1.1\r\n"
6811 "Host: www.google.com\r\n"
6812 "Connection: keep-alive\r\n"
6813 "Content-Length: 0\r\n\r\n"),
6816 // Lastly, the server responds with the actual content.
6817 MockRead data_reads
[] = {
6818 MockRead("HTTP/1.0 200 OK\r\n"),
6819 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6820 MockRead("Content-Length: 100\r\n\r\n"),
6821 MockRead(SYNCHRONOUS
, OK
),
6824 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6825 data_writes
, arraysize(data_writes
));
6826 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6828 TestCompletionCallback callback
;
6830 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6831 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6833 rv
= callback
.WaitForResult();
6837 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
6838 HttpRequestInfo request
;
6839 request
.method
= "PUT";
6840 request
.url
= GURL("http://www.google.com/");
6842 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6843 scoped_ptr
<HttpTransaction
> trans(
6844 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6846 MockWrite data_writes
[] = {
6847 MockWrite("PUT / HTTP/1.1\r\n"
6848 "Host: www.google.com\r\n"
6849 "Connection: keep-alive\r\n"
6850 "Content-Length: 0\r\n\r\n"),
6853 // Lastly, the server responds with the actual content.
6854 MockRead data_reads
[] = {
6855 MockRead("HTTP/1.0 200 OK\r\n"),
6856 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6857 MockRead("Content-Length: 100\r\n\r\n"),
6858 MockRead(SYNCHRONOUS
, OK
),
6861 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6862 data_writes
, arraysize(data_writes
));
6863 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6865 TestCompletionCallback callback
;
6867 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6868 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6870 rv
= callback
.WaitForResult();
6874 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
6875 HttpRequestInfo request
;
6876 request
.method
= "HEAD";
6877 request
.url
= GURL("http://www.google.com/");
6879 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6880 scoped_ptr
<HttpTransaction
> trans(
6881 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6883 MockWrite data_writes
[] = {
6884 MockWrite("HEAD / HTTP/1.1\r\n"
6885 "Host: www.google.com\r\n"
6886 "Connection: keep-alive\r\n"
6887 "Content-Length: 0\r\n\r\n"),
6890 // Lastly, the server responds with the actual content.
6891 MockRead data_reads
[] = {
6892 MockRead("HTTP/1.0 200 OK\r\n"),
6893 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6894 MockRead("Content-Length: 100\r\n\r\n"),
6895 MockRead(SYNCHRONOUS
, OK
),
6898 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6899 data_writes
, arraysize(data_writes
));
6900 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6902 TestCompletionCallback callback
;
6904 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6905 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6907 rv
= callback
.WaitForResult();
6911 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
6912 HttpRequestInfo request
;
6913 request
.method
= "GET";
6914 request
.url
= GURL("http://www.google.com/");
6915 request
.load_flags
= LOAD_BYPASS_CACHE
;
6917 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6918 scoped_ptr
<HttpTransaction
> trans(
6919 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6921 MockWrite data_writes
[] = {
6922 MockWrite("GET / HTTP/1.1\r\n"
6923 "Host: www.google.com\r\n"
6924 "Connection: keep-alive\r\n"
6925 "Pragma: no-cache\r\n"
6926 "Cache-Control: no-cache\r\n\r\n"),
6929 // Lastly, the server responds with the actual content.
6930 MockRead data_reads
[] = {
6931 MockRead("HTTP/1.0 200 OK\r\n"),
6932 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6933 MockRead("Content-Length: 100\r\n\r\n"),
6934 MockRead(SYNCHRONOUS
, OK
),
6937 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6938 data_writes
, arraysize(data_writes
));
6939 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6941 TestCompletionCallback callback
;
6943 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6944 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6946 rv
= callback
.WaitForResult();
6950 TEST_P(HttpNetworkTransactionTest
,
6951 BuildRequest_CacheControlValidateCache
) {
6952 HttpRequestInfo request
;
6953 request
.method
= "GET";
6954 request
.url
= GURL("http://www.google.com/");
6955 request
.load_flags
= LOAD_VALIDATE_CACHE
;
6957 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6958 scoped_ptr
<HttpTransaction
> trans(
6959 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6961 MockWrite data_writes
[] = {
6962 MockWrite("GET / HTTP/1.1\r\n"
6963 "Host: www.google.com\r\n"
6964 "Connection: keep-alive\r\n"
6965 "Cache-Control: max-age=0\r\n\r\n"),
6968 // Lastly, the server responds with the actual content.
6969 MockRead data_reads
[] = {
6970 MockRead("HTTP/1.0 200 OK\r\n"),
6971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6972 MockRead("Content-Length: 100\r\n\r\n"),
6973 MockRead(SYNCHRONOUS
, OK
),
6976 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6977 data_writes
, arraysize(data_writes
));
6978 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6980 TestCompletionCallback callback
;
6982 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6983 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6985 rv
= callback
.WaitForResult();
6989 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
6990 HttpRequestInfo request
;
6991 request
.method
= "GET";
6992 request
.url
= GURL("http://www.google.com/");
6993 request
.extra_headers
.SetHeader("FooHeader", "Bar");
6995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6996 scoped_ptr
<HttpTransaction
> trans(
6997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
6999 MockWrite data_writes
[] = {
7000 MockWrite("GET / HTTP/1.1\r\n"
7001 "Host: www.google.com\r\n"
7002 "Connection: keep-alive\r\n"
7003 "FooHeader: Bar\r\n\r\n"),
7006 // Lastly, the server responds with the actual content.
7007 MockRead data_reads
[] = {
7008 MockRead("HTTP/1.0 200 OK\r\n"),
7009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7010 MockRead("Content-Length: 100\r\n\r\n"),
7011 MockRead(SYNCHRONOUS
, OK
),
7014 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7015 data_writes
, arraysize(data_writes
));
7016 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7018 TestCompletionCallback callback
;
7020 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7021 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7023 rv
= callback
.WaitForResult();
7027 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7028 HttpRequestInfo request
;
7029 request
.method
= "GET";
7030 request
.url
= GURL("http://www.google.com/");
7031 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7032 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7033 request
.extra_headers
.SetHeader("FoO", "bar");
7035 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7036 scoped_ptr
<HttpTransaction
> trans(
7037 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7039 MockWrite data_writes
[] = {
7040 MockWrite("GET / HTTP/1.1\r\n"
7041 "Host: www.google.com\r\n"
7042 "Connection: keep-alive\r\n"
7043 "referer: www.foo.com\r\n"
7045 "FoO: bar\r\n\r\n"),
7048 // Lastly, the server responds with the actual content.
7049 MockRead data_reads
[] = {
7050 MockRead("HTTP/1.0 200 OK\r\n"),
7051 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7052 MockRead("Content-Length: 100\r\n\r\n"),
7053 MockRead(SYNCHRONOUS
, OK
),
7056 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7057 data_writes
, arraysize(data_writes
));
7058 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7060 TestCompletionCallback callback
;
7062 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7063 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7065 rv
= callback
.WaitForResult();
7069 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7070 HttpRequestInfo request
;
7071 request
.method
= "GET";
7072 request
.url
= GURL("http://www.google.com/");
7073 request
.load_flags
= 0;
7075 session_deps_
.proxy_service
.reset(
7076 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7077 CapturingNetLog net_log
;
7078 session_deps_
.net_log
= &net_log
;
7080 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7081 scoped_ptr
<HttpTransaction
> trans(
7082 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7084 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7085 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7087 MockWrite data_writes
[] = {
7088 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7089 MockWrite("GET / HTTP/1.1\r\n"
7090 "Host: www.google.com\r\n"
7091 "Connection: keep-alive\r\n\r\n")
7094 MockRead data_reads
[] = {
7095 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7096 MockRead("HTTP/1.0 200 OK\r\n"),
7097 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7098 MockRead("Payload"),
7099 MockRead(SYNCHRONOUS
, OK
)
7102 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7103 data_writes
, arraysize(data_writes
));
7104 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7106 TestCompletionCallback callback
;
7108 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7109 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7111 rv
= callback
.WaitForResult();
7114 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7115 ASSERT_TRUE(response
!= NULL
);
7117 LoadTimingInfo load_timing_info
;
7118 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7119 TestLoadTimingNotReusedWithPac(load_timing_info
,
7120 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7122 std::string response_text
;
7123 rv
= ReadTransaction(trans
.get(), &response_text
);
7125 EXPECT_EQ("Payload", response_text
);
7128 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7129 HttpRequestInfo request
;
7130 request
.method
= "GET";
7131 request
.url
= GURL("https://www.google.com/");
7132 request
.load_flags
= 0;
7134 session_deps_
.proxy_service
.reset(
7135 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7136 CapturingNetLog net_log
;
7137 session_deps_
.net_log
= &net_log
;
7139 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7140 scoped_ptr
<HttpTransaction
> trans(
7141 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7143 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7144 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7146 MockWrite data_writes
[] = {
7147 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7148 arraysize(write_buffer
)),
7149 MockWrite("GET / HTTP/1.1\r\n"
7150 "Host: www.google.com\r\n"
7151 "Connection: keep-alive\r\n\r\n")
7154 MockRead data_reads
[] = {
7155 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7156 arraysize(read_buffer
)),
7157 MockRead("HTTP/1.0 200 OK\r\n"),
7158 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7159 MockRead("Payload"),
7160 MockRead(SYNCHRONOUS
, OK
)
7163 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7164 data_writes
, arraysize(data_writes
));
7165 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7167 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7168 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7170 TestCompletionCallback callback
;
7172 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7173 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7175 rv
= callback
.WaitForResult();
7178 LoadTimingInfo load_timing_info
;
7179 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7180 TestLoadTimingNotReusedWithPac(load_timing_info
,
7181 CONNECT_TIMING_HAS_SSL_TIMES
);
7183 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7184 ASSERT_TRUE(response
!= NULL
);
7186 std::string response_text
;
7187 rv
= ReadTransaction(trans
.get(), &response_text
);
7189 EXPECT_EQ("Payload", response_text
);
7192 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7193 HttpRequestInfo request
;
7194 request
.method
= "GET";
7195 request
.url
= GURL("http://www.google.com/");
7196 request
.load_flags
= 0;
7198 session_deps_
.proxy_service
.reset(
7199 ProxyService::CreateFixed("socks4://myproxy:1080"));
7200 CapturingNetLog net_log
;
7201 session_deps_
.net_log
= &net_log
;
7203 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7204 scoped_ptr
<HttpTransaction
> trans(
7205 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7207 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7208 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7210 MockWrite data_writes
[] = {
7211 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7212 MockWrite("GET / HTTP/1.1\r\n"
7213 "Host: www.google.com\r\n"
7214 "Connection: keep-alive\r\n\r\n")
7217 MockRead data_reads
[] = {
7218 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7219 MockRead("HTTP/1.0 200 OK\r\n"),
7220 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7221 MockRead("Payload"),
7222 MockRead(SYNCHRONOUS
, OK
)
7225 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7226 data_writes
, arraysize(data_writes
));
7227 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7229 TestCompletionCallback callback
;
7231 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7232 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7234 rv
= callback
.WaitForResult();
7237 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7238 ASSERT_TRUE(response
!= NULL
);
7240 LoadTimingInfo load_timing_info
;
7241 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7242 TestLoadTimingNotReused(load_timing_info
,
7243 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7245 std::string response_text
;
7246 rv
= ReadTransaction(trans
.get(), &response_text
);
7248 EXPECT_EQ("Payload", response_text
);
7251 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7252 HttpRequestInfo request
;
7253 request
.method
= "GET";
7254 request
.url
= GURL("http://www.google.com/");
7255 request
.load_flags
= 0;
7257 session_deps_
.proxy_service
.reset(
7258 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7259 CapturingNetLog net_log
;
7260 session_deps_
.net_log
= &net_log
;
7262 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7263 scoped_ptr
<HttpTransaction
> trans(
7264 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7266 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7267 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7268 const char kSOCKS5OkRequest
[] = {
7270 0x01, // Command (CONNECT)
7272 0x03, // Address type (DOMAINNAME).
7273 0x0E, // Length of domain (14)
7275 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7276 0x00, 0x50, // 16-bit port (80)
7278 const char kSOCKS5OkResponse
[] =
7279 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7281 MockWrite data_writes
[] = {
7282 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7283 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7284 MockWrite("GET / HTTP/1.1\r\n"
7285 "Host: www.google.com\r\n"
7286 "Connection: keep-alive\r\n\r\n")
7289 MockRead data_reads
[] = {
7290 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7291 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7292 MockRead("HTTP/1.0 200 OK\r\n"),
7293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7294 MockRead("Payload"),
7295 MockRead(SYNCHRONOUS
, OK
)
7298 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7299 data_writes
, arraysize(data_writes
));
7300 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7302 TestCompletionCallback callback
;
7304 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7307 rv
= callback
.WaitForResult();
7310 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7311 ASSERT_TRUE(response
!= NULL
);
7313 LoadTimingInfo load_timing_info
;
7314 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7315 TestLoadTimingNotReusedWithPac(load_timing_info
,
7316 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7318 std::string response_text
;
7319 rv
= ReadTransaction(trans
.get(), &response_text
);
7321 EXPECT_EQ("Payload", response_text
);
7324 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7325 HttpRequestInfo request
;
7326 request
.method
= "GET";
7327 request
.url
= GURL("https://www.google.com/");
7328 request
.load_flags
= 0;
7330 session_deps_
.proxy_service
.reset(
7331 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7332 CapturingNetLog net_log
;
7333 session_deps_
.net_log
= &net_log
;
7335 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7336 scoped_ptr
<HttpTransaction
> trans(
7337 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7339 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7340 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7341 const unsigned char kSOCKS5OkRequest
[] = {
7343 0x01, // Command (CONNECT)
7345 0x03, // Address type (DOMAINNAME).
7346 0x0E, // Length of domain (14)
7348 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
7349 0x01, 0xBB, // 16-bit port (443)
7352 const char kSOCKS5OkResponse
[] =
7353 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7355 MockWrite data_writes
[] = {
7356 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7357 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7358 arraysize(kSOCKS5OkRequest
)),
7359 MockWrite("GET / HTTP/1.1\r\n"
7360 "Host: www.google.com\r\n"
7361 "Connection: keep-alive\r\n\r\n")
7364 MockRead data_reads
[] = {
7365 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7366 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7367 MockRead("HTTP/1.0 200 OK\r\n"),
7368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7369 MockRead("Payload"),
7370 MockRead(SYNCHRONOUS
, OK
)
7373 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7374 data_writes
, arraysize(data_writes
));
7375 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7377 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7378 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7380 TestCompletionCallback callback
;
7382 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7383 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7385 rv
= callback
.WaitForResult();
7388 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7389 ASSERT_TRUE(response
!= NULL
);
7391 LoadTimingInfo load_timing_info
;
7392 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7393 TestLoadTimingNotReusedWithPac(load_timing_info
,
7394 CONNECT_TIMING_HAS_SSL_TIMES
);
7396 std::string response_text
;
7397 rv
= ReadTransaction(trans
.get(), &response_text
);
7399 EXPECT_EQ("Payload", response_text
);
7404 // Tests that for connection endpoints the group names are correctly set.
7406 struct GroupNameTest
{
7407 std::string proxy_server
;
7409 std::string expected_group_name
;
7413 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7414 NextProto next_proto
,
7415 SpdySessionDependencies
* session_deps_
) {
7416 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7418 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7419 session
->http_server_properties();
7420 http_server_properties
->SetAlternateProtocol(
7421 HostPortPair("host.with.alternate", 80), 443,
7422 AlternateProtocolFromNextProto(next_proto
));
7427 int GroupNameTransactionHelper(
7428 const std::string
& url
,
7429 const scoped_refptr
<HttpNetworkSession
>& session
) {
7430 HttpRequestInfo request
;
7431 request
.method
= "GET";
7432 request
.url
= GURL(url
);
7433 request
.load_flags
= 0;
7435 scoped_ptr
<HttpTransaction
> trans(
7436 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7438 TestCompletionCallback callback
;
7440 // We do not complete this request, the dtor will clean the transaction up.
7441 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7446 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7447 const GroupNameTest tests
[] = {
7450 "http://www.google.com/direct",
7451 "www.google.com:80",
7456 "http://[2001:1418:13:1::25]/direct",
7457 "[2001:1418:13:1::25]:80",
7464 "https://www.google.com/direct_ssl",
7465 "ssl/www.google.com:443",
7470 "https://[2001:1418:13:1::25]/direct",
7471 "ssl/[2001:1418:13:1::25]:443",
7476 "http://host.with.alternate/direct",
7477 "ssl/host.with.alternate:443",
7482 HttpStreamFactory::set_use_alternate_protocols(true);
7484 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7485 session_deps_
.proxy_service
.reset(
7486 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7487 scoped_refptr
<HttpNetworkSession
> session(
7488 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7490 HttpNetworkSessionPeer
peer(session
);
7491 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7492 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7493 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7494 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7495 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7496 new MockClientSocketPoolManager
);
7497 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7498 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7499 peer
.SetClientSocketPoolManager(
7500 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7502 EXPECT_EQ(ERR_IO_PENDING
,
7503 GroupNameTransactionHelper(tests
[i
].url
, session
));
7505 EXPECT_EQ(tests
[i
].expected_group_name
,
7506 ssl_conn_pool
->last_group_name_received());
7508 EXPECT_EQ(tests
[i
].expected_group_name
,
7509 transport_conn_pool
->last_group_name_received());
7514 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7515 const GroupNameTest tests
[] = {
7518 "http://www.google.com/http_proxy_normal",
7519 "www.google.com:80",
7526 "https://www.google.com/http_connect_ssl",
7527 "ssl/www.google.com:443",
7533 "http://host.with.alternate/direct",
7534 "ssl/host.with.alternate:443",
7540 "ftp://ftp.google.com/http_proxy_normal",
7541 "ftp/ftp.google.com:21",
7546 HttpStreamFactory::set_use_alternate_protocols(true);
7548 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7549 session_deps_
.proxy_service
.reset(
7550 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7551 scoped_refptr
<HttpNetworkSession
> session(
7552 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7554 HttpNetworkSessionPeer
peer(session
);
7556 HostPortPair
proxy_host("http_proxy", 80);
7557 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
7558 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
7559 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7560 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7562 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7563 new MockClientSocketPoolManager
);
7564 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
7565 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7566 peer
.SetClientSocketPoolManager(
7567 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7569 EXPECT_EQ(ERR_IO_PENDING
,
7570 GroupNameTransactionHelper(tests
[i
].url
, session
));
7572 EXPECT_EQ(tests
[i
].expected_group_name
,
7573 ssl_conn_pool
->last_group_name_received());
7575 EXPECT_EQ(tests
[i
].expected_group_name
,
7576 http_proxy_pool
->last_group_name_received());
7580 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
7581 const GroupNameTest tests
[] = {
7583 "socks4://socks_proxy:1080",
7584 "http://www.google.com/socks4_direct",
7585 "socks4/www.google.com:80",
7589 "socks5://socks_proxy:1080",
7590 "http://www.google.com/socks5_direct",
7591 "socks5/www.google.com:80",
7597 "socks4://socks_proxy:1080",
7598 "https://www.google.com/socks4_ssl",
7599 "socks4/ssl/www.google.com:443",
7603 "socks5://socks_proxy:1080",
7604 "https://www.google.com/socks5_ssl",
7605 "socks5/ssl/www.google.com:443",
7610 "socks4://socks_proxy:1080",
7611 "http://host.with.alternate/direct",
7612 "socks4/ssl/host.with.alternate:443",
7617 HttpStreamFactory::set_use_alternate_protocols(true);
7619 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
7620 session_deps_
.proxy_service
.reset(
7621 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7622 scoped_refptr
<HttpNetworkSession
> session(
7623 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7625 HttpNetworkSessionPeer
peer(session
);
7627 HostPortPair
proxy_host("socks_proxy", 1080);
7628 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
7629 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
7630 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7631 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7633 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7634 new MockClientSocketPoolManager
);
7635 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
7636 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
7637 peer
.SetClientSocketPoolManager(
7638 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
7640 scoped_ptr
<HttpTransaction
> trans(
7641 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7643 EXPECT_EQ(ERR_IO_PENDING
,
7644 GroupNameTransactionHelper(tests
[i
].url
, session
));
7646 EXPECT_EQ(tests
[i
].expected_group_name
,
7647 ssl_conn_pool
->last_group_name_received());
7649 EXPECT_EQ(tests
[i
].expected_group_name
,
7650 socks_conn_pool
->last_group_name_received());
7654 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
7655 HttpRequestInfo request
;
7656 request
.method
= "GET";
7657 request
.url
= GURL("http://www.google.com/");
7659 session_deps_
.proxy_service
.reset(
7660 ProxyService::CreateFixed("myproxy:70;foobar:80"));
7662 // This simulates failure resolving all hostnames; that means we will fail
7663 // connecting to both proxies (myproxy:70 and foobar:80).
7664 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
7666 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7667 scoped_ptr
<HttpTransaction
> trans(
7668 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7670 TestCompletionCallback callback
;
7672 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7675 rv
= callback
.WaitForResult();
7676 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
7679 // Base test to make sure that when the load flags for a request specify to
7680 // bypass the cache, the DNS cache is not used.
7681 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
7683 // Issue a request, asking to bypass the cache(s).
7684 HttpRequestInfo request
;
7685 request
.method
= "GET";
7686 request
.load_flags
= load_flags
;
7687 request
.url
= GURL("http://www.google.com/");
7689 // Select a host resolver that does caching.
7690 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
7692 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7693 scoped_ptr
<HttpTransaction
> trans(
7694 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7696 // Warm up the host cache so it has an entry for "www.google.com".
7697 AddressList addrlist
;
7698 TestCompletionCallback callback
;
7699 int rv
= session_deps_
.host_resolver
->Resolve(
7700 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7703 callback
.callback(),
7706 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7707 rv
= callback
.WaitForResult();
7710 // Verify that it was added to host cache, by doing a subsequent async lookup
7711 // and confirming it completes synchronously.
7712 rv
= session_deps_
.host_resolver
->Resolve(
7713 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)),
7716 callback
.callback(),
7721 // Inject a failure the next time that "www.google.com" is resolved. This way
7722 // we can tell if the next lookup hit the cache, or the "network".
7723 // (cache --> success, "network" --> failure).
7724 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.google.com");
7726 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
7727 // first read -- this won't be reached as the host resolution will fail first.
7728 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
7729 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7730 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7733 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7734 ASSERT_EQ(ERR_IO_PENDING
, rv
);
7735 rv
= callback
.WaitForResult();
7737 // If we bypassed the cache, we would have gotten a failure while resolving
7738 // "www.google.com".
7739 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
7742 // There are multiple load flags that should trigger the host cache bypass.
7743 // Test each in isolation:
7744 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
7745 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
7748 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
7749 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
7752 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
7753 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
7756 // Make sure we can handle an error when writing the request.
7757 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
7758 HttpRequestInfo request
;
7759 request
.method
= "GET";
7760 request
.url
= GURL("http://www.foo.com/");
7761 request
.load_flags
= 0;
7763 MockWrite write_failure
[] = {
7764 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
7766 StaticSocketDataProvider
data(NULL
, 0,
7767 write_failure
, arraysize(write_failure
));
7768 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7769 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7771 TestCompletionCallback callback
;
7773 scoped_ptr
<HttpTransaction
> trans(
7774 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7776 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7779 rv
= callback
.WaitForResult();
7780 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
7783 // Check that a connection closed after the start of the headers finishes ok.
7784 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
7785 HttpRequestInfo request
;
7786 request
.method
= "GET";
7787 request
.url
= GURL("http://www.foo.com/");
7788 request
.load_flags
= 0;
7790 MockRead data_reads
[] = {
7791 MockRead("HTTP/1."),
7792 MockRead(SYNCHRONOUS
, OK
),
7795 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7796 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7797 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7799 TestCompletionCallback callback
;
7801 scoped_ptr
<HttpTransaction
> trans(
7802 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7804 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7805 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7807 rv
= callback
.WaitForResult();
7810 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7811 ASSERT_TRUE(response
!= NULL
);
7813 EXPECT_TRUE(response
->headers
.get() != NULL
);
7814 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7816 std::string response_data
;
7817 rv
= ReadTransaction(trans
.get(), &response_data
);
7819 EXPECT_EQ("", response_data
);
7822 // Make sure that a dropped connection while draining the body for auth
7823 // restart does the right thing.
7824 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
7825 HttpRequestInfo request
;
7826 request
.method
= "GET";
7827 request
.url
= GURL("http://www.google.com/");
7828 request
.load_flags
= 0;
7830 MockWrite data_writes1
[] = {
7831 MockWrite("GET / HTTP/1.1\r\n"
7832 "Host: www.google.com\r\n"
7833 "Connection: keep-alive\r\n\r\n"),
7836 MockRead data_reads1
[] = {
7837 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
7838 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7839 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7840 MockRead("Content-Length: 14\r\n\r\n"),
7842 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
7845 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
7846 data_writes1
, arraysize(data_writes1
));
7847 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
7849 // After calling trans->RestartWithAuth(), this is the request we should
7850 // be issuing -- the final header line contains the credentials.
7851 MockWrite data_writes2
[] = {
7852 MockWrite("GET / HTTP/1.1\r\n"
7853 "Host: www.google.com\r\n"
7854 "Connection: keep-alive\r\n"
7855 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
7858 // Lastly, the server responds with the actual content.
7859 MockRead data_reads2
[] = {
7860 MockRead("HTTP/1.1 200 OK\r\n"),
7861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7862 MockRead("Content-Length: 100\r\n\r\n"),
7863 MockRead(SYNCHRONOUS
, OK
),
7866 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
7867 data_writes2
, arraysize(data_writes2
));
7868 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
7869 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7871 TestCompletionCallback callback1
;
7873 scoped_ptr
<HttpTransaction
> trans(
7874 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7876 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
7877 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7879 rv
= callback1
.WaitForResult();
7882 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7883 ASSERT_TRUE(response
!= NULL
);
7884 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
7886 TestCompletionCallback callback2
;
7888 rv
= trans
->RestartWithAuth(
7889 AuthCredentials(kFoo
, kBar
), callback2
.callback());
7890 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7892 rv
= callback2
.WaitForResult();
7895 response
= trans
->GetResponseInfo();
7896 ASSERT_TRUE(response
!= NULL
);
7897 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
7898 EXPECT_EQ(100, response
->headers
->GetContentLength());
7901 // Test HTTPS connections going through a proxy that sends extra data.
7902 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
7903 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7905 HttpRequestInfo request
;
7906 request
.method
= "GET";
7907 request
.url
= GURL("https://www.google.com/");
7908 request
.load_flags
= 0;
7910 MockRead proxy_reads
[] = {
7911 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
7912 MockRead(SYNCHRONOUS
, OK
)
7915 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
7916 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7918 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7919 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7921 TestCompletionCallback callback
;
7923 session_deps_
.socket_factory
->ResetNextMockIndexes();
7925 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7926 scoped_ptr
<HttpTransaction
> trans(
7927 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7929 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7930 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7932 rv
= callback
.WaitForResult();
7933 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
7936 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
7937 HttpRequestInfo request
;
7938 request
.method
= "GET";
7939 request
.url
= GURL("http://www.google.com/");
7940 request
.load_flags
= 0;
7942 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7943 scoped_ptr
<HttpTransaction
> trans(
7944 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7946 MockRead data_reads
[] = {
7947 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
7948 MockRead(SYNCHRONOUS
, OK
),
7951 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
7952 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7954 TestCompletionCallback callback
;
7956 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7957 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7959 EXPECT_EQ(OK
, callback
.WaitForResult());
7961 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7962 ASSERT_TRUE(response
!= NULL
);
7964 EXPECT_TRUE(response
->headers
.get() != NULL
);
7965 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
7967 std::string response_data
;
7968 rv
= ReadTransaction(trans
.get(), &response_data
);
7969 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
7972 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
7973 base::FilePath temp_file_path
;
7974 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
7975 const uint64 kFakeSize
= 100000; // file is actually blank
7976 UploadFileElementReader::ScopedOverridingContentLengthForTests
7977 overriding_content_length(kFakeSize
);
7979 ScopedVector
<UploadElementReader
> element_readers
;
7980 element_readers
.push_back(
7981 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
7986 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
7988 HttpRequestInfo request
;
7989 request
.method
= "POST";
7990 request
.url
= GURL("http://www.google.com/upload");
7991 request
.upload_data_stream
= &upload_data_stream
;
7992 request
.load_flags
= 0;
7994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7995 scoped_ptr
<HttpTransaction
> trans(
7996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
7998 MockRead data_reads
[] = {
7999 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8000 MockRead("hello world"),
8001 MockRead(SYNCHRONOUS
, OK
),
8003 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8004 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8006 TestCompletionCallback callback
;
8008 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8009 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8011 rv
= callback
.WaitForResult();
8014 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8015 ASSERT_TRUE(response
!= NULL
);
8017 EXPECT_TRUE(response
->headers
.get() != NULL
);
8018 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8020 std::string response_data
;
8021 rv
= ReadTransaction(trans
.get(), &response_data
);
8023 EXPECT_EQ("hello world", response_data
);
8025 base::DeleteFile(temp_file_path
, false);
8028 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8029 base::FilePath temp_file
;
8030 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8031 std::string
temp_file_content("Unreadable file.");
8032 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8033 temp_file_content
.length()));
8034 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file
));
8036 ScopedVector
<UploadElementReader
> element_readers
;
8037 element_readers
.push_back(
8038 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8043 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8045 HttpRequestInfo request
;
8046 request
.method
= "POST";
8047 request
.url
= GURL("http://www.google.com/upload");
8048 request
.upload_data_stream
= &upload_data_stream
;
8049 request
.load_flags
= 0;
8051 // If we try to upload an unreadable file, the transaction should fail.
8052 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8053 scoped_ptr
<HttpTransaction
> trans(
8054 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8056 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8057 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8059 TestCompletionCallback callback
;
8061 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8062 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8064 rv
= callback
.WaitForResult();
8065 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8067 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8068 EXPECT_FALSE(response
);
8070 base::DeleteFile(temp_file
, false);
8073 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8074 class FakeUploadElementReader
: public UploadElementReader
{
8076 FakeUploadElementReader() {}
8077 virtual ~FakeUploadElementReader() {}
8079 const CompletionCallback
& callback() const { return callback_
; }
8081 // UploadElementReader overrides:
8082 virtual int Init(const CompletionCallback
& callback
) OVERRIDE
{
8083 callback_
= callback
;
8084 return ERR_IO_PENDING
;
8086 virtual uint64
GetContentLength() const OVERRIDE
{ return 0; }
8087 virtual uint64
BytesRemaining() const OVERRIDE
{ return 0; }
8088 virtual int Read(IOBuffer
* buf
,
8090 const CompletionCallback
& callback
) OVERRIDE
{
8095 CompletionCallback callback_
;
8098 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8099 ScopedVector
<UploadElementReader
> element_readers
;
8100 element_readers
.push_back(fake_reader
);
8101 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8103 HttpRequestInfo request
;
8104 request
.method
= "POST";
8105 request
.url
= GURL("http://www.google.com/upload");
8106 request
.upload_data_stream
= &upload_data_stream
;
8107 request
.load_flags
= 0;
8109 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8110 scoped_ptr
<HttpTransaction
> trans(
8111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8113 StaticSocketDataProvider data
;
8114 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8116 TestCompletionCallback callback
;
8117 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8118 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8119 base::MessageLoop::current()->RunUntilIdle();
8121 // Transaction is pending on request body initialization.
8122 ASSERT_FALSE(fake_reader
->callback().is_null());
8124 // Return Init()'s result after the transaction gets destroyed.
8126 fake_reader
->callback().Run(OK
); // Should not crash.
8129 // Tests that changes to Auth realms are treated like auth rejections.
8130 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8132 HttpRequestInfo request
;
8133 request
.method
= "GET";
8134 request
.url
= GURL("http://www.google.com/");
8135 request
.load_flags
= 0;
8137 // First transaction will request a resource and receive a Basic challenge
8138 // with realm="first_realm".
8139 MockWrite data_writes1
[] = {
8140 MockWrite("GET / HTTP/1.1\r\n"
8141 "Host: www.google.com\r\n"
8142 "Connection: keep-alive\r\n"
8145 MockRead data_reads1
[] = {
8146 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8147 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8151 // After calling trans->RestartWithAuth(), provide an Authentication header
8152 // for first_realm. The server will reject and provide a challenge with
8154 MockWrite data_writes2
[] = {
8155 MockWrite("GET / HTTP/1.1\r\n"
8156 "Host: www.google.com\r\n"
8157 "Connection: keep-alive\r\n"
8158 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8161 MockRead data_reads2
[] = {
8162 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8163 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8167 // This again fails, and goes back to first_realm. Make sure that the
8168 // entry is removed from cache.
8169 MockWrite data_writes3
[] = {
8170 MockWrite("GET / HTTP/1.1\r\n"
8171 "Host: www.google.com\r\n"
8172 "Connection: keep-alive\r\n"
8173 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8176 MockRead data_reads3
[] = {
8177 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8178 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8182 // Try one last time (with the correct password) and get the resource.
8183 MockWrite data_writes4
[] = {
8184 MockWrite("GET / HTTP/1.1\r\n"
8185 "Host: www.google.com\r\n"
8186 "Connection: keep-alive\r\n"
8187 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8190 MockRead data_reads4
[] = {
8191 MockRead("HTTP/1.1 200 OK\r\n"
8192 "Content-Type: text/html; charset=iso-8859-1\r\n"
8193 "Content-Length: 5\r\n"
8198 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8199 data_writes1
, arraysize(data_writes1
));
8200 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8201 data_writes2
, arraysize(data_writes2
));
8202 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8203 data_writes3
, arraysize(data_writes3
));
8204 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8205 data_writes4
, arraysize(data_writes4
));
8206 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8207 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8208 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8209 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8211 TestCompletionCallback callback1
;
8213 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8214 scoped_ptr
<HttpTransaction
> trans(
8215 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
8217 // Issue the first request with Authorize headers. There should be a
8218 // password prompt for first_realm waiting to be filled in after the
8219 // transaction completes.
8220 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8221 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8222 rv
= callback1
.WaitForResult();
8224 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8225 ASSERT_TRUE(response
!= NULL
);
8226 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8227 ASSERT_FALSE(challenge
== NULL
);
8228 EXPECT_FALSE(challenge
->is_proxy
);
8229 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8230 EXPECT_EQ("first_realm", challenge
->realm
);
8231 EXPECT_EQ("basic", challenge
->scheme
);
8233 // Issue the second request with an incorrect password. There should be a
8234 // password prompt for second_realm waiting to be filled in after the
8235 // transaction completes.
8236 TestCompletionCallback callback2
;
8237 rv
= trans
->RestartWithAuth(
8238 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8239 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8240 rv
= callback2
.WaitForResult();
8242 response
= trans
->GetResponseInfo();
8243 ASSERT_TRUE(response
!= NULL
);
8244 challenge
= response
->auth_challenge
.get();
8245 ASSERT_FALSE(challenge
== NULL
);
8246 EXPECT_FALSE(challenge
->is_proxy
);
8247 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8248 EXPECT_EQ("second_realm", challenge
->realm
);
8249 EXPECT_EQ("basic", challenge
->scheme
);
8251 // Issue the third request with another incorrect password. There should be
8252 // a password prompt for first_realm waiting to be filled in. If the password
8253 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8254 // first_realm was not correctly removed.
8255 TestCompletionCallback callback3
;
8256 rv
= trans
->RestartWithAuth(
8257 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8258 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8259 rv
= callback3
.WaitForResult();
8261 response
= trans
->GetResponseInfo();
8262 ASSERT_TRUE(response
!= NULL
);
8263 challenge
= response
->auth_challenge
.get();
8264 ASSERT_FALSE(challenge
== NULL
);
8265 EXPECT_FALSE(challenge
->is_proxy
);
8266 EXPECT_EQ("www.google.com:80", challenge
->challenger
.ToString());
8267 EXPECT_EQ("first_realm", challenge
->realm
);
8268 EXPECT_EQ("basic", challenge
->scheme
);
8270 // Issue the fourth request with the correct password and username.
8271 TestCompletionCallback callback4
;
8272 rv
= trans
->RestartWithAuth(
8273 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8275 rv
= callback4
.WaitForResult();
8277 response
= trans
->GetResponseInfo();
8278 ASSERT_TRUE(response
!= NULL
);
8279 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8282 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8283 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8284 HttpStreamFactory::set_use_alternate_protocols(true);
8286 std::string alternate_protocol_http_header
=
8287 GetAlternateProtocolHttpHeader();
8289 MockRead data_reads
[] = {
8290 MockRead("HTTP/1.1 200 OK\r\n"),
8291 MockRead(alternate_protocol_http_header
.c_str()),
8292 MockRead("hello world"),
8293 MockRead(SYNCHRONOUS
, OK
),
8296 HttpRequestInfo request
;
8297 request
.method
= "GET";
8298 request
.url
= GURL("http://www.google.com/");
8299 request
.load_flags
= 0;
8301 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8303 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8305 TestCompletionCallback callback
;
8307 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8308 scoped_ptr
<HttpTransaction
> trans(
8309 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8311 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8312 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8314 HostPortPair
http_host_port_pair("www.google.com", 80);
8315 HttpServerProperties
& http_server_properties
=
8316 *session
->http_server_properties();
8318 http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8320 EXPECT_EQ(OK
, callback
.WaitForResult());
8322 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8323 ASSERT_TRUE(response
!= NULL
);
8324 ASSERT_TRUE(response
->headers
.get() != NULL
);
8325 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8326 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8327 EXPECT_FALSE(response
->was_npn_negotiated
);
8329 std::string response_data
;
8330 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8331 EXPECT_EQ("hello world", response_data
);
8333 ASSERT_TRUE(http_server_properties
.HasAlternateProtocol(http_host_port_pair
));
8334 const PortAlternateProtocolPair alternate
=
8335 http_server_properties
.GetAlternateProtocol(http_host_port_pair
);
8336 PortAlternateProtocolPair expected_alternate
;
8337 expected_alternate
.port
= 443;
8338 expected_alternate
.protocol
= AlternateProtocolFromNextProto(GetParam());
8339 EXPECT_TRUE(expected_alternate
.Equals(alternate
));
8342 TEST_P(HttpNetworkTransactionTest
,
8343 MarkBrokenAlternateProtocolAndFallback
) {
8344 HttpStreamFactory::set_use_alternate_protocols(true);
8346 HttpRequestInfo request
;
8347 request
.method
= "GET";
8348 request
.url
= GURL("http://www.google.com/");
8349 request
.load_flags
= 0;
8351 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8352 StaticSocketDataProvider first_data
;
8353 first_data
.set_connect_data(mock_connect
);
8354 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8356 MockRead data_reads
[] = {
8357 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8358 MockRead("hello world"),
8359 MockRead(ASYNC
, OK
),
8361 StaticSocketDataProvider
second_data(
8362 data_reads
, arraysize(data_reads
), NULL
, 0);
8363 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8365 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8367 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8368 session
->http_server_properties();
8369 // Port must be < 1024, or the header will be ignored (since initial port was
8370 // port 80 (another restricted port).
8371 http_server_properties
->SetAlternateProtocol(
8372 HostPortPair::FromURL(request
.url
),
8373 666 /* port is ignored by MockConnect anyway */,
8374 AlternateProtocolFromNextProto(GetParam()));
8376 scoped_ptr
<HttpTransaction
> trans(
8377 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8378 TestCompletionCallback callback
;
8380 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8381 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8382 EXPECT_EQ(OK
, callback
.WaitForResult());
8384 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8385 ASSERT_TRUE(response
!= NULL
);
8386 ASSERT_TRUE(response
->headers
.get() != NULL
);
8387 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8389 std::string response_data
;
8390 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8391 EXPECT_EQ("hello world", response_data
);
8393 ASSERT_TRUE(http_server_properties
->HasAlternateProtocol(
8394 HostPortPair::FromURL(request
.url
)));
8395 const PortAlternateProtocolPair alternate
=
8396 http_server_properties
->GetAlternateProtocol(
8397 HostPortPair::FromURL(request
.url
));
8398 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN
, alternate
.protocol
);
8401 TEST_P(HttpNetworkTransactionTest
,
8402 AlternateProtocolPortRestrictedBlocked
) {
8403 // Ensure that we're not allowed to redirect traffic via an alternate
8404 // protocol to an unrestricted (port >= 1024) when the original traffic was
8405 // on a restricted port (port < 1024). Ensure that we can redirect in all
8407 HttpStreamFactory::set_use_alternate_protocols(true);
8409 HttpRequestInfo restricted_port_request
;
8410 restricted_port_request
.method
= "GET";
8411 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8412 restricted_port_request
.load_flags
= 0;
8414 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8415 StaticSocketDataProvider first_data
;
8416 first_data
.set_connect_data(mock_connect
);
8417 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8419 MockRead data_reads
[] = {
8420 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8421 MockRead("hello world"),
8422 MockRead(ASYNC
, OK
),
8424 StaticSocketDataProvider
second_data(
8425 data_reads
, arraysize(data_reads
), NULL
, 0);
8426 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8428 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8430 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8431 session
->http_server_properties();
8432 const int kUnrestrictedAlternatePort
= 1024;
8433 http_server_properties
->SetAlternateProtocol(
8434 HostPortPair::FromURL(restricted_port_request
.url
),
8435 kUnrestrictedAlternatePort
,
8436 AlternateProtocolFromNextProto(GetParam()));
8438 scoped_ptr
<HttpTransaction
> trans(
8439 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8440 TestCompletionCallback callback
;
8442 int rv
= trans
->Start(
8443 &restricted_port_request
,
8444 callback
.callback(), BoundNetLog());
8445 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8446 // Invalid change to unrestricted port should fail.
8447 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8450 TEST_P(HttpNetworkTransactionTest
,
8451 AlternateProtocolPortRestrictedPermitted
) {
8452 // Ensure that we're allowed to redirect traffic via an alternate
8453 // protocol to an unrestricted (port >= 1024) when the original traffic was
8454 // on a restricted port (port < 1024) if we set
8455 // enable_user_alternate_protocol_ports.
8457 HttpStreamFactory::set_use_alternate_protocols(true);
8458 session_deps_
.enable_user_alternate_protocol_ports
= true;
8460 HttpRequestInfo restricted_port_request
;
8461 restricted_port_request
.method
= "GET";
8462 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8463 restricted_port_request
.load_flags
= 0;
8465 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8466 StaticSocketDataProvider first_data
;
8467 first_data
.set_connect_data(mock_connect
);
8468 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8470 MockRead data_reads
[] = {
8471 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8472 MockRead("hello world"),
8473 MockRead(ASYNC
, OK
),
8475 StaticSocketDataProvider
second_data(
8476 data_reads
, arraysize(data_reads
), NULL
, 0);
8477 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8479 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8481 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8482 session
->http_server_properties();
8483 const int kUnrestrictedAlternatePort
= 1024;
8484 http_server_properties
->SetAlternateProtocol(
8485 HostPortPair::FromURL(restricted_port_request
.url
),
8486 kUnrestrictedAlternatePort
,
8487 AlternateProtocolFromNextProto(GetParam()));
8489 scoped_ptr
<HttpTransaction
> trans(
8490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8491 TestCompletionCallback callback
;
8493 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8494 &restricted_port_request
,
8495 callback
.callback(), BoundNetLog()));
8496 // Change to unrestricted port should succeed.
8497 EXPECT_EQ(OK
, callback
.WaitForResult());
8500 TEST_P(HttpNetworkTransactionTest
,
8501 AlternateProtocolPortRestrictedAllowed
) {
8502 // Ensure that we're not allowed to redirect traffic via an alternate
8503 // protocol to an unrestricted (port >= 1024) when the original traffic was
8504 // on a restricted port (port < 1024). Ensure that we can redirect in all
8506 HttpStreamFactory::set_use_alternate_protocols(true);
8508 HttpRequestInfo restricted_port_request
;
8509 restricted_port_request
.method
= "GET";
8510 restricted_port_request
.url
= GURL("http://www.google.com:1023/");
8511 restricted_port_request
.load_flags
= 0;
8513 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8514 StaticSocketDataProvider first_data
;
8515 first_data
.set_connect_data(mock_connect
);
8516 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8518 MockRead data_reads
[] = {
8519 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8520 MockRead("hello world"),
8521 MockRead(ASYNC
, OK
),
8523 StaticSocketDataProvider
second_data(
8524 data_reads
, arraysize(data_reads
), NULL
, 0);
8525 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8527 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8529 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8530 session
->http_server_properties();
8531 const int kRestrictedAlternatePort
= 80;
8532 http_server_properties
->SetAlternateProtocol(
8533 HostPortPair::FromURL(restricted_port_request
.url
),
8534 kRestrictedAlternatePort
,
8535 AlternateProtocolFromNextProto(GetParam()));
8537 scoped_ptr
<HttpTransaction
> trans(
8538 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8539 TestCompletionCallback callback
;
8541 int rv
= trans
->Start(
8542 &restricted_port_request
,
8543 callback
.callback(), BoundNetLog());
8544 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8545 // Valid change to restricted port should pass.
8546 EXPECT_EQ(OK
, callback
.WaitForResult());
8549 TEST_P(HttpNetworkTransactionTest
,
8550 AlternateProtocolPortUnrestrictedAllowed1
) {
8551 // Ensure that we're not allowed to redirect traffic via an alternate
8552 // protocol to an unrestricted (port >= 1024) when the original traffic was
8553 // on a restricted port (port < 1024). Ensure that we can redirect in all
8555 HttpStreamFactory::set_use_alternate_protocols(true);
8557 HttpRequestInfo unrestricted_port_request
;
8558 unrestricted_port_request
.method
= "GET";
8559 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8560 unrestricted_port_request
.load_flags
= 0;
8562 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8563 StaticSocketDataProvider first_data
;
8564 first_data
.set_connect_data(mock_connect
);
8565 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8567 MockRead data_reads
[] = {
8568 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8569 MockRead("hello world"),
8570 MockRead(ASYNC
, OK
),
8572 StaticSocketDataProvider
second_data(
8573 data_reads
, arraysize(data_reads
), NULL
, 0);
8574 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8576 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8578 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8579 session
->http_server_properties();
8580 const int kRestrictedAlternatePort
= 80;
8581 http_server_properties
->SetAlternateProtocol(
8582 HostPortPair::FromURL(unrestricted_port_request
.url
),
8583 kRestrictedAlternatePort
,
8584 AlternateProtocolFromNextProto(GetParam()));
8586 scoped_ptr
<HttpTransaction
> trans(
8587 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8588 TestCompletionCallback callback
;
8590 int rv
= trans
->Start(
8591 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8592 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8593 // Valid change to restricted port should pass.
8594 EXPECT_EQ(OK
, callback
.WaitForResult());
8597 TEST_P(HttpNetworkTransactionTest
,
8598 AlternateProtocolPortUnrestrictedAllowed2
) {
8599 // Ensure that we're not allowed to redirect traffic via an alternate
8600 // protocol to an unrestricted (port >= 1024) when the original traffic was
8601 // on a restricted port (port < 1024). Ensure that we can redirect in all
8603 HttpStreamFactory::set_use_alternate_protocols(true);
8605 HttpRequestInfo unrestricted_port_request
;
8606 unrestricted_port_request
.method
= "GET";
8607 unrestricted_port_request
.url
= GURL("http://www.google.com:1024/");
8608 unrestricted_port_request
.load_flags
= 0;
8610 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8611 StaticSocketDataProvider first_data
;
8612 first_data
.set_connect_data(mock_connect
);
8613 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8615 MockRead data_reads
[] = {
8616 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8617 MockRead("hello world"),
8618 MockRead(ASYNC
, OK
),
8620 StaticSocketDataProvider
second_data(
8621 data_reads
, arraysize(data_reads
), NULL
, 0);
8622 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8624 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8626 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8627 session
->http_server_properties();
8628 const int kUnrestrictedAlternatePort
= 1024;
8629 http_server_properties
->SetAlternateProtocol(
8630 HostPortPair::FromURL(unrestricted_port_request
.url
),
8631 kUnrestrictedAlternatePort
,
8632 AlternateProtocolFromNextProto(GetParam()));
8634 scoped_ptr
<HttpTransaction
> trans(
8635 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8636 TestCompletionCallback callback
;
8638 int rv
= trans
->Start(
8639 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
8640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8641 // Valid change to an unrestricted port should pass.
8642 EXPECT_EQ(OK
, callback
.WaitForResult());
8645 TEST_P(HttpNetworkTransactionTest
,
8646 AlternateProtocolUnsafeBlocked
) {
8647 // Ensure that we're not allowed to redirect traffic via an alternate
8648 // protocol to an unsafe port, and that we resume the second
8649 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
8650 HttpStreamFactory::set_use_alternate_protocols(true);
8652 HttpRequestInfo request
;
8653 request
.method
= "GET";
8654 request
.url
= GURL("http://www.google.com/");
8655 request
.load_flags
= 0;
8657 // The alternate protocol request will error out before we attempt to connect,
8658 // so only the standard HTTP request will try to connect.
8659 MockRead data_reads
[] = {
8660 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8661 MockRead("hello world"),
8662 MockRead(ASYNC
, OK
),
8664 StaticSocketDataProvider
data(
8665 data_reads
, arraysize(data_reads
), NULL
, 0);
8666 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8668 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8670 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8671 session
->http_server_properties();
8672 const int kUnsafePort
= 7;
8673 http_server_properties
->SetAlternateProtocol(
8674 HostPortPair::FromURL(request
.url
),
8676 AlternateProtocolFromNextProto(GetParam()));
8678 scoped_ptr
<HttpTransaction
> trans(
8679 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8680 TestCompletionCallback callback
;
8682 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8683 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8684 // The HTTP request should succeed.
8685 EXPECT_EQ(OK
, callback
.WaitForResult());
8687 // Disable alternate protocol before the asserts.
8688 HttpStreamFactory::set_use_alternate_protocols(false);
8690 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8691 ASSERT_TRUE(response
!= NULL
);
8692 ASSERT_TRUE(response
->headers
.get() != NULL
);
8693 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8695 std::string response_data
;
8696 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8697 EXPECT_EQ("hello world", response_data
);
8700 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
8701 HttpStreamFactory::set_use_alternate_protocols(true);
8702 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8704 HttpRequestInfo request
;
8705 request
.method
= "GET";
8706 request
.url
= GURL("http://www.google.com/");
8707 request
.load_flags
= 0;
8709 std::string alternate_protocol_http_header
=
8710 GetAlternateProtocolHttpHeader();
8712 MockRead data_reads
[] = {
8713 MockRead("HTTP/1.1 200 OK\r\n"),
8714 MockRead(alternate_protocol_http_header
.c_str()),
8715 MockRead("hello world"),
8716 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8720 StaticSocketDataProvider
first_transaction(
8721 data_reads
, arraysize(data_reads
), NULL
, 0);
8722 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8724 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8725 ssl
.SetNextProto(GetParam());
8726 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8728 scoped_ptr
<SpdyFrame
> req(
8729 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8730 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
8732 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8733 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8734 MockRead spdy_reads
[] = {
8735 CreateMockRead(*resp
),
8736 CreateMockRead(*data
),
8737 MockRead(ASYNC
, 0, 0),
8740 DelayedSocketData
spdy_data(
8741 1, // wait for one write to finish before reading.
8742 spdy_reads
, arraysize(spdy_reads
),
8743 spdy_writes
, arraysize(spdy_writes
));
8744 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8746 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8747 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
8749 hanging_non_alternate_protocol_socket
.set_connect_data(
8750 never_finishing_connect
);
8751 session_deps_
.socket_factory
->AddSocketDataProvider(
8752 &hanging_non_alternate_protocol_socket
);
8754 TestCompletionCallback callback
;
8756 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8757 scoped_ptr
<HttpTransaction
> trans(
8758 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8760 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8761 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8762 EXPECT_EQ(OK
, callback
.WaitForResult());
8764 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8765 ASSERT_TRUE(response
!= NULL
);
8766 ASSERT_TRUE(response
->headers
.get() != NULL
);
8767 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8769 std::string response_data
;
8770 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8771 EXPECT_EQ("hello world", response_data
);
8773 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8775 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8777 EXPECT_EQ(OK
, callback
.WaitForResult());
8779 response
= trans
->GetResponseInfo();
8780 ASSERT_TRUE(response
!= NULL
);
8781 ASSERT_TRUE(response
->headers
.get() != NULL
);
8782 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8783 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8784 EXPECT_TRUE(response
->was_npn_negotiated
);
8786 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8787 EXPECT_EQ("hello!", response_data
);
8790 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
8791 HttpStreamFactory::set_use_alternate_protocols(true);
8792 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8794 HttpRequestInfo request
;
8795 request
.method
= "GET";
8796 request
.url
= GURL("http://www.google.com/");
8797 request
.load_flags
= 0;
8799 std::string alternate_protocol_http_header
=
8800 GetAlternateProtocolHttpHeader();
8802 MockRead data_reads
[] = {
8803 MockRead("HTTP/1.1 200 OK\r\n"),
8804 MockRead(alternate_protocol_http_header
.c_str()),
8805 MockRead("hello world"),
8806 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8807 MockRead(ASYNC
, OK
),
8810 StaticSocketDataProvider
first_transaction(
8811 data_reads
, arraysize(data_reads
), NULL
, 0);
8812 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
8813 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8815 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8816 StaticSocketDataProvider
hanging_socket(
8818 hanging_socket
.set_connect_data(never_finishing_connect
);
8819 // Socket 2 and 3 are the hanging Alternate-Protocol and
8820 // non-Alternate-Protocol jobs from the 2nd transaction.
8821 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8822 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8824 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8825 ssl
.SetNextProto(GetParam());
8826 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8828 scoped_ptr
<SpdyFrame
> req1(
8829 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
8830 scoped_ptr
<SpdyFrame
> req2(
8831 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
8832 MockWrite spdy_writes
[] = {
8833 CreateMockWrite(*req1
),
8834 CreateMockWrite(*req2
),
8836 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
8837 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
8838 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
8839 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
8840 MockRead spdy_reads
[] = {
8841 CreateMockRead(*resp1
),
8842 CreateMockRead(*data1
),
8843 CreateMockRead(*resp2
),
8844 CreateMockRead(*data2
),
8845 MockRead(ASYNC
, 0, 0),
8848 DelayedSocketData
spdy_data(
8849 2, // wait for writes to finish before reading.
8850 spdy_reads
, arraysize(spdy_reads
),
8851 spdy_writes
, arraysize(spdy_writes
));
8852 // Socket 4 is the successful Alternate-Protocol for transaction 3.
8853 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
8855 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
8856 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
8858 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8859 TestCompletionCallback callback1
;
8860 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
8862 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
8863 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8864 EXPECT_EQ(OK
, callback1
.WaitForResult());
8866 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
8867 ASSERT_TRUE(response
!= NULL
);
8868 ASSERT_TRUE(response
->headers
.get() != NULL
);
8869 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8871 std::string response_data
;
8872 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
8873 EXPECT_EQ("hello world", response_data
);
8875 TestCompletionCallback callback2
;
8876 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
8877 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8880 TestCompletionCallback callback3
;
8881 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
8882 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
8883 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8885 EXPECT_EQ(OK
, callback2
.WaitForResult());
8886 EXPECT_EQ(OK
, callback3
.WaitForResult());
8888 response
= trans2
.GetResponseInfo();
8889 ASSERT_TRUE(response
!= NULL
);
8890 ASSERT_TRUE(response
->headers
.get() != NULL
);
8891 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8892 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8893 EXPECT_TRUE(response
->was_npn_negotiated
);
8894 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
8895 EXPECT_EQ("hello!", response_data
);
8897 response
= trans3
.GetResponseInfo();
8898 ASSERT_TRUE(response
!= NULL
);
8899 ASSERT_TRUE(response
->headers
.get() != NULL
);
8900 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8901 EXPECT_TRUE(response
->was_fetched_via_spdy
);
8902 EXPECT_TRUE(response
->was_npn_negotiated
);
8903 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
8904 EXPECT_EQ("hello!", response_data
);
8907 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
8908 HttpStreamFactory::set_use_alternate_protocols(true);
8909 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
8911 HttpRequestInfo request
;
8912 request
.method
= "GET";
8913 request
.url
= GURL("http://www.google.com/");
8914 request
.load_flags
= 0;
8916 std::string alternate_protocol_http_header
=
8917 GetAlternateProtocolHttpHeader();
8919 MockRead data_reads
[] = {
8920 MockRead("HTTP/1.1 200 OK\r\n"),
8921 MockRead(alternate_protocol_http_header
.c_str()),
8922 MockRead("hello world"),
8923 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
8924 MockRead(ASYNC
, OK
),
8927 StaticSocketDataProvider
first_transaction(
8928 data_reads
, arraysize(data_reads
), NULL
, 0);
8929 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8931 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8932 ssl
.SetNextProto(GetParam());
8933 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8935 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
8936 StaticSocketDataProvider
hanging_alternate_protocol_socket(
8938 hanging_alternate_protocol_socket
.set_connect_data(
8939 never_finishing_connect
);
8940 session_deps_
.socket_factory
->AddSocketDataProvider(
8941 &hanging_alternate_protocol_socket
);
8943 // 2nd request is just a copy of the first one, over HTTP again.
8944 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
8946 TestCompletionCallback callback
;
8948 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8949 scoped_ptr
<HttpTransaction
> trans(
8950 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8952 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8953 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8954 EXPECT_EQ(OK
, callback
.WaitForResult());
8956 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8957 ASSERT_TRUE(response
!= NULL
);
8958 ASSERT_TRUE(response
->headers
.get() != NULL
);
8959 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8961 std::string response_data
;
8962 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8963 EXPECT_EQ("hello world", response_data
);
8965 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8967 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8968 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8969 EXPECT_EQ(OK
, callback
.WaitForResult());
8971 response
= trans
->GetResponseInfo();
8972 ASSERT_TRUE(response
!= NULL
);
8973 ASSERT_TRUE(response
->headers
.get() != NULL
);
8974 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8975 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8976 EXPECT_FALSE(response
->was_npn_negotiated
);
8978 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8979 EXPECT_EQ("hello world", response_data
);
8982 class CapturingProxyResolver
: public ProxyResolver
{
8984 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
8985 virtual ~CapturingProxyResolver() {}
8987 virtual int GetProxyForURL(const GURL
& url
,
8989 const CompletionCallback
& callback
,
8990 RequestHandle
* request
,
8991 const BoundNetLog
& net_log
) OVERRIDE
{
8992 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
8993 HostPortPair("myproxy", 80));
8994 results
->UseProxyServer(proxy_server
);
8995 resolved_
.push_back(url
);
8999 virtual void CancelRequest(RequestHandle request
) OVERRIDE
{
9003 virtual LoadState
GetLoadState(RequestHandle request
) const OVERRIDE
{
9005 return LOAD_STATE_IDLE
;
9008 virtual void CancelSetPacScript() OVERRIDE
{
9012 virtual int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9013 const CompletionCallback
& /*callback*/) OVERRIDE
{
9017 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9020 std::vector
<GURL
> resolved_
;
9022 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9025 TEST_P(HttpNetworkTransactionTest
,
9026 UseAlternateProtocolForTunneledNpnSpdy
) {
9027 HttpStreamFactory::set_use_alternate_protocols(true);
9028 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9030 ProxyConfig proxy_config
;
9031 proxy_config
.set_auto_detect(true);
9032 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9034 CapturingProxyResolver
* capturing_proxy_resolver
=
9035 new CapturingProxyResolver();
9036 session_deps_
.proxy_service
.reset(new ProxyService(
9037 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
9039 CapturingNetLog net_log
;
9040 session_deps_
.net_log
= &net_log
;
9042 HttpRequestInfo request
;
9043 request
.method
= "GET";
9044 request
.url
= GURL("http://www.google.com/");
9045 request
.load_flags
= 0;
9047 std::string alternate_protocol_http_header
=
9048 GetAlternateProtocolHttpHeader();
9050 MockRead data_reads
[] = {
9051 MockRead("HTTP/1.1 200 OK\r\n"),
9052 MockRead(alternate_protocol_http_header
.c_str()),
9053 MockRead("hello world"),
9054 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9055 MockRead(ASYNC
, OK
),
9058 StaticSocketDataProvider
first_transaction(
9059 data_reads
, arraysize(data_reads
), NULL
, 0);
9060 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9062 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9063 ssl
.SetNextProto(GetParam());
9064 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9066 scoped_ptr
<SpdyFrame
> req(
9067 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9068 MockWrite spdy_writes
[] = {
9069 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
9070 "Host: www.google.com\r\n"
9071 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9072 CreateMockWrite(*req
), // 3
9075 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9077 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9078 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9079 MockRead spdy_reads
[] = {
9080 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9081 CreateMockRead(*resp
.get(), 4), // 2, 4
9082 CreateMockRead(*data
.get(), 4), // 5
9083 MockRead(ASYNC
, 0, 0, 4), // 6
9086 OrderedSocketData
spdy_data(
9087 spdy_reads
, arraysize(spdy_reads
),
9088 spdy_writes
, arraysize(spdy_writes
));
9089 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9091 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9092 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9094 hanging_non_alternate_protocol_socket
.set_connect_data(
9095 never_finishing_connect
);
9096 session_deps_
.socket_factory
->AddSocketDataProvider(
9097 &hanging_non_alternate_protocol_socket
);
9099 TestCompletionCallback callback
;
9101 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9102 scoped_ptr
<HttpTransaction
> trans(
9103 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9105 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9107 EXPECT_EQ(OK
, callback
.WaitForResult());
9109 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9110 ASSERT_TRUE(response
!= NULL
);
9111 ASSERT_TRUE(response
->headers
.get() != NULL
);
9112 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9113 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9114 EXPECT_FALSE(response
->was_npn_negotiated
);
9116 std::string response_data
;
9117 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9118 EXPECT_EQ("hello world", response_data
);
9120 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9122 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9124 EXPECT_EQ(OK
, callback
.WaitForResult());
9126 response
= trans
->GetResponseInfo();
9127 ASSERT_TRUE(response
!= NULL
);
9128 ASSERT_TRUE(response
->headers
.get() != NULL
);
9129 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9130 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9131 EXPECT_TRUE(response
->was_npn_negotiated
);
9133 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9134 EXPECT_EQ("hello!", response_data
);
9135 ASSERT_EQ(3u, capturing_proxy_resolver
->resolved().size());
9136 EXPECT_EQ("http://www.google.com/",
9137 capturing_proxy_resolver
->resolved()[0].spec());
9138 EXPECT_EQ("https://www.google.com/",
9139 capturing_proxy_resolver
->resolved()[1].spec());
9141 LoadTimingInfo load_timing_info
;
9142 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9143 TestLoadTimingNotReusedWithPac(load_timing_info
,
9144 CONNECT_TIMING_HAS_SSL_TIMES
);
9147 TEST_P(HttpNetworkTransactionTest
,
9148 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9149 HttpStreamFactory::set_use_alternate_protocols(true);
9150 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9152 HttpRequestInfo request
;
9153 request
.method
= "GET";
9154 request
.url
= GURL("http://www.google.com/");
9155 request
.load_flags
= 0;
9157 std::string alternate_protocol_http_header
=
9158 GetAlternateProtocolHttpHeader();
9160 MockRead data_reads
[] = {
9161 MockRead("HTTP/1.1 200 OK\r\n"),
9162 MockRead(alternate_protocol_http_header
.c_str()),
9163 MockRead("hello world"),
9164 MockRead(ASYNC
, OK
),
9167 StaticSocketDataProvider
first_transaction(
9168 data_reads
, arraysize(data_reads
), NULL
, 0);
9169 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9171 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9172 ssl
.SetNextProto(GetParam());
9173 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9175 scoped_ptr
<SpdyFrame
> req(
9176 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9177 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9179 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9180 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9181 MockRead spdy_reads
[] = {
9182 CreateMockRead(*resp
),
9183 CreateMockRead(*data
),
9184 MockRead(ASYNC
, 0, 0),
9187 DelayedSocketData
spdy_data(
9188 1, // wait for one write to finish before reading.
9189 spdy_reads
, arraysize(spdy_reads
),
9190 spdy_writes
, arraysize(spdy_writes
));
9191 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9193 TestCompletionCallback callback
;
9195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9197 scoped_ptr
<HttpTransaction
> trans(
9198 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9200 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9201 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9202 EXPECT_EQ(OK
, callback
.WaitForResult());
9204 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9205 ASSERT_TRUE(response
!= NULL
);
9206 ASSERT_TRUE(response
->headers
.get() != NULL
);
9207 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9209 std::string response_data
;
9210 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9211 EXPECT_EQ("hello world", response_data
);
9213 // Set up an initial SpdySession in the pool to reuse.
9214 HostPortPair
host_port_pair("www.google.com", 443);
9215 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9216 PRIVACY_MODE_DISABLED
);
9217 base::WeakPtr
<SpdySession
> spdy_session
=
9218 CreateSecureSpdySession(session
, key
, BoundNetLog());
9220 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9222 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9223 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9224 EXPECT_EQ(OK
, callback
.WaitForResult());
9226 response
= trans
->GetResponseInfo();
9227 ASSERT_TRUE(response
!= NULL
);
9228 ASSERT_TRUE(response
->headers
.get() != NULL
);
9229 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9230 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9231 EXPECT_TRUE(response
->was_npn_negotiated
);
9233 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9234 EXPECT_EQ("hello!", response_data
);
9237 // GenerateAuthToken is a mighty big test.
9238 // It tests all permutation of GenerateAuthToken behavior:
9239 // - Synchronous and Asynchronous completion.
9240 // - OK or error on completion.
9241 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9242 // - HTTP or HTTPS backend (to include proxy tunneling).
9243 // - Non-authenticating and authenticating backend.
9245 // In all, there are 44 reasonable permuations (for example, if there are
9246 // problems generating an auth token for an authenticating proxy, we don't
9247 // need to test all permutations of the backend server).
9249 // The test proceeds by going over each of the configuration cases, and
9250 // potentially running up to three rounds in each of the tests. The TestConfig
9251 // specifies both the configuration for the test as well as the expectations
9253 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9254 static const char kServer
[] = "http://www.example.com";
9255 static const char kSecureServer
[] = "https://www.example.com";
9256 static const char kProxy
[] = "myproxy:70";
9257 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9265 const MockWrite
kGet(
9266 "GET / HTTP/1.1\r\n"
9267 "Host: www.example.com\r\n"
9268 "Connection: keep-alive\r\n\r\n");
9269 const MockWrite
kGetProxy(
9270 "GET http://www.example.com/ HTTP/1.1\r\n"
9271 "Host: www.example.com\r\n"
9272 "Proxy-Connection: keep-alive\r\n\r\n");
9273 const MockWrite
kGetAuth(
9274 "GET / HTTP/1.1\r\n"
9275 "Host: www.example.com\r\n"
9276 "Connection: keep-alive\r\n"
9277 "Authorization: auth_token\r\n\r\n");
9278 const MockWrite
kGetProxyAuth(
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 "Proxy-Authorization: auth_token\r\n\r\n");
9283 const MockWrite
kGetAuthThroughProxy(
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 "Authorization: auth_token\r\n\r\n");
9288 const MockWrite
kGetAuthWithProxyAuth(
9289 "GET http://www.example.com/ HTTP/1.1\r\n"
9290 "Host: www.example.com\r\n"
9291 "Proxy-Connection: keep-alive\r\n"
9292 "Proxy-Authorization: auth_token\r\n"
9293 "Authorization: auth_token\r\n\r\n");
9294 const MockWrite
kConnect(
9295 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9296 "Host: www.example.com\r\n"
9297 "Proxy-Connection: keep-alive\r\n\r\n");
9298 const MockWrite
kConnectProxyAuth(
9299 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9300 "Host: www.example.com\r\n"
9301 "Proxy-Connection: keep-alive\r\n"
9302 "Proxy-Authorization: auth_token\r\n\r\n");
9304 const MockRead
kSuccess(
9305 "HTTP/1.1 200 OK\r\n"
9306 "Content-Type: text/html; charset=iso-8859-1\r\n"
9307 "Content-Length: 3\r\n\r\n"
9309 const MockRead
kFailure(
9310 "Should not be called.");
9311 const MockRead
kServerChallenge(
9312 "HTTP/1.1 401 Unauthorized\r\n"
9313 "WWW-Authenticate: Mock realm=server\r\n"
9314 "Content-Type: text/html; charset=iso-8859-1\r\n"
9315 "Content-Length: 14\r\n\r\n"
9316 "Unauthorized\r\n");
9317 const MockRead
kProxyChallenge(
9318 "HTTP/1.1 407 Unauthorized\r\n"
9319 "Proxy-Authenticate: Mock realm=proxy\r\n"
9320 "Proxy-Connection: close\r\n"
9321 "Content-Type: text/html; charset=iso-8859-1\r\n"
9322 "Content-Length: 14\r\n\r\n"
9323 "Unauthorized\r\n");
9324 const MockRead
kProxyConnected(
9325 "HTTP/1.1 200 Connection Established\r\n\r\n");
9327 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9328 // no constructors, but the C++ compiler on Windows warns about
9329 // unspecified data in compound literals. So, moved to using constructors,
9330 // and TestRound's created with the default constructor should not be used.
9333 : expected_rv(ERR_UNEXPECTED
),
9337 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9338 int expected_rv_arg
)
9341 expected_rv(expected_rv_arg
),
9345 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9346 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9347 const MockRead
* extra_read_arg
)
9350 expected_rv(expected_rv_arg
),
9351 extra_write(extra_write_arg
),
9352 extra_read(extra_read_arg
) {
9357 const MockWrite
* extra_write
;
9358 const MockRead
* extra_read
;
9361 static const int kNoSSL
= 500;
9364 const char* proxy_url
;
9365 AuthTiming proxy_auth_timing
;
9367 const char* server_url
;
9368 AuthTiming server_auth_timing
;
9370 int num_auth_rounds
;
9371 int first_ssl_round
;
9372 TestRound rounds
[3];
9373 } test_configs
[] = {
9374 // Non-authenticating HTTP server with a direct connection.
9375 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9376 { TestRound(kGet
, kSuccess
, OK
)}},
9377 // Authenticating HTTP server with a direct connection.
9378 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9379 { TestRound(kGet
, kServerChallenge
, OK
),
9380 TestRound(kGetAuth
, kSuccess
, OK
)}},
9381 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9382 { TestRound(kGet
, kServerChallenge
, OK
),
9383 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9384 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9385 { TestRound(kGet
, kServerChallenge
, OK
),
9386 TestRound(kGetAuth
, kSuccess
, OK
)}},
9387 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9388 { TestRound(kGet
, kServerChallenge
, OK
),
9389 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9390 // Non-authenticating HTTP server through a non-authenticating proxy.
9391 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9392 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9393 // Authenticating HTTP server through a non-authenticating proxy.
9394 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9395 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9396 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9397 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9398 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9399 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9400 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9401 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9402 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9403 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9404 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9405 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9406 // Non-authenticating HTTP server through an authenticating proxy.
9407 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9408 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9409 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9410 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9411 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9412 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9413 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9414 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9415 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9416 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9417 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9418 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9419 // Authenticating HTTP server through an authenticating proxy.
9420 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9421 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9422 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9423 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9424 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9425 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9426 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9427 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9428 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9429 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9430 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9431 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9432 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9433 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9434 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9435 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9436 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9437 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9438 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9439 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9440 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9441 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9442 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9443 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9444 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9445 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9446 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9447 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9448 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9449 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9450 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9451 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9452 // Non-authenticating HTTPS server with a direct connection.
9453 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9454 { TestRound(kGet
, kSuccess
, OK
)}},
9455 // Authenticating HTTPS server with a direct connection.
9456 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9457 { TestRound(kGet
, kServerChallenge
, OK
),
9458 TestRound(kGetAuth
, kSuccess
, OK
)}},
9459 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9460 { TestRound(kGet
, kServerChallenge
, OK
),
9461 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9462 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9463 { TestRound(kGet
, kServerChallenge
, OK
),
9464 TestRound(kGetAuth
, kSuccess
, OK
)}},
9465 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9466 { TestRound(kGet
, kServerChallenge
, OK
),
9467 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9468 // Non-authenticating HTTPS server with a non-authenticating proxy.
9469 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9470 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9471 // Authenticating HTTPS server through a non-authenticating proxy.
9472 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9473 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9474 TestRound(kGetAuth
, kSuccess
, OK
)}},
9475 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9476 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9477 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9478 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9479 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9480 TestRound(kGetAuth
, kSuccess
, OK
)}},
9481 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9482 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9483 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9484 // Non-Authenticating HTTPS server through an authenticating proxy.
9485 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9486 { TestRound(kConnect
, kProxyChallenge
, OK
),
9487 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9488 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9489 { TestRound(kConnect
, kProxyChallenge
, OK
),
9490 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9491 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9492 { TestRound(kConnect
, kProxyChallenge
, OK
),
9493 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9494 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9495 { TestRound(kConnect
, kProxyChallenge
, OK
),
9496 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
9497 // Authenticating HTTPS server through an authenticating proxy.
9498 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9499 { TestRound(kConnect
, kProxyChallenge
, OK
),
9500 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9501 &kGet
, &kServerChallenge
),
9502 TestRound(kGetAuth
, kSuccess
, OK
)}},
9503 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9504 { TestRound(kConnect
, kProxyChallenge
, OK
),
9505 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9506 &kGet
, &kServerChallenge
),
9507 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9508 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
9509 { TestRound(kConnect
, kProxyChallenge
, OK
),
9510 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9511 &kGet
, &kServerChallenge
),
9512 TestRound(kGetAuth
, kSuccess
, OK
)}},
9513 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
9514 { TestRound(kConnect
, kProxyChallenge
, OK
),
9515 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9516 &kGet
, &kServerChallenge
),
9517 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9518 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9519 { TestRound(kConnect
, kProxyChallenge
, OK
),
9520 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9521 &kGet
, &kServerChallenge
),
9522 TestRound(kGetAuth
, kSuccess
, OK
)}},
9523 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9524 { TestRound(kConnect
, kProxyChallenge
, OK
),
9525 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9526 &kGet
, &kServerChallenge
),
9527 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9528 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
9529 { TestRound(kConnect
, kProxyChallenge
, OK
),
9530 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9531 &kGet
, &kServerChallenge
),
9532 TestRound(kGetAuth
, kSuccess
, OK
)}},
9533 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
9534 { TestRound(kConnect
, kProxyChallenge
, OK
),
9535 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
9536 &kGet
, &kServerChallenge
),
9537 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9540 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(test_configs
); ++i
) {
9541 HttpAuthHandlerMock::Factory
* auth_factory(
9542 new HttpAuthHandlerMock::Factory());
9543 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9544 const TestConfig
& test_config
= test_configs
[i
];
9546 // Set up authentication handlers as necessary.
9547 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
9548 for (int n
= 0; n
< 2; n
++) {
9549 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9550 std::string auth_challenge
= "Mock realm=proxy";
9551 GURL
origin(test_config
.proxy_url
);
9552 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9553 auth_challenge
.end());
9554 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
9555 origin
, BoundNetLog());
9556 auth_handler
->SetGenerateExpectation(
9557 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
9558 test_config
.proxy_auth_rv
);
9559 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9562 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
9563 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9564 std::string auth_challenge
= "Mock realm=server";
9565 GURL
origin(test_config
.server_url
);
9566 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9567 auth_challenge
.end());
9568 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9569 origin
, BoundNetLog());
9570 auth_handler
->SetGenerateExpectation(
9571 test_config
.server_auth_timing
== AUTH_ASYNC
,
9572 test_config
.server_auth_rv
);
9573 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9575 if (test_config
.proxy_url
) {
9576 session_deps_
.proxy_service
.reset(
9577 ProxyService::CreateFixed(test_config
.proxy_url
));
9579 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9582 HttpRequestInfo request
;
9583 request
.method
= "GET";
9584 request
.url
= GURL(test_config
.server_url
);
9585 request
.load_flags
= 0;
9587 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9588 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
);
9590 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
9591 const TestRound
& read_write_round
= test_config
.rounds
[round
];
9593 // Set up expected reads and writes.
9595 reads
[0] = read_write_round
.read
;
9596 size_t length_reads
= 1;
9597 if (read_write_round
.extra_read
) {
9598 reads
[1] = *read_write_round
.extra_read
;
9602 MockWrite writes
[2];
9603 writes
[0] = read_write_round
.write
;
9604 size_t length_writes
= 1;
9605 if (read_write_round
.extra_write
) {
9606 writes
[1] = *read_write_round
.extra_write
;
9609 StaticSocketDataProvider
data_provider(
9610 reads
, length_reads
, writes
, length_writes
);
9611 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9613 // Add an SSL sequence if necessary.
9614 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
9615 if (round
>= test_config
.first_ssl_round
)
9616 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
9617 &ssl_socket_data_provider
);
9619 // Start or restart the transaction.
9620 TestCompletionCallback callback
;
9623 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
9625 rv
= trans
.RestartWithAuth(
9626 AuthCredentials(kFoo
, kBar
), callback
.callback());
9628 if (rv
== ERR_IO_PENDING
)
9629 rv
= callback
.WaitForResult();
9631 // Compare results with expected data.
9632 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
9633 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
9634 if (read_write_round
.expected_rv
== OK
) {
9635 ASSERT_TRUE(response
!= NULL
);
9637 EXPECT_TRUE(response
== NULL
);
9638 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
9641 if (round
+ 1 < test_config
.num_auth_rounds
) {
9642 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9644 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9650 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
9651 // Do multi-round authentication and make sure it works correctly.
9652 HttpAuthHandlerMock::Factory
* auth_factory(
9653 new HttpAuthHandlerMock::Factory());
9654 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9655 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
9656 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
9657 session_deps_
.host_resolver
->set_synchronous_mode(true);
9659 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
9660 auth_handler
->set_connection_based(true);
9661 std::string auth_challenge
= "Mock realm=server";
9662 GURL
origin("http://www.example.com");
9663 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
9664 auth_challenge
.end());
9665 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
9666 origin
, BoundNetLog());
9667 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
9670 const HttpResponseInfo
* response
= NULL
;
9671 HttpRequestInfo request
;
9672 request
.method
= "GET";
9673 request
.url
= origin
;
9674 request
.load_flags
= 0;
9676 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9678 // Use a TCP Socket Pool with only one connection per group. This is used
9679 // to validate that the TCP socket is not released to the pool between
9680 // each round of multi-round authentication.
9681 HttpNetworkSessionPeer
session_peer(session
);
9682 ClientSocketPoolHistograms
transport_pool_histograms("SmallTCP");
9683 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
9684 50, // Max sockets for pool
9685 1, // Max sockets per group
9686 &transport_pool_histograms
,
9687 session_deps_
.host_resolver
.get(),
9688 session_deps_
.socket_factory
.get(),
9689 session_deps_
.net_log
);
9690 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
9691 new MockClientSocketPoolManager
);
9692 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
9693 session_peer
.SetClientSocketPoolManager(
9694 mock_pool_manager
.PassAs
<ClientSocketPoolManager
>());
9696 scoped_ptr
<HttpTransaction
> trans(
9697 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9698 TestCompletionCallback callback
;
9700 const MockWrite
kGet(
9701 "GET / HTTP/1.1\r\n"
9702 "Host: www.example.com\r\n"
9703 "Connection: keep-alive\r\n\r\n");
9704 const MockWrite
kGetAuth(
9705 "GET / HTTP/1.1\r\n"
9706 "Host: www.example.com\r\n"
9707 "Connection: keep-alive\r\n"
9708 "Authorization: auth_token\r\n\r\n");
9710 const MockRead
kServerChallenge(
9711 "HTTP/1.1 401 Unauthorized\r\n"
9712 "WWW-Authenticate: Mock realm=server\r\n"
9713 "Content-Type: text/html; charset=iso-8859-1\r\n"
9714 "Content-Length: 14\r\n\r\n"
9715 "Unauthorized\r\n");
9716 const MockRead
kSuccess(
9717 "HTTP/1.1 200 OK\r\n"
9718 "Content-Type: text/html; charset=iso-8859-1\r\n"
9719 "Content-Length: 3\r\n\r\n"
9722 MockWrite writes
[] = {
9731 // Competing request
9734 MockRead reads
[] = {
9743 // Competing response
9746 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
9747 writes
, arraysize(writes
));
9748 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
9750 const char* const kSocketGroup
= "www.example.com:80";
9752 // First round of authentication.
9753 auth_handler
->SetGenerateExpectation(false, OK
);
9754 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9755 if (rv
== ERR_IO_PENDING
)
9756 rv
= callback
.WaitForResult();
9758 response
= trans
->GetResponseInfo();
9759 ASSERT_TRUE(response
!= NULL
);
9760 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
9761 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9763 // In between rounds, another request comes in for the same domain.
9764 // It should not be able to grab the TCP socket that trans has already
9766 scoped_ptr
<HttpTransaction
> trans_compete(
9767 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9768 TestCompletionCallback callback_compete
;
9769 rv
= trans_compete
->Start(
9770 &request
, callback_compete
.callback(), BoundNetLog());
9771 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9772 // callback_compete.WaitForResult at this point would stall forever,
9773 // since the HttpNetworkTransaction does not release the request back to
9774 // the pool until after authentication completes.
9776 // Second round of authentication.
9777 auth_handler
->SetGenerateExpectation(false, OK
);
9778 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
9779 if (rv
== ERR_IO_PENDING
)
9780 rv
= callback
.WaitForResult();
9782 response
= trans
->GetResponseInfo();
9783 ASSERT_TRUE(response
!= NULL
);
9784 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9785 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9787 // Third round of authentication.
9788 auth_handler
->SetGenerateExpectation(false, OK
);
9789 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9790 if (rv
== ERR_IO_PENDING
)
9791 rv
= callback
.WaitForResult();
9793 response
= trans
->GetResponseInfo();
9794 ASSERT_TRUE(response
!= NULL
);
9795 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9796 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9798 // Fourth round of authentication, which completes successfully.
9799 auth_handler
->SetGenerateExpectation(false, OK
);
9800 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
9801 if (rv
== ERR_IO_PENDING
)
9802 rv
= callback
.WaitForResult();
9804 response
= trans
->GetResponseInfo();
9805 ASSERT_TRUE(response
!= NULL
);
9806 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
9807 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9809 // Read the body since the fourth round was successful. This will also
9810 // release the socket back to the pool.
9811 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
9812 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9813 if (rv
== ERR_IO_PENDING
)
9814 rv
= callback
.WaitForResult();
9816 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9818 // There are still 0 idle sockets, since the trans_compete transaction
9819 // will be handed it immediately after trans releases it to the group.
9820 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9822 // The competing request can now finish. Wait for the headers and then
9824 rv
= callback_compete
.WaitForResult();
9826 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9827 if (rv
== ERR_IO_PENDING
)
9828 rv
= callback
.WaitForResult();
9830 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
9833 // Finally, the socket is released to the group.
9834 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
9837 // This tests the case that a request is issued via http instead of spdy after
9838 // npn is negotiated.
9839 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
9840 HttpStreamFactory::set_use_alternate_protocols(true);
9841 std::vector
<NextProto
> next_protos
;
9842 next_protos
.push_back(kProtoHTTP11
);
9843 HttpStreamFactory::SetNextProtos(next_protos
);
9844 HttpRequestInfo request
;
9845 request
.method
= "GET";
9846 request
.url
= GURL("https://www.google.com/");
9847 request
.load_flags
= 0;
9849 MockWrite data_writes
[] = {
9850 MockWrite("GET / HTTP/1.1\r\n"
9851 "Host: www.google.com\r\n"
9852 "Connection: keep-alive\r\n\r\n"),
9855 std::string alternate_protocol_http_header
=
9856 GetAlternateProtocolHttpHeader();
9858 MockRead data_reads
[] = {
9859 MockRead("HTTP/1.1 200 OK\r\n"),
9860 MockRead(alternate_protocol_http_header
.c_str()),
9861 MockRead("hello world"),
9862 MockRead(SYNCHRONOUS
, OK
),
9865 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9866 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
9867 ssl
.next_proto
= "http/1.1";
9868 ssl
.protocol_negotiated
= kProtoHTTP11
;
9870 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9872 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
9873 data_writes
, arraysize(data_writes
));
9874 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9876 TestCompletionCallback callback
;
9878 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9879 scoped_ptr
<HttpTransaction
> trans(
9880 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9882 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9884 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9885 EXPECT_EQ(OK
, callback
.WaitForResult());
9887 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9888 ASSERT_TRUE(response
!= NULL
);
9889 ASSERT_TRUE(response
->headers
.get() != NULL
);
9890 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9892 std::string response_data
;
9893 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9894 EXPECT_EQ("hello world", response_data
);
9896 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9897 EXPECT_TRUE(response
->was_npn_negotiated
);
9900 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
9901 // Simulate the SSL handshake completing with an NPN negotiation
9902 // followed by an immediate server closing of the socket.
9903 // Fix crash: http://crbug.com/46369
9904 HttpStreamFactory::set_use_alternate_protocols(true);
9905 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9907 HttpRequestInfo request
;
9908 request
.method
= "GET";
9909 request
.url
= GURL("https://www.google.com/");
9910 request
.load_flags
= 0;
9912 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9913 ssl
.SetNextProto(GetParam());
9914 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9916 scoped_ptr
<SpdyFrame
> req(
9917 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9918 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9920 MockRead spdy_reads
[] = {
9921 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
9924 DelayedSocketData
spdy_data(
9925 0, // don't wait in this case, immediate hangup.
9926 spdy_reads
, arraysize(spdy_reads
),
9927 spdy_writes
, arraysize(spdy_writes
));
9928 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9930 TestCompletionCallback callback
;
9932 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9933 scoped_ptr
<HttpTransaction
> trans(
9934 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9936 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9937 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9938 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
9941 // A subclass of HttpAuthHandlerMock that records the request URL when
9942 // it gets it. This is needed since the auth handler may get destroyed
9943 // before we get a chance to query it.
9944 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
9946 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
9948 virtual ~UrlRecordingHttpAuthHandlerMock() {}
9951 virtual int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
9952 const HttpRequestInfo
* request
,
9953 const CompletionCallback
& callback
,
9954 std::string
* auth_token
) OVERRIDE
{
9955 *url_
= request
->url
;
9956 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
9957 credentials
, request
, callback
, auth_token
);
9964 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
9965 // This test ensures that the URL passed into the proxy is upgraded
9966 // to https when doing an Alternate Protocol upgrade.
9967 HttpStreamFactory::set_use_alternate_protocols(true);
9968 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
9970 session_deps_
.proxy_service
.reset(
9971 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
9972 CapturingNetLog net_log
;
9973 session_deps_
.net_log
= &net_log
;
9976 HttpAuthHandlerMock::Factory
* auth_factory
=
9977 new HttpAuthHandlerMock::Factory();
9978 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
9979 new UrlRecordingHttpAuthHandlerMock(&request_url
);
9980 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
9981 auth_factory
->set_do_init_from_challenge(true);
9982 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
9985 HttpRequestInfo request
;
9986 request
.method
= "GET";
9987 request
.url
= GURL("http://www.google.com");
9988 request
.load_flags
= 0;
9990 // First round goes unauthenticated through the proxy.
9991 MockWrite data_writes_1
[] = {
9992 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
9993 "Host: www.google.com\r\n"
9994 "Proxy-Connection: keep-alive\r\n"
9997 MockRead data_reads_1
[] = {
9998 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9999 MockRead("HTTP/1.1 200 OK\r\n"
10000 "Alternate-Protocol: 443:npn-spdy/2\r\n"
10001 "Proxy-Connection: close\r\n"
10004 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10005 data_writes_1
, arraysize(data_writes_1
));
10007 // Second round tries to tunnel to www.google.com due to the
10008 // Alternate-Protocol announcement in the first round. It fails due
10009 // to a proxy authentication challenge.
10010 // After the failure, a tunnel is established to www.google.com using
10011 // Proxy-Authorization headers. There is then a SPDY request round.
10013 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10014 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10015 // does a Disconnect and Connect on the same socket, rather than trying
10016 // to obtain a new one.
10018 // NOTE: Originally, the proxy response to the second CONNECT request
10019 // simply returned another 407 so the unit test could skip the SSL connection
10020 // establishment and SPDY framing issues. Alas, the
10021 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10022 // complicated to set up expectations for than the SPDY session.
10024 scoped_ptr
<SpdyFrame
> req(
10025 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10026 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10027 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10029 MockWrite data_writes_2
[] = {
10030 // First connection attempt without Proxy-Authorization.
10031 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10032 "Host: www.google.com\r\n"
10033 "Proxy-Connection: keep-alive\r\n"
10036 // Second connection attempt with Proxy-Authorization.
10037 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10038 "Host: www.google.com\r\n"
10039 "Proxy-Connection: keep-alive\r\n"
10040 "Proxy-Authorization: auth_token\r\n"
10044 CreateMockWrite(*req
),
10046 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10047 "Proxy-Authenticate: Mock\r\n"
10048 "Proxy-Connection: close\r\n"
10050 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10051 MockRead data_reads_2
[] = {
10052 // First connection attempt fails
10053 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10054 MockRead(ASYNC
, kRejectConnectResponse
,
10055 arraysize(kRejectConnectResponse
) - 1, 1),
10057 // Second connection attempt passes
10058 MockRead(ASYNC
, kAcceptConnectResponse
,
10059 arraysize(kAcceptConnectResponse
) -1, 4),
10062 CreateMockRead(*resp
.get(), 6),
10063 CreateMockRead(*data
.get(), 6),
10064 MockRead(ASYNC
, 0, 0, 6),
10066 OrderedSocketData
data_2(
10067 data_reads_2
, arraysize(data_reads_2
),
10068 data_writes_2
, arraysize(data_writes_2
));
10070 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10071 ssl
.SetNextProto(GetParam());
10073 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10074 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10076 hanging_non_alternate_protocol_socket
.set_connect_data(
10077 never_finishing_connect
);
10079 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10080 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10081 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10082 session_deps_
.socket_factory
->AddSocketDataProvider(
10083 &hanging_non_alternate_protocol_socket
);
10084 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10086 // First round should work and provide the Alternate-Protocol state.
10087 TestCompletionCallback callback_1
;
10088 scoped_ptr
<HttpTransaction
> trans_1(
10089 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10090 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10091 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10092 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10094 // Second round should attempt a tunnel connect and get an auth challenge.
10095 TestCompletionCallback callback_2
;
10096 scoped_ptr
<HttpTransaction
> trans_2(
10097 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10098 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10099 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10100 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10101 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10102 ASSERT_TRUE(response
!= NULL
);
10103 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10105 // Restart with auth. Tunnel should work and response received.
10106 TestCompletionCallback callback_3
;
10107 rv
= trans_2
->RestartWithAuth(
10108 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10109 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10110 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10112 // After all that work, these two lines (or actually, just the scheme) are
10113 // what this test is all about. Make sure it happens correctly.
10114 EXPECT_EQ("https", request_url
.scheme());
10115 EXPECT_EQ("www.google.com", request_url
.host());
10117 LoadTimingInfo load_timing_info
;
10118 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10119 TestLoadTimingNotReusedWithPac(load_timing_info
,
10120 CONNECT_TIMING_HAS_SSL_TIMES
);
10123 // Test that if we cancel the transaction as the connection is completing, that
10124 // everything tears down correctly.
10125 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10126 // Setup everything about the connection to complete synchronously, so that
10127 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10128 // for is the callback from the HttpStreamRequest.
10129 // Then cancel the transaction.
10130 // Verify that we don't crash.
10131 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10132 MockRead data_reads
[] = {
10133 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10134 MockRead(SYNCHRONOUS
, "hello world"),
10135 MockRead(SYNCHRONOUS
, OK
),
10138 HttpRequestInfo request
;
10139 request
.method
= "GET";
10140 request
.url
= GURL("http://www.google.com/");
10141 request
.load_flags
= 0;
10143 session_deps_
.host_resolver
->set_synchronous_mode(true);
10144 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10145 scoped_ptr
<HttpTransaction
> trans(
10146 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
10148 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10149 data
.set_connect_data(mock_connect
);
10150 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10152 TestCompletionCallback callback
;
10154 CapturingBoundNetLog log
;
10155 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10156 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10157 trans
.reset(); // Cancel the transaction here.
10159 base::MessageLoop::current()->RunUntilIdle();
10162 // Test a basic GET request through a proxy.
10163 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10164 session_deps_
.proxy_service
.reset(
10165 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10166 CapturingBoundNetLog log
;
10167 session_deps_
.net_log
= log
.bound().net_log();
10168 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10170 HttpRequestInfo request
;
10171 request
.method
= "GET";
10172 request
.url
= GURL("http://www.google.com/");
10174 MockWrite data_writes1
[] = {
10175 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
10176 "Host: www.google.com\r\n"
10177 "Proxy-Connection: keep-alive\r\n\r\n"),
10180 MockRead data_reads1
[] = {
10181 MockRead("HTTP/1.1 200 OK\r\n"),
10182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10183 MockRead("Content-Length: 100\r\n\r\n"),
10184 MockRead(SYNCHRONOUS
, OK
),
10187 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10188 data_writes1
, arraysize(data_writes1
));
10189 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10191 TestCompletionCallback callback1
;
10193 scoped_ptr
<HttpTransaction
> trans(
10194 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10196 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10197 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10199 rv
= callback1
.WaitForResult();
10202 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10203 ASSERT_TRUE(response
!= NULL
);
10205 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10206 EXPECT_EQ(200, response
->headers
->response_code());
10207 EXPECT_EQ(100, response
->headers
->GetContentLength());
10208 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10209 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10211 LoadTimingInfo load_timing_info
;
10212 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10213 TestLoadTimingNotReusedWithPac(load_timing_info
,
10214 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10217 // Test a basic HTTPS GET request through a proxy.
10218 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10219 session_deps_
.proxy_service
.reset(
10220 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10221 CapturingBoundNetLog log
;
10222 session_deps_
.net_log
= log
.bound().net_log();
10223 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10225 HttpRequestInfo request
;
10226 request
.method
= "GET";
10227 request
.url
= GURL("https://www.google.com/");
10229 // Since we have proxy, should try to establish tunnel.
10230 MockWrite data_writes1
[] = {
10231 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10232 "Host: www.google.com\r\n"
10233 "Proxy-Connection: keep-alive\r\n\r\n"),
10235 MockWrite("GET / HTTP/1.1\r\n"
10236 "Host: www.google.com\r\n"
10237 "Connection: keep-alive\r\n\r\n"),
10240 MockRead data_reads1
[] = {
10241 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10243 MockRead("HTTP/1.1 200 OK\r\n"),
10244 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10245 MockRead("Content-Length: 100\r\n\r\n"),
10246 MockRead(SYNCHRONOUS
, OK
),
10249 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10250 data_writes1
, arraysize(data_writes1
));
10251 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10252 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10253 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10255 TestCompletionCallback callback1
;
10257 scoped_ptr
<HttpTransaction
> trans(
10258 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10260 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10261 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10263 rv
= callback1
.WaitForResult();
10265 net::CapturingNetLog::CapturedEntryList entries
;
10266 log
.GetEntries(&entries
);
10267 size_t pos
= ExpectLogContainsSomewhere(
10268 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10269 NetLog::PHASE_NONE
);
10270 ExpectLogContainsSomewhere(
10272 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10273 NetLog::PHASE_NONE
);
10275 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10276 ASSERT_TRUE(response
!= NULL
);
10278 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10279 EXPECT_EQ(200, response
->headers
->response_code());
10280 EXPECT_EQ(100, response
->headers
->GetContentLength());
10281 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10282 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10284 LoadTimingInfo load_timing_info
;
10285 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10286 TestLoadTimingNotReusedWithPac(load_timing_info
,
10287 CONNECT_TIMING_HAS_SSL_TIMES
);
10290 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10291 // while establishing the tunnel.
10292 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10293 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10294 CapturingBoundNetLog log
;
10295 session_deps_
.net_log
= log
.bound().net_log();
10296 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10298 HttpRequestInfo request
;
10299 request
.method
= "GET";
10300 request
.url
= GURL("https://www.google.com/");
10302 // Since we have proxy, should try to establish tunnel.
10303 MockWrite data_writes1
[] = {
10304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
10305 "Host: www.google.com\r\n"
10306 "Proxy-Connection: keep-alive\r\n\r\n"),
10308 MockWrite("GET / HTTP/1.1\r\n"
10309 "Host: www.google.com\r\n"
10310 "Connection: keep-alive\r\n\r\n"),
10313 MockRead data_reads1
[] = {
10314 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10315 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10316 MockRead(ASYNC
, 0, 0), // EOF
10319 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10320 data_writes1
, arraysize(data_writes1
));
10321 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10322 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10323 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10325 TestCompletionCallback callback1
;
10327 scoped_ptr
<HttpTransaction
> trans(
10328 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10330 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10331 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10333 rv
= callback1
.WaitForResult();
10334 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10335 net::CapturingNetLog::CapturedEntryList entries
;
10336 log
.GetEntries(&entries
);
10337 size_t pos
= ExpectLogContainsSomewhere(
10338 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10339 NetLog::PHASE_NONE
);
10340 ExpectLogContainsSomewhere(
10342 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10343 NetLog::PHASE_NONE
);
10346 // Test for crbug.com/55424.
10347 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10348 scoped_ptr
<SpdyFrame
> req(
10349 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10350 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10352 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10353 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10354 MockRead spdy_reads
[] = {
10355 CreateMockRead(*resp
),
10356 CreateMockRead(*data
),
10357 MockRead(ASYNC
, 0, 0),
10360 DelayedSocketData
spdy_data(
10361 1, // wait for one write to finish before reading.
10362 spdy_reads
, arraysize(spdy_reads
),
10363 spdy_writes
, arraysize(spdy_writes
));
10364 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10366 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10367 ssl
.SetNextProto(GetParam());
10368 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10370 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10372 // Set up an initial SpdySession in the pool to reuse.
10373 HostPortPair
host_port_pair("www.google.com", 443);
10374 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10375 PRIVACY_MODE_DISABLED
);
10376 base::WeakPtr
<SpdySession
> spdy_session
=
10377 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10379 HttpRequestInfo request
;
10380 request
.method
= "GET";
10381 request
.url
= GURL("https://www.google.com/");
10382 request
.load_flags
= 0;
10384 // This is the important line that marks this as a preconnect.
10385 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10387 scoped_ptr
<HttpTransaction
> trans(
10388 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10390 TestCompletionCallback callback
;
10391 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10392 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10393 EXPECT_EQ(OK
, callback
.WaitForResult());
10396 // Given a net error, cause that error to be returned from the first Write()
10397 // call and verify that the HttpTransaction fails with that error.
10398 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10399 int error
, IoMode mode
) {
10400 net::HttpRequestInfo request_info
;
10401 request_info
.url
= GURL("https://www.example.com/");
10402 request_info
.method
= "GET";
10403 request_info
.load_flags
= net::LOAD_NORMAL
;
10405 SSLSocketDataProvider
ssl_data(mode
, OK
);
10406 net::MockWrite data_writes
[] = {
10407 net::MockWrite(mode
, error
),
10409 net::StaticSocketDataProvider
data(NULL
, 0,
10410 data_writes
, arraysize(data_writes
));
10411 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10412 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10414 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10415 scoped_ptr
<HttpTransaction
> trans(
10416 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10418 TestCompletionCallback callback
;
10419 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10420 if (rv
== net::ERR_IO_PENDING
)
10421 rv
= callback
.WaitForResult();
10422 ASSERT_EQ(error
, rv
);
10425 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
10426 // Just check a grab bag of cert errors.
10427 static const int kErrors
[] = {
10428 ERR_CERT_COMMON_NAME_INVALID
,
10429 ERR_CERT_AUTHORITY_INVALID
,
10430 ERR_CERT_DATE_INVALID
,
10432 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
10433 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
10434 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
10438 // Ensure that a client certificate is removed from the SSL client auth
10440 // 1) No proxy is involved.
10441 // 2) TLS False Start is disabled.
10442 // 3) The initial TLS handshake requests a client certificate.
10443 // 4) The client supplies an invalid/unacceptable certificate.
10444 TEST_P(HttpNetworkTransactionTest
,
10445 ClientAuthCertCache_Direct_NoFalseStart
) {
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 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10452 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10454 // [ssl_]data1 contains the data for the first SSL handshake. When a
10455 // CertificateRequest is received for the first time, the handshake will
10456 // be aborted to allow the caller to provide a certificate.
10457 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10458 ssl_data1
.cert_request_info
= cert_request
.get();
10459 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10460 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10461 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10463 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
10464 // False Start is not being used, the result of the SSL handshake will be
10465 // returned as part of the SSLClientSocket::Connect() call. This test
10466 // matches the result of a server sending a handshake_failure alert,
10467 // rather than a Finished message, because it requires a client
10468 // certificate and none was supplied.
10469 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10470 ssl_data2
.cert_request_info
= cert_request
.get();
10471 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10472 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10473 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10475 // [ssl_]data3 contains the data for the third SSL handshake. When a
10476 // connection to a server fails during an SSL handshake,
10477 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
10478 // connection was attempted with TLSv1.1. This is transparent to the caller
10479 // of the HttpNetworkTransaction. Because this test failure is due to
10480 // requiring a client certificate, this fallback handshake should also
10482 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10483 ssl_data3
.cert_request_info
= cert_request
.get();
10484 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10485 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10486 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10488 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
10489 // connection to a server fails during an SSL handshake,
10490 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
10491 // connection was attempted with TLSv1. This is transparent to the caller
10492 // of the HttpNetworkTransaction. Because this test failure is due to
10493 // requiring a client certificate, this fallback handshake should also
10495 SSLSocketDataProvider
ssl_data4(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10496 ssl_data4
.cert_request_info
= cert_request
.get();
10497 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10498 net::StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
10499 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10501 // Need one more if TLSv1.2 is enabled.
10502 SSLSocketDataProvider
ssl_data5(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10503 ssl_data5
.cert_request_info
= cert_request
.get();
10504 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10505 net::StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
10506 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10508 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10509 scoped_ptr
<HttpTransaction
> trans(
10510 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10512 // Begin the SSL handshake with the peer. This consumes ssl_data1.
10513 TestCompletionCallback callback
;
10514 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10515 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10517 // Complete the SSL handshake, which should abort due to requiring a
10518 // client certificate.
10519 rv
= callback
.WaitForResult();
10520 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10522 // Indicate that no certificate should be supplied. From the perspective
10523 // of SSLClientCertCache, NULL is just as meaningful as a real
10524 // certificate, so this is the same as supply a
10525 // legitimate-but-unacceptable certificate.
10526 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10527 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10529 // Ensure the certificate was added to the client auth cache before
10530 // allowing the connection to continue restarting.
10531 scoped_refptr
<X509Certificate
> client_cert
;
10532 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10533 HostPortPair("www.example.com", 443), &client_cert
));
10534 ASSERT_EQ(NULL
, client_cert
.get());
10536 // Restart the handshake. This will consume ssl_data2, which fails, and
10537 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10538 // The result code is checked against what ssl_data4 should return.
10539 rv
= callback
.WaitForResult();
10540 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10542 // Ensure that the client certificate is removed from the cache on a
10543 // handshake failure.
10544 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10545 HostPortPair("www.example.com", 443), &client_cert
));
10548 // Ensure that a client certificate is removed from the SSL client auth
10550 // 1) No proxy is involved.
10551 // 2) TLS False Start is enabled.
10552 // 3) The initial TLS handshake requests a client certificate.
10553 // 4) The client supplies an invalid/unacceptable certificate.
10554 TEST_P(HttpNetworkTransactionTest
,
10555 ClientAuthCertCache_Direct_FalseStart
) {
10556 net::HttpRequestInfo request_info
;
10557 request_info
.url
= GURL("https://www.example.com/");
10558 request_info
.method
= "GET";
10559 request_info
.load_flags
= net::LOAD_NORMAL
;
10561 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10562 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
10564 // When TLS False Start is used, SSLClientSocket::Connect() calls will
10565 // return successfully after reading up to the peer's Certificate message.
10566 // This is to allow the caller to call SSLClientSocket::Write(), which can
10567 // enqueue application data to be sent in the same packet as the
10568 // ChangeCipherSpec and Finished messages.
10569 // The actual handshake will be finished when SSLClientSocket::Read() is
10570 // called, which expects to process the peer's ChangeCipherSpec and
10571 // Finished messages. If there was an error negotiating with the peer,
10572 // such as due to the peer requiring a client certificate when none was
10573 // supplied, the alert sent by the peer won't be processed until Read() is
10576 // Like the non-False Start case, when a client certificate is requested by
10577 // the peer, the handshake is aborted during the Connect() call.
10578 // [ssl_]data1 represents the initial SSL handshake with the peer.
10579 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10580 ssl_data1
.cert_request_info
= cert_request
.get();
10581 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10582 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10583 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10585 // When a client certificate is supplied, Connect() will not be aborted
10586 // when the peer requests the certificate. Instead, the handshake will
10587 // artificially succeed, allowing the caller to write the HTTP request to
10588 // the socket. The handshake messages are not processed until Read() is
10589 // called, which then detects that the handshake was aborted, due to the
10590 // peer sending a handshake_failure because it requires a client
10592 SSLSocketDataProvider
ssl_data2(ASYNC
, net::OK
);
10593 ssl_data2
.cert_request_info
= cert_request
.get();
10594 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10595 net::MockRead data2_reads
[] = {
10596 net::MockRead(ASYNC
/* async */, net::ERR_SSL_PROTOCOL_ERROR
),
10598 net::StaticSocketDataProvider
data2(
10599 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10600 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10602 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
10603 // the data for the SSL handshake once the TLSv1.1 connection falls back to
10604 // TLSv1. It has the same behaviour as [ssl_]data2.
10605 SSLSocketDataProvider
ssl_data3(ASYNC
, net::OK
);
10606 ssl_data3
.cert_request_info
= cert_request
.get();
10607 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10608 net::StaticSocketDataProvider
data3(
10609 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10610 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10612 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
10613 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
10614 SSLSocketDataProvider
ssl_data4(ASYNC
, net::OK
);
10615 ssl_data4
.cert_request_info
= cert_request
.get();
10616 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
10617 net::StaticSocketDataProvider
data4(
10618 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10619 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
10621 // Need one more if TLSv1.2 is enabled.
10622 SSLSocketDataProvider
ssl_data5(ASYNC
, net::OK
);
10623 ssl_data5
.cert_request_info
= cert_request
.get();
10624 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
10625 net::StaticSocketDataProvider
data5(
10626 data2_reads
, arraysize(data2_reads
), NULL
, 0);
10627 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
10629 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10630 scoped_ptr
<HttpTransaction
> trans(
10631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10633 // Begin the initial SSL handshake.
10634 TestCompletionCallback callback
;
10635 int rv
= trans
->Start(&request_info
, callback
.callback(), net::BoundNetLog());
10636 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10638 // Complete the SSL handshake, which should abort due to requiring a
10639 // client certificate.
10640 rv
= callback
.WaitForResult();
10641 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10643 // Indicate that no certificate should be supplied. From the perspective
10644 // of SSLClientCertCache, NULL is just as meaningful as a real
10645 // certificate, so this is the same as supply a
10646 // legitimate-but-unacceptable certificate.
10647 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10648 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10650 // Ensure the certificate was added to the client auth cache before
10651 // allowing the connection to continue restarting.
10652 scoped_refptr
<X509Certificate
> client_cert
;
10653 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10654 HostPortPair("www.example.com", 443), &client_cert
));
10655 ASSERT_EQ(NULL
, client_cert
.get());
10657 // Restart the handshake. This will consume ssl_data2, which fails, and
10658 // then consume ssl_data3 and ssl_data4, both of which should also fail.
10659 // The result code is checked against what ssl_data4 should return.
10660 rv
= callback
.WaitForResult();
10661 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, rv
);
10663 // Ensure that the client certificate is removed from the cache on a
10664 // handshake failure.
10665 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10666 HostPortPair("www.example.com", 443), &client_cert
));
10669 // Ensure that a client certificate is removed from the SSL client auth
10671 // 1) An HTTPS proxy is involved.
10672 // 3) The HTTPS proxy requests a client certificate.
10673 // 4) The client supplies an invalid/unacceptable certificate for the
10675 // The test is repeated twice, first for connecting to an HTTPS endpoint,
10676 // then for connecting to an HTTP endpoint.
10677 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
10678 session_deps_
.proxy_service
.reset(
10679 ProxyService::CreateFixed("https://proxy:70"));
10680 CapturingBoundNetLog log
;
10681 session_deps_
.net_log
= log
.bound().net_log();
10683 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
10684 cert_request
->host_and_port
= HostPortPair("proxy", 70);
10686 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
10687 // [ssl_]data[1-3]. Rather than represending the endpoint
10688 // (www.example.com:443), they represent failures with the HTTPS proxy
10690 SSLSocketDataProvider
ssl_data1(ASYNC
, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
10691 ssl_data1
.cert_request_info
= cert_request
.get();
10692 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
10693 net::StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
10694 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10696 SSLSocketDataProvider
ssl_data2(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10697 ssl_data2
.cert_request_info
= cert_request
.get();
10698 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
10699 net::StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
10700 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
10702 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
10704 SSLSocketDataProvider
ssl_data3(ASYNC
, net::ERR_SSL_PROTOCOL_ERROR
);
10705 ssl_data3
.cert_request_info
= cert_request
.get();
10706 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
10707 net::StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
10708 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
10711 net::HttpRequestInfo requests
[2];
10712 requests
[0].url
= GURL("https://www.example.com/");
10713 requests
[0].method
= "GET";
10714 requests
[0].load_flags
= net::LOAD_NORMAL
;
10716 requests
[1].url
= GURL("http://www.example.com/");
10717 requests
[1].method
= "GET";
10718 requests
[1].load_flags
= net::LOAD_NORMAL
;
10720 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
10721 session_deps_
.socket_factory
->ResetNextMockIndexes();
10722 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10723 scoped_ptr
<HttpNetworkTransaction
> trans(
10724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10726 // Begin the SSL handshake with the proxy.
10727 TestCompletionCallback callback
;
10728 int rv
= trans
->Start(
10729 &requests
[i
], callback
.callback(), net::BoundNetLog());
10730 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10732 // Complete the SSL handshake, which should abort due to requiring a
10733 // client certificate.
10734 rv
= callback
.WaitForResult();
10735 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
10737 // Indicate that no certificate should be supplied. From the perspective
10738 // of SSLClientCertCache, NULL is just as meaningful as a real
10739 // certificate, so this is the same as supply a
10740 // legitimate-but-unacceptable certificate.
10741 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
10742 ASSERT_EQ(net::ERR_IO_PENDING
, rv
);
10744 // Ensure the certificate was added to the client auth cache before
10745 // allowing the connection to continue restarting.
10746 scoped_refptr
<X509Certificate
> client_cert
;
10747 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
10748 HostPortPair("proxy", 70), &client_cert
));
10749 ASSERT_EQ(NULL
, client_cert
.get());
10750 // Ensure the certificate was NOT cached for the endpoint. This only
10751 // applies to HTTPS requests, but is fine to check for HTTP requests.
10752 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10753 HostPortPair("www.example.com", 443), &client_cert
));
10755 // Restart the handshake. This will consume ssl_data2, which fails, and
10756 // then consume ssl_data3, which should also fail. The result code is
10757 // checked against what ssl_data3 should return.
10758 rv
= callback
.WaitForResult();
10759 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED
, rv
);
10761 // Now that the new handshake has failed, ensure that the client
10762 // certificate was removed from the client auth cache.
10763 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10764 HostPortPair("proxy", 70), &client_cert
));
10765 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
10766 HostPortPair("www.example.com", 443), &client_cert
));
10770 // Unlike TEST/TEST_F, which are macros that expand to further macros,
10771 // TEST_P is a macro that expands directly to code that stringizes the
10772 // arguments. As a result, macros passed as parameters (such as prefix
10773 // or test_case_name) will not be expanded by the preprocessor. To
10774 // work around this, indirect the macro for TEST_P, so that the
10775 // pre-processor will expand macros such as MAYBE_test_name before
10776 // instantiating the test.
10777 #define WRAPPED_TEST_P(test_case_name, test_name) \
10778 TEST_P(test_case_name, test_name)
10780 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
10781 #if defined(OS_WIN)
10782 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
10784 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
10786 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
10787 HttpStreamFactory::set_use_alternate_protocols(true);
10788 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10790 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10791 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10792 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10793 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10794 pool_peer
.DisableDomainAuthenticationVerification();
10796 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10797 ssl
.SetNextProto(GetParam());
10798 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10800 scoped_ptr
<SpdyFrame
> host1_req(
10801 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10802 scoped_ptr
<SpdyFrame
> host2_req(
10803 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10804 MockWrite spdy_writes
[] = {
10805 CreateMockWrite(*host1_req
, 1),
10806 CreateMockWrite(*host2_req
, 4),
10808 scoped_ptr
<SpdyFrame
> host1_resp(
10809 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10810 scoped_ptr
<SpdyFrame
> host1_resp_body(
10811 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10812 scoped_ptr
<SpdyFrame
> host2_resp(
10813 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10814 scoped_ptr
<SpdyFrame
> host2_resp_body(
10815 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10816 MockRead spdy_reads
[] = {
10817 CreateMockRead(*host1_resp
, 2),
10818 CreateMockRead(*host1_resp_body
, 3),
10819 CreateMockRead(*host2_resp
, 5),
10820 CreateMockRead(*host2_resp_body
, 6),
10821 MockRead(ASYNC
, 0, 7),
10824 IPAddressNumber ip
;
10825 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10826 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10827 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10828 OrderedSocketData
spdy_data(
10830 spdy_reads
, arraysize(spdy_reads
),
10831 spdy_writes
, arraysize(spdy_writes
));
10832 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10834 TestCompletionCallback callback
;
10835 HttpRequestInfo request1
;
10836 request1
.method
= "GET";
10837 request1
.url
= GURL("https://www.google.com/");
10838 request1
.load_flags
= 0;
10839 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10841 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10843 EXPECT_EQ(OK
, callback
.WaitForResult());
10845 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10846 ASSERT_TRUE(response
!= NULL
);
10847 ASSERT_TRUE(response
->headers
.get() != NULL
);
10848 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10850 std::string response_data
;
10851 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
10852 EXPECT_EQ("hello!", response_data
);
10854 // Preload www.gmail.com into HostCache.
10855 HostPortPair
host_port("www.gmail.com", 443);
10856 HostResolver::RequestInfo
resolve_info(host_port
);
10857 AddressList ignored
;
10858 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
10861 callback
.callback(),
10864 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10865 rv
= callback
.WaitForResult();
10868 HttpRequestInfo request2
;
10869 request2
.method
= "GET";
10870 request2
.url
= GURL("https://www.gmail.com/");
10871 request2
.load_flags
= 0;
10872 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
10874 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
10875 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10876 EXPECT_EQ(OK
, callback
.WaitForResult());
10878 response
= trans2
.GetResponseInfo();
10879 ASSERT_TRUE(response
!= NULL
);
10880 ASSERT_TRUE(response
->headers
.get() != NULL
);
10881 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10882 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10883 EXPECT_TRUE(response
->was_npn_negotiated
);
10884 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
10885 EXPECT_EQ("hello!", response_data
);
10887 #undef MAYBE_UseIPConnectionPooling
10889 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
10890 HttpStreamFactory::set_use_alternate_protocols(true);
10891 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
10893 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
10894 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
10895 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10896 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
10897 pool_peer
.DisableDomainAuthenticationVerification();
10899 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10900 ssl
.SetNextProto(GetParam());
10901 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10903 scoped_ptr
<SpdyFrame
> host1_req(
10904 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
10905 scoped_ptr
<SpdyFrame
> host2_req(
10906 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
10907 MockWrite spdy_writes
[] = {
10908 CreateMockWrite(*host1_req
, 1),
10909 CreateMockWrite(*host2_req
, 4),
10911 scoped_ptr
<SpdyFrame
> host1_resp(
10912 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10913 scoped_ptr
<SpdyFrame
> host1_resp_body(
10914 spdy_util_
.ConstructSpdyBodyFrame(1, true));
10915 scoped_ptr
<SpdyFrame
> host2_resp(
10916 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
10917 scoped_ptr
<SpdyFrame
> host2_resp_body(
10918 spdy_util_
.ConstructSpdyBodyFrame(3, true));
10919 MockRead spdy_reads
[] = {
10920 CreateMockRead(*host1_resp
, 2),
10921 CreateMockRead(*host1_resp_body
, 3),
10922 CreateMockRead(*host2_resp
, 5),
10923 CreateMockRead(*host2_resp_body
, 6),
10924 MockRead(ASYNC
, 0, 7),
10927 IPAddressNumber ip
;
10928 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
10929 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
10930 MockConnect
connect(ASYNC
, OK
, peer_addr
);
10931 OrderedSocketData
spdy_data(
10933 spdy_reads
, arraysize(spdy_reads
),
10934 spdy_writes
, arraysize(spdy_writes
));
10935 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10937 TestCompletionCallback callback
;
10938 HttpRequestInfo request1
;
10939 request1
.method
= "GET";
10940 request1
.url
= GURL("https://www.google.com/");
10941 request1
.load_flags
= 0;
10942 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
10944 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
10945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10946 EXPECT_EQ(OK
, callback
.WaitForResult());
10948 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
10949 ASSERT_TRUE(response
!= NULL
);
10950 ASSERT_TRUE(response
->headers
.get() != NULL
);
10951 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10953 std::string response_data
;
10954 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
10955 EXPECT_EQ("hello!", response_data
);
10957 HttpRequestInfo request2
;
10958 request2
.method
= "GET";
10959 request2
.url
= GURL("https://www.gmail.com/");
10960 request2
.load_flags
= 0;
10961 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
10963 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
10964 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10965 EXPECT_EQ(OK
, callback
.WaitForResult());
10967 response
= trans2
.GetResponseInfo();
10968 ASSERT_TRUE(response
!= NULL
);
10969 ASSERT_TRUE(response
->headers
.get() != NULL
);
10970 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10971 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10972 EXPECT_TRUE(response
->was_npn_negotiated
);
10973 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
10974 EXPECT_EQ("hello!", response_data
);
10977 class OneTimeCachingHostResolver
: public net::HostResolver
{
10979 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
10980 : host_port_(host_port
) {}
10981 virtual ~OneTimeCachingHostResolver() {}
10983 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
10985 // HostResolver methods:
10986 virtual int Resolve(const RequestInfo
& info
,
10987 RequestPriority priority
,
10988 AddressList
* addresses
,
10989 const CompletionCallback
& callback
,
10990 RequestHandle
* out_req
,
10991 const BoundNetLog
& net_log
) OVERRIDE
{
10992 return host_resolver_
.Resolve(
10993 info
, priority
, addresses
, callback
, out_req
, net_log
);
10996 virtual int ResolveFromCache(const RequestInfo
& info
,
10997 AddressList
* addresses
,
10998 const BoundNetLog
& net_log
) OVERRIDE
{
10999 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11000 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11001 host_resolver_
.GetHostCache()->clear();
11005 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
11006 host_resolver_
.CancelRequest(req
);
11009 MockCachingHostResolver
* GetMockHostResolver() {
11010 return &host_resolver_
;
11014 MockCachingHostResolver host_resolver_
;
11015 const HostPortPair host_port_
;
11018 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11019 #if defined(OS_WIN)
11020 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11021 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11023 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11024 UseIPConnectionPoolingWithHostCacheExpiration
11026 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11027 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11028 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11029 // prefix doesn't work with parametrized tests).
11030 #if defined(OS_WIN)
11033 HttpStreamFactory::set_use_alternate_protocols(true);
11034 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11036 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11037 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11038 HttpNetworkSession::Params params
=
11039 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11040 params
.host_resolver
= &host_resolver
;
11041 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11042 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11043 pool_peer
.DisableDomainAuthenticationVerification();
11045 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11046 ssl
.SetNextProto(GetParam());
11047 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11049 scoped_ptr
<SpdyFrame
> host1_req(
11050 spdy_util_
.ConstructSpdyGet("https://www.google.com", false, 1, LOWEST
));
11051 scoped_ptr
<SpdyFrame
> host2_req(
11052 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11053 MockWrite spdy_writes
[] = {
11054 CreateMockWrite(*host1_req
, 1),
11055 CreateMockWrite(*host2_req
, 4),
11057 scoped_ptr
<SpdyFrame
> host1_resp(
11058 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11059 scoped_ptr
<SpdyFrame
> host1_resp_body(
11060 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11061 scoped_ptr
<SpdyFrame
> host2_resp(
11062 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11063 scoped_ptr
<SpdyFrame
> host2_resp_body(
11064 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11065 MockRead spdy_reads
[] = {
11066 CreateMockRead(*host1_resp
, 2),
11067 CreateMockRead(*host1_resp_body
, 3),
11068 CreateMockRead(*host2_resp
, 5),
11069 CreateMockRead(*host2_resp_body
, 6),
11070 MockRead(ASYNC
, 0, 7),
11073 IPAddressNumber ip
;
11074 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11075 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11076 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11077 OrderedSocketData
spdy_data(
11079 spdy_reads
, arraysize(spdy_reads
),
11080 spdy_writes
, arraysize(spdy_writes
));
11081 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11083 TestCompletionCallback callback
;
11084 HttpRequestInfo request1
;
11085 request1
.method
= "GET";
11086 request1
.url
= GURL("https://www.google.com/");
11087 request1
.load_flags
= 0;
11088 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11090 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11091 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11092 EXPECT_EQ(OK
, callback
.WaitForResult());
11094 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11095 ASSERT_TRUE(response
!= NULL
);
11096 ASSERT_TRUE(response
->headers
.get() != NULL
);
11097 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11099 std::string response_data
;
11100 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11101 EXPECT_EQ("hello!", response_data
);
11103 // Preload cache entries into HostCache.
11104 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11105 AddressList ignored
;
11106 rv
= host_resolver
.Resolve(resolve_info
,
11109 callback
.callback(),
11112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11113 rv
= callback
.WaitForResult();
11116 HttpRequestInfo request2
;
11117 request2
.method
= "GET";
11118 request2
.url
= GURL("https://www.gmail.com/");
11119 request2
.load_flags
= 0;
11120 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11122 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11124 EXPECT_EQ(OK
, callback
.WaitForResult());
11126 response
= trans2
.GetResponseInfo();
11127 ASSERT_TRUE(response
!= NULL
);
11128 ASSERT_TRUE(response
->headers
.get() != NULL
);
11129 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11130 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11131 EXPECT_TRUE(response
->was_npn_negotiated
);
11132 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11133 EXPECT_EQ("hello!", response_data
);
11136 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11138 TEST_P(HttpNetworkTransactionTest
, ReadPipelineEvictionFallback
) {
11139 MockRead data_reads1
[] = {
11140 MockRead(SYNCHRONOUS
, ERR_PIPELINE_EVICTION
),
11142 MockRead data_reads2
[] = {
11143 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11144 MockRead("hello world"),
11145 MockRead(SYNCHRONOUS
, OK
),
11147 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
), NULL
, 0);
11148 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
), NULL
, 0);
11149 StaticSocketDataProvider
* data
[] = { &data1
, &data2
};
11151 SimpleGetHelperResult out
= SimpleGetHelperForData(data
, arraysize(data
));
11153 EXPECT_EQ(OK
, out
.rv
);
11154 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
11155 EXPECT_EQ("hello world", out
.response_data
);
11158 TEST_P(HttpNetworkTransactionTest
, SendPipelineEvictionFallback
) {
11159 MockWrite data_writes1
[] = {
11160 MockWrite(SYNCHRONOUS
, ERR_PIPELINE_EVICTION
),
11162 MockWrite data_writes2
[] = {
11163 MockWrite("GET / HTTP/1.1\r\n"
11164 "Host: www.google.com\r\n"
11165 "Connection: keep-alive\r\n\r\n"),
11167 MockRead data_reads2
[] = {
11168 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
11169 MockRead("hello world"),
11170 MockRead(SYNCHRONOUS
, OK
),
11172 StaticSocketDataProvider
data1(NULL
, 0,
11173 data_writes1
, arraysize(data_writes1
));
11174 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
11175 data_writes2
, arraysize(data_writes2
));
11176 StaticSocketDataProvider
* data
[] = { &data1
, &data2
};
11178 SimpleGetHelperResult out
= SimpleGetHelperForData(data
, arraysize(data
));
11180 EXPECT_EQ(OK
, out
.rv
);
11181 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
11182 EXPECT_EQ("hello world", out
.response_data
);
11185 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11186 const std::string https_url
= "https://www.google.com/";
11187 const std::string http_url
= "http://www.google.com:443/";
11189 // SPDY GET for HTTPS URL
11190 scoped_ptr
<SpdyFrame
> req1(
11191 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11193 MockWrite writes1
[] = {
11194 CreateMockWrite(*req1
, 0),
11197 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11198 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11199 MockRead reads1
[] = {
11200 CreateMockRead(*resp1
, 1),
11201 CreateMockRead(*body1
, 2),
11202 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11205 DelayedSocketData
data1(
11206 1, reads1
, arraysize(reads1
),
11207 writes1
, arraysize(writes1
));
11208 MockConnect
connect_data1(ASYNC
, OK
);
11209 data1
.set_connect_data(connect_data1
);
11211 // HTTP GET for the HTTP URL
11212 MockWrite writes2
[] = {
11213 MockWrite(ASYNC
, 4,
11214 "GET / HTTP/1.1\r\n"
11215 "Host: www.google.com:443\r\n"
11216 "Connection: keep-alive\r\n\r\n"),
11219 MockRead reads2
[] = {
11220 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11221 MockRead(ASYNC
, 6, "hello"),
11222 MockRead(ASYNC
, 7, OK
),
11225 DelayedSocketData
data2(
11226 1, reads2
, arraysize(reads2
),
11227 writes2
, arraysize(writes2
));
11229 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11230 ssl
.SetNextProto(GetParam());
11231 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11232 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11233 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11235 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11237 // Start the first transaction to set up the SpdySession
11238 HttpRequestInfo request1
;
11239 request1
.method
= "GET";
11240 request1
.url
= GURL(https_url
);
11241 request1
.load_flags
= 0;
11242 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11243 TestCompletionCallback callback1
;
11244 EXPECT_EQ(ERR_IO_PENDING
,
11245 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11246 base::MessageLoop::current()->RunUntilIdle();
11248 EXPECT_EQ(OK
, callback1
.WaitForResult());
11249 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11251 // Now, start the HTTP request
11252 HttpRequestInfo request2
;
11253 request2
.method
= "GET";
11254 request2
.url
= GURL(http_url
);
11255 request2
.load_flags
= 0;
11256 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11257 TestCompletionCallback callback2
;
11258 EXPECT_EQ(ERR_IO_PENDING
,
11259 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11260 base::MessageLoop::current()->RunUntilIdle();
11262 EXPECT_EQ(OK
, callback2
.WaitForResult());
11263 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11266 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11267 const std::string https_url
= "https://www.google.com/";
11268 const std::string http_url
= "http://www.google.com:443/";
11270 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11271 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1,
11273 scoped_ptr
<SpdyFrame
> req1(
11274 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11275 scoped_ptr
<SpdyFrame
> wrapped_req1(
11276 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11278 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11279 SpdySynStreamIR
req2_ir(3);
11280 spdy_util_
.SetPriority(MEDIUM
, &req2_ir
);
11281 req2_ir
.set_fin(true);
11282 req2_ir
.SetHeader(spdy_util_
.GetMethodKey(), "GET");
11283 req2_ir
.SetHeader(spdy_util_
.GetPathKey(),
11284 spdy_util_
.is_spdy2() ? http_url
.c_str() : "/");
11285 req2_ir
.SetHeader(spdy_util_
.GetHostKey(), "www.google.com:443");
11286 req2_ir
.SetHeader(spdy_util_
.GetSchemeKey(), "http");
11287 spdy_util_
.MaybeAddVersionHeader(&req2_ir
);
11288 scoped_ptr
<SpdyFrame
> req2(
11289 spdy_util_
.CreateFramer(false)->SerializeFrame(req2_ir
));
11291 MockWrite writes1
[] = {
11292 CreateMockWrite(*connect
, 0),
11293 CreateMockWrite(*wrapped_req1
, 2),
11294 CreateMockWrite(*req2
, 5),
11297 scoped_ptr
<SpdyFrame
> conn_resp(
11298 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11299 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11300 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11301 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11302 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11303 scoped_ptr
<SpdyFrame
> wrapped_body1(
11304 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11305 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11306 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11307 MockRead reads1
[] = {
11308 CreateMockRead(*conn_resp
, 1),
11309 CreateMockRead(*wrapped_resp1
, 3),
11310 CreateMockRead(*wrapped_body1
, 4),
11311 CreateMockRead(*resp2
, 6),
11312 CreateMockRead(*body2
, 7),
11313 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11316 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11317 writes1
, arraysize(writes1
));
11318 MockConnect
connect_data1(ASYNC
, OK
);
11319 data1
.set_connect_data(connect_data1
);
11321 session_deps_
.proxy_service
.reset(
11322 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11323 CapturingNetLog log
;
11324 session_deps_
.net_log
= &log
;
11325 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11326 ssl1
.SetNextProto(GetParam());
11327 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11328 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11329 ssl2
.SetNextProto(GetParam());
11330 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11331 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11333 scoped_refptr
<HttpNetworkSession
> session(
11334 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11336 // Start the first transaction to set up the SpdySession
11337 HttpRequestInfo request1
;
11338 request1
.method
= "GET";
11339 request1
.url
= GURL(https_url
);
11340 request1
.load_flags
= 0;
11341 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11342 TestCompletionCallback callback1
;
11343 EXPECT_EQ(ERR_IO_PENDING
,
11344 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11345 base::MessageLoop::current()->RunUntilIdle();
11348 EXPECT_EQ(OK
, callback1
.WaitForResult());
11349 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11351 LoadTimingInfo load_timing_info1
;
11352 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11353 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11354 CONNECT_TIMING_HAS_SSL_TIMES
);
11356 // Now, start the HTTP request
11357 HttpRequestInfo request2
;
11358 request2
.method
= "GET";
11359 request2
.url
= GURL(http_url
);
11360 request2
.load_flags
= 0;
11361 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11362 TestCompletionCallback callback2
;
11363 EXPECT_EQ(ERR_IO_PENDING
,
11364 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11365 base::MessageLoop::current()->RunUntilIdle();
11368 EXPECT_EQ(OK
, callback2
.WaitForResult());
11369 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11371 LoadTimingInfo load_timing_info2
;
11372 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11373 // The established SPDY sessions is considered reused by the HTTP request.
11374 TestLoadTimingReusedWithPac(load_timing_info2
);
11375 // HTTP requests over a SPDY session should have a different connection
11376 // socket_log_id than requests over a tunnel.
11377 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11380 TEST_P(HttpNetworkTransactionTest
, UseSpdySessionForHttpWhenForced
) {
11381 HttpStreamFactory::set_force_spdy_always(true);
11382 const std::string https_url
= "https://www.google.com/";
11383 const std::string http_url
= "http://www.google.com:443/";
11385 // SPDY GET for HTTPS URL
11386 scoped_ptr
<SpdyFrame
> req1(
11387 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11388 // SPDY GET for the HTTP URL
11389 scoped_ptr
<SpdyFrame
> req2(
11390 spdy_util_
.ConstructSpdyGet(http_url
.c_str(), false, 3, MEDIUM
));
11392 MockWrite writes
[] = {
11393 CreateMockWrite(*req1
, 1),
11394 CreateMockWrite(*req2
, 4),
11397 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11398 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11399 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11400 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11401 MockRead reads
[] = {
11402 CreateMockRead(*resp1
, 2),
11403 CreateMockRead(*body1
, 3),
11404 CreateMockRead(*resp2
, 5),
11405 CreateMockRead(*body2
, 6),
11406 MockRead(ASYNC
, ERR_IO_PENDING
, 7)
11409 OrderedSocketData
data(reads
, arraysize(reads
),
11410 writes
, arraysize(writes
));
11412 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11413 ssl
.SetNextProto(GetParam());
11414 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11415 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11417 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11419 // Start the first transaction to set up the SpdySession
11420 HttpRequestInfo request1
;
11421 request1
.method
= "GET";
11422 request1
.url
= GURL(https_url
);
11423 request1
.load_flags
= 0;
11424 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11425 TestCompletionCallback callback1
;
11426 EXPECT_EQ(ERR_IO_PENDING
,
11427 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11428 base::MessageLoop::current()->RunUntilIdle();
11430 EXPECT_EQ(OK
, callback1
.WaitForResult());
11431 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11433 // Now, start the HTTP request
11434 HttpRequestInfo request2
;
11435 request2
.method
= "GET";
11436 request2
.url
= GURL(http_url
);
11437 request2
.load_flags
= 0;
11438 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11439 TestCompletionCallback callback2
;
11440 EXPECT_EQ(ERR_IO_PENDING
,
11441 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11442 base::MessageLoop::current()->RunUntilIdle();
11444 EXPECT_EQ(OK
, callback2
.WaitForResult());
11445 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11448 // Test that in the case where we have a SPDY session to a SPDY proxy
11449 // that we do not pool other origins that resolve to the same IP when
11450 // the certificate does not match the new origin.
11451 // http://crbug.com/134690
11452 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11453 const std::string url1
= "http://www.google.com/";
11454 const std::string url2
= "https://mail.google.com/";
11455 const std::string ip_addr
= "1.2.3.4";
11457 // SPDY GET for HTTP URL (through SPDY proxy)
11458 scoped_ptr
<SpdyHeaderBlock
> headers(
11459 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.google.com/"));
11460 scoped_ptr
<SpdyFrame
> req1(spdy_util_
.ConstructSpdyControlFrame(
11461 headers
.Pass(), false, 1, LOWEST
, SYN_STREAM
, CONTROL_FLAG_FIN
, 0));
11463 MockWrite writes1
[] = {
11464 CreateMockWrite(*req1
, 0),
11467 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11468 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11469 MockRead reads1
[] = {
11470 CreateMockRead(*resp1
, 1),
11471 CreateMockRead(*body1
, 2),
11472 MockRead(ASYNC
, OK
, 3) // EOF
11475 scoped_ptr
<DeterministicSocketData
> data1(
11476 new DeterministicSocketData(reads1
, arraysize(reads1
),
11477 writes1
, arraysize(writes1
)));
11478 IPAddressNumber ip
;
11479 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
11480 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11481 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
11482 data1
->set_connect_data(connect_data1
);
11484 // SPDY GET for HTTPS URL (direct)
11485 scoped_ptr
<SpdyFrame
> req2(
11486 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
11488 MockWrite writes2
[] = {
11489 CreateMockWrite(*req2
, 0),
11492 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11493 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11494 MockRead reads2
[] = {
11495 CreateMockRead(*resp2
, 1),
11496 CreateMockRead(*body2
, 2),
11497 MockRead(ASYNC
, OK
, 3) // EOF
11500 scoped_ptr
<DeterministicSocketData
> data2(
11501 new DeterministicSocketData(reads2
, arraysize(reads2
),
11502 writes2
, arraysize(writes2
)));
11503 MockConnect
connect_data2(ASYNC
, OK
);
11504 data2
->set_connect_data(connect_data2
);
11506 // Set up a proxy config that sends HTTP requests to a proxy, and
11507 // all others direct.
11508 ProxyConfig proxy_config
;
11509 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
11510 CapturingProxyResolver
* capturing_proxy_resolver
=
11511 new CapturingProxyResolver();
11512 session_deps_
.proxy_service
.reset(new ProxyService(
11513 new ProxyConfigServiceFixed(proxy_config
), capturing_proxy_resolver
,
11516 // Load a valid cert. Note, that this does not need to
11517 // be valid for proxy because the MockSSLClientSocket does
11518 // not actually verify it. But SpdySession will use this
11519 // to see if it is valid for the new origin
11520 base::FilePath certs_dir
= GetTestCertsDirectory();
11521 scoped_refptr
<X509Certificate
> server_cert(
11522 ImportCertFromFile(certs_dir
, "ok_cert.pem"));
11523 ASSERT_NE(static_cast<X509Certificate
*>(NULL
), server_cert
);
11525 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11526 ssl1
.SetNextProto(GetParam());
11527 ssl1
.cert
= server_cert
;
11528 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11529 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11532 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11533 ssl2
.SetNextProto(GetParam());
11534 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11535 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11538 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11539 session_deps_
.host_resolver
->rules()->AddRule("mail.google.com", ip_addr
);
11540 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
11542 scoped_refptr
<HttpNetworkSession
> session(
11543 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11545 // Start the first transaction to set up the SpdySession
11546 HttpRequestInfo request1
;
11547 request1
.method
= "GET";
11548 request1
.url
= GURL(url1
);
11549 request1
.load_flags
= 0;
11550 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11551 TestCompletionCallback callback1
;
11552 ASSERT_EQ(ERR_IO_PENDING
,
11553 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11556 ASSERT_TRUE(callback1
.have_result());
11557 EXPECT_EQ(OK
, callback1
.WaitForResult());
11558 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11560 // Now, start the HTTP request
11561 HttpRequestInfo request2
;
11562 request2
.method
= "GET";
11563 request2
.url
= GURL(url2
);
11564 request2
.load_flags
= 0;
11565 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11566 TestCompletionCallback callback2
;
11567 EXPECT_EQ(ERR_IO_PENDING
,
11568 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11569 base::MessageLoop::current()->RunUntilIdle();
11572 ASSERT_TRUE(callback2
.have_result());
11573 EXPECT_EQ(OK
, callback2
.WaitForResult());
11574 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11577 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
11578 // error) in SPDY session, removes the socket from pool and closes the SPDY
11579 // session. Verify that new url's from the same HttpNetworkSession (and a new
11580 // SpdySession) do work. http://crbug.com/224701
11581 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
11582 const std::string https_url
= "https://www.google.com/";
11584 MockRead reads1
[] = {
11585 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
11588 scoped_ptr
<DeterministicSocketData
> data1(
11589 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
11592 scoped_ptr
<SpdyFrame
> req2(
11593 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
11594 MockWrite writes2
[] = {
11595 CreateMockWrite(*req2
, 0),
11598 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11599 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11600 MockRead reads2
[] = {
11601 CreateMockRead(*resp2
, 1),
11602 CreateMockRead(*body2
, 2),
11603 MockRead(ASYNC
, OK
, 3) // EOF
11606 scoped_ptr
<DeterministicSocketData
> data2(
11607 new DeterministicSocketData(reads2
, arraysize(reads2
),
11608 writes2
, arraysize(writes2
)));
11610 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11611 ssl1
.SetNextProto(GetParam());
11612 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11613 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11616 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11617 ssl2
.SetNextProto(GetParam());
11618 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11619 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
11622 scoped_refptr
<HttpNetworkSession
> session(
11623 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11625 // Start the first transaction to set up the SpdySession and verify that
11626 // connection was closed.
11627 HttpRequestInfo request1
;
11628 request1
.method
= "GET";
11629 request1
.url
= GURL(https_url
);
11630 request1
.load_flags
= 0;
11631 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
11632 TestCompletionCallback callback1
;
11633 EXPECT_EQ(ERR_IO_PENDING
,
11634 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11635 base::MessageLoop::current()->RunUntilIdle();
11636 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
11638 // Now, start the second request and make sure it succeeds.
11639 HttpRequestInfo request2
;
11640 request2
.method
= "GET";
11641 request2
.url
= GURL(https_url
);
11642 request2
.load_flags
= 0;
11643 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11644 TestCompletionCallback callback2
;
11645 EXPECT_EQ(ERR_IO_PENDING
,
11646 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11647 base::MessageLoop::current()->RunUntilIdle();
11650 ASSERT_TRUE(callback2
.have_result());
11651 EXPECT_EQ(OK
, callback2
.WaitForResult());
11652 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11655 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
11656 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
11657 ClientSocketPoolManager::set_max_sockets_per_group(
11658 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11659 ClientSocketPoolManager::set_max_sockets_per_pool(
11660 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
11662 // Use two different hosts with different IPs so they don't get pooled.
11663 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
11664 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
11665 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11667 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
11668 ssl1
.SetNextProto(GetParam());
11669 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
11670 ssl2
.SetNextProto(GetParam());
11671 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11672 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11674 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
11675 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
11676 MockWrite spdy1_writes
[] = {
11677 CreateMockWrite(*host1_req
, 1),
11679 scoped_ptr
<SpdyFrame
> host1_resp(
11680 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11681 scoped_ptr
<SpdyFrame
> host1_resp_body(
11682 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11683 MockRead spdy1_reads
[] = {
11684 CreateMockRead(*host1_resp
, 2),
11685 CreateMockRead(*host1_resp_body
, 3),
11686 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11689 scoped_ptr
<OrderedSocketData
> spdy1_data(
11690 new OrderedSocketData(
11691 spdy1_reads
, arraysize(spdy1_reads
),
11692 spdy1_writes
, arraysize(spdy1_writes
)));
11693 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
11695 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
11696 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
11697 MockWrite spdy2_writes
[] = {
11698 CreateMockWrite(*host2_req
, 1),
11700 scoped_ptr
<SpdyFrame
> host2_resp(
11701 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11702 scoped_ptr
<SpdyFrame
> host2_resp_body(
11703 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11704 MockRead spdy2_reads
[] = {
11705 CreateMockRead(*host2_resp
, 2),
11706 CreateMockRead(*host2_resp_body
, 3),
11707 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
11710 scoped_ptr
<OrderedSocketData
> spdy2_data(
11711 new OrderedSocketData(
11712 spdy2_reads
, arraysize(spdy2_reads
),
11713 spdy2_writes
, arraysize(spdy2_writes
)));
11714 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
11716 MockWrite http_write
[] = {
11717 MockWrite("GET / HTTP/1.1\r\n"
11718 "Host: www.a.com\r\n"
11719 "Connection: keep-alive\r\n\r\n"),
11722 MockRead http_read
[] = {
11723 MockRead("HTTP/1.1 200 OK\r\n"),
11724 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11725 MockRead("Content-Length: 6\r\n\r\n"),
11726 MockRead("hello!"),
11728 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
11729 http_write
, arraysize(http_write
));
11730 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11732 HostPortPair
host_port_pair_a("www.a.com", 443);
11733 SpdySessionKey
spdy_session_key_a(
11734 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11736 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11738 TestCompletionCallback callback
;
11739 HttpRequestInfo request1
;
11740 request1
.method
= "GET";
11741 request1
.url
= GURL("https://www.a.com/");
11742 request1
.load_flags
= 0;
11743 scoped_ptr
<HttpNetworkTransaction
> trans(
11744 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11746 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
11747 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11748 EXPECT_EQ(OK
, callback
.WaitForResult());
11750 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11751 ASSERT_TRUE(response
!= NULL
);
11752 ASSERT_TRUE(response
->headers
.get() != NULL
);
11753 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11754 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11755 EXPECT_TRUE(response
->was_npn_negotiated
);
11757 std::string response_data
;
11758 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11759 EXPECT_EQ("hello!", response_data
);
11762 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11764 HostPortPair
host_port_pair_b("www.b.com", 443);
11765 SpdySessionKey
spdy_session_key_b(
11766 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11768 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11769 HttpRequestInfo request2
;
11770 request2
.method
= "GET";
11771 request2
.url
= GURL("https://www.b.com/");
11772 request2
.load_flags
= 0;
11773 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11775 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
11776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11777 EXPECT_EQ(OK
, callback
.WaitForResult());
11779 response
= trans
->GetResponseInfo();
11780 ASSERT_TRUE(response
!= NULL
);
11781 ASSERT_TRUE(response
->headers
.get() != NULL
);
11782 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11783 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11784 EXPECT_TRUE(response
->was_npn_negotiated
);
11785 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11786 EXPECT_EQ("hello!", response_data
);
11788 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11790 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11792 HostPortPair
host_port_pair_a1("www.a.com", 80);
11793 SpdySessionKey
spdy_session_key_a1(
11794 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
11796 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
11797 HttpRequestInfo request3
;
11798 request3
.method
= "GET";
11799 request3
.url
= GURL("http://www.a.com/");
11800 request3
.load_flags
= 0;
11801 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11803 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
11804 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11805 EXPECT_EQ(OK
, callback
.WaitForResult());
11807 response
= trans
->GetResponseInfo();
11808 ASSERT_TRUE(response
!= NULL
);
11809 ASSERT_TRUE(response
->headers
.get() != NULL
);
11810 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11811 EXPECT_FALSE(response
->was_fetched_via_spdy
);
11812 EXPECT_FALSE(response
->was_npn_negotiated
);
11813 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
11814 EXPECT_EQ("hello!", response_data
);
11816 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
11818 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
11821 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
11822 HttpRequestInfo request
;
11823 request
.method
= "GET";
11824 request
.url
= GURL("http://www.google.com/");
11825 request
.load_flags
= 0;
11827 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11828 scoped_ptr
<HttpTransaction
> trans(
11829 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11831 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
11832 StaticSocketDataProvider data
;
11833 data
.set_connect_data(mock_connect
);
11834 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11836 TestCompletionCallback callback
;
11838 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11839 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11841 rv
= callback
.WaitForResult();
11842 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11844 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11846 // We don't care whether this succeeds or fails, but it shouldn't crash.
11847 HttpRequestHeaders request_headers
;
11848 trans
->GetFullRequestHeaders(&request_headers
);
11851 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
11852 HttpRequestInfo request
;
11853 request
.method
= "GET";
11854 request
.url
= GURL("http://www.google.com/");
11855 request
.load_flags
= 0;
11857 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11858 scoped_ptr
<HttpTransaction
> trans(
11859 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11861 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11862 StaticSocketDataProvider data
;
11863 data
.set_connect_data(mock_connect
);
11864 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11866 TestCompletionCallback callback
;
11868 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11869 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11871 rv
= callback
.WaitForResult();
11872 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11874 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11876 // We don't care whether this succeeds or fails, but it shouldn't crash.
11877 HttpRequestHeaders request_headers
;
11878 trans
->GetFullRequestHeaders(&request_headers
);
11881 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
11882 HttpRequestInfo request
;
11883 request
.method
= "GET";
11884 request
.url
= GURL("http://www.google.com/");
11885 request
.load_flags
= 0;
11887 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11888 scoped_ptr
<HttpTransaction
> trans(
11889 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11891 MockWrite data_writes
[] = {
11892 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
11894 MockRead data_reads
[] = {
11895 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
11898 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11899 data_writes
, arraysize(data_writes
));
11900 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11902 TestCompletionCallback callback
;
11904 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11905 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11907 rv
= callback
.WaitForResult();
11908 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11910 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11912 HttpRequestHeaders request_headers
;
11913 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11914 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11917 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
11918 HttpRequestInfo request
;
11919 request
.method
= "GET";
11920 request
.url
= GURL("http://www.google.com/");
11921 request
.load_flags
= 0;
11923 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11924 scoped_ptr
<HttpTransaction
> trans(
11925 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11927 MockWrite data_writes
[] = {
11928 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
11930 MockRead data_reads
[] = {
11931 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
11934 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11935 data_writes
, arraysize(data_writes
));
11936 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11938 TestCompletionCallback callback
;
11940 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11943 rv
= callback
.WaitForResult();
11944 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11946 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11948 HttpRequestHeaders request_headers
;
11949 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11950 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11953 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
11954 HttpRequestInfo request
;
11955 request
.method
= "GET";
11956 request
.url
= GURL("http://www.google.com/");
11957 request
.load_flags
= 0;
11959 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11960 scoped_ptr
<HttpTransaction
> trans(
11961 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
11963 MockWrite data_writes
[] = {
11964 MockWrite("GET / HTTP/1.1\r\n"
11965 "Host: www.google.com\r\n"
11966 "Connection: keep-alive\r\n\r\n"),
11968 MockRead data_reads
[] = {
11969 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
11972 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
11973 data_writes
, arraysize(data_writes
));
11974 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11976 TestCompletionCallback callback
;
11978 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11981 rv
= callback
.WaitForResult();
11982 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
11984 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
11986 HttpRequestHeaders request_headers
;
11987 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
11988 EXPECT_TRUE(request_headers
.HasHeader("Host"));
11991 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
11992 HttpRequestInfo request
;
11993 request
.method
= "GET";
11994 request
.url
= GURL("http://www.google.com/");
11995 request
.load_flags
= 0;
11997 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11998 scoped_ptr
<HttpTransaction
> trans(
11999 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12001 MockWrite data_writes
[] = {
12002 MockWrite("GET / HTTP/1.1\r\n"
12003 "Host: www.google.com\r\n"
12004 "Connection: keep-alive\r\n\r\n"),
12006 MockRead data_reads
[] = {
12007 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12010 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12011 data_writes
, arraysize(data_writes
));
12012 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12014 TestCompletionCallback callback
;
12016 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12017 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12019 rv
= callback
.WaitForResult();
12020 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12022 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12024 HttpRequestHeaders request_headers
;
12025 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12026 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12029 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12030 HttpRequestInfo request
;
12031 request
.method
= "GET";
12032 request
.url
= GURL("http://www.google.com/");
12033 request
.load_flags
= 0;
12034 request
.extra_headers
.SetHeader("X-Foo", "bar");
12036 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12037 scoped_ptr
<HttpTransaction
> trans(
12038 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12040 MockWrite data_writes
[] = {
12041 MockWrite("GET / HTTP/1.1\r\n"
12042 "Host: www.google.com\r\n"
12043 "Connection: keep-alive\r\n"
12044 "X-Foo: bar\r\n\r\n"),
12046 MockRead data_reads
[] = {
12047 MockRead("HTTP/1.1 200 OK\r\n"
12048 "Content-Length: 5\r\n\r\n"
12050 MockRead(ASYNC
, ERR_UNEXPECTED
),
12053 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12054 data_writes
, arraysize(data_writes
));
12055 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12057 TestCompletionCallback callback
;
12059 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12060 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12062 rv
= callback
.WaitForResult();
12065 HttpRequestHeaders request_headers
;
12066 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12068 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12069 EXPECT_EQ("bar", foo
);
12074 // Fake HttpStreamBase that simply records calls to SetPriority().
12075 class FakeStream
: public HttpStreamBase
,
12076 public base::SupportsWeakPtr
<FakeStream
> {
12078 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12079 virtual ~FakeStream() {}
12081 RequestPriority
priority() const { return priority_
; }
12083 virtual int InitializeStream(const HttpRequestInfo
* request_info
,
12084 RequestPriority priority
,
12085 const BoundNetLog
& net_log
,
12086 const CompletionCallback
& callback
) OVERRIDE
{
12087 return ERR_IO_PENDING
;
12090 virtual int SendRequest(const HttpRequestHeaders
& request_headers
,
12091 HttpResponseInfo
* response
,
12092 const CompletionCallback
& callback
) OVERRIDE
{
12094 return ERR_UNEXPECTED
;
12097 virtual int ReadResponseHeaders(const CompletionCallback
& callback
) OVERRIDE
{
12099 return ERR_UNEXPECTED
;
12102 virtual const HttpResponseInfo
* GetResponseInfo() const OVERRIDE
{
12107 virtual int ReadResponseBody(IOBuffer
* buf
, int buf_len
,
12108 const CompletionCallback
& callback
) OVERRIDE
{
12110 return ERR_UNEXPECTED
;
12113 virtual void Close(bool not_reusable
) OVERRIDE
{}
12115 virtual bool IsResponseBodyComplete() const OVERRIDE
{
12120 virtual bool CanFindEndOfResponse() const OVERRIDE
{
12124 virtual bool IsConnectionReused() const OVERRIDE
{
12129 virtual void SetConnectionReused() OVERRIDE
{
12133 virtual bool IsConnectionReusable() const OVERRIDE
{
12138 virtual int64
GetTotalReceivedBytes() const OVERRIDE
{
12143 virtual bool GetLoadTimingInfo(
12144 LoadTimingInfo
* load_timing_info
) const OVERRIDE
{
12149 virtual void GetSSLInfo(SSLInfo
* ssl_info
) OVERRIDE
{
12153 virtual void GetSSLCertRequestInfo(
12154 SSLCertRequestInfo
* cert_request_info
) OVERRIDE
{
12158 virtual bool IsSpdyHttpStream() const OVERRIDE
{
12163 virtual void Drain(HttpNetworkSession
* session
) OVERRIDE
{
12167 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12168 priority_
= priority
;
12172 RequestPriority priority_
;
12174 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12177 // Fake HttpStreamRequest that simply records calls to SetPriority()
12178 // and vends FakeStreams with its current priority.
12179 class FakeStreamRequest
: public HttpStreamRequest
,
12180 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12182 FakeStreamRequest(RequestPriority priority
,
12183 HttpStreamRequest::Delegate
* delegate
)
12184 : priority_(priority
),
12185 delegate_(delegate
),
12186 websocket_stream_create_helper_(NULL
) {}
12188 FakeStreamRequest(RequestPriority priority
,
12189 HttpStreamRequest::Delegate
* delegate
,
12190 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12191 : priority_(priority
),
12192 delegate_(delegate
),
12193 websocket_stream_create_helper_(create_helper
) {}
12195 virtual ~FakeStreamRequest() {}
12197 RequestPriority
priority() const { return priority_
; }
12199 const WebSocketHandshakeStreamBase::CreateHelper
*
12200 websocket_stream_create_helper() const {
12201 return websocket_stream_create_helper_
;
12204 // Create a new FakeStream and pass it to the request's
12205 // delegate. Returns a weak pointer to the FakeStream.
12206 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12207 FakeStream
* fake_stream
= new FakeStream(priority_
);
12208 // Do this before calling OnStreamReady() as OnStreamReady() may
12209 // immediately delete |fake_stream|.
12210 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12211 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12212 return weak_stream
;
12215 virtual int RestartTunnelWithProxyAuth(
12216 const AuthCredentials
& credentials
) OVERRIDE
{
12218 return ERR_UNEXPECTED
;
12221 virtual LoadState
GetLoadState() const OVERRIDE
{
12223 return LoadState();
12226 virtual void SetPriority(RequestPriority priority
) OVERRIDE
{
12227 priority_
= priority
;
12230 virtual bool was_npn_negotiated() const OVERRIDE
{
12234 virtual NextProto
protocol_negotiated() const OVERRIDE
{
12235 return kProtoUnknown
;
12238 virtual bool using_spdy() const OVERRIDE
{
12243 RequestPriority priority_
;
12244 HttpStreamRequest::Delegate
* const delegate_
;
12245 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12247 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12250 // Fake HttpStreamFactory that vends FakeStreamRequests.
12251 class FakeStreamFactory
: public HttpStreamFactory
{
12253 FakeStreamFactory() {}
12254 virtual ~FakeStreamFactory() {}
12256 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12257 // RequestStream() (which may be NULL if it was destroyed already).
12258 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12259 return last_stream_request_
;
12262 virtual HttpStreamRequest
* RequestStream(
12263 const HttpRequestInfo
& info
,
12264 RequestPriority priority
,
12265 const SSLConfig
& server_ssl_config
,
12266 const SSLConfig
& proxy_ssl_config
,
12267 HttpStreamRequest::Delegate
* delegate
,
12268 const BoundNetLog
& net_log
) OVERRIDE
{
12269 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12270 last_stream_request_
= fake_request
->AsWeakPtr();
12271 return fake_request
;
12274 virtual HttpStreamRequest
* RequestWebSocketHandshakeStream(
12275 const HttpRequestInfo
& info
,
12276 RequestPriority priority
,
12277 const SSLConfig
& server_ssl_config
,
12278 const SSLConfig
& proxy_ssl_config
,
12279 HttpStreamRequest::Delegate
* delegate
,
12280 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12281 const BoundNetLog
& net_log
) OVERRIDE
{
12282 FakeStreamRequest
* fake_request
=
12283 new FakeStreamRequest(priority
, delegate
, create_helper
);
12284 last_stream_request_
= fake_request
->AsWeakPtr();
12285 return fake_request
;
12288 virtual void PreconnectStreams(int num_streams
,
12289 const HttpRequestInfo
& info
,
12290 RequestPriority priority
,
12291 const SSLConfig
& server_ssl_config
,
12292 const SSLConfig
& proxy_ssl_config
) OVERRIDE
{
12296 virtual base::Value
* PipelineInfoToValue() const OVERRIDE
{
12301 virtual const HostMappingRules
* GetHostMappingRules() const OVERRIDE
{
12307 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12309 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12312 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12314 class FakeWebSocketStreamCreateHelper
:
12315 public WebSocketHandshakeStreamBase::CreateHelper
{
12317 virtual WebSocketHandshakeStreamBase
* CreateBasicStream(
12318 scoped_ptr
<ClientSocketHandle
> connection
,
12319 bool using_proxy
) OVERRIDE
{
12324 virtual WebSocketHandshakeStreamBase
* CreateSpdyStream(
12325 const base::WeakPtr
<SpdySession
>& session
,
12326 bool use_relative_url
) OVERRIDE
{
12331 virtual ~FakeWebSocketStreamCreateHelper() {}
12333 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12335 return scoped_ptr
<WebSocketStream
>();
12341 // Make sure that HttpNetworkTransaction passes on its priority to its
12342 // stream request on start.
12343 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12344 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12345 HttpNetworkSessionPeer
peer(session
);
12346 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12347 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12349 HttpNetworkTransaction
trans(LOW
, session
);
12351 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12353 HttpRequestInfo request
;
12354 TestCompletionCallback callback
;
12355 EXPECT_EQ(ERR_IO_PENDING
,
12356 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12358 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12359 fake_factory
->last_stream_request();
12360 ASSERT_TRUE(fake_request
!= NULL
);
12361 EXPECT_EQ(LOW
, fake_request
->priority());
12364 // Make sure that HttpNetworkTransaction passes on its priority
12365 // updates to its stream request.
12366 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12367 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12368 HttpNetworkSessionPeer
peer(session
);
12369 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12370 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12372 HttpNetworkTransaction
trans(LOW
, session
);
12374 HttpRequestInfo request
;
12375 TestCompletionCallback callback
;
12376 EXPECT_EQ(ERR_IO_PENDING
,
12377 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12379 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12380 fake_factory
->last_stream_request();
12381 ASSERT_TRUE(fake_request
!= NULL
);
12382 EXPECT_EQ(LOW
, fake_request
->priority());
12384 trans
.SetPriority(LOWEST
);
12385 ASSERT_TRUE(fake_request
!= NULL
);
12386 EXPECT_EQ(LOWEST
, fake_request
->priority());
12389 // Make sure that HttpNetworkTransaction passes on its priority
12390 // updates to its stream.
12391 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12392 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12393 HttpNetworkSessionPeer
peer(session
);
12394 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12395 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12397 HttpNetworkTransaction
trans(LOW
, session
);
12399 HttpRequestInfo request
;
12400 TestCompletionCallback callback
;
12401 EXPECT_EQ(ERR_IO_PENDING
,
12402 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12404 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12405 fake_factory
->last_stream_request();
12406 ASSERT_TRUE(fake_request
!= NULL
);
12407 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
12408 ASSERT_TRUE(fake_stream
!= NULL
);
12409 EXPECT_EQ(LOW
, fake_stream
->priority());
12411 trans
.SetPriority(LOWEST
);
12412 EXPECT_EQ(LOWEST
, fake_stream
->priority());
12415 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
12416 // The same logic needs to be tested for both ws: and wss: schemes, but this
12417 // test is already parameterised on NextProto, so it uses a loop to verify
12418 // that the different schemes work.
12419 std::string test_cases
[] = {"ws://www.google.com/", "wss://www.google.com/"};
12420 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
12421 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12422 HttpNetworkSessionPeer
peer(session
);
12423 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12424 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
12425 peer
.SetHttpStreamFactoryForWebSocket(
12426 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12428 HttpNetworkTransaction
trans(LOW
, session
);
12429 trans
.SetWebSocketHandshakeStreamCreateHelper(
12430 &websocket_stream_create_helper
);
12432 HttpRequestInfo request
;
12433 TestCompletionCallback callback
;
12434 request
.method
= "GET";
12435 request
.url
= GURL(test_cases
[i
]);
12437 EXPECT_EQ(ERR_IO_PENDING
,
12438 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12440 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12441 fake_factory
->last_stream_request();
12442 ASSERT_TRUE(fake_request
!= NULL
);
12443 EXPECT_EQ(&websocket_stream_create_helper
,
12444 fake_request
->websocket_stream_create_helper());
12448 // Tests that when a used socket is returned to the SSL socket pool, it's closed
12449 // if the transport socket pool is stalled on the global socket limit.
12450 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
12451 ClientSocketPoolManager::set_max_sockets_per_group(
12452 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12453 ClientSocketPoolManager::set_max_sockets_per_pool(
12454 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12456 // Set up SSL request.
12458 HttpRequestInfo ssl_request
;
12459 ssl_request
.method
= "GET";
12460 ssl_request
.url
= GURL("https://www.google.com/");
12462 MockWrite ssl_writes
[] = {
12463 MockWrite("GET / HTTP/1.1\r\n"
12464 "Host: www.google.com\r\n"
12465 "Connection: keep-alive\r\n\r\n"),
12467 MockRead ssl_reads
[] = {
12468 MockRead("HTTP/1.1 200 OK\r\n"),
12469 MockRead("Content-Length: 11\r\n\r\n"),
12470 MockRead("hello world"),
12471 MockRead(SYNCHRONOUS
, OK
),
12473 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
12474 ssl_writes
, arraysize(ssl_writes
));
12475 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12477 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12478 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12480 // Set up HTTP request.
12482 HttpRequestInfo http_request
;
12483 http_request
.method
= "GET";
12484 http_request
.url
= GURL("http://www.google.com/");
12486 MockWrite http_writes
[] = {
12487 MockWrite("GET / HTTP/1.1\r\n"
12488 "Host: www.google.com\r\n"
12489 "Connection: keep-alive\r\n\r\n"),
12491 MockRead http_reads
[] = {
12492 MockRead("HTTP/1.1 200 OK\r\n"),
12493 MockRead("Content-Length: 7\r\n\r\n"),
12494 MockRead("falafel"),
12495 MockRead(SYNCHRONOUS
, OK
),
12497 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12498 http_writes
, arraysize(http_writes
));
12499 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12501 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12503 // Start the SSL request.
12504 TestCompletionCallback ssl_callback
;
12505 scoped_ptr
<HttpTransaction
> ssl_trans(
12506 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12507 ASSERT_EQ(ERR_IO_PENDING
,
12508 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
12511 // Start the HTTP request. Pool should stall.
12512 TestCompletionCallback http_callback
;
12513 scoped_ptr
<HttpTransaction
> http_trans(
12514 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12515 ASSERT_EQ(ERR_IO_PENDING
,
12516 http_trans
->Start(&http_request
, http_callback
.callback(),
12518 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12520 // Wait for response from SSL request.
12521 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
12522 std::string response_data
;
12523 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
12524 EXPECT_EQ("hello world", response_data
);
12526 // The SSL socket should automatically be closed, so the HTTP request can
12528 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12529 ASSERT_FALSE(IsTransportSocketPoolStalled(session
));
12531 // The HTTP request can now complete.
12532 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12533 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12534 EXPECT_EQ("falafel", response_data
);
12536 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12539 // Tests that when a SSL connection is established but there's no corresponding
12540 // request that needs it, the new socket is closed if the transport socket pool
12541 // is stalled on the global socket limit.
12542 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
12543 ClientSocketPoolManager::set_max_sockets_per_group(
12544 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12545 ClientSocketPoolManager::set_max_sockets_per_pool(
12546 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12548 // Set up an ssl request.
12550 HttpRequestInfo ssl_request
;
12551 ssl_request
.method
= "GET";
12552 ssl_request
.url
= GURL("https://www.foopy.com/");
12554 // No data will be sent on the SSL socket.
12555 StaticSocketDataProvider ssl_data
;
12556 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
12558 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12559 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12561 // Set up HTTP request.
12563 HttpRequestInfo http_request
;
12564 http_request
.method
= "GET";
12565 http_request
.url
= GURL("http://www.google.com/");
12567 MockWrite http_writes
[] = {
12568 MockWrite("GET / HTTP/1.1\r\n"
12569 "Host: www.google.com\r\n"
12570 "Connection: keep-alive\r\n\r\n"),
12572 MockRead http_reads
[] = {
12573 MockRead("HTTP/1.1 200 OK\r\n"),
12574 MockRead("Content-Length: 7\r\n\r\n"),
12575 MockRead("falafel"),
12576 MockRead(SYNCHRONOUS
, OK
),
12578 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12579 http_writes
, arraysize(http_writes
));
12580 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12582 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12584 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
12585 // cancelled when a normal transaction is cancelled.
12586 net::HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
12587 net::SSLConfig ssl_config
;
12588 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
12589 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
12590 ssl_config
, ssl_config
);
12591 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
));
12593 // Start the HTTP request. Pool should stall.
12594 TestCompletionCallback http_callback
;
12595 scoped_ptr
<HttpTransaction
> http_trans(
12596 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12597 ASSERT_EQ(ERR_IO_PENDING
,
12598 http_trans
->Start(&http_request
, http_callback
.callback(),
12600 EXPECT_TRUE(IsTransportSocketPoolStalled(session
));
12602 // The SSL connection will automatically be closed once the connection is
12603 // established, to let the HTTP request start.
12604 ASSERT_EQ(OK
, http_callback
.WaitForResult());
12605 std::string response_data
;
12606 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
12607 EXPECT_EQ("falafel", response_data
);
12609 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
));
12612 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
12613 ScopedVector
<UploadElementReader
> element_readers
;
12614 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12615 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12617 HttpRequestInfo request
;
12618 request
.method
= "POST";
12619 request
.url
= GURL("http://www.foo.com/");
12620 request
.upload_data_stream
= &upload_data_stream
;
12621 request
.load_flags
= 0;
12623 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12624 scoped_ptr
<HttpTransaction
> trans(
12625 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12626 // Send headers successfully, but get an error while sending the body.
12627 MockWrite data_writes
[] = {
12628 MockWrite("POST / HTTP/1.1\r\n"
12629 "Host: www.foo.com\r\n"
12630 "Connection: keep-alive\r\n"
12631 "Content-Length: 3\r\n\r\n"),
12632 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12635 MockRead data_reads
[] = {
12636 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12637 MockRead("hello world"),
12638 MockRead(SYNCHRONOUS
, OK
),
12640 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12641 arraysize(data_writes
));
12642 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12644 TestCompletionCallback callback
;
12646 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12647 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12649 rv
= callback
.WaitForResult();
12652 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12653 ASSERT_TRUE(response
!= NULL
);
12655 EXPECT_TRUE(response
->headers
.get() != NULL
);
12656 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12658 std::string response_data
;
12659 rv
= ReadTransaction(trans
.get(), &response_data
);
12661 EXPECT_EQ("hello world", response_data
);
12664 // This test makes sure the retry logic doesn't trigger when reading an error
12665 // response from a server that rejected a POST with a CONNECTION_RESET.
12666 TEST_P(HttpNetworkTransactionTest
,
12667 PostReadsErrorResponseAfterResetOnReusedSocket
) {
12668 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12669 MockWrite data_writes
[] = {
12670 MockWrite("GET / HTTP/1.1\r\n"
12671 "Host: www.foo.com\r\n"
12672 "Connection: keep-alive\r\n\r\n"),
12673 MockWrite("POST / HTTP/1.1\r\n"
12674 "Host: www.foo.com\r\n"
12675 "Connection: keep-alive\r\n"
12676 "Content-Length: 3\r\n\r\n"),
12677 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12680 MockRead data_reads
[] = {
12681 MockRead("HTTP/1.1 200 Peachy\r\n"
12682 "Content-Length: 14\r\n\r\n"),
12683 MockRead("first response"),
12684 MockRead("HTTP/1.1 400 Not OK\r\n"
12685 "Content-Length: 15\r\n\r\n"),
12686 MockRead("second response"),
12687 MockRead(SYNCHRONOUS
, OK
),
12689 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12690 arraysize(data_writes
));
12691 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12693 TestCompletionCallback callback
;
12694 HttpRequestInfo request1
;
12695 request1
.method
= "GET";
12696 request1
.url
= GURL("http://www.foo.com/");
12697 request1
.load_flags
= 0;
12699 scoped_ptr
<HttpTransaction
> trans1(
12700 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12701 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
12702 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12704 rv
= callback
.WaitForResult();
12707 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12708 ASSERT_TRUE(response1
!= NULL
);
12710 EXPECT_TRUE(response1
->headers
.get() != NULL
);
12711 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
12713 std::string response_data1
;
12714 rv
= ReadTransaction(trans1
.get(), &response_data1
);
12716 EXPECT_EQ("first response", response_data1
);
12717 // Delete the transaction to release the socket back into the socket pool.
12720 ScopedVector
<UploadElementReader
> element_readers
;
12721 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12722 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12724 HttpRequestInfo request2
;
12725 request2
.method
= "POST";
12726 request2
.url
= GURL("http://www.foo.com/");
12727 request2
.upload_data_stream
= &upload_data_stream
;
12728 request2
.load_flags
= 0;
12730 scoped_ptr
<HttpTransaction
> trans2(
12731 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12732 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
12733 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12735 rv
= callback
.WaitForResult();
12738 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
12739 ASSERT_TRUE(response2
!= NULL
);
12741 EXPECT_TRUE(response2
->headers
.get() != NULL
);
12742 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
12744 std::string response_data2
;
12745 rv
= ReadTransaction(trans2
.get(), &response_data2
);
12747 EXPECT_EQ("second response", response_data2
);
12750 TEST_P(HttpNetworkTransactionTest
,
12751 PostReadsErrorResponseAfterResetPartialBodySent
) {
12752 ScopedVector
<UploadElementReader
> element_readers
;
12753 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12754 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12756 HttpRequestInfo request
;
12757 request
.method
= "POST";
12758 request
.url
= GURL("http://www.foo.com/");
12759 request
.upload_data_stream
= &upload_data_stream
;
12760 request
.load_flags
= 0;
12762 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12763 scoped_ptr
<HttpTransaction
> trans(
12764 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12765 // Send headers successfully, but get an error while sending the body.
12766 MockWrite data_writes
[] = {
12767 MockWrite("POST / HTTP/1.1\r\n"
12768 "Host: www.foo.com\r\n"
12769 "Connection: keep-alive\r\n"
12770 "Content-Length: 3\r\n\r\n"
12772 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12775 MockRead data_reads
[] = {
12776 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12777 MockRead("hello world"),
12778 MockRead(SYNCHRONOUS
, OK
),
12780 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12781 arraysize(data_writes
));
12782 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12784 TestCompletionCallback callback
;
12786 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12789 rv
= callback
.WaitForResult();
12792 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12793 ASSERT_TRUE(response
!= NULL
);
12795 EXPECT_TRUE(response
->headers
.get() != NULL
);
12796 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12798 std::string response_data
;
12799 rv
= ReadTransaction(trans
.get(), &response_data
);
12801 EXPECT_EQ("hello world", response_data
);
12804 // This tests the more common case than the previous test, where headers and
12805 // body are not merged into a single request.
12806 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
12807 ScopedVector
<UploadElementReader
> element_readers
;
12808 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12809 UploadDataStream
upload_data_stream(UploadDataStream::CHUNKED
, 0);
12811 HttpRequestInfo request
;
12812 request
.method
= "POST";
12813 request
.url
= GURL("http://www.foo.com/");
12814 request
.upload_data_stream
= &upload_data_stream
;
12815 request
.load_flags
= 0;
12817 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12818 scoped_ptr
<HttpTransaction
> trans(
12819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12820 // Send headers successfully, but get an error while sending the body.
12821 MockWrite data_writes
[] = {
12822 MockWrite("POST / HTTP/1.1\r\n"
12823 "Host: www.foo.com\r\n"
12824 "Connection: keep-alive\r\n"
12825 "Transfer-Encoding: chunked\r\n\r\n"),
12826 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12829 MockRead data_reads
[] = {
12830 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12831 MockRead("hello world"),
12832 MockRead(SYNCHRONOUS
, OK
),
12834 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12835 arraysize(data_writes
));
12836 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12838 TestCompletionCallback callback
;
12840 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12841 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12842 // Make sure the headers are sent before adding a chunk. This ensures that
12843 // they can't be merged with the body in a single send. Not currently
12844 // necessary since a chunked body is never merged with headers, but this makes
12845 // the test more future proof.
12846 base::RunLoop().RunUntilIdle();
12848 upload_data_stream
.AppendChunk("last chunk", 10, true);
12850 rv
= callback
.WaitForResult();
12853 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12854 ASSERT_TRUE(response
!= NULL
);
12856 EXPECT_TRUE(response
->headers
.get() != NULL
);
12857 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12859 std::string response_data
;
12860 rv
= ReadTransaction(trans
.get(), &response_data
);
12862 EXPECT_EQ("hello world", response_data
);
12865 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
12866 ScopedVector
<UploadElementReader
> element_readers
;
12867 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12868 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12870 HttpRequestInfo request
;
12871 request
.method
= "POST";
12872 request
.url
= GURL("http://www.foo.com/");
12873 request
.upload_data_stream
= &upload_data_stream
;
12874 request
.load_flags
= 0;
12876 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12877 scoped_ptr
<HttpTransaction
> trans(
12878 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12880 MockWrite data_writes
[] = {
12881 MockWrite("POST / HTTP/1.1\r\n"
12882 "Host: www.foo.com\r\n"
12883 "Connection: keep-alive\r\n"
12884 "Content-Length: 3\r\n\r\n"),
12885 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12888 MockRead data_reads
[] = {
12889 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12890 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
12891 MockRead("hello world"),
12892 MockRead(SYNCHRONOUS
, OK
),
12894 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12895 arraysize(data_writes
));
12896 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12898 TestCompletionCallback callback
;
12900 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12901 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12903 rv
= callback
.WaitForResult();
12906 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12907 ASSERT_TRUE(response
!= NULL
);
12909 EXPECT_TRUE(response
->headers
.get() != NULL
);
12910 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
12912 std::string response_data
;
12913 rv
= ReadTransaction(trans
.get(), &response_data
);
12915 EXPECT_EQ("hello world", response_data
);
12918 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
12919 ScopedVector
<UploadElementReader
> element_readers
;
12920 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12921 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12923 HttpRequestInfo request
;
12924 request
.method
= "POST";
12925 request
.url
= GURL("http://www.foo.com/");
12926 request
.upload_data_stream
= &upload_data_stream
;
12927 request
.load_flags
= 0;
12929 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12930 scoped_ptr
<HttpTransaction
> trans(
12931 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12932 // Send headers successfully, but get an error while sending the body.
12933 MockWrite data_writes
[] = {
12934 MockWrite("POST / HTTP/1.1\r\n"
12935 "Host: www.foo.com\r\n"
12936 "Connection: keep-alive\r\n"
12937 "Content-Length: 3\r\n\r\n"),
12938 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12941 MockRead data_reads
[] = {
12942 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
12943 MockRead("hello world"),
12944 MockRead(SYNCHRONOUS
, OK
),
12946 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12947 arraysize(data_writes
));
12948 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12950 TestCompletionCallback callback
;
12952 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12953 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12955 rv
= callback
.WaitForResult();
12956 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12958 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12959 EXPECT_TRUE(response
== NULL
);
12962 TEST_P(HttpNetworkTransactionTest
,
12963 PostIgnoresNonErrorResponseAfterResetAnd100
) {
12964 ScopedVector
<UploadElementReader
> element_readers
;
12965 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
12966 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
12968 HttpRequestInfo request
;
12969 request
.method
= "POST";
12970 request
.url
= GURL("http://www.foo.com/");
12971 request
.upload_data_stream
= &upload_data_stream
;
12972 request
.load_flags
= 0;
12974 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12975 scoped_ptr
<HttpTransaction
> trans(
12976 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
12977 // Send headers successfully, but get an error while sending the body.
12978 MockWrite data_writes
[] = {
12979 MockWrite("POST / HTTP/1.1\r\n"
12980 "Host: www.foo.com\r\n"
12981 "Connection: keep-alive\r\n"
12982 "Content-Length: 3\r\n\r\n"),
12983 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12986 MockRead data_reads
[] = {
12987 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
12988 MockRead("HTTP/1.0 302 Redirect\r\n"),
12989 MockRead("Location: http://somewhere-else.com/\r\n"),
12990 MockRead("Content-Length: 0\r\n\r\n"),
12991 MockRead(SYNCHRONOUS
, OK
),
12993 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
12994 arraysize(data_writes
));
12995 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12997 TestCompletionCallback callback
;
12999 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13002 rv
= callback
.WaitForResult();
13003 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13005 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13006 EXPECT_TRUE(response
== NULL
);
13009 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13010 ScopedVector
<UploadElementReader
> element_readers
;
13011 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13012 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13014 HttpRequestInfo request
;
13015 request
.method
= "POST";
13016 request
.url
= GURL("http://www.foo.com/");
13017 request
.upload_data_stream
= &upload_data_stream
;
13018 request
.load_flags
= 0;
13020 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13021 scoped_ptr
<HttpTransaction
> trans(
13022 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13023 // Send headers successfully, but get an error while sending the body.
13024 MockWrite data_writes
[] = {
13025 MockWrite("POST / HTTP/1.1\r\n"
13026 "Host: www.foo.com\r\n"
13027 "Connection: keep-alive\r\n"
13028 "Content-Length: 3\r\n\r\n"),
13029 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13032 MockRead data_reads
[] = {
13033 MockRead("HTTP 0.9 rocks!"),
13034 MockRead(SYNCHRONOUS
, OK
),
13036 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13037 arraysize(data_writes
));
13038 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13040 TestCompletionCallback callback
;
13042 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13045 rv
= callback
.WaitForResult();
13046 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13048 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13049 EXPECT_TRUE(response
== NULL
);
13052 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13053 ScopedVector
<UploadElementReader
> element_readers
;
13054 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13055 UploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13057 HttpRequestInfo request
;
13058 request
.method
= "POST";
13059 request
.url
= GURL("http://www.foo.com/");
13060 request
.upload_data_stream
= &upload_data_stream
;
13061 request
.load_flags
= 0;
13063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13064 scoped_ptr
<HttpTransaction
> trans(
13065 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
));
13066 // Send headers successfully, but get an error while sending the body.
13067 MockWrite data_writes
[] = {
13068 MockWrite("POST / HTTP/1.1\r\n"
13069 "Host: www.foo.com\r\n"
13070 "Connection: keep-alive\r\n"
13071 "Content-Length: 3\r\n\r\n"),
13072 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13075 MockRead data_reads
[] = {
13076 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13077 MockRead(SYNCHRONOUS
, OK
),
13079 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13080 arraysize(data_writes
));
13081 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13083 TestCompletionCallback callback
;
13085 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13086 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13088 rv
= callback
.WaitForResult();
13089 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13091 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13092 EXPECT_TRUE(response
== NULL
);