1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/test_file_util.h"
25 #include "base/thread_task_runner_handle.h"
26 #include "net/base/auth.h"
27 #include "net/base/chunked_upload_data_stream.h"
28 #include "net/base/completion_callback.h"
29 #include "net/base/elements_upload_data_stream.h"
30 #include "net/base/load_timing_info.h"
31 #include "net/base/load_timing_info_test_util.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/request_priority.h"
34 #include "net/base/test_completion_callback.h"
35 #include "net/base/test_data_directory.h"
36 #include "net/base/upload_bytes_element_reader.h"
37 #include "net/base/upload_file_element_reader.h"
38 #include "net/cert/mock_cert_verifier.h"
39 #include "net/dns/host_cache.h"
40 #include "net/dns/mock_host_resolver.h"
41 #include "net/http/http_auth_challenge_tokenizer.h"
42 #include "net/http/http_auth_handler_digest.h"
43 #include "net/http/http_auth_handler_mock.h"
44 #include "net/http/http_auth_handler_ntlm.h"
45 #include "net/http/http_basic_state.h"
46 #include "net/http/http_basic_stream.h"
47 #include "net/http/http_network_session.h"
48 #include "net/http/http_network_session_peer.h"
49 #include "net/http/http_request_headers.h"
50 #include "net/http/http_server_properties_impl.h"
51 #include "net/http/http_stream.h"
52 #include "net/http/http_stream_factory.h"
53 #include "net/http/http_stream_parser.h"
54 #include "net/http/http_transaction_test_util.h"
55 #include "net/log/net_log.h"
56 #include "net/log/test_net_log.h"
57 #include "net/log/test_net_log_entry.h"
58 #include "net/log/test_net_log_util.h"
59 #include "net/proxy/mock_proxy_resolver.h"
60 #include "net/proxy/proxy_config_service_fixed.h"
61 #include "net/proxy/proxy_info.h"
62 #include "net/proxy/proxy_resolver.h"
63 #include "net/proxy/proxy_service.h"
64 #include "net/socket/client_socket_factory.h"
65 #include "net/socket/client_socket_pool_manager.h"
66 #include "net/socket/connection_attempts.h"
67 #include "net/socket/mock_client_socket_pool_manager.h"
68 #include "net/socket/next_proto.h"
69 #include "net/socket/socket_test_util.h"
70 #include "net/socket/ssl_client_socket.h"
71 #include "net/spdy/spdy_framer.h"
72 #include "net/spdy/spdy_session.h"
73 #include "net/spdy/spdy_session_pool.h"
74 #include "net/spdy/spdy_test_util_common.h"
75 #include "net/ssl/ssl_cert_request_info.h"
76 #include "net/ssl/ssl_config_service.h"
77 #include "net/ssl/ssl_config_service_defaults.h"
78 #include "net/ssl/ssl_info.h"
79 #include "net/test/cert_test_util.h"
80 #include "net/websockets/websocket_handshake_stream_base.h"
81 #include "testing/gtest/include/gtest/gtest.h"
82 #include "testing/platform_test.h"
85 using base::ASCIIToUTF16
;
87 //-----------------------------------------------------------------------------
93 const base::string16
kBar(ASCIIToUTF16("bar"));
94 const base::string16
kBar2(ASCIIToUTF16("bar2"));
95 const base::string16
kBar3(ASCIIToUTF16("bar3"));
96 const base::string16
kBaz(ASCIIToUTF16("baz"));
97 const base::string16
kFirst(ASCIIToUTF16("first"));
98 const base::string16
kFoo(ASCIIToUTF16("foo"));
99 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
100 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
101 const base::string16
kFou(ASCIIToUTF16("fou"));
102 const base::string16
kSecond(ASCIIToUTF16("second"));
103 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
104 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
106 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession
* session
) {
107 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
111 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession
* session
) {
112 return session
->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
116 bool IsTransportSocketPoolStalled(HttpNetworkSession
* session
) {
117 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
121 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
122 // a JSONified list of headers as a single string. Uses single quotes instead
123 // of double quotes for easier comparison. Returns false on failure.
124 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
127 base::ListValue
* header_list
;
128 if (!params
->GetList("headers", &header_list
))
130 std::string double_quote_headers
;
131 base::JSONWriter::Write(*header_list
, &double_quote_headers
);
132 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
136 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
138 void TestLoadTimingReused(const LoadTimingInfo
& load_timing_info
) {
139 EXPECT_TRUE(load_timing_info
.socket_reused
);
140 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
142 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
143 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
145 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
146 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
148 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
150 // Set at a higher level.
151 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
152 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
153 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
156 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
158 void TestLoadTimingNotReused(const LoadTimingInfo
& load_timing_info
,
159 int connect_timing_flags
) {
160 EXPECT_FALSE(load_timing_info
.socket_reused
);
161 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
163 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
164 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
166 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
167 connect_timing_flags
);
168 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
169 load_timing_info
.send_start
);
171 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
173 // Set at a higher level.
174 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
175 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
176 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
179 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
181 void TestLoadTimingReusedWithPac(const LoadTimingInfo
& load_timing_info
) {
182 EXPECT_TRUE(load_timing_info
.socket_reused
);
183 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
185 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
187 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
188 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
189 load_timing_info
.proxy_resolve_end
);
190 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
191 load_timing_info
.send_start
);
192 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
194 // Set at a higher level.
195 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
196 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
197 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
200 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
202 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo
& load_timing_info
,
203 int connect_timing_flags
) {
204 EXPECT_FALSE(load_timing_info
.socket_reused
);
205 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
207 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
208 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
209 load_timing_info
.proxy_resolve_end
);
210 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
211 load_timing_info
.connect_timing
.connect_start
);
212 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
213 connect_timing_flags
);
214 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
215 load_timing_info
.send_start
);
217 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
219 // Set at a higher level.
220 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
221 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
222 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
225 void AddWebSocketHeaders(HttpRequestHeaders
* headers
) {
226 headers
->SetHeader("Connection", "Upgrade");
227 headers
->SetHeader("Upgrade", "websocket");
228 headers
->SetHeader("Origin", "http://www.example.org");
229 headers
->SetHeader("Sec-WebSocket-Version", "13");
230 headers
->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
233 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
234 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
239 class HttpNetworkTransactionTest
240 : public PlatformTest
,
241 public ::testing::WithParamInterface
<NextProto
> {
243 virtual ~HttpNetworkTransactionTest() {
244 // Important to restore the per-pool limit first, since the pool limit must
245 // always be greater than group limit, and the tests reduce both limits.
246 ClientSocketPoolManager::set_max_sockets_per_pool(
247 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
248 ClientSocketPoolManager::set_max_sockets_per_group(
249 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
253 HttpNetworkTransactionTest()
254 : spdy_util_(GetParam()),
255 session_deps_(GetParam()),
256 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
257 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
258 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
259 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
262 struct SimpleGetHelperResult
{
264 std::string status_line
;
265 std::string response_data
;
266 int64 totalReceivedBytes
;
267 LoadTimingInfo load_timing_info
;
268 ConnectionAttempts connection_attempts
;
271 void SetUp() override
{
272 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
273 base::MessageLoop::current()->RunUntilIdle();
276 void TearDown() override
{
277 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
278 base::MessageLoop::current()->RunUntilIdle();
279 // Empty the current queue.
280 base::MessageLoop::current()->RunUntilIdle();
281 PlatformTest::TearDown();
282 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
283 base::MessageLoop::current()->RunUntilIdle();
286 const char* GetAlternateProtocolFromParam() {
288 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
291 // This is the expected return from a current server advertising SPDY.
292 std::string
GetAlternateProtocolHttpHeader() {
293 return std::string("Alternate-Protocol: 443:") +
294 GetAlternateProtocolFromParam() + "\r\n\r\n";
297 // Either |write_failure| specifies a write failure or |read_failure|
298 // specifies a read failure when using a reused socket. In either case, the
299 // failure should cause the network transaction to resend the request, and the
300 // other argument should be NULL.
301 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
302 const MockRead
* read_failure
);
304 // Either |write_failure| specifies a write failure or |read_failure|
305 // specifies a read failure when using a reused socket. In either case, the
306 // failure should cause the network transaction to resend the request, and the
307 // other argument should be NULL.
308 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
309 const MockRead
* read_failure
,
312 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
314 SimpleGetHelperResult out
;
316 HttpRequestInfo request
;
317 request
.method
= "GET";
318 request
.url
= GURL("http://www.example.org/");
319 request
.load_flags
= 0;
322 session_deps_
.net_log
= log
.bound().net_log();
323 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
324 scoped_ptr
<HttpTransaction
> trans(
325 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
327 for (size_t i
= 0; i
< data_count
; ++i
) {
328 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
331 TestCompletionCallback callback
;
333 EXPECT_TRUE(log
.bound().IsCapturing());
334 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
335 EXPECT_EQ(ERR_IO_PENDING
, rv
);
337 out
.rv
= callback
.WaitForResult();
339 // Even in the failure cases that use this function, connections are always
340 // successfully established before the error.
341 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
342 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
347 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
348 // Can't use ASSERT_* inside helper functions like this, so
350 if (response
== NULL
|| response
->headers
.get() == NULL
) {
351 out
.rv
= ERR_UNEXPECTED
;
354 out
.status_line
= response
->headers
->GetStatusLine();
356 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
357 EXPECT_EQ(80, response
->socket_address
.port());
359 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
362 TestNetLogEntry::List entries
;
363 log
.GetEntries(&entries
);
364 size_t pos
= ExpectLogContainsSomewhere(
365 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
367 ExpectLogContainsSomewhere(
369 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
373 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
374 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
376 HttpRequestHeaders request_headers
;
377 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
379 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
380 EXPECT_EQ("www.example.org", value
);
381 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
382 EXPECT_EQ("keep-alive", value
);
384 std::string response_headers
;
385 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
386 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
389 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
390 trans
->GetConnectionAttempts(&out
.connection_attempts
);
394 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
395 size_t reads_count
) {
396 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
397 StaticSocketDataProvider
* data
[] = { &reads
};
398 return SimpleGetHelperForData(data
, 1);
401 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
403 for (size_t i
= 0; i
< reads_count
; ++i
)
404 size
+= data_reads
[i
].data_len
;
408 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
409 int expected_status
);
411 void ConnectStatusHelper(const MockRead
& status
);
413 void BypassHostCacheOnRefreshHelper(int load_flags
);
415 void CheckErrorIsPassedBack(int error
, IoMode mode
);
417 SpdyTestUtil spdy_util_
;
418 SpdySessionDependencies session_deps_
;
420 // Original socket limits. Some tests set these. Safest to always restore
421 // them once each test has been run.
422 int old_max_group_sockets_
;
423 int old_max_pool_sockets_
;
426 INSTANTIATE_TEST_CASE_P(NextProto
,
427 HttpNetworkTransactionTest
,
428 testing::Values(kProtoSPDY31
,
434 class BeforeNetworkStartHandler
{
436 explicit BeforeNetworkStartHandler(bool defer
)
437 : defer_on_before_network_start_(defer
),
438 observed_before_network_start_(false) {}
440 void OnBeforeNetworkStart(bool* defer
) {
441 *defer
= defer_on_before_network_start_
;
442 observed_before_network_start_
= true;
445 bool observed_before_network_start() const {
446 return observed_before_network_start_
;
450 const bool defer_on_before_network_start_
;
451 bool observed_before_network_start_
;
453 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
456 class BeforeProxyHeadersSentHandler
{
458 BeforeProxyHeadersSentHandler()
459 : observed_before_proxy_headers_sent_(false) {}
461 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
462 HttpRequestHeaders
* request_headers
) {
463 observed_before_proxy_headers_sent_
= true;
464 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
467 bool observed_before_proxy_headers_sent() const {
468 return observed_before_proxy_headers_sent_
;
471 std::string
observed_proxy_server_uri() const {
472 return observed_proxy_server_uri_
;
476 bool observed_before_proxy_headers_sent_
;
477 std::string observed_proxy_server_uri_
;
479 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
482 // Fill |str| with a long header list that consumes >= |size| bytes.
483 void FillLargeHeadersString(std::string
* str
, int size
) {
485 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
486 const int sizeof_row
= strlen(row
);
487 const int num_rows
= static_cast<int>(
488 ceil(static_cast<float>(size
) / sizeof_row
));
489 const int sizeof_data
= num_rows
* sizeof_row
;
490 DCHECK(sizeof_data
>= size
);
491 str
->reserve(sizeof_data
);
493 for (int i
= 0; i
< num_rows
; ++i
)
494 str
->append(row
, sizeof_row
);
497 // Alternative functions that eliminate randomness and dependency on the local
498 // host name so that the generated NTLM messages are reproducible.
499 void MockGenerateRandom1(uint8
* output
, size_t n
) {
500 static const uint8 bytes
[] = {
501 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
503 static size_t current_byte
= 0;
504 for (size_t i
= 0; i
< n
; ++i
) {
505 output
[i
] = bytes
[current_byte
++];
506 current_byte
%= arraysize(bytes
);
510 void MockGenerateRandom2(uint8
* output
, size_t n
) {
511 static const uint8 bytes
[] = {
512 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
513 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
515 static size_t current_byte
= 0;
516 for (size_t i
= 0; i
< n
; ++i
) {
517 output
[i
] = bytes
[current_byte
++];
518 current_byte
%= arraysize(bytes
);
522 std::string
MockGetHostName() {
526 template<typename ParentPool
>
527 class CaptureGroupNameSocketPool
: public ParentPool
{
529 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
530 CertVerifier
* cert_verifier
);
532 const std::string
last_group_name_received() const {
533 return last_group_name_
;
536 int RequestSocket(const std::string
& group_name
,
537 const void* socket_params
,
538 RequestPriority priority
,
539 ClientSocketHandle
* handle
,
540 const CompletionCallback
& callback
,
541 const BoundNetLog
& net_log
) override
{
542 last_group_name_
= group_name
;
543 return ERR_IO_PENDING
;
545 void CancelRequest(const std::string
& group_name
,
546 ClientSocketHandle
* handle
) override
{}
547 void ReleaseSocket(const std::string
& group_name
,
548 scoped_ptr
<StreamSocket
> socket
,
550 void CloseIdleSockets() override
{}
551 int IdleSocketCount() const override
{ return 0; }
552 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
555 LoadState
GetLoadState(const std::string
& group_name
,
556 const ClientSocketHandle
* handle
) const override
{
557 return LOAD_STATE_IDLE
;
559 base::TimeDelta
ConnectionTimeout() const override
{
560 return base::TimeDelta();
564 std::string last_group_name_
;
567 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
568 CaptureGroupNameTransportSocketPool
;
569 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
570 CaptureGroupNameHttpProxySocketPool
;
571 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
572 CaptureGroupNameSOCKSSocketPool
;
573 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
574 CaptureGroupNameSSLSocketPool
;
576 template <typename ParentPool
>
577 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
578 HostResolver
* host_resolver
,
579 CertVerifier
* /* cert_verifier */)
580 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
584 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
585 HostResolver
* /* host_resolver */,
586 CertVerifier
* /* cert_verifier */)
587 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
591 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
592 HostResolver
* /* host_resolver */,
593 CertVerifier
* cert_verifier
)
594 : SSLClientSocketPool(0,
610 //-----------------------------------------------------------------------------
612 // Helper functions for validating that AuthChallengeInfo's are correctly
613 // configured for common cases.
614 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
617 EXPECT_FALSE(auth_challenge
->is_proxy
);
618 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
619 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
620 EXPECT_EQ("basic", auth_challenge
->scheme
);
624 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
627 EXPECT_TRUE(auth_challenge
->is_proxy
);
628 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
629 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
630 EXPECT_EQ("basic", auth_challenge
->scheme
);
634 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
637 EXPECT_FALSE(auth_challenge
->is_proxy
);
638 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
639 EXPECT_EQ("digestive", auth_challenge
->realm
);
640 EXPECT_EQ("digest", auth_challenge
->scheme
);
644 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
647 EXPECT_FALSE(auth_challenge
->is_proxy
);
648 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
649 EXPECT_EQ(std::string(), auth_challenge
->realm
);
650 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
656 TEST_P(HttpNetworkTransactionTest
, Basic
) {
657 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
658 scoped_ptr
<HttpTransaction
> trans(
659 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
662 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
663 MockRead data_reads
[] = {
664 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
665 MockRead("hello world"),
666 MockRead(SYNCHRONOUS
, OK
),
668 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
669 arraysize(data_reads
));
670 EXPECT_EQ(OK
, out
.rv
);
671 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
672 EXPECT_EQ("hello world", out
.response_data
);
673 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
674 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
675 EXPECT_EQ(0u, out
.connection_attempts
.size());
678 // Response with no status line.
679 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
680 MockRead data_reads
[] = {
681 MockRead("hello world"),
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("hello world", out
.response_data
);
689 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
690 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
693 // Allow up to 4 bytes of junk to precede status line.
694 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
695 MockRead data_reads
[] = {
696 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
697 MockRead(SYNCHRONOUS
, OK
),
699 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
700 arraysize(data_reads
));
701 EXPECT_EQ(OK
, out
.rv
);
702 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
703 EXPECT_EQ("DATA", out
.response_data
);
704 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
705 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
708 // Allow up to 4 bytes of junk to precede status line.
709 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
710 MockRead data_reads
[] = {
711 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
712 MockRead(SYNCHRONOUS
, OK
),
714 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
715 arraysize(data_reads
));
716 EXPECT_EQ(OK
, out
.rv
);
717 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
718 EXPECT_EQ("DATA", out
.response_data
);
719 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
720 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
723 // Beyond 4 bytes of slop and it should fail to find a status line.
724 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
725 MockRead data_reads
[] = {
726 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
727 MockRead(SYNCHRONOUS
, OK
),
729 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
730 arraysize(data_reads
));
731 EXPECT_EQ(OK
, out
.rv
);
732 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
733 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
734 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
735 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
738 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
739 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
740 MockRead data_reads
[] = {
745 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
746 MockRead(SYNCHRONOUS
, OK
),
748 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
749 arraysize(data_reads
));
750 EXPECT_EQ(OK
, out
.rv
);
751 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
752 EXPECT_EQ("DATA", out
.response_data
);
753 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
754 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
757 // Close the connection before enough bytes to have a status line.
758 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
759 MockRead data_reads
[] = {
761 MockRead(SYNCHRONOUS
, OK
),
763 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
764 arraysize(data_reads
));
765 EXPECT_EQ(OK
, out
.rv
);
766 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
767 EXPECT_EQ("HTT", out
.response_data
);
768 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
769 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
772 // Simulate a 204 response, lacking a Content-Length header, sent over a
773 // persistent connection. The response should still terminate since a 204
774 // cannot have a response body.
775 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
776 char junk
[] = "junk";
777 MockRead data_reads
[] = {
778 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
779 MockRead(junk
), // Should not be read!!
780 MockRead(SYNCHRONOUS
, OK
),
782 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
783 arraysize(data_reads
));
784 EXPECT_EQ(OK
, out
.rv
);
785 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
786 EXPECT_EQ("", out
.response_data
);
787 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
788 int64 response_size
= reads_size
- strlen(junk
);
789 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
792 // A simple request using chunked encoding with some extra data after.
793 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
794 std::string final_chunk
= "0\r\n\r\n";
795 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
796 std::string last_read
= final_chunk
+ extra_data
;
797 MockRead data_reads
[] = {
798 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
799 MockRead("5\r\nHello\r\n"),
802 MockRead("5\r\nworld\r\n"),
803 MockRead(last_read
.data()),
804 MockRead(SYNCHRONOUS
, OK
),
806 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
807 arraysize(data_reads
));
808 EXPECT_EQ(OK
, out
.rv
);
809 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
810 EXPECT_EQ("Hello world", out
.response_data
);
811 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
812 int64 response_size
= reads_size
- extra_data
.size();
813 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
816 // Next tests deal with http://crbug.com/56344.
818 TEST_P(HttpNetworkTransactionTest
,
819 MultipleContentLengthHeadersNoTransferEncoding
) {
820 MockRead data_reads
[] = {
821 MockRead("HTTP/1.1 200 OK\r\n"),
822 MockRead("Content-Length: 10\r\n"),
823 MockRead("Content-Length: 5\r\n\r\n"),
825 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
826 arraysize(data_reads
));
827 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
830 TEST_P(HttpNetworkTransactionTest
,
831 DuplicateContentLengthHeadersNoTransferEncoding
) {
832 MockRead data_reads
[] = {
833 MockRead("HTTP/1.1 200 OK\r\n"),
834 MockRead("Content-Length: 5\r\n"),
835 MockRead("Content-Length: 5\r\n\r\n"),
838 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
839 arraysize(data_reads
));
840 EXPECT_EQ(OK
, out
.rv
);
841 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
842 EXPECT_EQ("Hello", out
.response_data
);
845 TEST_P(HttpNetworkTransactionTest
,
846 ComplexContentLengthHeadersNoTransferEncoding
) {
847 // More than 2 dupes.
849 MockRead data_reads
[] = {
850 MockRead("HTTP/1.1 200 OK\r\n"),
851 MockRead("Content-Length: 5\r\n"),
852 MockRead("Content-Length: 5\r\n"),
853 MockRead("Content-Length: 5\r\n\r\n"),
856 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
857 arraysize(data_reads
));
858 EXPECT_EQ(OK
, out
.rv
);
859 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
860 EXPECT_EQ("Hello", out
.response_data
);
864 MockRead data_reads
[] = {
865 MockRead("HTTP/1.0 200 OK\r\n"),
866 MockRead("Content-Length: 5\r\n"),
867 MockRead("Content-Length: 5\r\n"),
868 MockRead("Content-Length: 5\r\n\r\n"),
871 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
872 arraysize(data_reads
));
873 EXPECT_EQ(OK
, out
.rv
);
874 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
875 EXPECT_EQ("Hello", out
.response_data
);
877 // 2 dupes and one mismatched.
879 MockRead data_reads
[] = {
880 MockRead("HTTP/1.1 200 OK\r\n"),
881 MockRead("Content-Length: 10\r\n"),
882 MockRead("Content-Length: 10\r\n"),
883 MockRead("Content-Length: 5\r\n\r\n"),
885 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
886 arraysize(data_reads
));
887 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
891 TEST_P(HttpNetworkTransactionTest
,
892 MultipleContentLengthHeadersTransferEncoding
) {
893 MockRead data_reads
[] = {
894 MockRead("HTTP/1.1 200 OK\r\n"),
895 MockRead("Content-Length: 666\r\n"),
896 MockRead("Content-Length: 1337\r\n"),
897 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
898 MockRead("5\r\nHello\r\n"),
901 MockRead("5\r\nworld\r\n"),
902 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
903 MockRead(SYNCHRONOUS
, OK
),
905 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
906 arraysize(data_reads
));
907 EXPECT_EQ(OK
, out
.rv
);
908 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
909 EXPECT_EQ("Hello world", out
.response_data
);
912 // Next tests deal with http://crbug.com/98895.
914 // Checks that a single Content-Disposition header results in no error.
915 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
916 MockRead data_reads
[] = {
917 MockRead("HTTP/1.1 200 OK\r\n"),
918 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
919 MockRead("Content-Length: 5\r\n\r\n"),
922 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
923 arraysize(data_reads
));
924 EXPECT_EQ(OK
, out
.rv
);
925 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
926 EXPECT_EQ("Hello", out
.response_data
);
929 // Checks that two identical Content-Disposition headers result in no error.
930 TEST_P(HttpNetworkTransactionTest
,
931 TwoIdenticalContentDispositionHeaders
) {
932 MockRead data_reads
[] = {
933 MockRead("HTTP/1.1 200 OK\r\n"),
934 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
935 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
936 MockRead("Content-Length: 5\r\n\r\n"),
939 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
940 arraysize(data_reads
));
941 EXPECT_EQ(OK
, out
.rv
);
942 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
943 EXPECT_EQ("Hello", out
.response_data
);
946 // Checks that two distinct Content-Disposition headers result in an error.
947 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
948 MockRead data_reads
[] = {
949 MockRead("HTTP/1.1 200 OK\r\n"),
950 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
951 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
952 MockRead("Content-Length: 5\r\n\r\n"),
955 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
956 arraysize(data_reads
));
957 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
960 // Checks that two identical Location headers result in no error.
961 // Also tests Location header behavior.
962 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
963 MockRead data_reads
[] = {
964 MockRead("HTTP/1.1 302 Redirect\r\n"),
965 MockRead("Location: http://good.com/\r\n"),
966 MockRead("Location: http://good.com/\r\n"),
967 MockRead("Content-Length: 0\r\n\r\n"),
968 MockRead(SYNCHRONOUS
, OK
),
971 HttpRequestInfo request
;
972 request
.method
= "GET";
973 request
.url
= GURL("http://redirect.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
.get()));
980 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
981 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
983 TestCompletionCallback callback
;
985 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
986 EXPECT_EQ(ERR_IO_PENDING
, rv
);
988 EXPECT_EQ(OK
, callback
.WaitForResult());
990 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
991 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
992 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
994 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
995 EXPECT_EQ("http://good.com/", url
);
996 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
999 // Checks that two distinct Location headers result in an error.
1000 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
1001 MockRead data_reads
[] = {
1002 MockRead("HTTP/1.1 302 Redirect\r\n"),
1003 MockRead("Location: http://good.com/\r\n"),
1004 MockRead("Location: http://evil.com/\r\n"),
1005 MockRead("Content-Length: 0\r\n\r\n"),
1006 MockRead(SYNCHRONOUS
, OK
),
1008 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1009 arraysize(data_reads
));
1010 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1013 // Do a request using the HEAD method. Verify that we don't try to read the
1014 // message body (since HEAD has none).
1015 TEST_P(HttpNetworkTransactionTest
, Head
) {
1016 HttpRequestInfo request
;
1017 request
.method
= "HEAD";
1018 request
.url
= GURL("http://www.example.org/");
1019 request
.load_flags
= 0;
1021 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1022 scoped_ptr
<HttpTransaction
> trans(
1023 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1024 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1025 trans
->SetBeforeProxyHeadersSentCallback(
1026 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1027 base::Unretained(&proxy_headers_handler
)));
1029 MockWrite data_writes1
[] = {
1031 "HEAD / HTTP/1.1\r\n"
1032 "Host: www.example.org\r\n"
1033 "Connection: keep-alive\r\n"
1034 "Content-Length: 0\r\n\r\n"),
1036 MockRead data_reads1
[] = {
1037 MockRead("HTTP/1.1 404 Not Found\r\n"),
1038 MockRead("Server: Blah\r\n"),
1039 MockRead("Content-Length: 1234\r\n\r\n"),
1041 // No response body because the test stops reading here.
1042 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1045 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1046 data_writes1
, arraysize(data_writes1
));
1047 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1049 TestCompletionCallback callback1
;
1051 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1054 rv
= callback1
.WaitForResult();
1057 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1058 ASSERT_TRUE(response
!= NULL
);
1060 // Check that the headers got parsed.
1061 EXPECT_TRUE(response
->headers
.get() != NULL
);
1062 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1063 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1064 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1065 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1067 std::string server_header
;
1069 bool has_server_header
= response
->headers
->EnumerateHeader(
1070 &iter
, "Server", &server_header
);
1071 EXPECT_TRUE(has_server_header
);
1072 EXPECT_EQ("Blah", server_header
);
1074 // Reading should give EOF right away, since there is no message body
1075 // (despite non-zero content-length).
1076 std::string response_data
;
1077 rv
= ReadTransaction(trans
.get(), &response_data
);
1079 EXPECT_EQ("", response_data
);
1082 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1083 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1085 MockRead data_reads
[] = {
1086 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1088 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1090 MockRead(SYNCHRONOUS
, OK
),
1092 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1093 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1095 const char* const kExpectedResponseData
[] = {
1099 for (int i
= 0; i
< 2; ++i
) {
1100 HttpRequestInfo request
;
1101 request
.method
= "GET";
1102 request
.url
= GURL("http://www.example.org/");
1103 request
.load_flags
= 0;
1105 scoped_ptr
<HttpTransaction
> trans(
1106 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1108 TestCompletionCallback callback
;
1110 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1111 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1113 rv
= callback
.WaitForResult();
1116 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1117 ASSERT_TRUE(response
!= NULL
);
1119 EXPECT_TRUE(response
->headers
.get() != NULL
);
1120 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1121 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1123 std::string response_data
;
1124 rv
= ReadTransaction(trans
.get(), &response_data
);
1126 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1130 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1131 ScopedVector
<UploadElementReader
> element_readers
;
1132 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1133 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1135 HttpRequestInfo request
;
1136 request
.method
= "POST";
1137 request
.url
= GURL("http://www.foo.com/");
1138 request
.upload_data_stream
= &upload_data_stream
;
1139 request
.load_flags
= 0;
1141 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1142 scoped_ptr
<HttpTransaction
> trans(
1143 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1145 MockRead data_reads
[] = {
1146 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1147 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1148 MockRead("hello world"),
1149 MockRead(SYNCHRONOUS
, OK
),
1151 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1152 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1154 TestCompletionCallback callback
;
1156 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1159 rv
= callback
.WaitForResult();
1162 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1163 ASSERT_TRUE(response
!= NULL
);
1165 EXPECT_TRUE(response
->headers
.get() != NULL
);
1166 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1168 std::string response_data
;
1169 rv
= ReadTransaction(trans
.get(), &response_data
);
1171 EXPECT_EQ("hello world", response_data
);
1174 // This test is almost the same as Ignores100 above, but the response contains
1175 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1176 // HTTP/1.1 and the two status headers are read in one read.
1177 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1178 HttpRequestInfo request
;
1179 request
.method
= "GET";
1180 request
.url
= GURL("http://www.foo.com/");
1181 request
.load_flags
= 0;
1183 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1184 scoped_ptr
<HttpTransaction
> trans(
1185 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1187 MockRead data_reads
[] = {
1188 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1189 "HTTP/1.1 200 OK\r\n\r\n"),
1190 MockRead("hello world"),
1191 MockRead(SYNCHRONOUS
, OK
),
1193 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1194 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1196 TestCompletionCallback callback
;
1198 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1199 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1201 rv
= callback
.WaitForResult();
1204 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1205 ASSERT_TRUE(response
!= NULL
);
1207 EXPECT_TRUE(response
->headers
.get() != NULL
);
1208 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1210 std::string response_data
;
1211 rv
= ReadTransaction(trans
.get(), &response_data
);
1213 EXPECT_EQ("hello world", response_data
);
1216 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1217 HttpRequestInfo request
;
1218 request
.method
= "POST";
1219 request
.url
= GURL("http://www.foo.com/");
1220 request
.load_flags
= 0;
1222 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1223 scoped_ptr
<HttpTransaction
> trans(
1224 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1226 MockRead data_reads
[] = {
1227 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1230 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1231 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1233 TestCompletionCallback callback
;
1235 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1236 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1238 rv
= callback
.WaitForResult();
1241 std::string response_data
;
1242 rv
= ReadTransaction(trans
.get(), &response_data
);
1244 EXPECT_EQ("", response_data
);
1247 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1248 HttpRequestInfo request
;
1249 request
.method
= "POST";
1250 request
.url
= GURL("http://www.foo.com/");
1251 request
.load_flags
= 0;
1253 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1254 scoped_ptr
<HttpTransaction
> trans(
1255 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1257 MockRead data_reads
[] = {
1260 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1261 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1263 TestCompletionCallback callback
;
1265 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1266 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1268 rv
= callback
.WaitForResult();
1269 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1272 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1273 const MockWrite
* write_failure
,
1274 const MockRead
* read_failure
) {
1275 HttpRequestInfo request
;
1276 request
.method
= "GET";
1277 request
.url
= GURL("http://www.foo.com/");
1278 request
.load_flags
= 0;
1281 session_deps_
.net_log
= &net_log
;
1282 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1284 // Written data for successfully sending both requests.
1285 MockWrite data1_writes
[] = {
1286 MockWrite("GET / HTTP/1.1\r\n"
1287 "Host: www.foo.com\r\n"
1288 "Connection: keep-alive\r\n\r\n"),
1289 MockWrite("GET / HTTP/1.1\r\n"
1290 "Host: www.foo.com\r\n"
1291 "Connection: keep-alive\r\n\r\n")
1294 // Read results for the first request.
1295 MockRead data1_reads
[] = {
1296 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1298 MockRead(ASYNC
, OK
),
1301 if (write_failure
) {
1302 ASSERT_FALSE(read_failure
);
1303 data1_writes
[1] = *write_failure
;
1305 ASSERT_TRUE(read_failure
);
1306 data1_reads
[2] = *read_failure
;
1309 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1310 data1_writes
, arraysize(data1_writes
));
1311 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1313 MockRead data2_reads
[] = {
1314 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1316 MockRead(ASYNC
, OK
),
1318 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1319 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1321 const char* const kExpectedResponseData
[] = {
1325 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1326 for (int i
= 0; i
< 2; ++i
) {
1327 TestCompletionCallback callback
;
1329 scoped_ptr
<HttpTransaction
> trans(
1330 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1332 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1333 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1335 rv
= callback
.WaitForResult();
1338 LoadTimingInfo load_timing_info
;
1339 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1340 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1342 first_socket_log_id
= load_timing_info
.socket_log_id
;
1344 // The second request should be using a new socket.
1345 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1348 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1349 ASSERT_TRUE(response
!= NULL
);
1351 EXPECT_TRUE(response
->headers
.get() != NULL
);
1352 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1354 std::string response_data
;
1355 rv
= ReadTransaction(trans
.get(), &response_data
);
1357 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1361 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1362 const MockWrite
* write_failure
,
1363 const MockRead
* read_failure
,
1365 HttpRequestInfo request
;
1366 request
.method
= "GET";
1367 request
.url
= GURL("https://www.foo.com/");
1368 request
.load_flags
= 0;
1371 session_deps_
.net_log
= &net_log
;
1372 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1374 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1375 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1377 ssl1
.SetNextProto(GetParam());
1378 ssl2
.SetNextProto(GetParam());
1380 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1381 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1383 // SPDY versions of the request and response.
1384 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1385 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1386 scoped_ptr
<SpdyFrame
> spdy_response(
1387 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1388 scoped_ptr
<SpdyFrame
> spdy_data(
1389 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1391 // HTTP/1.1 versions of the request and response.
1392 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1393 "Host: www.foo.com\r\n"
1394 "Connection: keep-alive\r\n\r\n";
1395 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1396 const char kHttpData
[] = "hello";
1398 std::vector
<MockRead
> data1_reads
;
1399 std::vector
<MockWrite
> data1_writes
;
1400 if (write_failure
) {
1401 ASSERT_FALSE(read_failure
);
1402 data1_writes
.push_back(*write_failure
);
1403 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1405 ASSERT_TRUE(read_failure
);
1407 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1409 data1_writes
.push_back(MockWrite(kHttpRequest
));
1411 data1_reads
.push_back(*read_failure
);
1414 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1415 &data1_writes
[0], data1_writes
.size());
1416 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1418 std::vector
<MockRead
> data2_reads
;
1419 std::vector
<MockWrite
> data2_writes
;
1422 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1424 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1425 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1426 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1428 data2_writes
.push_back(
1429 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1431 data2_reads
.push_back(
1432 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1433 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1434 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1436 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1437 &data2_writes
[0], data2_writes
.size());
1438 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1440 // Preconnect a socket.
1441 SSLConfig ssl_config
;
1442 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1443 session
->GetNextProtos(&ssl_config
.next_protos
);
1444 session
->http_stream_factory()->PreconnectStreams(1, request
, ssl_config
,
1446 // Wait for the preconnect to complete.
1447 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1448 base::RunLoop().RunUntilIdle();
1449 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1451 // Make the request.
1452 TestCompletionCallback callback
;
1454 scoped_ptr
<HttpTransaction
> trans(
1455 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1457 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1458 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1460 rv
= callback
.WaitForResult();
1463 LoadTimingInfo load_timing_info
;
1464 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1465 TestLoadTimingNotReused(
1467 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1469 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1470 ASSERT_TRUE(response
!= NULL
);
1472 EXPECT_TRUE(response
->headers
.get() != NULL
);
1473 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1475 std::string response_data
;
1476 rv
= ReadTransaction(trans
.get(), &response_data
);
1478 EXPECT_EQ(kHttpData
, response_data
);
1481 TEST_P(HttpNetworkTransactionTest
,
1482 KeepAliveConnectionNotConnectedOnWrite
) {
1483 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1484 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1487 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1488 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1489 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1492 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1493 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1494 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1497 // Make sure that on a 408 response (Request Timeout), the request is retried,
1498 // if the socket was a reused keep alive socket.
1499 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1500 MockRead
read_failure(SYNCHRONOUS
,
1501 "HTTP/1.1 408 Request Timeout\r\n"
1502 "Connection: Keep-Alive\r\n"
1503 "Content-Length: 6\r\n\r\n"
1505 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1508 TEST_P(HttpNetworkTransactionTest
,
1509 PreconnectErrorNotConnectedOnWrite
) {
1510 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1511 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1514 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1515 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1516 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1519 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1520 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1521 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1524 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1525 MockRead
read_failure(ASYNC
, OK
); // EOF
1526 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1529 // Make sure that on a 408 response (Request Timeout), the request is retried,
1530 // if the socket was a preconnected (UNUSED_IDLE) socket.
1531 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1532 MockRead
read_failure(SYNCHRONOUS
,
1533 "HTTP/1.1 408 Request Timeout\r\n"
1534 "Connection: Keep-Alive\r\n"
1535 "Content-Length: 6\r\n\r\n"
1537 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1538 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1541 TEST_P(HttpNetworkTransactionTest
,
1542 SpdyPreconnectErrorNotConnectedOnWrite
) {
1543 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1544 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1547 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1548 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1549 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1552 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1553 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1554 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1557 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1558 MockRead
read_failure(ASYNC
, OK
); // EOF
1559 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1562 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1563 HttpRequestInfo request
;
1564 request
.method
= "GET";
1565 request
.url
= GURL("http://www.example.org/");
1566 request
.load_flags
= 0;
1568 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1569 scoped_ptr
<HttpTransaction
> trans(
1570 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1572 MockRead data_reads
[] = {
1573 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1574 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1575 MockRead("hello world"),
1576 MockRead(SYNCHRONOUS
, OK
),
1578 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1579 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1581 TestCompletionCallback callback
;
1583 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1584 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1586 rv
= callback
.WaitForResult();
1587 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1590 // What do various browsers do when the server closes a non-keepalive
1591 // connection without sending any response header or body?
1594 // Safari 3.1.2 (Windows): error page
1595 // Firefox 3.0.1: blank page
1596 // Opera 9.52: after five attempts, blank page
1597 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1598 // Us: error page (EMPTY_RESPONSE)
1599 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1600 MockRead data_reads
[] = {
1601 MockRead(SYNCHRONOUS
, OK
), // EOF
1602 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1603 MockRead("hello world"),
1604 MockRead(SYNCHRONOUS
, OK
),
1606 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1607 arraysize(data_reads
));
1608 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1611 // Test that network access can be deferred and resumed.
1612 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1613 HttpRequestInfo request
;
1614 request
.method
= "GET";
1615 request
.url
= GURL("http://www.example.org/");
1616 request
.load_flags
= 0;
1618 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1619 scoped_ptr
<HttpTransaction
> trans(
1620 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1622 // Defer on OnBeforeNetworkStart.
1623 BeforeNetworkStartHandler
net_start_handler(true); // defer
1624 trans
->SetBeforeNetworkStartCallback(
1625 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1626 base::Unretained(&net_start_handler
)));
1628 MockRead data_reads
[] = {
1629 MockRead("HTTP/1.0 200 OK\r\n"),
1630 MockRead("Content-Length: 5\r\n\r\n"),
1632 MockRead(SYNCHRONOUS
, 0),
1634 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1635 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1637 TestCompletionCallback callback
;
1639 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1641 base::MessageLoop::current()->RunUntilIdle();
1643 // Should have deferred for network start.
1644 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1645 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1647 trans
->ResumeNetworkStart();
1648 rv
= callback
.WaitForResult();
1650 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1652 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1653 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1654 if (rv
== ERR_IO_PENDING
)
1655 rv
= callback
.WaitForResult();
1660 // Test that network use can be deferred and canceled.
1661 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1662 HttpRequestInfo request
;
1663 request
.method
= "GET";
1664 request
.url
= GURL("http://www.example.org/");
1665 request
.load_flags
= 0;
1667 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1668 scoped_ptr
<HttpTransaction
> trans(
1669 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1671 // Defer on OnBeforeNetworkStart.
1672 BeforeNetworkStartHandler
net_start_handler(true); // defer
1673 trans
->SetBeforeNetworkStartCallback(
1674 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1675 base::Unretained(&net_start_handler
)));
1677 TestCompletionCallback callback
;
1679 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1681 base::MessageLoop::current()->RunUntilIdle();
1683 // Should have deferred for network start.
1684 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1685 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1688 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1689 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1690 // destructor in such situations.
1691 // See http://crbug.com/154712 and http://crbug.com/156609.
1692 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1693 HttpRequestInfo request
;
1694 request
.method
= "GET";
1695 request
.url
= GURL("http://www.example.org/");
1696 request
.load_flags
= 0;
1698 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1699 scoped_ptr
<HttpTransaction
> trans(
1700 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1702 MockRead data_reads
[] = {
1703 MockRead("HTTP/1.0 200 OK\r\n"),
1704 MockRead("Connection: keep-alive\r\n"),
1705 MockRead("Content-Length: 100\r\n\r\n"),
1707 MockRead(SYNCHRONOUS
, 0),
1709 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1710 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1712 TestCompletionCallback callback
;
1714 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1715 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1717 rv
= callback
.WaitForResult();
1720 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1721 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1722 if (rv
== ERR_IO_PENDING
)
1723 rv
= callback
.WaitForResult();
1725 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1726 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1729 base::MessageLoop::current()->RunUntilIdle();
1730 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1733 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1734 HttpRequestInfo request
;
1735 request
.method
= "GET";
1736 request
.url
= GURL("http://www.example.org/");
1737 request
.load_flags
= 0;
1739 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1740 scoped_ptr
<HttpTransaction
> trans(
1741 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1743 MockRead data_reads
[] = {
1744 MockRead("HTTP/1.0 200 OK\r\n"),
1745 MockRead("Connection: keep-alive\r\n"),
1746 MockRead("Content-Length: 100\r\n\r\n"),
1747 MockRead(SYNCHRONOUS
, 0),
1749 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1750 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1752 TestCompletionCallback callback
;
1754 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1755 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1757 rv
= callback
.WaitForResult();
1760 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1761 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1762 if (rv
== ERR_IO_PENDING
)
1763 rv
= callback
.WaitForResult();
1764 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1767 base::MessageLoop::current()->RunUntilIdle();
1768 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1771 // Test that we correctly reuse a keep-alive connection after not explicitly
1772 // reading the body.
1773 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1774 HttpRequestInfo request
;
1775 request
.method
= "GET";
1776 request
.url
= GURL("http://www.foo.com/");
1777 request
.load_flags
= 0;
1780 session_deps_
.net_log
= &net_log
;
1781 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1783 // Note that because all these reads happen in the same
1784 // StaticSocketDataProvider, it shows that the same socket is being reused for
1785 // all transactions.
1786 MockRead data1_reads
[] = {
1787 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1788 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1789 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1790 MockRead("HTTP/1.1 302 Found\r\n"
1791 "Content-Length: 0\r\n\r\n"),
1792 MockRead("HTTP/1.1 302 Found\r\n"
1793 "Content-Length: 5\r\n\r\n"
1795 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1796 "Content-Length: 0\r\n\r\n"),
1797 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1798 "Content-Length: 5\r\n\r\n"
1800 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1803 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1804 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1806 MockRead data2_reads
[] = {
1807 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1809 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1810 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1812 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1813 std::string response_lines
[kNumUnreadBodies
];
1815 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1816 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1817 TestCompletionCallback callback
;
1819 scoped_ptr
<HttpTransaction
> trans(
1820 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1822 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1823 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1825 rv
= callback
.WaitForResult();
1828 LoadTimingInfo load_timing_info
;
1829 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1831 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1832 first_socket_log_id
= load_timing_info
.socket_log_id
;
1834 TestLoadTimingReused(load_timing_info
);
1835 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1838 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1839 ASSERT_TRUE(response
!= NULL
);
1841 ASSERT_TRUE(response
->headers
.get() != NULL
);
1842 response_lines
[i
] = response
->headers
->GetStatusLine();
1844 // We intentionally don't read the response bodies.
1847 const char* const kStatusLines
[] = {
1848 "HTTP/1.1 204 No Content",
1849 "HTTP/1.1 205 Reset Content",
1850 "HTTP/1.1 304 Not Modified",
1851 "HTTP/1.1 302 Found",
1852 "HTTP/1.1 302 Found",
1853 "HTTP/1.1 301 Moved Permanently",
1854 "HTTP/1.1 301 Moved Permanently",
1857 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1858 "forgot to update kStatusLines");
1860 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1861 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1863 TestCompletionCallback callback
;
1864 scoped_ptr
<HttpTransaction
> trans(
1865 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1866 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1867 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1868 rv
= callback
.WaitForResult();
1870 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1871 ASSERT_TRUE(response
!= NULL
);
1872 ASSERT_TRUE(response
->headers
.get() != NULL
);
1873 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1874 std::string response_data
;
1875 rv
= ReadTransaction(trans
.get(), &response_data
);
1877 EXPECT_EQ("hello", response_data
);
1880 // Test the request-challenge-retry sequence for basic auth.
1881 // (basic auth is the easiest to mock, because it has no randomness).
1882 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1883 HttpRequestInfo request
;
1884 request
.method
= "GET";
1885 request
.url
= GURL("http://www.example.org/");
1886 request
.load_flags
= 0;
1889 session_deps_
.net_log
= &log
;
1890 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1891 scoped_ptr
<HttpTransaction
> trans(
1892 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1894 MockWrite data_writes1
[] = {
1896 "GET / HTTP/1.1\r\n"
1897 "Host: www.example.org\r\n"
1898 "Connection: keep-alive\r\n\r\n"),
1901 MockRead data_reads1
[] = {
1902 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1903 // Give a couple authenticate options (only the middle one is actually
1905 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1906 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1907 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909 // Large content-length -- won't matter, as connection will be reset.
1910 MockRead("Content-Length: 10000\r\n\r\n"),
1911 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1914 // After calling trans->RestartWithAuth(), this is the request we should
1915 // be issuing -- the final header line contains the credentials.
1916 MockWrite data_writes2
[] = {
1918 "GET / HTTP/1.1\r\n"
1919 "Host: www.example.org\r\n"
1920 "Connection: keep-alive\r\n"
1921 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1924 // Lastly, the server responds with the actual content.
1925 MockRead data_reads2
[] = {
1926 MockRead("HTTP/1.0 200 OK\r\n"),
1927 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1928 MockRead("Content-Length: 100\r\n\r\n"),
1929 MockRead(SYNCHRONOUS
, OK
),
1932 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1933 data_writes1
, arraysize(data_writes1
));
1934 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1935 data_writes2
, arraysize(data_writes2
));
1936 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1937 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1939 TestCompletionCallback callback1
;
1941 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1944 rv
= callback1
.WaitForResult();
1947 LoadTimingInfo load_timing_info1
;
1948 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1949 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1951 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1952 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1954 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1955 ASSERT_TRUE(response
!= NULL
);
1956 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1958 TestCompletionCallback callback2
;
1960 rv
= trans
->RestartWithAuth(
1961 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1962 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1964 rv
= callback2
.WaitForResult();
1967 LoadTimingInfo load_timing_info2
;
1968 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1969 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1970 // The load timing after restart should have a new socket ID, and times after
1971 // those of the first load timing.
1972 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1973 load_timing_info2
.connect_timing
.connect_start
);
1974 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1976 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1977 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1979 response
= trans
->GetResponseInfo();
1980 ASSERT_TRUE(response
!= NULL
);
1981 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1982 EXPECT_EQ(100, response
->headers
->GetContentLength());
1985 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1986 HttpRequestInfo request
;
1987 request
.method
= "GET";
1988 request
.url
= GURL("http://www.example.org/");
1989 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1991 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1992 scoped_ptr
<HttpTransaction
> trans(
1993 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1995 MockWrite data_writes
[] = {
1997 "GET / HTTP/1.1\r\n"
1998 "Host: www.example.org\r\n"
1999 "Connection: keep-alive\r\n\r\n"),
2002 MockRead data_reads
[] = {
2003 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2004 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2006 // Large content-length -- won't matter, as connection will be reset.
2007 MockRead("Content-Length: 10000\r\n\r\n"),
2008 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2011 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2012 data_writes
, arraysize(data_writes
));
2013 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2014 TestCompletionCallback callback
;
2016 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2017 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2019 rv
= callback
.WaitForResult();
2022 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2023 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2025 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2026 ASSERT_TRUE(response
!= NULL
);
2027 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2030 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2032 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2033 HttpRequestInfo request
;
2034 request
.method
= "GET";
2035 request
.url
= GURL("http://www.example.org/");
2036 request
.load_flags
= 0;
2039 session_deps_
.net_log
= &log
;
2040 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2042 MockWrite data_writes1
[] = {
2044 "GET / HTTP/1.1\r\n"
2045 "Host: www.example.org\r\n"
2046 "Connection: keep-alive\r\n\r\n"),
2048 // After calling trans->RestartWithAuth(), this is the request we should
2049 // be issuing -- the final header line contains the credentials.
2051 "GET / HTTP/1.1\r\n"
2052 "Host: www.example.org\r\n"
2053 "Connection: keep-alive\r\n"
2054 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2057 MockRead data_reads1
[] = {
2058 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2059 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2060 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2061 MockRead("Content-Length: 14\r\n\r\n"),
2062 MockRead("Unauthorized\r\n"),
2064 // Lastly, the server responds with the actual content.
2065 MockRead("HTTP/1.1 200 OK\r\n"),
2066 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2067 MockRead("Content-Length: 5\r\n\r\n"),
2071 // If there is a regression where we disconnect a Keep-Alive
2072 // connection during an auth roundtrip, we'll end up reading this.
2073 MockRead data_reads2
[] = {
2074 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2077 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2078 data_writes1
, arraysize(data_writes1
));
2079 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2081 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2082 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2084 TestCompletionCallback callback1
;
2086 scoped_ptr
<HttpTransaction
> trans(
2087 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2088 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2089 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2091 rv
= callback1
.WaitForResult();
2094 LoadTimingInfo load_timing_info1
;
2095 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2096 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2098 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2099 ASSERT_TRUE(response
!= NULL
);
2100 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2102 TestCompletionCallback callback2
;
2104 rv
= trans
->RestartWithAuth(
2105 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2108 rv
= callback2
.WaitForResult();
2111 LoadTimingInfo load_timing_info2
;
2112 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2113 TestLoadTimingReused(load_timing_info2
);
2114 // The load timing after restart should have the same socket ID, and times
2115 // those of the first load timing.
2116 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2117 load_timing_info2
.send_start
);
2118 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2120 response
= trans
->GetResponseInfo();
2121 ASSERT_TRUE(response
!= NULL
);
2122 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2123 EXPECT_EQ(5, response
->headers
->GetContentLength());
2125 std::string response_data
;
2126 rv
= ReadTransaction(trans
.get(), &response_data
);
2128 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2129 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2132 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2133 // connection and with no response body to drain.
2134 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2135 HttpRequestInfo request
;
2136 request
.method
= "GET";
2137 request
.url
= GURL("http://www.example.org/");
2138 request
.load_flags
= 0;
2140 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2142 MockWrite data_writes1
[] = {
2144 "GET / HTTP/1.1\r\n"
2145 "Host: www.example.org\r\n"
2146 "Connection: keep-alive\r\n\r\n"),
2148 // After calling trans->RestartWithAuth(), this is the request we should
2149 // be issuing -- the final header line contains the credentials.
2151 "GET / HTTP/1.1\r\n"
2152 "Host: www.example.org\r\n"
2153 "Connection: keep-alive\r\n"
2154 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2157 MockRead data_reads1
[] = {
2158 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2159 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2160 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2162 // Lastly, the server responds with the actual content.
2163 MockRead("HTTP/1.1 200 OK\r\n"),
2164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2165 MockRead("Content-Length: 5\r\n\r\n"),
2169 // An incorrect reconnect would cause this to be read.
2170 MockRead data_reads2
[] = {
2171 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2174 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2175 data_writes1
, arraysize(data_writes1
));
2176 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2178 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2179 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2181 TestCompletionCallback callback1
;
2183 scoped_ptr
<HttpTransaction
> trans(
2184 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2185 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2186 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2188 rv
= callback1
.WaitForResult();
2191 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2192 ASSERT_TRUE(response
!= NULL
);
2193 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2195 TestCompletionCallback callback2
;
2197 rv
= trans
->RestartWithAuth(
2198 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2199 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2201 rv
= callback2
.WaitForResult();
2204 response
= trans
->GetResponseInfo();
2205 ASSERT_TRUE(response
!= NULL
);
2206 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2207 EXPECT_EQ(5, response
->headers
->GetContentLength());
2210 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2211 // connection and with a large response body to drain.
2212 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2213 HttpRequestInfo request
;
2214 request
.method
= "GET";
2215 request
.url
= GURL("http://www.example.org/");
2216 request
.load_flags
= 0;
2218 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2220 MockWrite data_writes1
[] = {
2222 "GET / HTTP/1.1\r\n"
2223 "Host: www.example.org\r\n"
2224 "Connection: keep-alive\r\n\r\n"),
2226 // After calling trans->RestartWithAuth(), this is the request we should
2227 // be issuing -- the final header line contains the credentials.
2229 "GET / HTTP/1.1\r\n"
2230 "Host: www.example.org\r\n"
2231 "Connection: keep-alive\r\n"
2232 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2235 // Respond with 5 kb of response body.
2236 std::string
large_body_string("Unauthorized");
2237 large_body_string
.append(5 * 1024, ' ');
2238 large_body_string
.append("\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 // 5134 = 12 + 5 * 1024 + 2
2245 MockRead("Content-Length: 5134\r\n\r\n"),
2246 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2248 // Lastly, the server responds with the actual content.
2249 MockRead("HTTP/1.1 200 OK\r\n"),
2250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2251 MockRead("Content-Length: 5\r\n\r\n"),
2255 // An incorrect reconnect would cause this to be read.
2256 MockRead data_reads2
[] = {
2257 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2260 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2261 data_writes1
, arraysize(data_writes1
));
2262 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2264 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2265 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2267 TestCompletionCallback callback1
;
2269 scoped_ptr
<HttpTransaction
> trans(
2270 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2271 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2274 rv
= callback1
.WaitForResult();
2277 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2278 ASSERT_TRUE(response
!= NULL
);
2279 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2281 TestCompletionCallback callback2
;
2283 rv
= trans
->RestartWithAuth(
2284 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2285 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2287 rv
= callback2
.WaitForResult();
2290 response
= trans
->GetResponseInfo();
2291 ASSERT_TRUE(response
!= NULL
);
2292 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2293 EXPECT_EQ(5, response
->headers
->GetContentLength());
2296 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2297 // connection, but the server gets impatient and closes the connection.
2298 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2299 HttpRequestInfo request
;
2300 request
.method
= "GET";
2301 request
.url
= GURL("http://www.example.org/");
2302 request
.load_flags
= 0;
2304 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2306 MockWrite data_writes1
[] = {
2308 "GET / HTTP/1.1\r\n"
2309 "Host: www.example.org\r\n"
2310 "Connection: keep-alive\r\n\r\n"),
2311 // This simulates the seemingly successful write to a closed connection
2312 // if the bug is not fixed.
2314 "GET / HTTP/1.1\r\n"
2315 "Host: www.example.org\r\n"
2316 "Connection: keep-alive\r\n"
2317 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2320 MockRead data_reads1
[] = {
2321 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2322 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2324 MockRead("Content-Length: 14\r\n\r\n"),
2325 // Tell MockTCPClientSocket to simulate the server closing the connection.
2326 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2327 MockRead("Unauthorized\r\n"),
2328 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2331 // After calling trans->RestartWithAuth(), this is the request we should
2332 // be issuing -- the final header line contains the credentials.
2333 MockWrite data_writes2
[] = {
2335 "GET / HTTP/1.1\r\n"
2336 "Host: www.example.org\r\n"
2337 "Connection: keep-alive\r\n"
2338 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2341 // Lastly, the server responds with the actual content.
2342 MockRead data_reads2
[] = {
2343 MockRead("HTTP/1.1 200 OK\r\n"),
2344 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2345 MockRead("Content-Length: 5\r\n\r\n"),
2349 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2350 data_writes1
, arraysize(data_writes1
));
2351 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2352 data_writes2
, arraysize(data_writes2
));
2353 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2354 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2356 TestCompletionCallback callback1
;
2358 scoped_ptr
<HttpTransaction
> trans(
2359 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2360 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2361 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2363 rv
= callback1
.WaitForResult();
2366 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2367 ASSERT_TRUE(response
!= NULL
);
2368 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2370 TestCompletionCallback callback2
;
2372 rv
= trans
->RestartWithAuth(
2373 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2374 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2376 rv
= callback2
.WaitForResult();
2379 response
= trans
->GetResponseInfo();
2380 ASSERT_TRUE(response
!= NULL
);
2381 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2382 EXPECT_EQ(5, response
->headers
->GetContentLength());
2385 // Test the request-challenge-retry sequence for basic auth, over a connection
2386 // that requires a restart when setting up an SSL tunnel.
2387 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2388 HttpRequestInfo request
;
2389 request
.method
= "GET";
2390 request
.url
= GURL("https://www.example.org/");
2391 // when the no authentication data flag is set.
2392 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2394 // Configure against proxy server "myproxy:70".
2395 session_deps_
.proxy_service
.reset(
2396 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2397 BoundTestNetLog log
;
2398 session_deps_
.net_log
= log
.bound().net_log();
2399 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2401 // Since we have proxy, should try to establish tunnel.
2402 MockWrite data_writes1
[] = {
2404 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2405 "Host: www.example.org\r\n"
2406 "Proxy-Connection: keep-alive\r\n\r\n"),
2408 // After calling trans->RestartWithAuth(), this is the request we should
2409 // be issuing -- the final header line contains the credentials.
2411 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2412 "Host: www.example.org\r\n"
2413 "Proxy-Connection: keep-alive\r\n"
2414 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2417 "GET / HTTP/1.1\r\n"
2418 "Host: www.example.org\r\n"
2419 "Connection: keep-alive\r\n\r\n"),
2422 // The proxy responds to the connect with a 407, using a persistent
2424 MockRead data_reads1
[] = {
2426 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2427 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2429 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2431 MockRead("HTTP/1.1 200 OK\r\n"),
2432 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2433 MockRead("Content-Length: 5\r\n\r\n"),
2434 MockRead(SYNCHRONOUS
, "hello"),
2437 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2438 data_writes1
, arraysize(data_writes1
));
2439 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2440 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2441 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2443 TestCompletionCallback callback1
;
2445 scoped_ptr
<HttpTransaction
> trans(
2446 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2448 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2449 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2451 rv
= callback1
.WaitForResult();
2453 TestNetLogEntry::List entries
;
2454 log
.GetEntries(&entries
);
2455 size_t pos
= ExpectLogContainsSomewhere(
2456 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2457 NetLog::PHASE_NONE
);
2458 ExpectLogContainsSomewhere(
2459 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2460 NetLog::PHASE_NONE
);
2462 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2463 ASSERT_TRUE(response
!= NULL
);
2464 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2465 ASSERT_FALSE(response
->headers
.get() == NULL
);
2466 EXPECT_EQ(407, response
->headers
->response_code());
2467 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2468 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2470 LoadTimingInfo load_timing_info
;
2471 // CONNECT requests and responses are handled at the connect job level, so
2472 // the transaction does not yet have a connection.
2473 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2475 TestCompletionCallback callback2
;
2478 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2479 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2481 rv
= callback2
.WaitForResult();
2484 response
= trans
->GetResponseInfo();
2485 ASSERT_TRUE(response
!= NULL
);
2487 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2488 EXPECT_EQ(200, response
->headers
->response_code());
2489 EXPECT_EQ(5, response
->headers
->GetContentLength());
2490 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2492 // The password prompt info should not be set.
2493 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2495 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2496 TestLoadTimingNotReusedWithPac(load_timing_info
,
2497 CONNECT_TIMING_HAS_SSL_TIMES
);
2500 session
->CloseAllConnections();
2503 // Test the request-challenge-retry sequence for basic auth, over a connection
2504 // that requires a restart when setting up an SSL tunnel.
2505 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2506 HttpRequestInfo request
;
2507 request
.method
= "GET";
2508 request
.url
= GURL("https://www.example.org/");
2509 // when the no authentication data flag is set.
2510 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2512 // Configure against proxy server "myproxy:70".
2513 session_deps_
.proxy_service
.reset(
2514 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2515 BoundTestNetLog log
;
2516 session_deps_
.net_log
= log
.bound().net_log();
2517 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2519 // Since we have proxy, should try to establish tunnel.
2520 MockWrite data_writes1
[] = {
2522 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2523 "Host: www.example.org\r\n"
2524 "Proxy-Connection: keep-alive\r\n\r\n"),
2526 // After calling trans->RestartWithAuth(), this is the request we should
2527 // be issuing -- the final header line contains the credentials.
2529 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2530 "Host: www.example.org\r\n"
2531 "Proxy-Connection: keep-alive\r\n"
2532 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2535 "GET / HTTP/1.1\r\n"
2536 "Host: www.example.org\r\n"
2537 "Connection: keep-alive\r\n\r\n"),
2540 // The proxy responds to the connect with a 407, using a persistent
2542 MockRead data_reads1
[] = {
2544 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2545 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2546 MockRead("Proxy-Connection: close\r\n\r\n"),
2548 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2550 MockRead("HTTP/1.1 200 OK\r\n"),
2551 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2552 MockRead("Content-Length: 5\r\n\r\n"),
2553 MockRead(SYNCHRONOUS
, "hello"),
2556 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2557 data_writes1
, arraysize(data_writes1
));
2558 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2559 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2560 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2562 TestCompletionCallback callback1
;
2564 scoped_ptr
<HttpTransaction
> trans(
2565 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2567 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2570 rv
= callback1
.WaitForResult();
2572 TestNetLogEntry::List entries
;
2573 log
.GetEntries(&entries
);
2574 size_t pos
= ExpectLogContainsSomewhere(
2575 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2576 NetLog::PHASE_NONE
);
2577 ExpectLogContainsSomewhere(
2579 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2580 NetLog::PHASE_NONE
);
2582 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2583 ASSERT_TRUE(response
!= NULL
);
2584 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2585 ASSERT_FALSE(response
->headers
.get() == NULL
);
2586 EXPECT_EQ(407, response
->headers
->response_code());
2587 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2588 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2590 LoadTimingInfo load_timing_info
;
2591 // CONNECT requests and responses are handled at the connect job level, so
2592 // the transaction does not yet have a connection.
2593 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2595 TestCompletionCallback callback2
;
2597 rv
= trans
->RestartWithAuth(
2598 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2599 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2601 rv
= callback2
.WaitForResult();
2604 response
= trans
->GetResponseInfo();
2605 ASSERT_TRUE(response
!= NULL
);
2607 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2608 EXPECT_EQ(200, response
->headers
->response_code());
2609 EXPECT_EQ(5, response
->headers
->GetContentLength());
2610 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2612 // The password prompt info should not be set.
2613 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2615 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2616 TestLoadTimingNotReusedWithPac(load_timing_info
,
2617 CONNECT_TIMING_HAS_SSL_TIMES
);
2620 session
->CloseAllConnections();
2623 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2624 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2625 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2626 HttpRequestInfo request
;
2627 request
.method
= "GET";
2628 request
.url
= GURL("https://www.example.org/");
2629 // Ensure that proxy authentication is attempted even
2630 // when the no authentication data flag is set.
2631 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2633 // Configure against proxy server "myproxy:70".
2634 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2635 BoundTestNetLog log
;
2636 session_deps_
.net_log
= log
.bound().net_log();
2637 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2639 scoped_ptr
<HttpTransaction
> trans(
2640 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2642 // Since we have proxy, should try to establish tunnel.
2643 MockWrite data_writes1
[] = {
2645 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2646 "Host: www.example.org\r\n"
2647 "Proxy-Connection: keep-alive\r\n\r\n"),
2649 // After calling trans->RestartWithAuth(), this is the request we should
2650 // be issuing -- the final header line contains the credentials.
2652 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2653 "Host: www.example.org\r\n"
2654 "Proxy-Connection: keep-alive\r\n"
2655 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2658 // The proxy responds to the connect with a 407, using a persistent
2659 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2660 MockRead data_reads1
[] = {
2662 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2663 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2664 MockRead("Proxy-Connection: keep-alive\r\n"),
2665 MockRead("Content-Length: 10\r\n\r\n"),
2666 MockRead("0123456789"),
2668 // Wrong credentials (wrong password).
2669 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2670 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2671 MockRead("Proxy-Connection: keep-alive\r\n"),
2672 MockRead("Content-Length: 10\r\n\r\n"),
2673 // No response body because the test stops reading here.
2674 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2677 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2678 data_writes1
, arraysize(data_writes1
));
2679 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2681 TestCompletionCallback callback1
;
2683 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2684 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2686 rv
= callback1
.WaitForResult();
2688 TestNetLogEntry::List entries
;
2689 log
.GetEntries(&entries
);
2690 size_t pos
= ExpectLogContainsSomewhere(
2691 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2692 NetLog::PHASE_NONE
);
2693 ExpectLogContainsSomewhere(
2694 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2695 NetLog::PHASE_NONE
);
2697 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2698 ASSERT_TRUE(response
);
2699 ASSERT_TRUE(response
->headers
);
2700 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2701 EXPECT_EQ(407, response
->headers
->response_code());
2702 EXPECT_EQ(10, response
->headers
->GetContentLength());
2703 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2704 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2706 TestCompletionCallback callback2
;
2708 // Wrong password (should be "bar").
2710 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2711 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2713 rv
= callback2
.WaitForResult();
2716 response
= trans
->GetResponseInfo();
2717 ASSERT_TRUE(response
);
2718 ASSERT_TRUE(response
->headers
);
2719 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2720 EXPECT_EQ(407, response
->headers
->response_code());
2721 EXPECT_EQ(10, response
->headers
->GetContentLength());
2722 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2723 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2725 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2727 session
->CloseAllConnections();
2730 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2731 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2732 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2733 HttpRequestInfo request
;
2734 request
.method
= "GET";
2735 request
.url
= GURL("https://www.example.org/");
2736 // Ensure that proxy authentication is attempted even
2737 // when the no authentication data flag is set.
2738 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2740 // Configure against proxy server "myproxy:70".
2741 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2742 BoundTestNetLog log
;
2743 session_deps_
.net_log
= log
.bound().net_log();
2744 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2746 scoped_ptr
<HttpTransaction
> trans(
2747 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2749 // Since we have proxy, should try to establish tunnel.
2750 MockWrite data_writes1
[] = {
2752 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2753 "Host: www.example.org\r\n"
2754 "Proxy-Connection: keep-alive\r\n\r\n"),
2756 // After calling trans->RestartWithAuth(), this is the request we should
2757 // be issuing -- the final header line contains the credentials.
2759 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2760 "Host: www.example.org\r\n"
2761 "Proxy-Connection: keep-alive\r\n"
2762 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2765 // The proxy responds to the connect with a 407, using a persistent
2767 MockRead data_reads1
[] = {
2769 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2770 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2771 MockRead("Content-Length: 10\r\n\r\n"),
2772 MockRead("0123456789"),
2774 // Wrong credentials (wrong password).
2775 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2776 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2777 MockRead("Content-Length: 10\r\n\r\n"),
2778 // No response body because the test stops reading here.
2779 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2782 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2783 data_writes1
, arraysize(data_writes1
));
2784 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2786 TestCompletionCallback callback1
;
2788 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2789 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2791 rv
= callback1
.WaitForResult();
2793 TestNetLogEntry::List entries
;
2794 log
.GetEntries(&entries
);
2795 size_t pos
= ExpectLogContainsSomewhere(
2796 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2797 NetLog::PHASE_NONE
);
2798 ExpectLogContainsSomewhere(
2800 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2801 NetLog::PHASE_NONE
);
2803 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2804 ASSERT_TRUE(response
);
2805 ASSERT_TRUE(response
->headers
);
2806 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2807 EXPECT_EQ(407, response
->headers
->response_code());
2808 EXPECT_EQ(10, response
->headers
->GetContentLength());
2809 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2810 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2812 TestCompletionCallback callback2
;
2814 // Wrong password (should be "bar").
2815 rv
= trans
->RestartWithAuth(
2816 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2817 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2819 rv
= callback2
.WaitForResult();
2822 response
= trans
->GetResponseInfo();
2823 ASSERT_TRUE(response
);
2824 ASSERT_TRUE(response
->headers
);
2825 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2826 EXPECT_EQ(407, response
->headers
->response_code());
2827 EXPECT_EQ(10, response
->headers
->GetContentLength());
2828 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2829 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2831 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2833 session
->CloseAllConnections();
2836 // Test that we don't read the response body when we fail to establish a tunnel,
2837 // even if the user cancels the proxy's auth attempt.
2838 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2839 HttpRequestInfo request
;
2840 request
.method
= "GET";
2841 request
.url
= GURL("https://www.example.org/");
2842 request
.load_flags
= 0;
2844 // Configure against proxy server "myproxy:70".
2845 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2847 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2849 scoped_ptr
<HttpTransaction
> trans(
2850 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2852 // Since we have proxy, should try to establish tunnel.
2853 MockWrite data_writes
[] = {
2855 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2856 "Host: www.example.org\r\n"
2857 "Proxy-Connection: keep-alive\r\n\r\n"),
2860 // The proxy responds to the connect with a 407.
2861 MockRead data_reads
[] = {
2862 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2863 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2864 MockRead("Content-Length: 10\r\n\r\n"),
2865 MockRead("0123456789"), // Should not be reached.
2866 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2869 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2870 data_writes
, arraysize(data_writes
));
2871 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2873 TestCompletionCallback callback
;
2875 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2878 rv
= callback
.WaitForResult();
2881 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2882 ASSERT_TRUE(response
);
2883 ASSERT_TRUE(response
->headers
);
2884 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2885 EXPECT_EQ(407, response
->headers
->response_code());
2886 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2888 std::string response_data
;
2889 rv
= ReadTransaction(trans
.get(), &response_data
);
2890 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2892 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2893 session
->CloseAllConnections();
2896 // Test that we don't pass extraneous headers from the proxy's response to the
2897 // caller when the proxy responds to CONNECT with 407.
2898 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2899 HttpRequestInfo request
;
2900 request
.method
= "GET";
2901 request
.url
= GURL("https://www.example.org/");
2902 request
.load_flags
= 0;
2904 // Configure against proxy server "myproxy:70".
2905 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2907 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2909 scoped_ptr
<HttpTransaction
> trans(
2910 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2912 // Since we have proxy, should try to establish tunnel.
2913 MockWrite data_writes
[] = {
2915 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2916 "Host: www.example.org\r\n"
2917 "Proxy-Connection: keep-alive\r\n\r\n"),
2920 // The proxy responds to the connect with a 407.
2921 MockRead data_reads
[] = {
2922 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2923 MockRead("X-Foo: bar\r\n"),
2924 MockRead("Set-Cookie: foo=bar\r\n"),
2925 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2926 MockRead("Content-Length: 10\r\n\r\n"),
2927 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2930 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2931 arraysize(data_writes
));
2932 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2934 TestCompletionCallback callback
;
2936 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2937 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2939 rv
= callback
.WaitForResult();
2942 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2943 ASSERT_TRUE(response
);
2944 ASSERT_TRUE(response
->headers
);
2945 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2946 EXPECT_EQ(407, response
->headers
->response_code());
2947 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2948 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2949 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2951 std::string response_data
;
2952 rv
= ReadTransaction(trans
.get(), &response_data
);
2953 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2955 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2956 session
->CloseAllConnections();
2959 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2960 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2961 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2962 HttpRequestInfo request
;
2963 request
.method
= "GET";
2964 request
.url
= GURL("http://www.example.org/");
2965 request
.load_flags
= 0;
2967 // We are using a DIRECT connection (i.e. no proxy) for this session.
2968 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2969 scoped_ptr
<HttpTransaction
> trans(
2970 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2972 MockWrite data_writes1
[] = {
2974 "GET / HTTP/1.1\r\n"
2975 "Host: www.example.org\r\n"
2976 "Connection: keep-alive\r\n\r\n"),
2979 MockRead data_reads1
[] = {
2980 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2981 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2982 // Large content-length -- won't matter, as connection will be reset.
2983 MockRead("Content-Length: 10000\r\n\r\n"),
2984 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2987 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2988 data_writes1
, arraysize(data_writes1
));
2989 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2991 TestCompletionCallback callback
;
2993 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2994 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2996 rv
= callback
.WaitForResult();
2997 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3000 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3001 // through a non-authenticating proxy. The request should fail with
3002 // ERR_UNEXPECTED_PROXY_AUTH.
3003 // Note that it is impossible to detect if an HTTP server returns a 407 through
3004 // a non-authenticating proxy - there is nothing to indicate whether the
3005 // response came from the proxy or the server, so it is treated as if the proxy
3006 // issued the challenge.
3007 TEST_P(HttpNetworkTransactionTest
,
3008 HttpsServerRequestsProxyAuthThroughProxy
) {
3009 HttpRequestInfo request
;
3010 request
.method
= "GET";
3011 request
.url
= GURL("https://www.example.org/");
3013 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3014 BoundTestNetLog log
;
3015 session_deps_
.net_log
= log
.bound().net_log();
3016 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3018 // Since we have proxy, should try to establish tunnel.
3019 MockWrite data_writes1
[] = {
3021 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3022 "Host: www.example.org\r\n"
3023 "Proxy-Connection: keep-alive\r\n\r\n"),
3026 "GET / HTTP/1.1\r\n"
3027 "Host: www.example.org\r\n"
3028 "Connection: keep-alive\r\n\r\n"),
3031 MockRead data_reads1
[] = {
3032 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3034 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3035 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3037 MockRead(SYNCHRONOUS
, OK
),
3040 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3041 data_writes1
, arraysize(data_writes1
));
3042 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3043 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3044 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3046 TestCompletionCallback callback1
;
3048 scoped_ptr
<HttpTransaction
> trans(
3049 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3051 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3054 rv
= callback1
.WaitForResult();
3055 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3056 TestNetLogEntry::List entries
;
3057 log
.GetEntries(&entries
);
3058 size_t pos
= ExpectLogContainsSomewhere(
3059 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3060 NetLog::PHASE_NONE
);
3061 ExpectLogContainsSomewhere(
3063 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3064 NetLog::PHASE_NONE
);
3067 // Test the load timing for HTTPS requests with an HTTP proxy.
3068 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3069 HttpRequestInfo request1
;
3070 request1
.method
= "GET";
3071 request1
.url
= GURL("https://www.example.org/1");
3073 HttpRequestInfo request2
;
3074 request2
.method
= "GET";
3075 request2
.url
= GURL("https://www.example.org/2");
3077 // Configure against proxy server "myproxy:70".
3078 session_deps_
.proxy_service
.reset(
3079 ProxyService::CreateFixed("PROXY myproxy:70"));
3080 BoundTestNetLog log
;
3081 session_deps_
.net_log
= log
.bound().net_log();
3082 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3084 // Since we have proxy, should try to establish tunnel.
3085 MockWrite data_writes1
[] = {
3087 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3088 "Host: www.example.org\r\n"
3089 "Proxy-Connection: keep-alive\r\n\r\n"),
3092 "GET /1 HTTP/1.1\r\n"
3093 "Host: www.example.org\r\n"
3094 "Connection: keep-alive\r\n\r\n"),
3097 "GET /2 HTTP/1.1\r\n"
3098 "Host: www.example.org\r\n"
3099 "Connection: keep-alive\r\n\r\n"),
3102 // The proxy responds to the connect with a 407, using a persistent
3104 MockRead data_reads1
[] = {
3105 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3107 MockRead("HTTP/1.1 200 OK\r\n"),
3108 MockRead("Content-Length: 1\r\n\r\n"),
3109 MockRead(SYNCHRONOUS
, "1"),
3111 MockRead("HTTP/1.1 200 OK\r\n"),
3112 MockRead("Content-Length: 2\r\n\r\n"),
3113 MockRead(SYNCHRONOUS
, "22"),
3116 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3117 data_writes1
, arraysize(data_writes1
));
3118 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3119 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3120 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3122 TestCompletionCallback callback1
;
3123 scoped_ptr
<HttpTransaction
> trans1(
3124 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3126 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3127 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3129 rv
= callback1
.WaitForResult();
3132 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3133 ASSERT_TRUE(response1
!= NULL
);
3134 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3135 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3137 LoadTimingInfo load_timing_info1
;
3138 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3139 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3143 TestCompletionCallback callback2
;
3144 scoped_ptr
<HttpTransaction
> trans2(
3145 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3147 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3148 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3150 rv
= callback2
.WaitForResult();
3153 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3154 ASSERT_TRUE(response2
!= NULL
);
3155 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3156 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3158 LoadTimingInfo load_timing_info2
;
3159 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3160 TestLoadTimingReused(load_timing_info2
);
3162 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3165 session
->CloseAllConnections();
3168 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3169 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3170 HttpRequestInfo request1
;
3171 request1
.method
= "GET";
3172 request1
.url
= GURL("https://www.example.org/1");
3174 HttpRequestInfo request2
;
3175 request2
.method
= "GET";
3176 request2
.url
= GURL("https://www.example.org/2");
3178 // Configure against proxy server "myproxy:70".
3179 session_deps_
.proxy_service
.reset(
3180 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3181 BoundTestNetLog log
;
3182 session_deps_
.net_log
= log
.bound().net_log();
3183 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3185 // Since we have proxy, should try to establish tunnel.
3186 MockWrite data_writes1
[] = {
3188 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3189 "Host: www.example.org\r\n"
3190 "Proxy-Connection: keep-alive\r\n\r\n"),
3193 "GET /1 HTTP/1.1\r\n"
3194 "Host: www.example.org\r\n"
3195 "Connection: keep-alive\r\n\r\n"),
3198 "GET /2 HTTP/1.1\r\n"
3199 "Host: www.example.org\r\n"
3200 "Connection: keep-alive\r\n\r\n"),
3203 // The proxy responds to the connect with a 407, using a persistent
3205 MockRead data_reads1
[] = {
3206 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3208 MockRead("HTTP/1.1 200 OK\r\n"),
3209 MockRead("Content-Length: 1\r\n\r\n"),
3210 MockRead(SYNCHRONOUS
, "1"),
3212 MockRead("HTTP/1.1 200 OK\r\n"),
3213 MockRead("Content-Length: 2\r\n\r\n"),
3214 MockRead(SYNCHRONOUS
, "22"),
3217 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3218 data_writes1
, arraysize(data_writes1
));
3219 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3220 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3221 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3223 TestCompletionCallback callback1
;
3224 scoped_ptr
<HttpTransaction
> trans1(
3225 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3227 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3228 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3230 rv
= callback1
.WaitForResult();
3233 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3234 ASSERT_TRUE(response1
!= NULL
);
3235 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3236 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3238 LoadTimingInfo load_timing_info1
;
3239 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3240 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3241 CONNECT_TIMING_HAS_SSL_TIMES
);
3245 TestCompletionCallback callback2
;
3246 scoped_ptr
<HttpTransaction
> trans2(
3247 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3249 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3252 rv
= callback2
.WaitForResult();
3255 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3256 ASSERT_TRUE(response2
!= NULL
);
3257 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3258 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3260 LoadTimingInfo load_timing_info2
;
3261 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3262 TestLoadTimingReusedWithPac(load_timing_info2
);
3264 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3267 session
->CloseAllConnections();
3270 // Test a simple get through an HTTPS Proxy.
3271 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3272 HttpRequestInfo request
;
3273 request
.method
= "GET";
3274 request
.url
= GURL("http://www.example.org/");
3276 // Configure against https proxy server "proxy:70".
3277 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3278 "https://proxy:70"));
3279 BoundTestNetLog log
;
3280 session_deps_
.net_log
= log
.bound().net_log();
3281 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3283 // Since we have proxy, should use full url
3284 MockWrite data_writes1
[] = {
3286 "GET http://www.example.org/ HTTP/1.1\r\n"
3287 "Host: www.example.org\r\n"
3288 "Proxy-Connection: keep-alive\r\n\r\n"),
3291 MockRead data_reads1
[] = {
3292 MockRead("HTTP/1.1 200 OK\r\n"),
3293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3294 MockRead("Content-Length: 100\r\n\r\n"),
3295 MockRead(SYNCHRONOUS
, OK
),
3298 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3299 data_writes1
, arraysize(data_writes1
));
3300 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3301 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3302 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3304 TestCompletionCallback callback1
;
3306 scoped_ptr
<HttpTransaction
> trans(
3307 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3309 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3312 rv
= callback1
.WaitForResult();
3315 LoadTimingInfo load_timing_info
;
3316 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3317 TestLoadTimingNotReused(load_timing_info
,
3318 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3320 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3321 ASSERT_TRUE(response
!= NULL
);
3323 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3324 EXPECT_EQ(200, response
->headers
->response_code());
3325 EXPECT_EQ(100, response
->headers
->GetContentLength());
3326 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3328 // The password prompt info should not be set.
3329 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3332 // Test a SPDY get through an HTTPS Proxy.
3333 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3334 HttpRequestInfo request
;
3335 request
.method
= "GET";
3336 request
.url
= GURL("http://www.example.org/");
3337 request
.load_flags
= 0;
3339 // Configure against https proxy server "proxy:70".
3340 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3341 "https://proxy:70"));
3342 BoundTestNetLog log
;
3343 session_deps_
.net_log
= log
.bound().net_log();
3344 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3346 // fetch http://www.example.org/ via SPDY
3347 scoped_ptr
<SpdyFrame
> req(
3348 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3349 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3351 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3352 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3353 MockRead spdy_reads
[] = {
3354 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3357 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3358 arraysize(spdy_writes
));
3359 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3361 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3362 ssl
.SetNextProto(GetParam());
3363 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3365 TestCompletionCallback callback1
;
3367 scoped_ptr
<HttpTransaction
> trans(
3368 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3370 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3371 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3373 rv
= callback1
.WaitForResult();
3376 LoadTimingInfo load_timing_info
;
3377 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3378 TestLoadTimingNotReused(load_timing_info
,
3379 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3381 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3382 ASSERT_TRUE(response
!= NULL
);
3383 ASSERT_TRUE(response
->headers
.get() != NULL
);
3384 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3386 std::string response_data
;
3387 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3388 EXPECT_EQ(kUploadData
, response_data
);
3391 // Verifies that a session which races and wins against the owning transaction
3392 // (completing prior to host resolution), doesn't fail the transaction.
3393 // Regression test for crbug.com/334413.
3394 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3395 HttpRequestInfo request
;
3396 request
.method
= "GET";
3397 request
.url
= GURL("http://www.example.org/");
3398 request
.load_flags
= 0;
3400 // Configure SPDY proxy server "proxy:70".
3401 session_deps_
.proxy_service
.reset(
3402 ProxyService::CreateFixed("https://proxy:70"));
3403 BoundTestNetLog log
;
3404 session_deps_
.net_log
= log
.bound().net_log();
3405 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3407 // Fetch http://www.example.org/ through the SPDY proxy.
3408 scoped_ptr
<SpdyFrame
> req(
3409 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3410 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3412 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3413 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3414 MockRead spdy_reads
[] = {
3415 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3418 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3419 arraysize(spdy_writes
));
3420 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3422 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3423 ssl
.SetNextProto(GetParam());
3424 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3426 TestCompletionCallback callback1
;
3428 scoped_ptr
<HttpTransaction
> trans(
3429 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3431 // Stall the hostname resolution begun by the transaction.
3432 session_deps_
.host_resolver
->set_synchronous_mode(false);
3433 session_deps_
.host_resolver
->set_ondemand_mode(true);
3435 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3438 // Race a session to the proxy, which completes first.
3439 session_deps_
.host_resolver
->set_ondemand_mode(false);
3441 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3442 base::WeakPtr
<SpdySession
> spdy_session
=
3443 CreateSecureSpdySession(session
, key
, log
.bound());
3445 // Unstall the resolution begun by the transaction.
3446 session_deps_
.host_resolver
->set_ondemand_mode(true);
3447 session_deps_
.host_resolver
->ResolveAllPending();
3449 EXPECT_FALSE(callback1
.have_result());
3450 rv
= callback1
.WaitForResult();
3453 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3454 ASSERT_TRUE(response
!= NULL
);
3455 ASSERT_TRUE(response
->headers
.get() != NULL
);
3456 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3458 std::string response_data
;
3459 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3460 EXPECT_EQ(kUploadData
, response_data
);
3463 // Test a SPDY get through an HTTPS Proxy.
3464 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3465 HttpRequestInfo request
;
3466 request
.method
= "GET";
3467 request
.url
= GURL("http://www.example.org/");
3468 request
.load_flags
= 0;
3470 // Configure against https proxy server "myproxy:70".
3471 session_deps_
.proxy_service
.reset(
3472 ProxyService::CreateFixed("https://myproxy:70"));
3473 BoundTestNetLog log
;
3474 session_deps_
.net_log
= log
.bound().net_log();
3475 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3477 // The first request will be a bare GET, the second request will be a
3478 // GET with a Proxy-Authorization header.
3479 scoped_ptr
<SpdyFrame
> req_get(
3480 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3481 const char* const kExtraAuthorizationHeaders
[] = {
3482 "proxy-authorization", "Basic Zm9vOmJhcg=="
3484 scoped_ptr
<SpdyFrame
> req_get_authorization(
3485 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3486 arraysize(kExtraAuthorizationHeaders
) / 2,
3491 MockWrite spdy_writes
[] = {
3492 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3495 // The first response is a 407 proxy authentication challenge, and the second
3496 // response will be a 200 response since the second request includes a valid
3497 // Authorization header.
3498 const char* const kExtraAuthenticationHeaders
[] = {
3499 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3501 scoped_ptr
<SpdyFrame
> resp_authentication(
3502 spdy_util_
.ConstructSpdySynReplyError(
3503 "407 Proxy Authentication Required",
3504 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3506 scoped_ptr
<SpdyFrame
> body_authentication(
3507 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3508 scoped_ptr
<SpdyFrame
> resp_data(
3509 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3510 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3511 MockRead spdy_reads
[] = {
3512 CreateMockRead(*resp_authentication
, 1),
3513 CreateMockRead(*body_authentication
, 2),
3514 CreateMockRead(*resp_data
, 4),
3515 CreateMockRead(*body_data
, 5),
3516 MockRead(ASYNC
, 0, 6),
3519 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3520 arraysize(spdy_writes
));
3521 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3523 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3524 ssl
.SetNextProto(GetParam());
3525 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3527 TestCompletionCallback callback1
;
3529 scoped_ptr
<HttpTransaction
> trans(
3530 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3532 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3533 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3535 rv
= callback1
.WaitForResult();
3538 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3540 ASSERT_TRUE(response
!= NULL
);
3541 ASSERT_TRUE(response
->headers
.get() != NULL
);
3542 EXPECT_EQ(407, response
->headers
->response_code());
3543 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3544 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3546 TestCompletionCallback callback2
;
3548 rv
= trans
->RestartWithAuth(
3549 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3550 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3552 rv
= callback2
.WaitForResult();
3555 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3557 ASSERT_TRUE(response_restart
!= NULL
);
3558 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3559 EXPECT_EQ(200, response_restart
->headers
->response_code());
3560 // The password prompt info should not be set.
3561 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3564 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3565 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3566 HttpRequestInfo request
;
3567 request
.method
= "GET";
3568 request
.url
= GURL("https://www.example.org/");
3569 request
.load_flags
= 0;
3571 // Configure against https proxy server "proxy:70".
3572 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3573 "https://proxy:70"));
3574 BoundTestNetLog log
;
3575 session_deps_
.net_log
= log
.bound().net_log();
3576 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3578 scoped_ptr
<HttpTransaction
> trans(
3579 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3581 // CONNECT to www.example.org:443 via SPDY
3582 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3583 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3584 // fetch https://www.example.org/ via HTTP
3587 "GET / HTTP/1.1\r\n"
3588 "Host: www.example.org\r\n"
3589 "Connection: keep-alive\r\n\r\n";
3590 scoped_ptr
<SpdyFrame
> wrapped_get(
3591 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3592 scoped_ptr
<SpdyFrame
> conn_resp(
3593 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3594 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3595 "Content-Length: 10\r\n\r\n";
3596 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3597 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3598 scoped_ptr
<SpdyFrame
> wrapped_body(
3599 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3600 scoped_ptr
<SpdyFrame
> window_update(
3601 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3603 MockWrite spdy_writes
[] = {
3604 CreateMockWrite(*connect
, 0),
3605 CreateMockWrite(*wrapped_get
, 2),
3606 CreateMockWrite(*window_update
, 6),
3609 MockRead spdy_reads
[] = {
3610 CreateMockRead(*conn_resp
, 1, ASYNC
),
3611 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3612 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3613 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3614 MockRead(ASYNC
, 0, 7),
3617 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3618 arraysize(spdy_writes
));
3619 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3621 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3622 ssl
.SetNextProto(GetParam());
3623 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3624 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3625 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3627 TestCompletionCallback callback1
;
3629 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3630 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3632 rv
= callback1
.WaitForResult();
3635 LoadTimingInfo load_timing_info
;
3636 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3637 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3639 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3640 ASSERT_TRUE(response
!= NULL
);
3641 ASSERT_TRUE(response
->headers
.get() != NULL
);
3642 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3644 std::string response_data
;
3645 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3646 EXPECT_EQ("1234567890", response_data
);
3649 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3650 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3651 HttpRequestInfo request
;
3652 request
.method
= "GET";
3653 request
.url
= GURL("https://www.example.org/");
3654 request
.load_flags
= 0;
3656 // Configure against https proxy server "proxy:70".
3657 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3658 "https://proxy:70"));
3659 BoundTestNetLog log
;
3660 session_deps_
.net_log
= log
.bound().net_log();
3661 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3663 scoped_ptr
<HttpTransaction
> trans(
3664 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3666 // CONNECT to www.example.org:443 via SPDY
3667 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3668 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3669 // fetch https://www.example.org/ via SPDY
3670 const char kMyUrl
[] = "https://www.example.org/";
3671 scoped_ptr
<SpdyFrame
> get(
3672 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3673 scoped_ptr
<SpdyFrame
> wrapped_get(
3674 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3675 scoped_ptr
<SpdyFrame
> conn_resp(
3676 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3677 scoped_ptr
<SpdyFrame
> get_resp(
3678 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3679 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3680 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3681 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3682 scoped_ptr
<SpdyFrame
> wrapped_body(
3683 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3684 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3685 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3686 scoped_ptr
<SpdyFrame
> window_update_body(
3687 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3689 MockWrite spdy_writes
[] = {
3690 CreateMockWrite(*connect
, 0),
3691 CreateMockWrite(*wrapped_get
, 2),
3692 CreateMockWrite(*window_update_get_resp
, 6),
3693 CreateMockWrite(*window_update_body
, 7),
3696 MockRead spdy_reads
[] = {
3697 CreateMockRead(*conn_resp
, 1, ASYNC
),
3698 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3699 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3700 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3701 MockRead(ASYNC
, 0, 8),
3704 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3705 arraysize(spdy_writes
));
3706 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3708 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3709 ssl
.SetNextProto(GetParam());
3710 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3711 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3712 ssl2
.SetNextProto(GetParam());
3713 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3715 TestCompletionCallback callback1
;
3717 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3718 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3720 // Allow the SpdyProxyClientSocket's write callback to complete.
3721 base::MessageLoop::current()->RunUntilIdle();
3722 // Now allow the read of the response to complete.
3723 spdy_data
.CompleteRead();
3724 rv
= callback1
.WaitForResult();
3727 LoadTimingInfo load_timing_info
;
3728 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3729 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3731 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3732 ASSERT_TRUE(response
!= NULL
);
3733 ASSERT_TRUE(response
->headers
.get() != NULL
);
3734 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3736 std::string response_data
;
3737 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3738 EXPECT_EQ(kUploadData
, response_data
);
3741 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3742 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3743 HttpRequestInfo request
;
3744 request
.method
= "GET";
3745 request
.url
= GURL("https://www.example.org/");
3746 request
.load_flags
= 0;
3748 // Configure against https proxy server "proxy:70".
3749 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3750 "https://proxy:70"));
3751 BoundTestNetLog log
;
3752 session_deps_
.net_log
= log
.bound().net_log();
3753 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3755 scoped_ptr
<HttpTransaction
> trans(
3756 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3758 // CONNECT to www.example.org:443 via SPDY
3759 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3760 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3761 scoped_ptr
<SpdyFrame
> get(
3762 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3764 MockWrite spdy_writes
[] = {
3765 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3768 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3769 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3770 MockRead spdy_reads
[] = {
3771 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3774 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3775 arraysize(spdy_writes
));
3776 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3778 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3779 ssl
.SetNextProto(GetParam());
3780 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3781 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3782 ssl2
.SetNextProto(GetParam());
3783 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3785 TestCompletionCallback callback1
;
3787 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3790 rv
= callback1
.WaitForResult();
3791 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3793 // TODO(ttuttle): Anything else to check here?
3796 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3797 // HTTPS Proxy to different servers.
3798 TEST_P(HttpNetworkTransactionTest
,
3799 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3800 // Configure against https proxy server "proxy:70".
3801 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3802 "https://proxy:70"));
3803 BoundTestNetLog log
;
3804 session_deps_
.net_log
= log
.bound().net_log();
3805 scoped_refptr
<HttpNetworkSession
> session(
3806 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3808 HttpRequestInfo request1
;
3809 request1
.method
= "GET";
3810 request1
.url
= GURL("https://www.example.org/");
3811 request1
.load_flags
= 0;
3813 HttpRequestInfo request2
;
3814 request2
.method
= "GET";
3815 request2
.url
= GURL("https://mail.example.org/");
3816 request2
.load_flags
= 0;
3818 // CONNECT to www.example.org:443 via SPDY.
3819 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3820 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3821 scoped_ptr
<SpdyFrame
> conn_resp1(
3822 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3824 // Fetch https://www.example.org/ via HTTP.
3826 "GET / HTTP/1.1\r\n"
3827 "Host: www.example.org\r\n"
3828 "Connection: keep-alive\r\n\r\n";
3829 scoped_ptr
<SpdyFrame
> wrapped_get1(
3830 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3831 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3832 "Content-Length: 1\r\n\r\n";
3833 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3834 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3835 scoped_ptr
<SpdyFrame
> wrapped_body1(
3836 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3837 scoped_ptr
<SpdyFrame
> window_update(
3838 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3840 // CONNECT to mail.example.org:443 via SPDY.
3841 SpdyHeaderBlock connect2_block
;
3842 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3843 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3844 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3845 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3846 scoped_ptr
<SpdyFrame
> connect2(
3847 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3849 scoped_ptr
<SpdyFrame
> conn_resp2(
3850 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3852 // Fetch https://mail.example.org/ via HTTP.
3854 "GET / HTTP/1.1\r\n"
3855 "Host: mail.example.org\r\n"
3856 "Connection: keep-alive\r\n\r\n";
3857 scoped_ptr
<SpdyFrame
> wrapped_get2(
3858 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3859 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3860 "Content-Length: 2\r\n\r\n";
3861 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3862 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3863 scoped_ptr
<SpdyFrame
> wrapped_body2(
3864 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3866 MockWrite spdy_writes
[] = {
3867 CreateMockWrite(*connect1
, 0),
3868 CreateMockWrite(*wrapped_get1
, 2),
3869 CreateMockWrite(*connect2
, 5),
3870 CreateMockWrite(*wrapped_get2
, 7),
3873 MockRead spdy_reads
[] = {
3874 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3875 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3876 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3877 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3878 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3879 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3880 MockRead(ASYNC
, 0, 10),
3883 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3884 arraysize(spdy_writes
));
3885 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3887 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3888 ssl
.SetNextProto(GetParam());
3889 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3890 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3891 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3892 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3893 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3895 TestCompletionCallback callback
;
3897 scoped_ptr
<HttpTransaction
> trans(
3898 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3899 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3900 EXPECT_EQ(OK
, callback
.GetResult(rv
));
3902 LoadTimingInfo load_timing_info
;
3903 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3904 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3906 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3907 ASSERT_TRUE(response
!= NULL
);
3908 ASSERT_TRUE(response
->headers
.get() != NULL
);
3909 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3911 std::string response_data
;
3912 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3913 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
3914 EXPECT_EQ(1, callback
.GetResult(rv
));
3916 scoped_ptr
<HttpTransaction
> trans2(
3917 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3918 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3919 EXPECT_EQ(OK
, callback
.GetResult(rv
));
3921 LoadTimingInfo load_timing_info2
;
3922 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3923 // Even though the SPDY connection is reused, a new tunnelled connection has
3924 // to be created, so the socket's load timing looks like a fresh connection.
3925 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3927 // The requests should have different IDs, since they each are using their own
3929 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3931 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
3932 EXPECT_EQ(2, callback
.GetResult(rv
));
3935 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3936 // HTTPS Proxy to the same server.
3937 TEST_P(HttpNetworkTransactionTest
,
3938 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3939 // Configure against https proxy server "proxy:70".
3940 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3941 "https://proxy:70"));
3942 BoundTestNetLog log
;
3943 session_deps_
.net_log
= log
.bound().net_log();
3944 scoped_refptr
<HttpNetworkSession
> session(
3945 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3947 HttpRequestInfo request1
;
3948 request1
.method
= "GET";
3949 request1
.url
= GURL("https://www.example.org/");
3950 request1
.load_flags
= 0;
3952 HttpRequestInfo request2
;
3953 request2
.method
= "GET";
3954 request2
.url
= GURL("https://www.example.org/2");
3955 request2
.load_flags
= 0;
3957 // CONNECT to www.example.org:443 via SPDY.
3958 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3959 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3960 scoped_ptr
<SpdyFrame
> conn_resp1(
3961 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3963 // Fetch https://www.example.org/ via HTTP.
3965 "GET / HTTP/1.1\r\n"
3966 "Host: www.example.org\r\n"
3967 "Connection: keep-alive\r\n\r\n";
3968 scoped_ptr
<SpdyFrame
> wrapped_get1(
3969 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3970 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3971 "Content-Length: 1\r\n\r\n";
3972 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3973 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3974 scoped_ptr
<SpdyFrame
> wrapped_body1(
3975 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3976 scoped_ptr
<SpdyFrame
> window_update(
3977 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3979 // Fetch https://www.example.org/2 via HTTP.
3981 "GET /2 HTTP/1.1\r\n"
3982 "Host: www.example.org\r\n"
3983 "Connection: keep-alive\r\n\r\n";
3984 scoped_ptr
<SpdyFrame
> wrapped_get2(
3985 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3986 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3987 "Content-Length: 2\r\n\r\n";
3988 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3989 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3990 scoped_ptr
<SpdyFrame
> wrapped_body2(
3991 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
3993 MockWrite spdy_writes
[] = {
3994 CreateMockWrite(*connect1
, 0),
3995 CreateMockWrite(*wrapped_get1
, 2),
3996 CreateMockWrite(*wrapped_get2
, 5),
3999 MockRead spdy_reads
[] = {
4000 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4001 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4002 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4003 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4004 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4005 MockRead(ASYNC
, 0, 8),
4008 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4009 arraysize(spdy_writes
));
4010 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4012 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4013 ssl
.SetNextProto(GetParam());
4014 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4015 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4016 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4018 TestCompletionCallback callback
;
4020 scoped_ptr
<HttpTransaction
> trans(
4021 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4022 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4023 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4025 rv
= callback
.WaitForResult();
4028 LoadTimingInfo load_timing_info
;
4029 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4030 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4032 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4033 ASSERT_TRUE(response
!= NULL
);
4034 ASSERT_TRUE(response
->headers
.get() != NULL
);
4035 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4037 std::string response_data
;
4038 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4039 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4042 scoped_ptr
<HttpTransaction
> trans2(
4043 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4044 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4047 rv
= callback
.WaitForResult();
4050 LoadTimingInfo load_timing_info2
;
4051 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4052 TestLoadTimingReused(load_timing_info2
);
4054 // The requests should have the same ID.
4055 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4057 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4060 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4061 // Proxy to different servers.
4062 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4063 // Configure against https proxy server "proxy:70".
4064 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4065 "https://proxy:70"));
4066 BoundTestNetLog log
;
4067 session_deps_
.net_log
= log
.bound().net_log();
4068 scoped_refptr
<HttpNetworkSession
> session(
4069 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4071 HttpRequestInfo request1
;
4072 request1
.method
= "GET";
4073 request1
.url
= GURL("http://www.example.org/");
4074 request1
.load_flags
= 0;
4076 HttpRequestInfo request2
;
4077 request2
.method
= "GET";
4078 request2
.url
= GURL("http://mail.example.org/");
4079 request2
.load_flags
= 0;
4081 // http://www.example.org/
4082 scoped_ptr
<SpdyHeaderBlock
> headers(
4083 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4084 scoped_ptr
<SpdyFrame
> get1(
4085 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4086 scoped_ptr
<SpdyFrame
> get_resp1(
4087 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4088 scoped_ptr
<SpdyFrame
> body1(
4089 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4091 // http://mail.example.org/
4092 scoped_ptr
<SpdyHeaderBlock
> headers2(
4093 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4094 scoped_ptr
<SpdyFrame
> get2(
4095 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4096 scoped_ptr
<SpdyFrame
> get_resp2(
4097 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4098 scoped_ptr
<SpdyFrame
> body2(
4099 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4101 MockWrite spdy_writes
[] = {
4102 CreateMockWrite(*get1
, 0),
4103 CreateMockWrite(*get2
, 3),
4106 MockRead spdy_reads
[] = {
4107 CreateMockRead(*get_resp1
, 1, ASYNC
),
4108 CreateMockRead(*body1
, 2, ASYNC
),
4109 CreateMockRead(*get_resp2
, 4, ASYNC
),
4110 CreateMockRead(*body2
, 5, ASYNC
),
4111 MockRead(ASYNC
, 0, 6),
4114 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4115 arraysize(spdy_writes
));
4116 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4118 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4119 ssl
.SetNextProto(GetParam());
4120 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4122 TestCompletionCallback callback
;
4124 scoped_ptr
<HttpTransaction
> trans(
4125 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4126 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4127 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4129 LoadTimingInfo load_timing_info
;
4130 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4131 TestLoadTimingNotReused(load_timing_info
,
4132 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4134 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4135 ASSERT_TRUE(response
!= NULL
);
4136 ASSERT_TRUE(response
->headers
.get() != NULL
);
4137 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4139 std::string response_data
;
4140 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4141 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4142 EXPECT_EQ(1, callback
.GetResult(rv
));
4143 // Delete the first request, so the second one can reuse the socket.
4146 scoped_ptr
<HttpTransaction
> trans2(
4147 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4148 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4149 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4151 LoadTimingInfo load_timing_info2
;
4152 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4153 TestLoadTimingReused(load_timing_info2
);
4155 // The requests should have the same ID.
4156 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4158 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4159 EXPECT_EQ(2, callback
.GetResult(rv
));
4162 // Test the challenge-response-retry sequence through an HTTPS Proxy
4163 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4164 HttpRequestInfo request
;
4165 request
.method
= "GET";
4166 request
.url
= GURL("http://www.example.org/");
4167 // when the no authentication data flag is set.
4168 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4170 // Configure against https proxy server "myproxy:70".
4171 session_deps_
.proxy_service
.reset(
4172 ProxyService::CreateFixed("https://myproxy:70"));
4173 BoundTestNetLog log
;
4174 session_deps_
.net_log
= log
.bound().net_log();
4175 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4177 // Since we have proxy, should use full url
4178 MockWrite data_writes1
[] = {
4180 "GET http://www.example.org/ HTTP/1.1\r\n"
4181 "Host: www.example.org\r\n"
4182 "Proxy-Connection: keep-alive\r\n\r\n"),
4184 // After calling trans->RestartWithAuth(), this is the request we should
4185 // be issuing -- the final header line contains the credentials.
4187 "GET http://www.example.org/ HTTP/1.1\r\n"
4188 "Host: www.example.org\r\n"
4189 "Proxy-Connection: keep-alive\r\n"
4190 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4193 // The proxy responds to the GET with a 407, using a persistent
4195 MockRead data_reads1
[] = {
4197 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4198 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4199 MockRead("Proxy-Connection: keep-alive\r\n"),
4200 MockRead("Content-Length: 0\r\n\r\n"),
4202 MockRead("HTTP/1.1 200 OK\r\n"),
4203 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4204 MockRead("Content-Length: 100\r\n\r\n"),
4205 MockRead(SYNCHRONOUS
, OK
),
4208 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4209 data_writes1
, arraysize(data_writes1
));
4210 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4211 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4212 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4214 TestCompletionCallback callback1
;
4216 scoped_ptr
<HttpTransaction
> trans(
4217 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4219 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4220 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4222 rv
= callback1
.WaitForResult();
4225 LoadTimingInfo load_timing_info
;
4226 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4227 TestLoadTimingNotReused(load_timing_info
,
4228 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4230 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4231 ASSERT_TRUE(response
!= NULL
);
4232 ASSERT_FALSE(response
->headers
.get() == NULL
);
4233 EXPECT_EQ(407, response
->headers
->response_code());
4234 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4235 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4237 TestCompletionCallback callback2
;
4239 rv
= trans
->RestartWithAuth(
4240 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4241 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4243 rv
= callback2
.WaitForResult();
4246 load_timing_info
= LoadTimingInfo();
4247 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4248 // Retrying with HTTP AUTH is considered to be reusing a socket.
4249 TestLoadTimingReused(load_timing_info
);
4251 response
= trans
->GetResponseInfo();
4252 ASSERT_TRUE(response
!= NULL
);
4254 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4255 EXPECT_EQ(200, response
->headers
->response_code());
4256 EXPECT_EQ(100, response
->headers
->GetContentLength());
4257 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4259 // The password prompt info should not be set.
4260 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4263 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4264 const MockRead
& status
, int expected_status
) {
4265 HttpRequestInfo request
;
4266 request
.method
= "GET";
4267 request
.url
= GURL("https://www.example.org/");
4268 request
.load_flags
= 0;
4270 // Configure against proxy server "myproxy:70".
4271 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4272 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4274 // Since we have proxy, should try to establish tunnel.
4275 MockWrite data_writes
[] = {
4277 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4278 "Host: www.example.org\r\n"
4279 "Proxy-Connection: keep-alive\r\n\r\n"),
4282 MockRead data_reads
[] = {
4284 MockRead("Content-Length: 10\r\n\r\n"),
4285 // No response body because the test stops reading here.
4286 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4289 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4290 data_writes
, arraysize(data_writes
));
4291 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4293 TestCompletionCallback callback
;
4295 scoped_ptr
<HttpTransaction
> trans(
4296 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4298 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4299 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4301 rv
= callback
.WaitForResult();
4302 EXPECT_EQ(expected_status
, rv
);
4305 void HttpNetworkTransactionTest::ConnectStatusHelper(
4306 const MockRead
& status
) {
4307 ConnectStatusHelperWithExpectedStatus(
4308 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4311 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4312 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4315 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4316 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4319 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4320 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4323 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4324 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4327 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4328 ConnectStatusHelper(
4329 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4332 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4333 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4336 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4337 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4340 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4341 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4344 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4345 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4348 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4349 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4352 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4353 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4356 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4357 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4360 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4361 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4364 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4365 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4368 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4369 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4372 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4373 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4376 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4377 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4380 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4381 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4384 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4385 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4388 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4389 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4392 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4393 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4396 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4397 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4400 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4401 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4404 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4405 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4408 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4409 ConnectStatusHelperWithExpectedStatus(
4410 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4411 ERR_PROXY_AUTH_UNSUPPORTED
);
4414 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4415 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4418 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4419 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4422 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4423 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4426 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4427 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4430 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4434 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4435 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4438 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4439 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4442 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4443 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4446 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4447 ConnectStatusHelper(
4448 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4451 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4452 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4455 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4456 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4459 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4460 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4463 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4467 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4471 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4475 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4479 // Test the flow when both the proxy server AND origin server require
4480 // authentication. Again, this uses basic auth for both since that is
4481 // the simplest to mock.
4482 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4483 HttpRequestInfo request
;
4484 request
.method
= "GET";
4485 request
.url
= GURL("http://www.example.org/");
4486 request
.load_flags
= 0;
4488 // Configure against proxy server "myproxy:70".
4489 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4492 scoped_ptr
<HttpTransaction
> trans(
4493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4495 MockWrite data_writes1
[] = {
4497 "GET http://www.example.org/ HTTP/1.1\r\n"
4498 "Host: www.example.org\r\n"
4499 "Proxy-Connection: keep-alive\r\n\r\n"),
4502 MockRead data_reads1
[] = {
4503 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4504 // Give a couple authenticate options (only the middle one is actually
4506 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4507 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4508 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4509 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4510 // Large content-length -- won't matter, as connection will be reset.
4511 MockRead("Content-Length: 10000\r\n\r\n"),
4512 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4515 // After calling trans->RestartWithAuth() the first time, this is the
4516 // request we should be issuing -- the final header line contains the
4517 // proxy's credentials.
4518 MockWrite data_writes2
[] = {
4520 "GET http://www.example.org/ HTTP/1.1\r\n"
4521 "Host: www.example.org\r\n"
4522 "Proxy-Connection: keep-alive\r\n"
4523 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4526 // Now the proxy server lets the request pass through to origin server.
4527 // The origin server responds with a 401.
4528 MockRead data_reads2
[] = {
4529 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4530 // Note: We are using the same realm-name as the proxy server. This is
4531 // completely valid, as realms are unique across hosts.
4532 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4533 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4534 MockRead("Content-Length: 2000\r\n\r\n"),
4535 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4538 // After calling trans->RestartWithAuth() the second time, we should send
4539 // the credentials for both the proxy and origin server.
4540 MockWrite data_writes3
[] = {
4542 "GET http://www.example.org/ HTTP/1.1\r\n"
4543 "Host: www.example.org\r\n"
4544 "Proxy-Connection: keep-alive\r\n"
4545 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4546 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4549 // Lastly we get the desired content.
4550 MockRead data_reads3
[] = {
4551 MockRead("HTTP/1.0 200 OK\r\n"),
4552 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4553 MockRead("Content-Length: 100\r\n\r\n"),
4554 MockRead(SYNCHRONOUS
, OK
),
4557 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4558 data_writes1
, arraysize(data_writes1
));
4559 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4560 data_writes2
, arraysize(data_writes2
));
4561 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4562 data_writes3
, arraysize(data_writes3
));
4563 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4564 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4565 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4567 TestCompletionCallback callback1
;
4569 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4570 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4572 rv
= callback1
.WaitForResult();
4575 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4576 ASSERT_TRUE(response
!= NULL
);
4577 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4579 TestCompletionCallback callback2
;
4581 rv
= trans
->RestartWithAuth(
4582 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4583 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4585 rv
= callback2
.WaitForResult();
4588 response
= trans
->GetResponseInfo();
4589 ASSERT_TRUE(response
!= NULL
);
4590 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4592 TestCompletionCallback callback3
;
4594 rv
= trans
->RestartWithAuth(
4595 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4596 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4598 rv
= callback3
.WaitForResult();
4601 response
= trans
->GetResponseInfo();
4602 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4603 EXPECT_EQ(100, response
->headers
->GetContentLength());
4606 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4607 // can't hook into its internals to cause it to generate predictable NTLM
4608 // authorization headers.
4609 #if defined(NTLM_PORTABLE)
4610 // The NTLM authentication unit tests were generated by capturing the HTTP
4611 // requests and responses using Fiddler 2 and inspecting the generated random
4612 // bytes in the debugger.
4614 // Enter the correct password and authenticate successfully.
4615 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4616 HttpRequestInfo request
;
4617 request
.method
= "GET";
4618 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4620 // Ensure load is not disrupted by flags which suppress behaviour specific
4621 // to other auth schemes.
4622 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4624 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4626 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4628 MockWrite data_writes1
[] = {
4629 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4630 "Host: 172.22.68.17\r\n"
4631 "Connection: keep-alive\r\n\r\n"),
4634 MockRead data_reads1
[] = {
4635 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4636 // Negotiate and NTLM are often requested together. However, we only want
4637 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4638 // the header that requests Negotiate for this test.
4639 MockRead("WWW-Authenticate: NTLM\r\n"),
4640 MockRead("Connection: close\r\n"),
4641 MockRead("Content-Length: 42\r\n"),
4642 MockRead("Content-Type: text/html\r\n\r\n"),
4643 // Missing content -- won't matter, as connection will be reset.
4644 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4647 MockWrite data_writes2
[] = {
4648 // After restarting with a null identity, this is the
4649 // request we should be issuing -- the final header line contains a Type
4651 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4652 "Host: 172.22.68.17\r\n"
4653 "Connection: keep-alive\r\n"
4654 "Authorization: NTLM "
4655 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4657 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4658 // (the credentials for the origin server). The second request continues
4659 // on the same connection.
4660 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4661 "Host: 172.22.68.17\r\n"
4662 "Connection: keep-alive\r\n"
4663 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4664 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4665 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4666 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4667 "ahlhx5I=\r\n\r\n"),
4670 MockRead data_reads2
[] = {
4671 // The origin server responds with a Type 2 message.
4672 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4673 MockRead("WWW-Authenticate: NTLM "
4674 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4675 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4676 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4677 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4678 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4679 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4681 MockRead("Content-Length: 42\r\n"),
4682 MockRead("Content-Type: text/html\r\n\r\n"),
4683 MockRead("You are not authorized to view this page\r\n"),
4685 // Lastly we get the desired content.
4686 MockRead("HTTP/1.1 200 OK\r\n"),
4687 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4688 MockRead("Content-Length: 13\r\n\r\n"),
4689 MockRead("Please Login\r\n"),
4690 MockRead(SYNCHRONOUS
, OK
),
4693 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4694 data_writes1
, arraysize(data_writes1
));
4695 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4696 data_writes2
, arraysize(data_writes2
));
4697 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4698 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4700 TestCompletionCallback callback1
;
4702 scoped_ptr
<HttpTransaction
> trans(
4703 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4705 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4706 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4708 rv
= callback1
.WaitForResult();
4711 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4713 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4714 ASSERT_FALSE(response
== NULL
);
4715 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4717 TestCompletionCallback callback2
;
4719 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4720 callback2
.callback());
4721 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4723 rv
= callback2
.WaitForResult();
4726 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4728 response
= trans
->GetResponseInfo();
4729 ASSERT_TRUE(response
!= NULL
);
4730 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4732 TestCompletionCallback callback3
;
4734 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4735 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4737 rv
= callback3
.WaitForResult();
4740 response
= trans
->GetResponseInfo();
4741 ASSERT_TRUE(response
!= NULL
);
4742 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4743 EXPECT_EQ(13, response
->headers
->GetContentLength());
4746 // Enter a wrong password, and then the correct one.
4747 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4748 HttpRequestInfo request
;
4749 request
.method
= "GET";
4750 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4751 request
.load_flags
= 0;
4753 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4755 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4757 MockWrite data_writes1
[] = {
4758 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4759 "Host: 172.22.68.17\r\n"
4760 "Connection: keep-alive\r\n\r\n"),
4763 MockRead data_reads1
[] = {
4764 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4765 // Negotiate and NTLM are often requested together. However, we only want
4766 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4767 // the header that requests Negotiate for this test.
4768 MockRead("WWW-Authenticate: NTLM\r\n"),
4769 MockRead("Connection: close\r\n"),
4770 MockRead("Content-Length: 42\r\n"),
4771 MockRead("Content-Type: text/html\r\n\r\n"),
4772 // Missing content -- won't matter, as connection will be reset.
4773 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4776 MockWrite data_writes2
[] = {
4777 // After restarting with a null identity, this is the
4778 // request we should be issuing -- the final header line contains a Type
4780 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4781 "Host: 172.22.68.17\r\n"
4782 "Connection: keep-alive\r\n"
4783 "Authorization: NTLM "
4784 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4786 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4787 // (the credentials for the origin server). The second request continues
4788 // on the same connection.
4789 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4790 "Host: 172.22.68.17\r\n"
4791 "Connection: keep-alive\r\n"
4792 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4793 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4794 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4795 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4796 "4Ww7b7E=\r\n\r\n"),
4799 MockRead data_reads2
[] = {
4800 // The origin server responds with a Type 2 message.
4801 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4802 MockRead("WWW-Authenticate: NTLM "
4803 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4804 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4805 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4806 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4807 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4808 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4810 MockRead("Content-Length: 42\r\n"),
4811 MockRead("Content-Type: text/html\r\n\r\n"),
4812 MockRead("You are not authorized to view this page\r\n"),
4815 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4816 MockRead("WWW-Authenticate: NTLM\r\n"),
4817 MockRead("Connection: close\r\n"),
4818 MockRead("Content-Length: 42\r\n"),
4819 MockRead("Content-Type: text/html\r\n\r\n"),
4820 // Missing content -- won't matter, as connection will be reset.
4821 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4824 MockWrite data_writes3
[] = {
4825 // After restarting with a null identity, this is the
4826 // request we should be issuing -- the final header line contains a Type
4828 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4829 "Host: 172.22.68.17\r\n"
4830 "Connection: keep-alive\r\n"
4831 "Authorization: NTLM "
4832 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4834 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4835 // (the credentials for the origin server). The second request continues
4836 // on the same connection.
4837 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4838 "Host: 172.22.68.17\r\n"
4839 "Connection: keep-alive\r\n"
4840 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4841 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4842 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4843 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4844 "+4MUm7c=\r\n\r\n"),
4847 MockRead data_reads3
[] = {
4848 // The origin server responds with a Type 2 message.
4849 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4850 MockRead("WWW-Authenticate: NTLM "
4851 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4852 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4853 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4854 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4855 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4856 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4858 MockRead("Content-Length: 42\r\n"),
4859 MockRead("Content-Type: text/html\r\n\r\n"),
4860 MockRead("You are not authorized to view this page\r\n"),
4862 // Lastly we get the desired content.
4863 MockRead("HTTP/1.1 200 OK\r\n"),
4864 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4865 MockRead("Content-Length: 13\r\n\r\n"),
4866 MockRead("Please Login\r\n"),
4867 MockRead(SYNCHRONOUS
, OK
),
4870 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4871 data_writes1
, arraysize(data_writes1
));
4872 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4873 data_writes2
, arraysize(data_writes2
));
4874 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4875 data_writes3
, arraysize(data_writes3
));
4876 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4877 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4878 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4880 TestCompletionCallback callback1
;
4882 scoped_ptr
<HttpTransaction
> trans(
4883 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4885 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4886 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4888 rv
= callback1
.WaitForResult();
4891 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4893 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4894 ASSERT_TRUE(response
!= NULL
);
4895 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4897 TestCompletionCallback callback2
;
4899 // Enter the wrong password.
4900 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4901 callback2
.callback());
4902 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4904 rv
= callback2
.WaitForResult();
4907 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4908 TestCompletionCallback callback3
;
4909 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4911 rv
= callback3
.WaitForResult();
4913 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4915 response
= trans
->GetResponseInfo();
4916 ASSERT_FALSE(response
== NULL
);
4917 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4919 TestCompletionCallback callback4
;
4921 // Now enter the right password.
4922 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4923 callback4
.callback());
4924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4926 rv
= callback4
.WaitForResult();
4929 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4931 TestCompletionCallback callback5
;
4933 // One more roundtrip
4934 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4935 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4937 rv
= callback5
.WaitForResult();
4940 response
= trans
->GetResponseInfo();
4941 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4942 EXPECT_EQ(13, response
->headers
->GetContentLength());
4944 #endif // NTLM_PORTABLE
4946 // Test reading a server response which has only headers, and no body.
4947 // After some maximum number of bytes is consumed, the transaction should
4948 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4949 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4950 HttpRequestInfo request
;
4951 request
.method
= "GET";
4952 request
.url
= GURL("http://www.example.org/");
4953 request
.load_flags
= 0;
4955 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4956 scoped_ptr
<HttpTransaction
> trans(
4957 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4959 // Respond with 300 kb of headers (we should fail after 256 kb).
4960 std::string large_headers_string
;
4961 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4963 MockRead data_reads
[] = {
4964 MockRead("HTTP/1.0 200 OK\r\n"),
4965 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4966 MockRead("\r\nBODY"),
4967 MockRead(SYNCHRONOUS
, OK
),
4969 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4970 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4972 TestCompletionCallback callback
;
4974 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4975 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4977 rv
= callback
.WaitForResult();
4978 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4981 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4982 // establish tunnel.
4983 // http://code.google.com/p/chromium/issues/detail?id=3772
4984 TEST_P(HttpNetworkTransactionTest
,
4985 DontRecycleTransportSocketForSSLTunnel
) {
4986 HttpRequestInfo request
;
4987 request
.method
= "GET";
4988 request
.url
= GURL("https://www.example.org/");
4989 request
.load_flags
= 0;
4991 // Configure against proxy server "myproxy:70".
4992 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4996 scoped_ptr
<HttpTransaction
> trans(
4997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4999 // Since we have proxy, should try to establish tunnel.
5000 MockWrite data_writes1
[] = {
5002 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5003 "Host: www.example.org\r\n"
5004 "Proxy-Connection: keep-alive\r\n\r\n"),
5007 // The proxy responds to the connect with a 404, using a persistent
5008 // connection. Usually a proxy would return 501 (not implemented),
5009 // or 200 (tunnel established).
5010 MockRead data_reads1
[] = {
5011 MockRead("HTTP/1.1 404 Not Found\r\n"),
5012 MockRead("Content-Length: 10\r\n\r\n"),
5013 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5016 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5017 data_writes1
, arraysize(data_writes1
));
5018 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5020 TestCompletionCallback callback1
;
5022 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5023 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5025 rv
= callback1
.WaitForResult();
5026 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5028 // Empty the current queue. This is necessary because idle sockets are
5029 // added to the connection pool asynchronously with a PostTask.
5030 base::MessageLoop::current()->RunUntilIdle();
5032 // We now check to make sure the TCPClientSocket was not added back to
5034 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5036 base::MessageLoop::current()->RunUntilIdle();
5037 // Make sure that the socket didn't get recycled after calling the destructor.
5038 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5041 // Make sure that we recycle a socket after reading all of the response body.
5042 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5043 HttpRequestInfo request
;
5044 request
.method
= "GET";
5045 request
.url
= GURL("http://www.example.org/");
5046 request
.load_flags
= 0;
5048 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5050 scoped_ptr
<HttpTransaction
> trans(
5051 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5053 MockRead data_reads
[] = {
5054 // A part of the response body is received with the response headers.
5055 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5056 // The rest of the response body is received in two parts.
5059 MockRead("junk"), // Should not be read!!
5060 MockRead(SYNCHRONOUS
, OK
),
5063 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5064 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5066 TestCompletionCallback callback
;
5068 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5071 rv
= callback
.WaitForResult();
5074 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5075 ASSERT_TRUE(response
!= NULL
);
5077 EXPECT_TRUE(response
->headers
.get() != NULL
);
5078 std::string status_line
= response
->headers
->GetStatusLine();
5079 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5081 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5083 std::string response_data
;
5084 rv
= ReadTransaction(trans
.get(), &response_data
);
5086 EXPECT_EQ("hello world", response_data
);
5088 // Empty the current queue. This is necessary because idle sockets are
5089 // added to the connection pool asynchronously with a PostTask.
5090 base::MessageLoop::current()->RunUntilIdle();
5092 // We now check to make sure the socket was added back to the pool.
5093 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5096 // Make sure that we recycle a SSL socket after reading all of the response
5098 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5099 HttpRequestInfo request
;
5100 request
.method
= "GET";
5101 request
.url
= GURL("https://www.example.org/");
5102 request
.load_flags
= 0;
5104 MockWrite data_writes
[] = {
5106 "GET / HTTP/1.1\r\n"
5107 "Host: www.example.org\r\n"
5108 "Connection: keep-alive\r\n\r\n"),
5111 MockRead data_reads
[] = {
5112 MockRead("HTTP/1.1 200 OK\r\n"),
5113 MockRead("Content-Length: 11\r\n\r\n"),
5114 MockRead("hello world"),
5115 MockRead(SYNCHRONOUS
, OK
),
5118 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5119 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5121 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5122 data_writes
, arraysize(data_writes
));
5123 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5125 TestCompletionCallback callback
;
5127 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5128 scoped_ptr
<HttpTransaction
> trans(
5129 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5131 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5134 EXPECT_EQ(OK
, callback
.WaitForResult());
5136 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5137 ASSERT_TRUE(response
!= NULL
);
5138 ASSERT_TRUE(response
->headers
.get() != NULL
);
5139 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5141 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5143 std::string response_data
;
5144 rv
= ReadTransaction(trans
.get(), &response_data
);
5146 EXPECT_EQ("hello world", response_data
);
5148 // Empty the current queue. This is necessary because idle sockets are
5149 // added to the connection pool asynchronously with a PostTask.
5150 base::MessageLoop::current()->RunUntilIdle();
5152 // We now check to make sure the socket was added back to the pool.
5153 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5156 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5157 // from the pool and make sure that we recover okay.
5158 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5159 HttpRequestInfo request
;
5160 request
.method
= "GET";
5161 request
.url
= GURL("https://www.example.org/");
5162 request
.load_flags
= 0;
5164 MockWrite data_writes
[] = {
5166 "GET / HTTP/1.1\r\n"
5167 "Host: www.example.org\r\n"
5168 "Connection: keep-alive\r\n\r\n"),
5170 "GET / HTTP/1.1\r\n"
5171 "Host: www.example.org\r\n"
5172 "Connection: keep-alive\r\n\r\n"),
5175 MockRead data_reads
[] = {
5176 MockRead("HTTP/1.1 200 OK\r\n"),
5177 MockRead("Content-Length: 11\r\n\r\n"),
5178 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5179 MockRead("hello world"),
5180 MockRead(ASYNC
, 0, 0) // EOF
5183 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5184 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5185 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5186 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5188 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5189 data_writes
, arraysize(data_writes
));
5190 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5191 data_writes
, arraysize(data_writes
));
5192 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5193 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5195 TestCompletionCallback callback
;
5197 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5198 scoped_ptr
<HttpTransaction
> trans(
5199 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5201 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5204 EXPECT_EQ(OK
, callback
.WaitForResult());
5206 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5207 ASSERT_TRUE(response
!= NULL
);
5208 ASSERT_TRUE(response
->headers
.get() != NULL
);
5209 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5211 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5213 std::string response_data
;
5214 rv
= ReadTransaction(trans
.get(), &response_data
);
5216 EXPECT_EQ("hello world", response_data
);
5218 // Empty the current queue. This is necessary because idle sockets are
5219 // added to the connection pool asynchronously with a PostTask.
5220 base::MessageLoop::current()->RunUntilIdle();
5222 // We now check to make sure the socket was added back to the pool.
5223 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5225 // Now start the second transaction, which should reuse the previous socket.
5227 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5229 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5231 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5232 EXPECT_EQ(OK
, callback
.WaitForResult());
5234 response
= trans
->GetResponseInfo();
5235 ASSERT_TRUE(response
!= NULL
);
5236 ASSERT_TRUE(response
->headers
.get() != NULL
);
5237 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5239 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5241 rv
= ReadTransaction(trans
.get(), &response_data
);
5243 EXPECT_EQ("hello world", response_data
);
5245 // Empty the current queue. This is necessary because idle sockets are
5246 // added to the connection pool asynchronously with a PostTask.
5247 base::MessageLoop::current()->RunUntilIdle();
5249 // We now check to make sure the socket was added back to the pool.
5250 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5253 // Make sure that we recycle a socket after a zero-length response.
5254 // http://crbug.com/9880
5255 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5256 HttpRequestInfo request
;
5257 request
.method
= "GET";
5259 "http://www.example.org/csi?v=3&s=web&action=&"
5260 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5261 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5262 "rt=prt.2642,ol.2649,xjs.2951");
5263 request
.load_flags
= 0;
5265 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5267 scoped_ptr
<HttpTransaction
> trans(
5268 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5270 MockRead data_reads
[] = {
5271 MockRead("HTTP/1.1 204 No Content\r\n"
5272 "Content-Length: 0\r\n"
5273 "Content-Type: text/html\r\n\r\n"),
5274 MockRead("junk"), // Should not be read!!
5275 MockRead(SYNCHRONOUS
, OK
),
5278 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5279 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5281 TestCompletionCallback callback
;
5283 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5284 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5286 rv
= callback
.WaitForResult();
5289 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5290 ASSERT_TRUE(response
!= NULL
);
5292 EXPECT_TRUE(response
->headers
.get() != NULL
);
5293 std::string status_line
= response
->headers
->GetStatusLine();
5294 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5296 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5298 std::string response_data
;
5299 rv
= ReadTransaction(trans
.get(), &response_data
);
5301 EXPECT_EQ("", response_data
);
5303 // Empty the current queue. This is necessary because idle sockets are
5304 // added to the connection pool asynchronously with a PostTask.
5305 base::MessageLoop::current()->RunUntilIdle();
5307 // We now check to make sure the socket was added back to the pool.
5308 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5311 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5312 ScopedVector
<UploadElementReader
> element_readers
;
5313 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5314 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5316 HttpRequestInfo request
[2];
5317 // Transaction 1: a GET request that succeeds. The socket is recycled
5319 request
[0].method
= "GET";
5320 request
[0].url
= GURL("http://www.google.com/");
5321 request
[0].load_flags
= 0;
5322 // Transaction 2: a POST request. Reuses the socket kept alive from
5323 // transaction 1. The first attempts fails when writing the POST data.
5324 // This causes the transaction to retry with a new socket. The second
5325 // attempt succeeds.
5326 request
[1].method
= "POST";
5327 request
[1].url
= GURL("http://www.google.com/login.cgi");
5328 request
[1].upload_data_stream
= &upload_data_stream
;
5329 request
[1].load_flags
= 0;
5331 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5333 // The first socket is used for transaction 1 and the first attempt of
5336 // The response of transaction 1.
5337 MockRead data_reads1
[] = {
5338 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5339 MockRead("hello world"),
5340 MockRead(SYNCHRONOUS
, OK
),
5342 // The mock write results of transaction 1 and the first attempt of
5344 MockWrite data_writes1
[] = {
5345 MockWrite(SYNCHRONOUS
, 64), // GET
5346 MockWrite(SYNCHRONOUS
, 93), // POST
5347 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5349 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5350 data_writes1
, arraysize(data_writes1
));
5352 // The second socket is used for the second attempt of transaction 2.
5354 // The response of transaction 2.
5355 MockRead data_reads2
[] = {
5356 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5357 MockRead("welcome"),
5358 MockRead(SYNCHRONOUS
, OK
),
5360 // The mock write results of the second attempt of transaction 2.
5361 MockWrite data_writes2
[] = {
5362 MockWrite(SYNCHRONOUS
, 93), // POST
5363 MockWrite(SYNCHRONOUS
, 3), // POST data
5365 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5366 data_writes2
, arraysize(data_writes2
));
5368 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5369 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5371 const char* const kExpectedResponseData
[] = {
5372 "hello world", "welcome"
5375 for (int i
= 0; i
< 2; ++i
) {
5376 scoped_ptr
<HttpTransaction
> trans(
5377 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5379 TestCompletionCallback callback
;
5381 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5382 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5384 rv
= callback
.WaitForResult();
5387 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5388 ASSERT_TRUE(response
!= NULL
);
5390 EXPECT_TRUE(response
->headers
.get() != NULL
);
5391 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5393 std::string response_data
;
5394 rv
= ReadTransaction(trans
.get(), &response_data
);
5396 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5400 // Test the request-challenge-retry sequence for basic auth when there is
5401 // an identity in the URL. The request should be sent as normal, but when
5402 // it fails the identity from the URL is used to answer the challenge.
5403 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5404 HttpRequestInfo request
;
5405 request
.method
= "GET";
5406 request
.url
= GURL("http://foo:b@r@www.example.org/");
5407 request
.load_flags
= LOAD_NORMAL
;
5409 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5410 scoped_ptr
<HttpTransaction
> trans(
5411 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5413 // The password contains an escaped character -- for this test to pass it
5414 // will need to be unescaped by HttpNetworkTransaction.
5415 EXPECT_EQ("b%40r", request
.url
.password());
5417 MockWrite data_writes1
[] = {
5419 "GET / HTTP/1.1\r\n"
5420 "Host: www.example.org\r\n"
5421 "Connection: keep-alive\r\n\r\n"),
5424 MockRead data_reads1
[] = {
5425 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5426 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5427 MockRead("Content-Length: 10\r\n\r\n"),
5428 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5431 // After the challenge above, the transaction will be restarted using the
5432 // identity from the url (foo, b@r) to answer the challenge.
5433 MockWrite data_writes2
[] = {
5435 "GET / HTTP/1.1\r\n"
5436 "Host: www.example.org\r\n"
5437 "Connection: keep-alive\r\n"
5438 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5441 MockRead data_reads2
[] = {
5442 MockRead("HTTP/1.0 200 OK\r\n"),
5443 MockRead("Content-Length: 100\r\n\r\n"),
5444 MockRead(SYNCHRONOUS
, OK
),
5447 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5448 data_writes1
, arraysize(data_writes1
));
5449 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5450 data_writes2
, arraysize(data_writes2
));
5451 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5452 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5454 TestCompletionCallback callback1
;
5455 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5456 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5457 rv
= callback1
.WaitForResult();
5459 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5461 TestCompletionCallback callback2
;
5462 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5463 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5464 rv
= callback2
.WaitForResult();
5466 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5468 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5469 ASSERT_TRUE(response
!= NULL
);
5471 // There is no challenge info, since the identity in URL worked.
5472 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5474 EXPECT_EQ(100, response
->headers
->GetContentLength());
5476 // Empty the current queue.
5477 base::MessageLoop::current()->RunUntilIdle();
5480 // Test the request-challenge-retry sequence for basic auth when there is an
5481 // incorrect identity in the URL. The identity from the URL should be used only
5483 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5484 HttpRequestInfo request
;
5485 request
.method
= "GET";
5486 // Note: the URL has a username:password in it. The password "baz" is
5487 // wrong (should be "bar").
5488 request
.url
= GURL("http://foo:baz@www.example.org/");
5490 request
.load_flags
= LOAD_NORMAL
;
5492 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5493 scoped_ptr
<HttpTransaction
> trans(
5494 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5496 MockWrite data_writes1
[] = {
5498 "GET / HTTP/1.1\r\n"
5499 "Host: www.example.org\r\n"
5500 "Connection: keep-alive\r\n\r\n"),
5503 MockRead data_reads1
[] = {
5504 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5505 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5506 MockRead("Content-Length: 10\r\n\r\n"),
5507 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5510 // After the challenge above, the transaction will be restarted using the
5511 // identity from the url (foo, baz) to answer the challenge.
5512 MockWrite data_writes2
[] = {
5514 "GET / HTTP/1.1\r\n"
5515 "Host: www.example.org\r\n"
5516 "Connection: keep-alive\r\n"
5517 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5520 MockRead data_reads2
[] = {
5521 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5522 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5523 MockRead("Content-Length: 10\r\n\r\n"),
5524 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5527 // After the challenge above, the transaction will be restarted using the
5528 // identity supplied by the user (foo, bar) to answer the challenge.
5529 MockWrite data_writes3
[] = {
5531 "GET / HTTP/1.1\r\n"
5532 "Host: www.example.org\r\n"
5533 "Connection: keep-alive\r\n"
5534 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5537 MockRead data_reads3
[] = {
5538 MockRead("HTTP/1.0 200 OK\r\n"),
5539 MockRead("Content-Length: 100\r\n\r\n"),
5540 MockRead(SYNCHRONOUS
, OK
),
5543 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5544 data_writes1
, arraysize(data_writes1
));
5545 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5546 data_writes2
, arraysize(data_writes2
));
5547 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5548 data_writes3
, arraysize(data_writes3
));
5549 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5550 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5551 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5553 TestCompletionCallback callback1
;
5555 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5558 rv
= callback1
.WaitForResult();
5561 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5562 TestCompletionCallback callback2
;
5563 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5564 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5565 rv
= callback2
.WaitForResult();
5567 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5569 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5570 ASSERT_TRUE(response
!= NULL
);
5571 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5573 TestCompletionCallback callback3
;
5574 rv
= trans
->RestartWithAuth(
5575 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5576 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5577 rv
= callback3
.WaitForResult();
5579 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5581 response
= trans
->GetResponseInfo();
5582 ASSERT_TRUE(response
!= NULL
);
5584 // There is no challenge info, since the identity worked.
5585 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5587 EXPECT_EQ(100, response
->headers
->GetContentLength());
5589 // Empty the current queue.
5590 base::MessageLoop::current()->RunUntilIdle();
5594 // Test the request-challenge-retry sequence for basic auth when there is a
5595 // correct identity in the URL, but its use is being suppressed. The identity
5596 // from the URL should never be used.
5597 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5598 HttpRequestInfo request
;
5599 request
.method
= "GET";
5600 request
.url
= GURL("http://foo:bar@www.example.org/");
5601 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5603 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5604 scoped_ptr
<HttpTransaction
> trans(
5605 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5607 MockWrite data_writes1
[] = {
5609 "GET / HTTP/1.1\r\n"
5610 "Host: www.example.org\r\n"
5611 "Connection: keep-alive\r\n\r\n"),
5614 MockRead data_reads1
[] = {
5615 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5616 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5617 MockRead("Content-Length: 10\r\n\r\n"),
5618 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5621 // After the challenge above, the transaction will be restarted using the
5622 // identity supplied by the user, not the one in the URL, to answer the
5624 MockWrite data_writes3
[] = {
5626 "GET / HTTP/1.1\r\n"
5627 "Host: www.example.org\r\n"
5628 "Connection: keep-alive\r\n"
5629 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5632 MockRead data_reads3
[] = {
5633 MockRead("HTTP/1.0 200 OK\r\n"),
5634 MockRead("Content-Length: 100\r\n\r\n"),
5635 MockRead(SYNCHRONOUS
, OK
),
5638 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5639 data_writes1
, arraysize(data_writes1
));
5640 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5641 data_writes3
, arraysize(data_writes3
));
5642 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5643 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5645 TestCompletionCallback callback1
;
5646 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5647 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5648 rv
= callback1
.WaitForResult();
5650 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5652 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5653 ASSERT_TRUE(response
!= NULL
);
5654 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5656 TestCompletionCallback callback3
;
5657 rv
= trans
->RestartWithAuth(
5658 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5659 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5660 rv
= callback3
.WaitForResult();
5662 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5664 response
= trans
->GetResponseInfo();
5665 ASSERT_TRUE(response
!= NULL
);
5667 // There is no challenge info, since the identity worked.
5668 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5669 EXPECT_EQ(100, response
->headers
->GetContentLength());
5671 // Empty the current queue.
5672 base::MessageLoop::current()->RunUntilIdle();
5675 // Test that previously tried username/passwords for a realm get re-used.
5676 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5677 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5679 // Transaction 1: authenticate (foo, bar) on MyRealm1
5681 HttpRequestInfo request
;
5682 request
.method
= "GET";
5683 request
.url
= GURL("http://www.example.org/x/y/z");
5684 request
.load_flags
= 0;
5686 scoped_ptr
<HttpTransaction
> trans(
5687 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5689 MockWrite data_writes1
[] = {
5691 "GET /x/y/z HTTP/1.1\r\n"
5692 "Host: www.example.org\r\n"
5693 "Connection: keep-alive\r\n\r\n"),
5696 MockRead data_reads1
[] = {
5697 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5698 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5699 MockRead("Content-Length: 10000\r\n\r\n"),
5700 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5703 // Resend with authorization (username=foo, password=bar)
5704 MockWrite data_writes2
[] = {
5706 "GET /x/y/z HTTP/1.1\r\n"
5707 "Host: www.example.org\r\n"
5708 "Connection: keep-alive\r\n"
5709 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5712 // Sever accepts the authorization.
5713 MockRead data_reads2
[] = {
5714 MockRead("HTTP/1.0 200 OK\r\n"),
5715 MockRead("Content-Length: 100\r\n\r\n"),
5716 MockRead(SYNCHRONOUS
, OK
),
5719 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5720 data_writes1
, arraysize(data_writes1
));
5721 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5722 data_writes2
, arraysize(data_writes2
));
5723 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5724 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5726 TestCompletionCallback callback1
;
5728 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5729 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5731 rv
= callback1
.WaitForResult();
5734 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5735 ASSERT_TRUE(response
!= NULL
);
5736 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5738 TestCompletionCallback callback2
;
5740 rv
= trans
->RestartWithAuth(
5741 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5742 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5744 rv
= callback2
.WaitForResult();
5747 response
= trans
->GetResponseInfo();
5748 ASSERT_TRUE(response
!= NULL
);
5749 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5750 EXPECT_EQ(100, response
->headers
->GetContentLength());
5753 // ------------------------------------------------------------------------
5755 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5757 HttpRequestInfo request
;
5758 request
.method
= "GET";
5759 // Note that Transaction 1 was at /x/y/z, so this is in the same
5760 // protection space as MyRealm1.
5761 request
.url
= GURL("http://www.example.org/x/y/a/b");
5762 request
.load_flags
= 0;
5764 scoped_ptr
<HttpTransaction
> trans(
5765 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5767 MockWrite data_writes1
[] = {
5769 "GET /x/y/a/b HTTP/1.1\r\n"
5770 "Host: www.example.org\r\n"
5771 "Connection: keep-alive\r\n"
5772 // Send preemptive authorization for MyRealm1
5773 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5776 // The server didn't like the preemptive authorization, and
5777 // challenges us for a different realm (MyRealm2).
5778 MockRead data_reads1
[] = {
5779 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5780 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5781 MockRead("Content-Length: 10000\r\n\r\n"),
5782 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5785 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5786 MockWrite data_writes2
[] = {
5788 "GET /x/y/a/b HTTP/1.1\r\n"
5789 "Host: www.example.org\r\n"
5790 "Connection: keep-alive\r\n"
5791 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5794 // Sever accepts the authorization.
5795 MockRead data_reads2
[] = {
5796 MockRead("HTTP/1.0 200 OK\r\n"),
5797 MockRead("Content-Length: 100\r\n\r\n"),
5798 MockRead(SYNCHRONOUS
, OK
),
5801 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5802 data_writes1
, arraysize(data_writes1
));
5803 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5804 data_writes2
, arraysize(data_writes2
));
5805 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5806 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5808 TestCompletionCallback callback1
;
5810 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5811 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5813 rv
= callback1
.WaitForResult();
5816 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5817 ASSERT_TRUE(response
!= NULL
);
5818 ASSERT_TRUE(response
->auth_challenge
.get());
5819 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5820 EXPECT_EQ("www.example.org:80",
5821 response
->auth_challenge
->challenger
.ToString());
5822 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5823 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5825 TestCompletionCallback callback2
;
5827 rv
= trans
->RestartWithAuth(
5828 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5829 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5831 rv
= callback2
.WaitForResult();
5834 response
= trans
->GetResponseInfo();
5835 ASSERT_TRUE(response
!= NULL
);
5836 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5837 EXPECT_EQ(100, response
->headers
->GetContentLength());
5840 // ------------------------------------------------------------------------
5842 // Transaction 3: Resend a request in MyRealm's protection space --
5843 // succeed with preemptive authorization.
5845 HttpRequestInfo request
;
5846 request
.method
= "GET";
5847 request
.url
= GURL("http://www.example.org/x/y/z2");
5848 request
.load_flags
= 0;
5850 scoped_ptr
<HttpTransaction
> trans(
5851 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5853 MockWrite data_writes1
[] = {
5855 "GET /x/y/z2 HTTP/1.1\r\n"
5856 "Host: www.example.org\r\n"
5857 "Connection: keep-alive\r\n"
5858 // The authorization for MyRealm1 gets sent preemptively
5859 // (since the url is in the same protection space)
5860 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5863 // Sever accepts the preemptive authorization
5864 MockRead data_reads1
[] = {
5865 MockRead("HTTP/1.0 200 OK\r\n"),
5866 MockRead("Content-Length: 100\r\n\r\n"),
5867 MockRead(SYNCHRONOUS
, OK
),
5870 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5871 data_writes1
, arraysize(data_writes1
));
5872 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5874 TestCompletionCallback callback1
;
5876 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5877 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5879 rv
= callback1
.WaitForResult();
5882 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5883 ASSERT_TRUE(response
!= NULL
);
5885 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5886 EXPECT_EQ(100, response
->headers
->GetContentLength());
5889 // ------------------------------------------------------------------------
5891 // Transaction 4: request another URL in MyRealm (however the
5892 // url is not known to belong to the protection space, so no pre-auth).
5894 HttpRequestInfo request
;
5895 request
.method
= "GET";
5896 request
.url
= GURL("http://www.example.org/x/1");
5897 request
.load_flags
= 0;
5899 scoped_ptr
<HttpTransaction
> trans(
5900 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5902 MockWrite data_writes1
[] = {
5904 "GET /x/1 HTTP/1.1\r\n"
5905 "Host: www.example.org\r\n"
5906 "Connection: keep-alive\r\n\r\n"),
5909 MockRead data_reads1
[] = {
5910 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5911 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5912 MockRead("Content-Length: 10000\r\n\r\n"),
5913 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5916 // Resend with authorization from MyRealm's cache.
5917 MockWrite data_writes2
[] = {
5919 "GET /x/1 HTTP/1.1\r\n"
5920 "Host: www.example.org\r\n"
5921 "Connection: keep-alive\r\n"
5922 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5925 // Sever accepts the authorization.
5926 MockRead data_reads2
[] = {
5927 MockRead("HTTP/1.0 200 OK\r\n"),
5928 MockRead("Content-Length: 100\r\n\r\n"),
5929 MockRead(SYNCHRONOUS
, OK
),
5932 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5933 data_writes1
, arraysize(data_writes1
));
5934 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5935 data_writes2
, arraysize(data_writes2
));
5936 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5937 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5939 TestCompletionCallback callback1
;
5941 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5944 rv
= callback1
.WaitForResult();
5947 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5948 TestCompletionCallback callback2
;
5949 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5951 rv
= callback2
.WaitForResult();
5953 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5955 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5956 ASSERT_TRUE(response
!= NULL
);
5957 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5958 EXPECT_EQ(100, response
->headers
->GetContentLength());
5961 // ------------------------------------------------------------------------
5963 // Transaction 5: request a URL in MyRealm, but the server rejects the
5964 // cached identity. Should invalidate and re-prompt.
5966 HttpRequestInfo request
;
5967 request
.method
= "GET";
5968 request
.url
= GURL("http://www.example.org/p/q/t");
5969 request
.load_flags
= 0;
5971 scoped_ptr
<HttpTransaction
> trans(
5972 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5974 MockWrite data_writes1
[] = {
5976 "GET /p/q/t HTTP/1.1\r\n"
5977 "Host: www.example.org\r\n"
5978 "Connection: keep-alive\r\n\r\n"),
5981 MockRead data_reads1
[] = {
5982 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5983 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5984 MockRead("Content-Length: 10000\r\n\r\n"),
5985 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5988 // Resend with authorization from cache for MyRealm.
5989 MockWrite data_writes2
[] = {
5991 "GET /p/q/t HTTP/1.1\r\n"
5992 "Host: www.example.org\r\n"
5993 "Connection: keep-alive\r\n"
5994 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5997 // Sever rejects the authorization.
5998 MockRead data_reads2
[] = {
5999 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6000 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6001 MockRead("Content-Length: 10000\r\n\r\n"),
6002 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6005 // At this point we should prompt for new credentials for MyRealm.
6006 // Restart with username=foo3, password=foo4.
6007 MockWrite data_writes3
[] = {
6009 "GET /p/q/t HTTP/1.1\r\n"
6010 "Host: www.example.org\r\n"
6011 "Connection: keep-alive\r\n"
6012 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6015 // Sever accepts the authorization.
6016 MockRead data_reads3
[] = {
6017 MockRead("HTTP/1.0 200 OK\r\n"),
6018 MockRead("Content-Length: 100\r\n\r\n"),
6019 MockRead(SYNCHRONOUS
, OK
),
6022 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6023 data_writes1
, arraysize(data_writes1
));
6024 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6025 data_writes2
, arraysize(data_writes2
));
6026 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6027 data_writes3
, arraysize(data_writes3
));
6028 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6029 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6030 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6032 TestCompletionCallback callback1
;
6034 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6037 rv
= callback1
.WaitForResult();
6040 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6041 TestCompletionCallback callback2
;
6042 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6044 rv
= callback2
.WaitForResult();
6046 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6048 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6049 ASSERT_TRUE(response
!= NULL
);
6050 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6052 TestCompletionCallback callback3
;
6054 rv
= trans
->RestartWithAuth(
6055 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6056 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6058 rv
= callback3
.WaitForResult();
6061 response
= trans
->GetResponseInfo();
6062 ASSERT_TRUE(response
!= NULL
);
6063 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6064 EXPECT_EQ(100, response
->headers
->GetContentLength());
6068 // Tests that nonce count increments when multiple auth attempts
6069 // are started with the same nonce.
6070 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6071 HttpAuthHandlerDigest::Factory
* digest_factory
=
6072 new HttpAuthHandlerDigest::Factory();
6073 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6074 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6075 digest_factory
->set_nonce_generator(nonce_generator
);
6076 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6077 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6079 // Transaction 1: authenticate (foo, bar) on MyRealm1
6081 HttpRequestInfo request
;
6082 request
.method
= "GET";
6083 request
.url
= GURL("http://www.example.org/x/y/z");
6084 request
.load_flags
= 0;
6086 scoped_ptr
<HttpTransaction
> trans(
6087 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6089 MockWrite data_writes1
[] = {
6091 "GET /x/y/z HTTP/1.1\r\n"
6092 "Host: www.example.org\r\n"
6093 "Connection: keep-alive\r\n\r\n"),
6096 MockRead data_reads1
[] = {
6097 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6098 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6099 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6100 MockRead(SYNCHRONOUS
, OK
),
6103 // Resend with authorization (username=foo, password=bar)
6104 MockWrite data_writes2
[] = {
6106 "GET /x/y/z HTTP/1.1\r\n"
6107 "Host: www.example.org\r\n"
6108 "Connection: keep-alive\r\n"
6109 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6110 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6111 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6112 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6115 // Sever accepts the authorization.
6116 MockRead data_reads2
[] = {
6117 MockRead("HTTP/1.0 200 OK\r\n"),
6118 MockRead(SYNCHRONOUS
, OK
),
6121 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6122 data_writes1
, arraysize(data_writes1
));
6123 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6124 data_writes2
, arraysize(data_writes2
));
6125 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6126 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6128 TestCompletionCallback callback1
;
6130 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6131 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6133 rv
= callback1
.WaitForResult();
6136 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6137 ASSERT_TRUE(response
!= NULL
);
6138 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6140 TestCompletionCallback callback2
;
6142 rv
= trans
->RestartWithAuth(
6143 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6146 rv
= callback2
.WaitForResult();
6149 response
= trans
->GetResponseInfo();
6150 ASSERT_TRUE(response
!= NULL
);
6151 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6154 // ------------------------------------------------------------------------
6156 // Transaction 2: Request another resource in digestive's protection space.
6157 // This will preemptively add an Authorization header which should have an
6158 // "nc" value of 2 (as compared to 1 in the first use.
6160 HttpRequestInfo request
;
6161 request
.method
= "GET";
6162 // Note that Transaction 1 was at /x/y/z, so this is in the same
6163 // protection space as digest.
6164 request
.url
= GURL("http://www.example.org/x/y/a/b");
6165 request
.load_flags
= 0;
6167 scoped_ptr
<HttpTransaction
> trans(
6168 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6170 MockWrite data_writes1
[] = {
6172 "GET /x/y/a/b HTTP/1.1\r\n"
6173 "Host: www.example.org\r\n"
6174 "Connection: keep-alive\r\n"
6175 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6176 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6177 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6178 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6181 // Sever accepts the authorization.
6182 MockRead data_reads1
[] = {
6183 MockRead("HTTP/1.0 200 OK\r\n"),
6184 MockRead("Content-Length: 100\r\n\r\n"),
6185 MockRead(SYNCHRONOUS
, OK
),
6188 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6189 data_writes1
, arraysize(data_writes1
));
6190 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6192 TestCompletionCallback callback1
;
6194 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6195 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6197 rv
= callback1
.WaitForResult();
6200 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6201 ASSERT_TRUE(response
!= NULL
);
6202 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6206 // Test the ResetStateForRestart() private method.
6207 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6208 // Create a transaction (the dependencies aren't important).
6209 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6210 scoped_ptr
<HttpNetworkTransaction
> trans(
6211 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6213 // Setup some state (which we expect ResetStateForRestart() will clear).
6214 trans
->read_buf_
= new IOBuffer(15);
6215 trans
->read_buf_len_
= 15;
6216 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6218 // Setup state in response_
6219 HttpResponseInfo
* response
= &trans
->response_
;
6220 response
->auth_challenge
= new AuthChallengeInfo();
6221 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6222 response
->response_time
= base::Time::Now();
6223 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6225 { // Setup state for response_.vary_data
6226 HttpRequestInfo request
;
6227 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6228 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6229 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6230 request
.extra_headers
.SetHeader("Foo", "1");
6231 request
.extra_headers
.SetHeader("bar", "23");
6232 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6235 // Cause the above state to be reset.
6236 trans
->ResetStateForRestart();
6238 // Verify that the state that needed to be reset, has been reset.
6239 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6240 EXPECT_EQ(0, trans
->read_buf_len_
);
6241 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6242 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6243 EXPECT_TRUE(response
->headers
.get() == NULL
);
6244 EXPECT_FALSE(response
->was_cached
);
6245 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6246 EXPECT_FALSE(response
->vary_data
.is_valid());
6249 // Test HTTPS connections to a site with a bad certificate
6250 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6251 HttpRequestInfo request
;
6252 request
.method
= "GET";
6253 request
.url
= GURL("https://www.example.org/");
6254 request
.load_flags
= 0;
6256 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6257 scoped_ptr
<HttpTransaction
> trans(
6258 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6260 MockWrite data_writes
[] = {
6262 "GET / HTTP/1.1\r\n"
6263 "Host: www.example.org\r\n"
6264 "Connection: keep-alive\r\n\r\n"),
6267 MockRead data_reads
[] = {
6268 MockRead("HTTP/1.0 200 OK\r\n"),
6269 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6270 MockRead("Content-Length: 100\r\n\r\n"),
6271 MockRead(SYNCHRONOUS
, OK
),
6274 StaticSocketDataProvider ssl_bad_certificate
;
6275 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6276 data_writes
, arraysize(data_writes
));
6277 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6278 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6280 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6281 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6282 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6283 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6285 TestCompletionCallback callback
;
6287 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6288 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6290 rv
= callback
.WaitForResult();
6291 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6293 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6294 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6296 rv
= callback
.WaitForResult();
6299 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6301 ASSERT_TRUE(response
!= NULL
);
6302 EXPECT_EQ(100, response
->headers
->GetContentLength());
6305 // Test HTTPS connections to a site with a bad certificate, going through a
6307 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6308 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6310 HttpRequestInfo request
;
6311 request
.method
= "GET";
6312 request
.url
= GURL("https://www.example.org/");
6313 request
.load_flags
= 0;
6315 MockWrite proxy_writes
[] = {
6317 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6318 "Host: www.example.org\r\n"
6319 "Proxy-Connection: keep-alive\r\n\r\n"),
6322 MockRead proxy_reads
[] = {
6323 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6324 MockRead(SYNCHRONOUS
, OK
)
6327 MockWrite data_writes
[] = {
6329 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6330 "Host: www.example.org\r\n"
6331 "Proxy-Connection: keep-alive\r\n\r\n"),
6333 "GET / HTTP/1.1\r\n"
6334 "Host: www.example.org\r\n"
6335 "Connection: keep-alive\r\n\r\n"),
6338 MockRead data_reads
[] = {
6339 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6340 MockRead("HTTP/1.0 200 OK\r\n"),
6341 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6342 MockRead("Content-Length: 100\r\n\r\n"),
6343 MockRead(SYNCHRONOUS
, OK
),
6346 StaticSocketDataProvider
ssl_bad_certificate(
6347 proxy_reads
, arraysize(proxy_reads
),
6348 proxy_writes
, arraysize(proxy_writes
));
6349 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6350 data_writes
, arraysize(data_writes
));
6351 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6352 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6354 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6355 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6356 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6357 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6359 TestCompletionCallback callback
;
6361 for (int i
= 0; i
< 2; i
++) {
6362 session_deps_
.socket_factory
->ResetNextMockIndexes();
6364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6365 scoped_ptr
<HttpTransaction
> trans(
6366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6368 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6371 rv
= callback
.WaitForResult();
6372 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6374 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6377 rv
= callback
.WaitForResult();
6380 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6382 ASSERT_TRUE(response
!= NULL
);
6383 EXPECT_EQ(100, response
->headers
->GetContentLength());
6388 // Test HTTPS connections to a site, going through an HTTPS proxy
6389 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6390 session_deps_
.proxy_service
.reset(
6391 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6393 session_deps_
.net_log
= &net_log
;
6395 HttpRequestInfo request
;
6396 request
.method
= "GET";
6397 request
.url
= GURL("https://www.example.org/");
6398 request
.load_flags
= 0;
6400 MockWrite data_writes
[] = {
6402 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6403 "Host: www.example.org\r\n"
6404 "Proxy-Connection: keep-alive\r\n\r\n"),
6406 "GET / HTTP/1.1\r\n"
6407 "Host: www.example.org\r\n"
6408 "Connection: keep-alive\r\n\r\n"),
6411 MockRead data_reads
[] = {
6412 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6413 MockRead("HTTP/1.1 200 OK\r\n"),
6414 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6415 MockRead("Content-Length: 100\r\n\r\n"),
6416 MockRead(SYNCHRONOUS
, OK
),
6419 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6420 data_writes
, arraysize(data_writes
));
6421 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6422 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6424 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6425 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6426 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6428 TestCompletionCallback callback
;
6430 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6431 scoped_ptr
<HttpTransaction
> trans(
6432 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6434 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6435 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6437 rv
= callback
.WaitForResult();
6439 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6441 ASSERT_TRUE(response
!= NULL
);
6443 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6444 EXPECT_EQ(200, response
->headers
->response_code());
6445 EXPECT_EQ(100, response
->headers
->GetContentLength());
6446 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6448 LoadTimingInfo load_timing_info
;
6449 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6450 TestLoadTimingNotReusedWithPac(load_timing_info
,
6451 CONNECT_TIMING_HAS_SSL_TIMES
);
6454 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6455 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6456 session_deps_
.proxy_service
.reset(
6457 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6459 session_deps_
.net_log
= &net_log
;
6461 HttpRequestInfo request
;
6462 request
.method
= "GET";
6463 request
.url
= GURL("https://www.example.org/");
6464 request
.load_flags
= 0;
6466 MockWrite data_writes
[] = {
6468 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6469 "Host: www.example.org\r\n"
6470 "Proxy-Connection: keep-alive\r\n\r\n"),
6473 MockRead data_reads
[] = {
6474 MockRead("HTTP/1.1 302 Redirect\r\n"),
6475 MockRead("Location: http://login.example.com/\r\n"),
6476 MockRead("Content-Length: 0\r\n\r\n"),
6477 MockRead(SYNCHRONOUS
, OK
),
6480 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6481 data_writes
, arraysize(data_writes
));
6482 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6484 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6485 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6487 TestCompletionCallback callback
;
6489 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6490 scoped_ptr
<HttpTransaction
> trans(
6491 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6493 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6494 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6496 rv
= callback
.WaitForResult();
6498 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6500 ASSERT_TRUE(response
!= NULL
);
6502 EXPECT_EQ(302, response
->headers
->response_code());
6504 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6505 EXPECT_EQ("http://login.example.com/", url
);
6507 // In the case of redirects from proxies, HttpNetworkTransaction returns
6508 // timing for the proxy connection instead of the connection to the host,
6509 // and no send / receive times.
6510 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6511 LoadTimingInfo load_timing_info
;
6512 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6514 EXPECT_FALSE(load_timing_info
.socket_reused
);
6515 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6517 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6518 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6519 load_timing_info
.proxy_resolve_end
);
6520 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6521 load_timing_info
.connect_timing
.connect_start
);
6522 ExpectConnectTimingHasTimes(
6523 load_timing_info
.connect_timing
,
6524 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6526 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6527 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6528 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6531 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6532 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6533 session_deps_
.proxy_service
.reset(
6534 ProxyService::CreateFixed("https://proxy:70"));
6536 HttpRequestInfo request
;
6537 request
.method
= "GET";
6538 request
.url
= GURL("https://www.example.org/");
6539 request
.load_flags
= 0;
6541 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6542 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6543 scoped_ptr
<SpdyFrame
> goaway(
6544 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6545 MockWrite data_writes
[] = {
6546 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6547 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6550 static const char* const kExtraHeaders
[] = {
6552 "http://login.example.com/",
6554 scoped_ptr
<SpdyFrame
> resp(
6555 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6556 arraysize(kExtraHeaders
)/2, 1));
6557 MockRead data_reads
[] = {
6558 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6561 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6562 arraysize(data_writes
));
6563 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6564 proxy_ssl
.SetNextProto(GetParam());
6566 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6567 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6569 TestCompletionCallback callback
;
6571 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6572 scoped_ptr
<HttpTransaction
> trans(
6573 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6575 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6576 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6578 rv
= callback
.WaitForResult();
6580 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6582 ASSERT_TRUE(response
!= NULL
);
6584 EXPECT_EQ(302, response
->headers
->response_code());
6586 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6587 EXPECT_EQ("http://login.example.com/", url
);
6590 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6591 TEST_P(HttpNetworkTransactionTest
,
6592 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6593 session_deps_
.proxy_service
.reset(
6594 ProxyService::CreateFixed("https://proxy:70"));
6596 HttpRequestInfo request
;
6597 request
.method
= "GET";
6598 request
.url
= GURL("https://www.example.org/");
6599 request
.load_flags
= 0;
6601 MockWrite data_writes
[] = {
6603 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6604 "Host: www.example.org\r\n"
6605 "Proxy-Connection: keep-alive\r\n\r\n"),
6608 MockRead data_reads
[] = {
6609 MockRead("HTTP/1.1 404 Not Found\r\n"),
6610 MockRead("Content-Length: 23\r\n\r\n"),
6611 MockRead("The host does not exist"),
6612 MockRead(SYNCHRONOUS
, OK
),
6615 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6616 data_writes
, arraysize(data_writes
));
6617 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6619 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6620 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6622 TestCompletionCallback callback
;
6624 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6625 scoped_ptr
<HttpTransaction
> trans(
6626 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6628 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6629 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6631 rv
= callback
.WaitForResult();
6632 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6634 // TODO(ttuttle): Anything else to check here?
6637 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6638 TEST_P(HttpNetworkTransactionTest
,
6639 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6640 session_deps_
.proxy_service
.reset(
6641 ProxyService::CreateFixed("https://proxy:70"));
6643 HttpRequestInfo request
;
6644 request
.method
= "GET";
6645 request
.url
= GURL("https://www.example.org/");
6646 request
.load_flags
= 0;
6648 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6649 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6650 scoped_ptr
<SpdyFrame
> rst(
6651 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6652 MockWrite data_writes
[] = {
6653 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6656 static const char* const kExtraHeaders
[] = {
6658 "http://login.example.com/",
6660 scoped_ptr
<SpdyFrame
> resp(
6661 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6662 arraysize(kExtraHeaders
)/2, 1));
6663 scoped_ptr
<SpdyFrame
> body(
6664 spdy_util_
.ConstructSpdyBodyFrame(
6665 1, "The host does not exist", 23, true));
6666 MockRead data_reads
[] = {
6667 CreateMockRead(*resp
.get(), 1),
6668 CreateMockRead(*body
.get(), 2),
6669 MockRead(ASYNC
, 0, 4), // EOF
6672 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6673 arraysize(data_writes
));
6674 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6675 proxy_ssl
.SetNextProto(GetParam());
6677 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6678 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6680 TestCompletionCallback callback
;
6682 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6683 scoped_ptr
<HttpTransaction
> trans(
6684 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6686 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6687 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6689 rv
= callback
.WaitForResult();
6690 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6692 // TODO(ttuttle): Anything else to check here?
6695 // Test the request-challenge-retry sequence for basic auth, through
6696 // a SPDY proxy over a single SPDY session.
6697 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6698 HttpRequestInfo request
;
6699 request
.method
= "GET";
6700 request
.url
= GURL("https://www.example.org/");
6701 // when the no authentication data flag is set.
6702 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6704 // Configure against https proxy server "myproxy:70".
6705 session_deps_
.proxy_service
.reset(
6706 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6707 BoundTestNetLog log
;
6708 session_deps_
.net_log
= log
.bound().net_log();
6709 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6711 // Since we have proxy, should try to establish tunnel.
6712 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6713 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6714 scoped_ptr
<SpdyFrame
> rst(
6715 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6717 // After calling trans->RestartWithAuth(), this is the request we should
6718 // be issuing -- the final header line contains the credentials.
6719 const char* const kAuthCredentials
[] = {
6720 "proxy-authorization", "Basic Zm9vOmJhcg==",
6722 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6723 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6724 HostPortPair("www.example.org", 443)));
6725 // fetch https://www.example.org/ via HTTP
6727 "GET / HTTP/1.1\r\n"
6728 "Host: www.example.org\r\n"
6729 "Connection: keep-alive\r\n\r\n";
6730 scoped_ptr
<SpdyFrame
> wrapped_get(
6731 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6733 MockWrite spdy_writes
[] = {
6734 CreateMockWrite(*req
, 0, ASYNC
),
6735 CreateMockWrite(*rst
, 2, ASYNC
),
6736 CreateMockWrite(*connect2
, 3),
6737 CreateMockWrite(*wrapped_get
, 5),
6740 // The proxy responds to the connect with a 407, using a persistent
6742 const char kAuthStatus
[] = "407";
6743 const char* const kAuthChallenge
[] = {
6744 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6746 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6747 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6749 scoped_ptr
<SpdyFrame
> conn_resp(
6750 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6751 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6752 "Content-Length: 5\r\n\r\n";
6754 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6755 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6756 scoped_ptr
<SpdyFrame
> wrapped_body(
6757 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6758 MockRead spdy_reads
[] = {
6759 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6760 CreateMockRead(*conn_resp
, 4, ASYNC
),
6761 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6762 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6763 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6766 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6767 arraysize(spdy_writes
));
6768 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6769 // Negotiate SPDY to the proxy
6770 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6771 proxy
.SetNextProto(GetParam());
6772 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6773 // Vanilla SSL to the server
6774 SSLSocketDataProvider
server(ASYNC
, OK
);
6775 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6777 TestCompletionCallback callback1
;
6779 scoped_ptr
<HttpTransaction
> trans(
6780 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6782 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6783 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6785 rv
= callback1
.WaitForResult();
6787 TestNetLogEntry::List entries
;
6788 log
.GetEntries(&entries
);
6789 size_t pos
= ExpectLogContainsSomewhere(
6790 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6791 NetLog::PHASE_NONE
);
6792 ExpectLogContainsSomewhere(
6794 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6795 NetLog::PHASE_NONE
);
6797 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6798 ASSERT_TRUE(response
!= NULL
);
6799 ASSERT_FALSE(response
->headers
.get() == NULL
);
6800 EXPECT_EQ(407, response
->headers
->response_code());
6801 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6802 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6803 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6805 TestCompletionCallback callback2
;
6807 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6808 callback2
.callback());
6809 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6811 rv
= callback2
.WaitForResult();
6814 response
= trans
->GetResponseInfo();
6815 ASSERT_TRUE(response
!= NULL
);
6817 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6818 EXPECT_EQ(200, response
->headers
->response_code());
6819 EXPECT_EQ(5, response
->headers
->GetContentLength());
6820 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6822 // The password prompt info should not be set.
6823 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6825 LoadTimingInfo load_timing_info
;
6826 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6827 TestLoadTimingNotReusedWithPac(load_timing_info
,
6828 CONNECT_TIMING_HAS_SSL_TIMES
);
6831 session
->CloseAllConnections();
6834 // Test that an explicitly trusted SPDY proxy can push a resource from an
6835 // origin that is different from that of its associated resource.
6836 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6837 HttpRequestInfo request
;
6838 HttpRequestInfo push_request
;
6840 request
.method
= "GET";
6841 request
.url
= GURL("http://www.example.org/");
6842 push_request
.method
= "GET";
6843 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6845 // Configure against https proxy server "myproxy:70".
6846 session_deps_
.proxy_service
.reset(
6847 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6848 BoundTestNetLog log
;
6849 session_deps_
.net_log
= log
.bound().net_log();
6851 // Enable cross-origin push.
6852 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6854 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6856 scoped_ptr
<SpdyFrame
> stream1_syn(
6857 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6859 MockWrite spdy_writes
[] = {
6860 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6863 scoped_ptr
<SpdyFrame
>
6864 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6866 scoped_ptr
<SpdyFrame
>
6867 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6869 scoped_ptr
<SpdyFrame
>
6870 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6874 "http://www.another-origin.com/foo.dat"));
6875 const char kPushedData
[] = "pushed";
6876 scoped_ptr
<SpdyFrame
> stream2_body(
6877 spdy_util_
.ConstructSpdyBodyFrame(
6878 2, kPushedData
, strlen(kPushedData
), true));
6880 MockRead spdy_reads
[] = {
6881 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6882 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6883 CreateMockRead(*stream1_body
, 3, ASYNC
),
6884 CreateMockRead(*stream2_body
, 4, ASYNC
),
6885 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
6888 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6889 arraysize(spdy_writes
));
6890 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6891 // Negotiate SPDY to the proxy
6892 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6893 proxy
.SetNextProto(GetParam());
6894 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6896 scoped_ptr
<HttpTransaction
> trans(
6897 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6898 TestCompletionCallback callback
;
6899 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6900 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6902 rv
= callback
.WaitForResult();
6904 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6906 scoped_ptr
<HttpTransaction
> push_trans(
6907 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6908 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6909 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6911 rv
= callback
.WaitForResult();
6913 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6915 ASSERT_TRUE(response
!= NULL
);
6916 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6918 EXPECT_EQ(200, response
->headers
->response_code());
6919 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6921 std::string response_data
;
6922 rv
= ReadTransaction(trans
.get(), &response_data
);
6924 EXPECT_EQ("hello!", response_data
);
6926 LoadTimingInfo load_timing_info
;
6927 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6928 TestLoadTimingNotReusedWithPac(load_timing_info
,
6929 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6931 // Verify the pushed stream.
6932 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6933 EXPECT_EQ(200, push_response
->headers
->response_code());
6935 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6937 EXPECT_EQ("pushed", response_data
);
6939 LoadTimingInfo push_load_timing_info
;
6940 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6941 TestLoadTimingReusedWithPac(push_load_timing_info
);
6942 // The transactions should share a socket ID, despite being for different
6944 EXPECT_EQ(load_timing_info
.socket_log_id
,
6945 push_load_timing_info
.socket_log_id
);
6949 session
->CloseAllConnections();
6952 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6953 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6954 HttpRequestInfo request
;
6956 request
.method
= "GET";
6957 request
.url
= GURL("http://www.example.org/");
6959 // Configure against https proxy server "myproxy:70".
6960 session_deps_
.proxy_service
.reset(
6961 ProxyService::CreateFixed("https://myproxy:70"));
6962 BoundTestNetLog log
;
6963 session_deps_
.net_log
= log
.bound().net_log();
6965 // Enable cross-origin push.
6966 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6968 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6970 scoped_ptr
<SpdyFrame
> stream1_syn(
6971 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6973 scoped_ptr
<SpdyFrame
> push_rst(
6974 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6976 MockWrite spdy_writes
[] = {
6977 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
6980 scoped_ptr
<SpdyFrame
>
6981 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6983 scoped_ptr
<SpdyFrame
>
6984 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6986 scoped_ptr
<SpdyFrame
>
6987 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6991 "https://www.another-origin.com/foo.dat"));
6993 MockRead spdy_reads
[] = {
6994 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6995 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6996 CreateMockRead(*stream1_body
, 4, ASYNC
),
6997 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7000 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7001 arraysize(spdy_writes
));
7002 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7003 // Negotiate SPDY to the proxy
7004 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7005 proxy
.SetNextProto(GetParam());
7006 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7008 scoped_ptr
<HttpTransaction
> trans(
7009 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7010 TestCompletionCallback callback
;
7011 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7012 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7014 rv
= callback
.WaitForResult();
7016 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7018 ASSERT_TRUE(response
!= NULL
);
7019 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7021 EXPECT_EQ(200, response
->headers
->response_code());
7022 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7024 std::string response_data
;
7025 rv
= ReadTransaction(trans
.get(), &response_data
);
7027 EXPECT_EQ("hello!", response_data
);
7030 session
->CloseAllConnections();
7033 // Test HTTPS connections to a site with a bad certificate, going through an
7035 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7036 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7037 "https://proxy:70"));
7039 HttpRequestInfo request
;
7040 request
.method
= "GET";
7041 request
.url
= GURL("https://www.example.org/");
7042 request
.load_flags
= 0;
7044 // Attempt to fetch the URL from a server with a bad cert
7045 MockWrite bad_cert_writes
[] = {
7047 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7048 "Host: www.example.org\r\n"
7049 "Proxy-Connection: keep-alive\r\n\r\n"),
7052 MockRead bad_cert_reads
[] = {
7053 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7054 MockRead(SYNCHRONOUS
, OK
)
7057 // Attempt to fetch the URL with a good cert
7058 MockWrite good_data_writes
[] = {
7060 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7061 "Host: www.example.org\r\n"
7062 "Proxy-Connection: keep-alive\r\n\r\n"),
7064 "GET / HTTP/1.1\r\n"
7065 "Host: www.example.org\r\n"
7066 "Connection: keep-alive\r\n\r\n"),
7069 MockRead good_cert_reads
[] = {
7070 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7071 MockRead("HTTP/1.0 200 OK\r\n"),
7072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7073 MockRead("Content-Length: 100\r\n\r\n"),
7074 MockRead(SYNCHRONOUS
, OK
),
7077 StaticSocketDataProvider
ssl_bad_certificate(
7078 bad_cert_reads
, arraysize(bad_cert_reads
),
7079 bad_cert_writes
, arraysize(bad_cert_writes
));
7080 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7081 good_data_writes
, arraysize(good_data_writes
));
7082 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7083 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7085 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7086 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7087 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7088 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7090 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7091 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7092 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7093 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7095 TestCompletionCallback callback
;
7097 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7098 scoped_ptr
<HttpTransaction
> trans(
7099 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7101 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7102 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7104 rv
= callback
.WaitForResult();
7105 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7107 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7108 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7110 rv
= callback
.WaitForResult();
7113 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7115 ASSERT_TRUE(response
!= NULL
);
7116 EXPECT_EQ(100, response
->headers
->GetContentLength());
7119 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7120 HttpRequestInfo request
;
7121 request
.method
= "GET";
7122 request
.url
= GURL("http://www.example.org/");
7123 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7124 "Chromium Ultra Awesome X Edition");
7126 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7127 scoped_ptr
<HttpTransaction
> trans(
7128 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7130 MockWrite data_writes
[] = {
7132 "GET / HTTP/1.1\r\n"
7133 "Host: www.example.org\r\n"
7134 "Connection: keep-alive\r\n"
7135 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7138 // Lastly, the server responds with the actual content.
7139 MockRead data_reads
[] = {
7140 MockRead("HTTP/1.0 200 OK\r\n"),
7141 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7142 MockRead("Content-Length: 100\r\n\r\n"),
7143 MockRead(SYNCHRONOUS
, OK
),
7146 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7147 data_writes
, arraysize(data_writes
));
7148 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7150 TestCompletionCallback callback
;
7152 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7153 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7155 rv
= callback
.WaitForResult();
7159 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7160 HttpRequestInfo request
;
7161 request
.method
= "GET";
7162 request
.url
= GURL("https://www.example.org/");
7163 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7164 "Chromium Ultra Awesome X Edition");
7166 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7167 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7168 scoped_ptr
<HttpTransaction
> trans(
7169 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7171 MockWrite data_writes
[] = {
7173 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7174 "Host: www.example.org\r\n"
7175 "Proxy-Connection: keep-alive\r\n"
7176 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7178 MockRead data_reads
[] = {
7179 // Return an error, so the transaction stops here (this test isn't
7180 // interested in the rest).
7181 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7182 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7183 MockRead("Proxy-Connection: close\r\n\r\n"),
7186 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7187 data_writes
, arraysize(data_writes
));
7188 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7190 TestCompletionCallback callback
;
7192 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7193 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7195 rv
= callback
.WaitForResult();
7199 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7200 HttpRequestInfo request
;
7201 request
.method
= "GET";
7202 request
.url
= GURL("http://www.example.org/");
7203 request
.load_flags
= 0;
7204 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7205 "http://the.previous.site.com/");
7207 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7208 scoped_ptr
<HttpTransaction
> trans(
7209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7211 MockWrite data_writes
[] = {
7213 "GET / HTTP/1.1\r\n"
7214 "Host: www.example.org\r\n"
7215 "Connection: keep-alive\r\n"
7216 "Referer: http://the.previous.site.com/\r\n\r\n"),
7219 // Lastly, the server responds with the actual content.
7220 MockRead data_reads
[] = {
7221 MockRead("HTTP/1.0 200 OK\r\n"),
7222 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7223 MockRead("Content-Length: 100\r\n\r\n"),
7224 MockRead(SYNCHRONOUS
, OK
),
7227 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7228 data_writes
, arraysize(data_writes
));
7229 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7231 TestCompletionCallback callback
;
7233 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7234 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7236 rv
= callback
.WaitForResult();
7240 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7241 HttpRequestInfo request
;
7242 request
.method
= "POST";
7243 request
.url
= GURL("http://www.example.org/");
7245 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7246 scoped_ptr
<HttpTransaction
> trans(
7247 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7249 MockWrite data_writes
[] = {
7251 "POST / HTTP/1.1\r\n"
7252 "Host: www.example.org\r\n"
7253 "Connection: keep-alive\r\n"
7254 "Content-Length: 0\r\n\r\n"),
7257 // Lastly, the server responds with the actual content.
7258 MockRead data_reads
[] = {
7259 MockRead("HTTP/1.0 200 OK\r\n"),
7260 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7261 MockRead("Content-Length: 100\r\n\r\n"),
7262 MockRead(SYNCHRONOUS
, OK
),
7265 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7266 data_writes
, arraysize(data_writes
));
7267 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7269 TestCompletionCallback callback
;
7271 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7274 rv
= callback
.WaitForResult();
7278 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7279 HttpRequestInfo request
;
7280 request
.method
= "PUT";
7281 request
.url
= GURL("http://www.example.org/");
7283 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7284 scoped_ptr
<HttpTransaction
> trans(
7285 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7287 MockWrite data_writes
[] = {
7289 "PUT / HTTP/1.1\r\n"
7290 "Host: www.example.org\r\n"
7291 "Connection: keep-alive\r\n"
7292 "Content-Length: 0\r\n\r\n"),
7295 // Lastly, the server responds with the actual content.
7296 MockRead data_reads
[] = {
7297 MockRead("HTTP/1.0 200 OK\r\n"),
7298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7299 MockRead("Content-Length: 100\r\n\r\n"),
7300 MockRead(SYNCHRONOUS
, OK
),
7303 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7304 data_writes
, arraysize(data_writes
));
7305 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7307 TestCompletionCallback callback
;
7309 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7312 rv
= callback
.WaitForResult();
7316 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7317 HttpRequestInfo request
;
7318 request
.method
= "HEAD";
7319 request
.url
= GURL("http://www.example.org/");
7321 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7322 scoped_ptr
<HttpTransaction
> trans(
7323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7325 MockWrite data_writes
[] = {
7327 "HEAD / HTTP/1.1\r\n"
7328 "Host: www.example.org\r\n"
7329 "Connection: keep-alive\r\n"
7330 "Content-Length: 0\r\n\r\n"),
7333 // Lastly, the server responds with the actual content.
7334 MockRead data_reads
[] = {
7335 MockRead("HTTP/1.0 200 OK\r\n"),
7336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7337 MockRead("Content-Length: 100\r\n\r\n"),
7338 MockRead(SYNCHRONOUS
, OK
),
7341 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7342 data_writes
, arraysize(data_writes
));
7343 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7345 TestCompletionCallback callback
;
7347 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7350 rv
= callback
.WaitForResult();
7354 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7355 HttpRequestInfo request
;
7356 request
.method
= "GET";
7357 request
.url
= GURL("http://www.example.org/");
7358 request
.load_flags
= LOAD_BYPASS_CACHE
;
7360 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7361 scoped_ptr
<HttpTransaction
> trans(
7362 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7364 MockWrite data_writes
[] = {
7366 "GET / HTTP/1.1\r\n"
7367 "Host: www.example.org\r\n"
7368 "Connection: keep-alive\r\n"
7369 "Pragma: no-cache\r\n"
7370 "Cache-Control: no-cache\r\n\r\n"),
7373 // Lastly, the server responds with the actual content.
7374 MockRead data_reads
[] = {
7375 MockRead("HTTP/1.0 200 OK\r\n"),
7376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7377 MockRead("Content-Length: 100\r\n\r\n"),
7378 MockRead(SYNCHRONOUS
, OK
),
7381 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7382 data_writes
, arraysize(data_writes
));
7383 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7385 TestCompletionCallback callback
;
7387 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7388 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7390 rv
= callback
.WaitForResult();
7394 TEST_P(HttpNetworkTransactionTest
,
7395 BuildRequest_CacheControlValidateCache
) {
7396 HttpRequestInfo request
;
7397 request
.method
= "GET";
7398 request
.url
= GURL("http://www.example.org/");
7399 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7401 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7402 scoped_ptr
<HttpTransaction
> trans(
7403 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7405 MockWrite data_writes
[] = {
7407 "GET / HTTP/1.1\r\n"
7408 "Host: www.example.org\r\n"
7409 "Connection: keep-alive\r\n"
7410 "Cache-Control: max-age=0\r\n\r\n"),
7413 // Lastly, the server responds with the actual content.
7414 MockRead data_reads
[] = {
7415 MockRead("HTTP/1.0 200 OK\r\n"),
7416 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7417 MockRead("Content-Length: 100\r\n\r\n"),
7418 MockRead(SYNCHRONOUS
, OK
),
7421 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7422 data_writes
, arraysize(data_writes
));
7423 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7425 TestCompletionCallback callback
;
7427 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7428 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7430 rv
= callback
.WaitForResult();
7434 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7435 HttpRequestInfo request
;
7436 request
.method
= "GET";
7437 request
.url
= GURL("http://www.example.org/");
7438 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7440 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7441 scoped_ptr
<HttpTransaction
> trans(
7442 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7444 MockWrite data_writes
[] = {
7446 "GET / HTTP/1.1\r\n"
7447 "Host: www.example.org\r\n"
7448 "Connection: keep-alive\r\n"
7449 "FooHeader: Bar\r\n\r\n"),
7452 // Lastly, the server responds with the actual content.
7453 MockRead data_reads
[] = {
7454 MockRead("HTTP/1.0 200 OK\r\n"),
7455 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7456 MockRead("Content-Length: 100\r\n\r\n"),
7457 MockRead(SYNCHRONOUS
, OK
),
7460 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7461 data_writes
, arraysize(data_writes
));
7462 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7464 TestCompletionCallback callback
;
7466 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7467 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7469 rv
= callback
.WaitForResult();
7473 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7474 HttpRequestInfo request
;
7475 request
.method
= "GET";
7476 request
.url
= GURL("http://www.example.org/");
7477 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7478 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7479 request
.extra_headers
.SetHeader("FoO", "bar");
7481 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7482 scoped_ptr
<HttpTransaction
> trans(
7483 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7485 MockWrite data_writes
[] = {
7487 "GET / HTTP/1.1\r\n"
7488 "Host: www.example.org\r\n"
7489 "Connection: keep-alive\r\n"
7490 "referer: www.foo.com\r\n"
7492 "FoO: bar\r\n\r\n"),
7495 // Lastly, the server responds with the actual content.
7496 MockRead data_reads
[] = {
7497 MockRead("HTTP/1.0 200 OK\r\n"),
7498 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7499 MockRead("Content-Length: 100\r\n\r\n"),
7500 MockRead(SYNCHRONOUS
, OK
),
7503 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7504 data_writes
, arraysize(data_writes
));
7505 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7507 TestCompletionCallback callback
;
7509 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7510 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7512 rv
= callback
.WaitForResult();
7516 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7517 HttpRequestInfo request
;
7518 request
.method
= "GET";
7519 request
.url
= GURL("http://www.example.org/");
7520 request
.load_flags
= 0;
7522 session_deps_
.proxy_service
.reset(
7523 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7525 session_deps_
.net_log
= &net_log
;
7527 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7528 scoped_ptr
<HttpTransaction
> trans(
7529 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7531 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7532 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7534 MockWrite data_writes
[] = {
7535 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7537 "GET / HTTP/1.1\r\n"
7538 "Host: www.example.org\r\n"
7539 "Connection: keep-alive\r\n\r\n")};
7541 MockRead data_reads
[] = {
7542 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7543 MockRead("HTTP/1.0 200 OK\r\n"),
7544 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7545 MockRead("Payload"),
7546 MockRead(SYNCHRONOUS
, OK
)
7549 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7550 data_writes
, arraysize(data_writes
));
7551 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7553 TestCompletionCallback callback
;
7555 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7558 rv
= callback
.WaitForResult();
7561 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7562 ASSERT_TRUE(response
!= NULL
);
7564 LoadTimingInfo load_timing_info
;
7565 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7566 TestLoadTimingNotReusedWithPac(load_timing_info
,
7567 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7569 std::string response_text
;
7570 rv
= ReadTransaction(trans
.get(), &response_text
);
7572 EXPECT_EQ("Payload", response_text
);
7575 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7576 HttpRequestInfo request
;
7577 request
.method
= "GET";
7578 request
.url
= GURL("https://www.example.org/");
7579 request
.load_flags
= 0;
7581 session_deps_
.proxy_service
.reset(
7582 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7584 session_deps_
.net_log
= &net_log
;
7586 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7587 scoped_ptr
<HttpTransaction
> trans(
7588 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7590 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7591 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7593 MockWrite data_writes
[] = {
7594 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7595 arraysize(write_buffer
)),
7597 "GET / HTTP/1.1\r\n"
7598 "Host: www.example.org\r\n"
7599 "Connection: keep-alive\r\n\r\n")};
7601 MockRead data_reads
[] = {
7602 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7603 arraysize(read_buffer
)),
7604 MockRead("HTTP/1.0 200 OK\r\n"),
7605 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7606 MockRead("Payload"),
7607 MockRead(SYNCHRONOUS
, OK
)
7610 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7611 data_writes
, arraysize(data_writes
));
7612 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7614 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7615 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7617 TestCompletionCallback callback
;
7619 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7620 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7622 rv
= callback
.WaitForResult();
7625 LoadTimingInfo load_timing_info
;
7626 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7627 TestLoadTimingNotReusedWithPac(load_timing_info
,
7628 CONNECT_TIMING_HAS_SSL_TIMES
);
7630 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7631 ASSERT_TRUE(response
!= NULL
);
7633 std::string response_text
;
7634 rv
= ReadTransaction(trans
.get(), &response_text
);
7636 EXPECT_EQ("Payload", response_text
);
7639 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7640 HttpRequestInfo request
;
7641 request
.method
= "GET";
7642 request
.url
= GURL("http://www.example.org/");
7643 request
.load_flags
= 0;
7645 session_deps_
.proxy_service
.reset(
7646 ProxyService::CreateFixed("socks4://myproxy:1080"));
7648 session_deps_
.net_log
= &net_log
;
7650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7651 scoped_ptr
<HttpTransaction
> trans(
7652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7654 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7655 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7657 MockWrite data_writes
[] = {
7658 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7660 "GET / HTTP/1.1\r\n"
7661 "Host: www.example.org\r\n"
7662 "Connection: keep-alive\r\n\r\n")};
7664 MockRead data_reads
[] = {
7665 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7666 MockRead("HTTP/1.0 200 OK\r\n"),
7667 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7668 MockRead("Payload"),
7669 MockRead(SYNCHRONOUS
, OK
)
7672 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7673 data_writes
, arraysize(data_writes
));
7674 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7676 TestCompletionCallback callback
;
7678 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7679 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7681 rv
= callback
.WaitForResult();
7684 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7685 ASSERT_TRUE(response
!= NULL
);
7687 LoadTimingInfo load_timing_info
;
7688 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7689 TestLoadTimingNotReused(load_timing_info
,
7690 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7692 std::string response_text
;
7693 rv
= ReadTransaction(trans
.get(), &response_text
);
7695 EXPECT_EQ("Payload", response_text
);
7698 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7699 HttpRequestInfo request
;
7700 request
.method
= "GET";
7701 request
.url
= GURL("http://www.example.org/");
7702 request
.load_flags
= 0;
7704 session_deps_
.proxy_service
.reset(
7705 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7707 session_deps_
.net_log
= &net_log
;
7709 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7710 scoped_ptr
<HttpTransaction
> trans(
7711 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7713 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7714 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7715 const char kSOCKS5OkRequest
[] = {
7717 0x01, // Command (CONNECT)
7719 0x03, // Address type (DOMAINNAME).
7720 0x0F, // Length of domain (15)
7721 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7722 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7724 const char kSOCKS5OkResponse
[] =
7725 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7727 MockWrite data_writes
[] = {
7728 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7729 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7731 "GET / HTTP/1.1\r\n"
7732 "Host: www.example.org\r\n"
7733 "Connection: keep-alive\r\n\r\n")};
7735 MockRead data_reads
[] = {
7736 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7737 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7738 MockRead("HTTP/1.0 200 OK\r\n"),
7739 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7740 MockRead("Payload"),
7741 MockRead(SYNCHRONOUS
, OK
)
7744 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7745 data_writes
, arraysize(data_writes
));
7746 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7748 TestCompletionCallback callback
;
7750 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7751 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7753 rv
= callback
.WaitForResult();
7756 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7757 ASSERT_TRUE(response
!= NULL
);
7759 LoadTimingInfo load_timing_info
;
7760 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7761 TestLoadTimingNotReusedWithPac(load_timing_info
,
7762 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7764 std::string response_text
;
7765 rv
= ReadTransaction(trans
.get(), &response_text
);
7767 EXPECT_EQ("Payload", response_text
);
7770 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7771 HttpRequestInfo request
;
7772 request
.method
= "GET";
7773 request
.url
= GURL("https://www.example.org/");
7774 request
.load_flags
= 0;
7776 session_deps_
.proxy_service
.reset(
7777 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7779 session_deps_
.net_log
= &net_log
;
7781 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7782 scoped_ptr
<HttpTransaction
> trans(
7783 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7785 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7786 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7787 const unsigned char kSOCKS5OkRequest
[] = {
7789 0x01, // Command (CONNECT)
7791 0x03, // Address type (DOMAINNAME).
7792 0x0F, // Length of domain (15)
7793 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7794 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7797 const char kSOCKS5OkResponse
[] =
7798 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7800 MockWrite data_writes
[] = {
7801 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7802 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7803 arraysize(kSOCKS5OkRequest
)),
7805 "GET / HTTP/1.1\r\n"
7806 "Host: www.example.org\r\n"
7807 "Connection: keep-alive\r\n\r\n")};
7809 MockRead data_reads
[] = {
7810 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7811 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7812 MockRead("HTTP/1.0 200 OK\r\n"),
7813 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7814 MockRead("Payload"),
7815 MockRead(SYNCHRONOUS
, OK
)
7818 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7819 data_writes
, arraysize(data_writes
));
7820 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7822 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7823 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7825 TestCompletionCallback callback
;
7827 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7828 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7830 rv
= callback
.WaitForResult();
7833 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7834 ASSERT_TRUE(response
!= NULL
);
7836 LoadTimingInfo load_timing_info
;
7837 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7838 TestLoadTimingNotReusedWithPac(load_timing_info
,
7839 CONNECT_TIMING_HAS_SSL_TIMES
);
7841 std::string response_text
;
7842 rv
= ReadTransaction(trans
.get(), &response_text
);
7844 EXPECT_EQ("Payload", response_text
);
7849 // Tests that for connection endpoints the group names are correctly set.
7851 struct GroupNameTest
{
7852 std::string proxy_server
;
7854 std::string expected_group_name
;
7858 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7859 NextProto next_proto
,
7860 SpdySessionDependencies
* session_deps_
) {
7861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7863 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7864 session
->http_server_properties();
7865 AlternativeService
alternative_service(
7866 AlternateProtocolFromNextProto(next_proto
), "", 443);
7867 http_server_properties
->SetAlternativeService(
7868 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0);
7873 int GroupNameTransactionHelper(
7874 const std::string
& url
,
7875 const scoped_refptr
<HttpNetworkSession
>& session
) {
7876 HttpRequestInfo request
;
7877 request
.method
= "GET";
7878 request
.url
= GURL(url
);
7879 request
.load_flags
= 0;
7881 scoped_ptr
<HttpTransaction
> trans(
7882 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7884 TestCompletionCallback callback
;
7886 // We do not complete this request, the dtor will clean the transaction up.
7887 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7892 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7893 const GroupNameTest tests
[] = {
7896 "http://www.example.org/direct",
7897 "www.example.org:80",
7902 "http://[2001:1418:13:1::25]/direct",
7903 "[2001:1418:13:1::25]:80",
7910 "https://www.example.org/direct_ssl",
7911 "ssl/www.example.org:443",
7916 "https://[2001:1418:13:1::25]/direct",
7917 "ssl/[2001:1418:13:1::25]:443",
7922 "http://host.with.alternate/direct",
7923 "ssl/host.with.alternate:443",
7928 session_deps_
.use_alternate_protocols
= true;
7930 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7931 session_deps_
.proxy_service
.reset(
7932 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7933 scoped_refptr
<HttpNetworkSession
> session(
7934 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7936 HttpNetworkSessionPeer
peer(session
);
7937 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7938 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7939 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7940 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7941 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7942 new MockClientSocketPoolManager
);
7943 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7944 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7945 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7947 EXPECT_EQ(ERR_IO_PENDING
,
7948 GroupNameTransactionHelper(tests
[i
].url
, session
));
7950 EXPECT_EQ(tests
[i
].expected_group_name
,
7951 ssl_conn_pool
->last_group_name_received());
7953 EXPECT_EQ(tests
[i
].expected_group_name
,
7954 transport_conn_pool
->last_group_name_received());
7959 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7960 const GroupNameTest tests
[] = {
7963 "http://www.example.org/http_proxy_normal",
7964 "www.example.org:80",
7971 "https://www.example.org/http_connect_ssl",
7972 "ssl/www.example.org:443",
7978 "http://host.with.alternate/direct",
7979 "ssl/host.with.alternate:443",
7985 "ftp://ftp.google.com/http_proxy_normal",
7986 "ftp/ftp.google.com:21",
7991 session_deps_
.use_alternate_protocols
= true;
7993 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7994 session_deps_
.proxy_service
.reset(
7995 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7996 scoped_refptr
<HttpNetworkSession
> session(
7997 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7999 HttpNetworkSessionPeer
peer(session
);
8001 HostPortPair
proxy_host("http_proxy", 80);
8002 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8003 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8004 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8005 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8007 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8008 new MockClientSocketPoolManager
);
8009 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8010 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8011 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8013 EXPECT_EQ(ERR_IO_PENDING
,
8014 GroupNameTransactionHelper(tests
[i
].url
, session
));
8016 EXPECT_EQ(tests
[i
].expected_group_name
,
8017 ssl_conn_pool
->last_group_name_received());
8019 EXPECT_EQ(tests
[i
].expected_group_name
,
8020 http_proxy_pool
->last_group_name_received());
8024 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8025 const GroupNameTest tests
[] = {
8027 "socks4://socks_proxy:1080",
8028 "http://www.example.org/socks4_direct",
8029 "socks4/www.example.org:80",
8033 "socks5://socks_proxy:1080",
8034 "http://www.example.org/socks5_direct",
8035 "socks5/www.example.org:80",
8041 "socks4://socks_proxy:1080",
8042 "https://www.example.org/socks4_ssl",
8043 "socks4/ssl/www.example.org:443",
8047 "socks5://socks_proxy:1080",
8048 "https://www.example.org/socks5_ssl",
8049 "socks5/ssl/www.example.org:443",
8054 "socks4://socks_proxy:1080",
8055 "http://host.with.alternate/direct",
8056 "socks4/ssl/host.with.alternate:443",
8061 session_deps_
.use_alternate_protocols
= true;
8063 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8064 session_deps_
.proxy_service
.reset(
8065 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8066 scoped_refptr
<HttpNetworkSession
> session(
8067 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8069 HttpNetworkSessionPeer
peer(session
);
8071 HostPortPair
proxy_host("socks_proxy", 1080);
8072 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8073 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8074 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8075 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8077 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8078 new MockClientSocketPoolManager
);
8079 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8080 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8081 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8083 scoped_ptr
<HttpTransaction
> trans(
8084 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8086 EXPECT_EQ(ERR_IO_PENDING
,
8087 GroupNameTransactionHelper(tests
[i
].url
, session
));
8089 EXPECT_EQ(tests
[i
].expected_group_name
,
8090 ssl_conn_pool
->last_group_name_received());
8092 EXPECT_EQ(tests
[i
].expected_group_name
,
8093 socks_conn_pool
->last_group_name_received());
8097 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8098 HttpRequestInfo request
;
8099 request
.method
= "GET";
8100 request
.url
= GURL("http://www.example.org/");
8102 session_deps_
.proxy_service
.reset(
8103 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8105 // This simulates failure resolving all hostnames; that means we will fail
8106 // connecting to both proxies (myproxy:70 and foobar:80).
8107 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8109 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8110 scoped_ptr
<HttpTransaction
> trans(
8111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8113 TestCompletionCallback callback
;
8115 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8118 rv
= callback
.WaitForResult();
8119 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8122 // Base test to make sure that when the load flags for a request specify to
8123 // bypass the cache, the DNS cache is not used.
8124 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8126 // Issue a request, asking to bypass the cache(s).
8127 HttpRequestInfo request
;
8128 request
.method
= "GET";
8129 request
.load_flags
= load_flags
;
8130 request
.url
= GURL("http://www.example.org/");
8132 // Select a host resolver that does caching.
8133 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8135 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8136 scoped_ptr
<HttpTransaction
> trans(
8137 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8139 // Warm up the host cache so it has an entry for "www.example.org".
8140 AddressList addrlist
;
8141 TestCompletionCallback callback
;
8142 int rv
= session_deps_
.host_resolver
->Resolve(
8143 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8144 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8145 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8146 rv
= callback
.WaitForResult();
8149 // Verify that it was added to host cache, by doing a subsequent async lookup
8150 // and confirming it completes synchronously.
8151 rv
= session_deps_
.host_resolver
->Resolve(
8152 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8153 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8156 // Inject a failure the next time that "www.example.org" is resolved. This way
8157 // we can tell if the next lookup hit the cache, or the "network".
8158 // (cache --> success, "network" --> failure).
8159 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8161 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8162 // first read -- this won't be reached as the host resolution will fail first.
8163 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8164 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8165 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8168 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8169 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8170 rv
= callback
.WaitForResult();
8172 // If we bypassed the cache, we would have gotten a failure while resolving
8173 // "www.example.org".
8174 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8177 // There are multiple load flags that should trigger the host cache bypass.
8178 // Test each in isolation:
8179 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8180 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8183 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8184 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8187 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8188 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8191 // Make sure we can handle an error when writing the request.
8192 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8193 HttpRequestInfo request
;
8194 request
.method
= "GET";
8195 request
.url
= GURL("http://www.foo.com/");
8196 request
.load_flags
= 0;
8198 MockWrite write_failure
[] = {
8199 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8201 StaticSocketDataProvider
data(NULL
, 0,
8202 write_failure
, arraysize(write_failure
));
8203 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8204 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8206 TestCompletionCallback callback
;
8208 scoped_ptr
<HttpTransaction
> trans(
8209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8211 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8212 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8214 rv
= callback
.WaitForResult();
8215 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8218 // Check that a connection closed after the start of the headers finishes ok.
8219 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8220 HttpRequestInfo request
;
8221 request
.method
= "GET";
8222 request
.url
= GURL("http://www.foo.com/");
8223 request
.load_flags
= 0;
8225 MockRead data_reads
[] = {
8226 MockRead("HTTP/1."),
8227 MockRead(SYNCHRONOUS
, OK
),
8230 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8231 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8232 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8234 TestCompletionCallback callback
;
8236 scoped_ptr
<HttpTransaction
> trans(
8237 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8239 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8240 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8242 rv
= callback
.WaitForResult();
8245 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8246 ASSERT_TRUE(response
!= NULL
);
8248 EXPECT_TRUE(response
->headers
.get() != NULL
);
8249 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8251 std::string response_data
;
8252 rv
= ReadTransaction(trans
.get(), &response_data
);
8254 EXPECT_EQ("", response_data
);
8257 // Make sure that a dropped connection while draining the body for auth
8258 // restart does the right thing.
8259 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8260 HttpRequestInfo request
;
8261 request
.method
= "GET";
8262 request
.url
= GURL("http://www.example.org/");
8263 request
.load_flags
= 0;
8265 MockWrite data_writes1
[] = {
8267 "GET / HTTP/1.1\r\n"
8268 "Host: www.example.org\r\n"
8269 "Connection: keep-alive\r\n\r\n"),
8272 MockRead data_reads1
[] = {
8273 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8274 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8275 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8276 MockRead("Content-Length: 14\r\n\r\n"),
8278 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8281 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8282 data_writes1
, arraysize(data_writes1
));
8283 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8285 // After calling trans->RestartWithAuth(), this is the request we should
8286 // be issuing -- the final header line contains the credentials.
8287 MockWrite data_writes2
[] = {
8289 "GET / HTTP/1.1\r\n"
8290 "Host: www.example.org\r\n"
8291 "Connection: keep-alive\r\n"
8292 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8295 // Lastly, the server responds with the actual content.
8296 MockRead data_reads2
[] = {
8297 MockRead("HTTP/1.1 200 OK\r\n"),
8298 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8299 MockRead("Content-Length: 100\r\n\r\n"),
8300 MockRead(SYNCHRONOUS
, OK
),
8303 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8304 data_writes2
, arraysize(data_writes2
));
8305 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8306 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8308 TestCompletionCallback callback1
;
8310 scoped_ptr
<HttpTransaction
> trans(
8311 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8313 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8314 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8316 rv
= callback1
.WaitForResult();
8319 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8320 ASSERT_TRUE(response
!= NULL
);
8321 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8323 TestCompletionCallback callback2
;
8325 rv
= trans
->RestartWithAuth(
8326 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8327 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8329 rv
= callback2
.WaitForResult();
8332 response
= trans
->GetResponseInfo();
8333 ASSERT_TRUE(response
!= NULL
);
8334 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8335 EXPECT_EQ(100, response
->headers
->GetContentLength());
8338 // Test HTTPS connections going through a proxy that sends extra data.
8339 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8340 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8342 HttpRequestInfo request
;
8343 request
.method
= "GET";
8344 request
.url
= GURL("https://www.example.org/");
8345 request
.load_flags
= 0;
8347 MockRead proxy_reads
[] = {
8348 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8349 MockRead(SYNCHRONOUS
, OK
)
8352 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8353 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8355 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8356 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8358 TestCompletionCallback callback
;
8360 session_deps_
.socket_factory
->ResetNextMockIndexes();
8362 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8363 scoped_ptr
<HttpTransaction
> trans(
8364 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8366 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8367 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8369 rv
= callback
.WaitForResult();
8370 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8373 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8374 HttpRequestInfo request
;
8375 request
.method
= "GET";
8376 request
.url
= GURL("http://www.example.org/");
8377 request
.load_flags
= 0;
8379 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8380 scoped_ptr
<HttpTransaction
> trans(
8381 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8383 MockRead data_reads
[] = {
8384 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8385 MockRead(SYNCHRONOUS
, OK
),
8388 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8389 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8391 TestCompletionCallback callback
;
8393 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8394 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8396 EXPECT_EQ(OK
, callback
.WaitForResult());
8398 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8399 ASSERT_TRUE(response
!= NULL
);
8401 EXPECT_TRUE(response
->headers
.get() != NULL
);
8402 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8404 std::string response_data
;
8405 rv
= ReadTransaction(trans
.get(), &response_data
);
8406 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8409 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8410 base::FilePath temp_file_path
;
8411 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8412 const uint64 kFakeSize
= 100000; // file is actually blank
8413 UploadFileElementReader::ScopedOverridingContentLengthForTests
8414 overriding_content_length(kFakeSize
);
8416 ScopedVector
<UploadElementReader
> element_readers
;
8417 element_readers
.push_back(
8418 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8419 temp_file_path
, 0, kuint64max
, base::Time()));
8420 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8422 HttpRequestInfo request
;
8423 request
.method
= "POST";
8424 request
.url
= GURL("http://www.example.org/upload");
8425 request
.upload_data_stream
= &upload_data_stream
;
8426 request
.load_flags
= 0;
8428 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8429 scoped_ptr
<HttpTransaction
> trans(
8430 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8432 MockRead data_reads
[] = {
8433 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8434 MockRead("hello world"),
8435 MockRead(SYNCHRONOUS
, OK
),
8437 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8438 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8440 TestCompletionCallback callback
;
8442 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8443 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8445 rv
= callback
.WaitForResult();
8448 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8449 ASSERT_TRUE(response
!= NULL
);
8451 EXPECT_TRUE(response
->headers
.get() != NULL
);
8452 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8454 std::string response_data
;
8455 rv
= ReadTransaction(trans
.get(), &response_data
);
8457 EXPECT_EQ("hello world", response_data
);
8459 base::DeleteFile(temp_file_path
, false);
8462 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8463 base::FilePath temp_file
;
8464 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8465 std::string
temp_file_content("Unreadable file.");
8466 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8467 temp_file_content
.length()));
8468 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8470 ScopedVector
<UploadElementReader
> element_readers
;
8471 element_readers
.push_back(
8472 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8473 temp_file
, 0, kuint64max
, base::Time()));
8474 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8476 HttpRequestInfo request
;
8477 request
.method
= "POST";
8478 request
.url
= GURL("http://www.example.org/upload");
8479 request
.upload_data_stream
= &upload_data_stream
;
8480 request
.load_flags
= 0;
8482 // If we try to upload an unreadable file, the transaction should fail.
8483 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8484 scoped_ptr
<HttpTransaction
> trans(
8485 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8487 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8488 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8490 TestCompletionCallback callback
;
8492 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8493 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8495 rv
= callback
.WaitForResult();
8496 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8498 base::DeleteFile(temp_file
, false);
8501 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8502 class FakeUploadElementReader
: public UploadElementReader
{
8504 FakeUploadElementReader() {}
8505 ~FakeUploadElementReader() override
{}
8507 const CompletionCallback
& callback() const { return callback_
; }
8509 // UploadElementReader overrides:
8510 int Init(const CompletionCallback
& callback
) override
{
8511 callback_
= callback
;
8512 return ERR_IO_PENDING
;
8514 uint64
GetContentLength() const override
{ return 0; }
8515 uint64
BytesRemaining() const override
{ return 0; }
8516 int Read(IOBuffer
* buf
,
8518 const CompletionCallback
& callback
) override
{
8523 CompletionCallback callback_
;
8526 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8527 ScopedVector
<UploadElementReader
> element_readers
;
8528 element_readers
.push_back(fake_reader
);
8529 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8531 HttpRequestInfo request
;
8532 request
.method
= "POST";
8533 request
.url
= GURL("http://www.example.org/upload");
8534 request
.upload_data_stream
= &upload_data_stream
;
8535 request
.load_flags
= 0;
8537 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8538 scoped_ptr
<HttpTransaction
> trans(
8539 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8541 StaticSocketDataProvider data
;
8542 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8544 TestCompletionCallback callback
;
8545 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8546 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8547 base::MessageLoop::current()->RunUntilIdle();
8549 // Transaction is pending on request body initialization.
8550 ASSERT_FALSE(fake_reader
->callback().is_null());
8552 // Return Init()'s result after the transaction gets destroyed.
8554 fake_reader
->callback().Run(OK
); // Should not crash.
8557 // Tests that changes to Auth realms are treated like auth rejections.
8558 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8560 HttpRequestInfo request
;
8561 request
.method
= "GET";
8562 request
.url
= GURL("http://www.example.org/");
8563 request
.load_flags
= 0;
8565 // First transaction will request a resource and receive a Basic challenge
8566 // with realm="first_realm".
8567 MockWrite data_writes1
[] = {
8569 "GET / HTTP/1.1\r\n"
8570 "Host: www.example.org\r\n"
8571 "Connection: keep-alive\r\n"
8574 MockRead data_reads1
[] = {
8575 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8576 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8580 // After calling trans->RestartWithAuth(), provide an Authentication header
8581 // for first_realm. The server will reject and provide a challenge with
8583 MockWrite data_writes2
[] = {
8585 "GET / HTTP/1.1\r\n"
8586 "Host: www.example.org\r\n"
8587 "Connection: keep-alive\r\n"
8588 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8591 MockRead data_reads2
[] = {
8592 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8593 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8597 // This again fails, and goes back to first_realm. Make sure that the
8598 // entry is removed from cache.
8599 MockWrite data_writes3
[] = {
8601 "GET / HTTP/1.1\r\n"
8602 "Host: www.example.org\r\n"
8603 "Connection: keep-alive\r\n"
8604 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8607 MockRead data_reads3
[] = {
8608 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8609 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8613 // Try one last time (with the correct password) and get the resource.
8614 MockWrite data_writes4
[] = {
8616 "GET / HTTP/1.1\r\n"
8617 "Host: www.example.org\r\n"
8618 "Connection: keep-alive\r\n"
8619 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8622 MockRead data_reads4
[] = {
8623 MockRead("HTTP/1.1 200 OK\r\n"
8624 "Content-Type: text/html; charset=iso-8859-1\r\n"
8625 "Content-Length: 5\r\n"
8630 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8631 data_writes1
, arraysize(data_writes1
));
8632 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8633 data_writes2
, arraysize(data_writes2
));
8634 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8635 data_writes3
, arraysize(data_writes3
));
8636 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8637 data_writes4
, arraysize(data_writes4
));
8638 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8639 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8640 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8641 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8643 TestCompletionCallback callback1
;
8645 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8646 scoped_ptr
<HttpTransaction
> trans(
8647 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8649 // Issue the first request with Authorize headers. There should be a
8650 // password prompt for first_realm waiting to be filled in after the
8651 // transaction completes.
8652 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8653 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8654 rv
= callback1
.WaitForResult();
8656 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8657 ASSERT_TRUE(response
!= NULL
);
8658 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8659 ASSERT_FALSE(challenge
== NULL
);
8660 EXPECT_FALSE(challenge
->is_proxy
);
8661 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8662 EXPECT_EQ("first_realm", challenge
->realm
);
8663 EXPECT_EQ("basic", challenge
->scheme
);
8665 // Issue the second request with an incorrect password. There should be a
8666 // password prompt for second_realm waiting to be filled in after the
8667 // transaction completes.
8668 TestCompletionCallback callback2
;
8669 rv
= trans
->RestartWithAuth(
8670 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8672 rv
= callback2
.WaitForResult();
8674 response
= trans
->GetResponseInfo();
8675 ASSERT_TRUE(response
!= NULL
);
8676 challenge
= response
->auth_challenge
.get();
8677 ASSERT_FALSE(challenge
== NULL
);
8678 EXPECT_FALSE(challenge
->is_proxy
);
8679 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8680 EXPECT_EQ("second_realm", challenge
->realm
);
8681 EXPECT_EQ("basic", challenge
->scheme
);
8683 // Issue the third request with another incorrect password. There should be
8684 // a password prompt for first_realm waiting to be filled in. If the password
8685 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8686 // first_realm was not correctly removed.
8687 TestCompletionCallback callback3
;
8688 rv
= trans
->RestartWithAuth(
8689 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8690 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8691 rv
= callback3
.WaitForResult();
8693 response
= trans
->GetResponseInfo();
8694 ASSERT_TRUE(response
!= NULL
);
8695 challenge
= response
->auth_challenge
.get();
8696 ASSERT_FALSE(challenge
== NULL
);
8697 EXPECT_FALSE(challenge
->is_proxy
);
8698 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8699 EXPECT_EQ("first_realm", challenge
->realm
);
8700 EXPECT_EQ("basic", challenge
->scheme
);
8702 // Issue the fourth request with the correct password and username.
8703 TestCompletionCallback callback4
;
8704 rv
= trans
->RestartWithAuth(
8705 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8706 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8707 rv
= callback4
.WaitForResult();
8709 response
= trans
->GetResponseInfo();
8710 ASSERT_TRUE(response
!= NULL
);
8711 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8714 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8715 session_deps_
.next_protos
= SpdyNextProtos();
8716 session_deps_
.use_alternate_protocols
= true;
8718 std::string alternate_protocol_http_header
=
8719 GetAlternateProtocolHttpHeader();
8721 MockRead data_reads
[] = {
8722 MockRead("HTTP/1.1 200 OK\r\n"),
8723 MockRead(alternate_protocol_http_header
.c_str()),
8724 MockRead("hello world"),
8725 MockRead(SYNCHRONOUS
, OK
),
8728 HttpRequestInfo request
;
8729 request
.method
= "GET";
8730 request
.url
= GURL("http://www.example.org/");
8731 request
.load_flags
= 0;
8733 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8735 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8737 TestCompletionCallback callback
;
8739 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8740 scoped_ptr
<HttpTransaction
> trans(
8741 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8743 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8744 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8746 HostPortPair
http_host_port_pair("www.example.org", 80);
8747 HttpServerProperties
& http_server_properties
=
8748 *session
->http_server_properties();
8749 AlternativeServiceVector alternative_service_vector
=
8750 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8751 EXPECT_TRUE(alternative_service_vector
.empty());
8753 EXPECT_EQ(OK
, callback
.WaitForResult());
8755 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8756 ASSERT_TRUE(response
!= NULL
);
8757 ASSERT_TRUE(response
->headers
.get() != NULL
);
8758 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8759 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8760 EXPECT_FALSE(response
->was_npn_negotiated
);
8762 std::string response_data
;
8763 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8764 EXPECT_EQ("hello world", response_data
);
8766 alternative_service_vector
=
8767 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8768 ASSERT_EQ(1u, alternative_service_vector
.size());
8769 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8770 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8771 alternative_service_vector
[0].protocol
);
8774 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8775 session_deps_
.next_protos
= SpdyNextProtos();
8776 session_deps_
.use_alternate_protocols
= true;
8778 MockRead data_reads
[] = {
8779 MockRead("HTTP/1.1 200 OK\r\n"),
8780 MockRead("Alternate-Protocol: \r\n\r\n"),
8781 MockRead("hello world"),
8782 MockRead(SYNCHRONOUS
, OK
),
8785 HttpRequestInfo request
;
8786 request
.method
= "GET";
8787 request
.url
= GURL("http://www.example.org/");
8788 request
.load_flags
= 0;
8790 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8792 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8794 TestCompletionCallback callback
;
8796 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8798 HostPortPair
http_host_port_pair("www.example.org", 80);
8799 HttpServerProperties
& http_server_properties
=
8800 *session
->http_server_properties();
8801 AlternativeService
alternative_service(QUIC
, "", 80);
8802 http_server_properties
.SetAlternativeService(http_host_port_pair
,
8803 alternative_service
, 1.0);
8805 AlternativeServiceVector alternative_service_vector
=
8806 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8807 ASSERT_EQ(1u, alternative_service_vector
.size());
8808 EXPECT_EQ(QUIC
, alternative_service_vector
[0].protocol
);
8810 scoped_ptr
<HttpTransaction
> trans(
8811 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8813 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8814 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8816 EXPECT_EQ(OK
, callback
.WaitForResult());
8818 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8819 ASSERT_TRUE(response
!= NULL
);
8820 ASSERT_TRUE(response
->headers
.get() != NULL
);
8821 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8822 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8823 EXPECT_FALSE(response
->was_npn_negotiated
);
8825 std::string response_data
;
8826 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8827 EXPECT_EQ("hello world", response_data
);
8829 alternative_service_vector
=
8830 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8831 EXPECT_TRUE(alternative_service_vector
.empty());
8834 TEST_P(HttpNetworkTransactionTest
,
8835 MarkBrokenAlternateProtocolAndFallback
) {
8836 session_deps_
.use_alternate_protocols
= true;
8838 HttpRequestInfo request
;
8839 request
.method
= "GET";
8840 request
.url
= GURL("http://www.example.org/");
8841 request
.load_flags
= 0;
8843 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8844 StaticSocketDataProvider first_data
;
8845 first_data
.set_connect_data(mock_connect
);
8846 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8848 MockRead data_reads
[] = {
8849 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8850 MockRead("hello world"),
8851 MockRead(ASYNC
, OK
),
8853 StaticSocketDataProvider
second_data(
8854 data_reads
, arraysize(data_reads
), NULL
, 0);
8855 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8857 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8859 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8860 session
->http_server_properties();
8861 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
8862 // Port must be < 1024, or the header will be ignored (since initial port was
8863 // port 80 (another restricted port).
8864 const AlternativeService
alternative_service(
8865 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8866 666); // Port is ignored by MockConnect anyway.
8867 http_server_properties
->SetAlternativeService(host_port_pair
,
8868 alternative_service
, 1.0);
8870 scoped_ptr
<HttpTransaction
> trans(
8871 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8872 TestCompletionCallback callback
;
8874 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8875 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8876 EXPECT_EQ(OK
, callback
.WaitForResult());
8878 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8879 ASSERT_TRUE(response
!= NULL
);
8880 ASSERT_TRUE(response
->headers
.get() != NULL
);
8881 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8883 std::string response_data
;
8884 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8885 EXPECT_EQ("hello world", response_data
);
8887 const AlternativeServiceVector alternative_service_vector
=
8888 http_server_properties
->GetAlternativeServices(host_port_pair
);
8889 ASSERT_EQ(1u, alternative_service_vector
.size());
8890 EXPECT_EQ(alternative_service
, alternative_service_vector
[0]);
8891 EXPECT_TRUE(http_server_properties
->IsAlternativeServiceBroken(
8892 alternative_service_vector
[0]));
8895 TEST_P(HttpNetworkTransactionTest
,
8896 AlternateProtocolPortRestrictedBlocked
) {
8897 // Ensure that we're not allowed to redirect traffic via an alternate
8898 // protocol to an unrestricted (port >= 1024) when the original traffic was
8899 // on a restricted port (port < 1024). Ensure that we can redirect in all
8901 session_deps_
.use_alternate_protocols
= true;
8903 HttpRequestInfo restricted_port_request
;
8904 restricted_port_request
.method
= "GET";
8905 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8906 restricted_port_request
.load_flags
= 0;
8908 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8909 StaticSocketDataProvider first_data
;
8910 first_data
.set_connect_data(mock_connect
);
8911 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8913 MockRead data_reads
[] = {
8914 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8915 MockRead("hello world"),
8916 MockRead(ASYNC
, OK
),
8918 StaticSocketDataProvider
second_data(
8919 data_reads
, arraysize(data_reads
), NULL
, 0);
8920 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8922 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8924 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8925 session
->http_server_properties();
8926 const int kUnrestrictedAlternatePort
= 1024;
8927 AlternativeService
alternative_service(
8928 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8929 kUnrestrictedAlternatePort
);
8930 http_server_properties
->SetAlternativeService(
8931 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8934 scoped_ptr
<HttpTransaction
> trans(
8935 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8936 TestCompletionCallback callback
;
8938 int rv
= trans
->Start(
8939 &restricted_port_request
,
8940 callback
.callback(), BoundNetLog());
8941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8942 // Invalid change to unrestricted port should fail.
8943 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8946 TEST_P(HttpNetworkTransactionTest
,
8947 AlternateProtocolPortRestrictedPermitted
) {
8948 // Ensure that we're allowed to redirect traffic via an alternate
8949 // protocol to an unrestricted (port >= 1024) when the original traffic was
8950 // on a restricted port (port < 1024) if we set
8951 // enable_user_alternate_protocol_ports.
8953 session_deps_
.use_alternate_protocols
= true;
8954 session_deps_
.enable_user_alternate_protocol_ports
= true;
8956 HttpRequestInfo restricted_port_request
;
8957 restricted_port_request
.method
= "GET";
8958 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8959 restricted_port_request
.load_flags
= 0;
8961 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8962 StaticSocketDataProvider first_data
;
8963 first_data
.set_connect_data(mock_connect
);
8964 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8966 MockRead data_reads
[] = {
8967 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8968 MockRead("hello world"),
8969 MockRead(ASYNC
, OK
),
8971 StaticSocketDataProvider
second_data(
8972 data_reads
, arraysize(data_reads
), NULL
, 0);
8973 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8975 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8977 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8978 session
->http_server_properties();
8979 const int kUnrestrictedAlternatePort
= 1024;
8980 AlternativeService
alternative_service(
8981 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8982 kUnrestrictedAlternatePort
);
8983 http_server_properties
->SetAlternativeService(
8984 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8987 scoped_ptr
<HttpTransaction
> trans(
8988 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8989 TestCompletionCallback callback
;
8991 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
8992 &restricted_port_request
,
8993 callback
.callback(), BoundNetLog()));
8994 // Change to unrestricted port should succeed.
8995 EXPECT_EQ(OK
, callback
.WaitForResult());
8998 TEST_P(HttpNetworkTransactionTest
,
8999 AlternateProtocolPortRestrictedAllowed
) {
9000 // Ensure that we're not allowed to redirect traffic via an alternate
9001 // protocol to an unrestricted (port >= 1024) when the original traffic was
9002 // on a restricted port (port < 1024). Ensure that we can redirect in all
9004 session_deps_
.use_alternate_protocols
= true;
9006 HttpRequestInfo restricted_port_request
;
9007 restricted_port_request
.method
= "GET";
9008 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9009 restricted_port_request
.load_flags
= 0;
9011 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9012 StaticSocketDataProvider first_data
;
9013 first_data
.set_connect_data(mock_connect
);
9014 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9016 MockRead data_reads
[] = {
9017 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9018 MockRead("hello world"),
9019 MockRead(ASYNC
, OK
),
9021 StaticSocketDataProvider
second_data(
9022 data_reads
, arraysize(data_reads
), NULL
, 0);
9023 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9025 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9027 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9028 session
->http_server_properties();
9029 const int kRestrictedAlternatePort
= 80;
9030 AlternativeService
alternative_service(
9031 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9032 kRestrictedAlternatePort
);
9033 http_server_properties
->SetAlternativeService(
9034 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9037 scoped_ptr
<HttpTransaction
> trans(
9038 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9039 TestCompletionCallback callback
;
9041 int rv
= trans
->Start(
9042 &restricted_port_request
,
9043 callback
.callback(), BoundNetLog());
9044 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9045 // Valid change to restricted port should pass.
9046 EXPECT_EQ(OK
, callback
.WaitForResult());
9049 TEST_P(HttpNetworkTransactionTest
,
9050 AlternateProtocolPortUnrestrictedAllowed1
) {
9051 // Ensure that we're not allowed to redirect traffic via an alternate
9052 // protocol to an unrestricted (port >= 1024) when the original traffic was
9053 // on a restricted port (port < 1024). Ensure that we can redirect in all
9055 session_deps_
.use_alternate_protocols
= true;
9057 HttpRequestInfo unrestricted_port_request
;
9058 unrestricted_port_request
.method
= "GET";
9059 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9060 unrestricted_port_request
.load_flags
= 0;
9062 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9063 StaticSocketDataProvider first_data
;
9064 first_data
.set_connect_data(mock_connect
);
9065 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9067 MockRead data_reads
[] = {
9068 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9069 MockRead("hello world"),
9070 MockRead(ASYNC
, OK
),
9072 StaticSocketDataProvider
second_data(
9073 data_reads
, arraysize(data_reads
), NULL
, 0);
9074 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9078 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9079 session
->http_server_properties();
9080 const int kRestrictedAlternatePort
= 80;
9081 AlternativeService
alternative_service(
9082 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9083 kRestrictedAlternatePort
);
9084 http_server_properties
->SetAlternativeService(
9085 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9088 scoped_ptr
<HttpTransaction
> trans(
9089 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9090 TestCompletionCallback callback
;
9092 int rv
= trans
->Start(
9093 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9094 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9095 // Valid change to restricted port should pass.
9096 EXPECT_EQ(OK
, callback
.WaitForResult());
9099 TEST_P(HttpNetworkTransactionTest
,
9100 AlternateProtocolPortUnrestrictedAllowed2
) {
9101 // Ensure that we're not allowed to redirect traffic via an alternate
9102 // protocol to an unrestricted (port >= 1024) when the original traffic was
9103 // on a restricted port (port < 1024). Ensure that we can redirect in all
9105 session_deps_
.use_alternate_protocols
= true;
9107 HttpRequestInfo unrestricted_port_request
;
9108 unrestricted_port_request
.method
= "GET";
9109 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9110 unrestricted_port_request
.load_flags
= 0;
9112 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9113 StaticSocketDataProvider first_data
;
9114 first_data
.set_connect_data(mock_connect
);
9115 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9117 MockRead data_reads
[] = {
9118 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9119 MockRead("hello world"),
9120 MockRead(ASYNC
, OK
),
9122 StaticSocketDataProvider
second_data(
9123 data_reads
, arraysize(data_reads
), NULL
, 0);
9124 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9126 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9128 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9129 session
->http_server_properties();
9130 const int kUnrestrictedAlternatePort
= 1025;
9131 AlternativeService
alternative_service(
9132 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9133 kUnrestrictedAlternatePort
);
9134 http_server_properties
->SetAlternativeService(
9135 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9138 scoped_ptr
<HttpTransaction
> trans(
9139 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9140 TestCompletionCallback callback
;
9142 int rv
= trans
->Start(
9143 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9145 // Valid change to an unrestricted port should pass.
9146 EXPECT_EQ(OK
, callback
.WaitForResult());
9149 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9150 // Ensure that we're not allowed to redirect traffic via an alternate
9151 // protocol to an unsafe port, and that we resume the second
9152 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9153 session_deps_
.use_alternate_protocols
= true;
9155 HttpRequestInfo request
;
9156 request
.method
= "GET";
9157 request
.url
= GURL("http://www.example.org/");
9158 request
.load_flags
= 0;
9160 // The alternate protocol request will error out before we attempt to connect,
9161 // so only the standard HTTP request will try to connect.
9162 MockRead data_reads
[] = {
9163 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9164 MockRead("hello world"),
9165 MockRead(ASYNC
, OK
),
9167 StaticSocketDataProvider
data(
9168 data_reads
, arraysize(data_reads
), NULL
, 0);
9169 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9171 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9173 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9174 session
->http_server_properties();
9175 const int kUnsafePort
= 7;
9176 AlternativeService
alternative_service(
9177 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9179 http_server_properties
->SetAlternativeService(
9180 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0);
9182 scoped_ptr
<HttpTransaction
> trans(
9183 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9184 TestCompletionCallback callback
;
9186 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9187 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9188 // The HTTP request should succeed.
9189 EXPECT_EQ(OK
, callback
.WaitForResult());
9191 // Disable alternate protocol before the asserts.
9192 // HttpStreamFactory::set_use_alternate_protocols(false);
9194 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9195 ASSERT_TRUE(response
!= NULL
);
9196 ASSERT_TRUE(response
->headers
.get() != NULL
);
9197 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9199 std::string response_data
;
9200 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9201 EXPECT_EQ("hello world", response_data
);
9204 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9205 session_deps_
.use_alternate_protocols
= true;
9206 session_deps_
.next_protos
= SpdyNextProtos();
9208 HttpRequestInfo request
;
9209 request
.method
= "GET";
9210 request
.url
= GURL("http://www.example.org/");
9211 request
.load_flags
= 0;
9213 std::string alternate_protocol_http_header
=
9214 GetAlternateProtocolHttpHeader();
9216 MockRead data_reads
[] = {
9217 MockRead("HTTP/1.1 200 OK\r\n"),
9218 MockRead(alternate_protocol_http_header
.c_str()),
9219 MockRead("hello world"),
9220 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9224 StaticSocketDataProvider
first_transaction(
9225 data_reads
, arraysize(data_reads
), NULL
, 0);
9226 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9228 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9229 ssl
.SetNextProto(GetParam());
9230 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9231 ASSERT_TRUE(ssl
.cert
.get());
9232 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9234 scoped_ptr
<SpdyFrame
> req(
9235 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9236 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9238 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9239 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9240 MockRead spdy_reads
[] = {
9241 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9244 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9245 arraysize(spdy_writes
));
9246 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9248 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9249 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9251 hanging_non_alternate_protocol_socket
.set_connect_data(
9252 never_finishing_connect
);
9253 session_deps_
.socket_factory
->AddSocketDataProvider(
9254 &hanging_non_alternate_protocol_socket
);
9256 TestCompletionCallback callback
;
9258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9259 scoped_ptr
<HttpTransaction
> trans(
9260 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9262 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9263 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9264 EXPECT_EQ(OK
, callback
.WaitForResult());
9266 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9267 ASSERT_TRUE(response
!= NULL
);
9268 ASSERT_TRUE(response
->headers
.get() != NULL
);
9269 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9271 std::string response_data
;
9272 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9273 EXPECT_EQ("hello world", response_data
);
9275 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9277 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9278 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9279 EXPECT_EQ(OK
, callback
.WaitForResult());
9281 response
= trans
->GetResponseInfo();
9282 ASSERT_TRUE(response
!= NULL
);
9283 ASSERT_TRUE(response
->headers
.get() != NULL
);
9284 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9285 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9286 EXPECT_TRUE(response
->was_npn_negotiated
);
9288 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9289 EXPECT_EQ("hello!", response_data
);
9292 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9293 session_deps_
.use_alternate_protocols
= true;
9294 session_deps_
.next_protos
= SpdyNextProtos();
9296 HttpRequestInfo request
;
9297 request
.method
= "GET";
9298 request
.url
= GURL("http://www.example.org/");
9299 request
.load_flags
= 0;
9301 std::string alternate_protocol_http_header
=
9302 GetAlternateProtocolHttpHeader();
9304 MockRead data_reads
[] = {
9305 MockRead("HTTP/1.1 200 OK\r\n"),
9306 MockRead(alternate_protocol_http_header
.c_str()),
9307 MockRead("hello world"),
9308 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9309 MockRead(ASYNC
, OK
),
9312 StaticSocketDataProvider
first_transaction(
9313 data_reads
, arraysize(data_reads
), NULL
, 0);
9314 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9315 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9317 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9318 StaticSocketDataProvider
hanging_socket(
9320 hanging_socket
.set_connect_data(never_finishing_connect
);
9321 // Socket 2 and 3 are the hanging Alternate-Protocol and
9322 // non-Alternate-Protocol jobs from the 2nd transaction.
9323 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9324 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9326 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9327 ssl
.SetNextProto(GetParam());
9328 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9329 ASSERT_TRUE(ssl
.cert
.get());
9330 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9332 scoped_ptr
<SpdyFrame
> req1(
9333 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9334 scoped_ptr
<SpdyFrame
> req2(
9335 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9336 MockWrite spdy_writes
[] = {
9337 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9339 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9340 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9341 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9342 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9343 MockRead spdy_reads
[] = {
9344 CreateMockRead(*resp1
, 2),
9345 CreateMockRead(*data1
, 3),
9346 CreateMockRead(*resp2
, 4),
9347 CreateMockRead(*data2
, 5),
9348 MockRead(ASYNC
, 0, 6),
9351 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9352 arraysize(spdy_writes
));
9353 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9354 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9356 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9357 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9359 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9360 TestCompletionCallback callback1
;
9361 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9363 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9364 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9365 EXPECT_EQ(OK
, callback1
.WaitForResult());
9367 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9368 ASSERT_TRUE(response
!= NULL
);
9369 ASSERT_TRUE(response
->headers
.get() != NULL
);
9370 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9372 std::string response_data
;
9373 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9374 EXPECT_EQ("hello world", response_data
);
9376 TestCompletionCallback callback2
;
9377 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9378 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9379 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9381 TestCompletionCallback callback3
;
9382 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9383 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9384 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9386 EXPECT_EQ(OK
, callback2
.WaitForResult());
9387 EXPECT_EQ(OK
, callback3
.WaitForResult());
9389 response
= trans2
.GetResponseInfo();
9390 ASSERT_TRUE(response
!= NULL
);
9391 ASSERT_TRUE(response
->headers
.get() != NULL
);
9392 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9393 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9394 EXPECT_TRUE(response
->was_npn_negotiated
);
9395 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9396 EXPECT_EQ("hello!", response_data
);
9398 response
= trans3
.GetResponseInfo();
9399 ASSERT_TRUE(response
!= NULL
);
9400 ASSERT_TRUE(response
->headers
.get() != NULL
);
9401 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9402 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9403 EXPECT_TRUE(response
->was_npn_negotiated
);
9404 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9405 EXPECT_EQ("hello!", response_data
);
9408 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9409 session_deps_
.use_alternate_protocols
= true;
9410 session_deps_
.next_protos
= SpdyNextProtos();
9412 HttpRequestInfo request
;
9413 request
.method
= "GET";
9414 request
.url
= GURL("http://www.example.org/");
9415 request
.load_flags
= 0;
9417 std::string alternate_protocol_http_header
=
9418 GetAlternateProtocolHttpHeader();
9420 MockRead data_reads
[] = {
9421 MockRead("HTTP/1.1 200 OK\r\n"),
9422 MockRead(alternate_protocol_http_header
.c_str()),
9423 MockRead("hello world"),
9424 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9425 MockRead(ASYNC
, OK
),
9428 StaticSocketDataProvider
first_transaction(
9429 data_reads
, arraysize(data_reads
), NULL
, 0);
9430 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9432 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9433 ssl
.SetNextProto(GetParam());
9434 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9436 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9437 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9439 hanging_alternate_protocol_socket
.set_connect_data(
9440 never_finishing_connect
);
9441 session_deps_
.socket_factory
->AddSocketDataProvider(
9442 &hanging_alternate_protocol_socket
);
9444 // 2nd request is just a copy of the first one, over HTTP again.
9445 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9447 TestCompletionCallback callback
;
9449 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9450 scoped_ptr
<HttpTransaction
> trans(
9451 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9453 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9455 EXPECT_EQ(OK
, callback
.WaitForResult());
9457 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9458 ASSERT_TRUE(response
!= NULL
);
9459 ASSERT_TRUE(response
->headers
.get() != NULL
);
9460 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9462 std::string response_data
;
9463 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9464 EXPECT_EQ("hello world", response_data
);
9466 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9468 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9469 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9470 EXPECT_EQ(OK
, callback
.WaitForResult());
9472 response
= trans
->GetResponseInfo();
9473 ASSERT_TRUE(response
!= NULL
);
9474 ASSERT_TRUE(response
->headers
.get() != NULL
);
9475 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9476 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9477 EXPECT_FALSE(response
->was_npn_negotiated
);
9479 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9480 EXPECT_EQ("hello world", response_data
);
9483 class CapturingProxyResolver
: public ProxyResolver
{
9485 CapturingProxyResolver() {}
9486 ~CapturingProxyResolver() override
{}
9488 int GetProxyForURL(const GURL
& url
,
9490 const CompletionCallback
& callback
,
9491 RequestHandle
* request
,
9492 const BoundNetLog
& net_log
) override
{
9493 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9494 HostPortPair("myproxy", 80));
9495 results
->UseProxyServer(proxy_server
);
9496 resolved_
.push_back(url
);
9500 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9502 LoadState
GetLoadState(RequestHandle request
) const override
{
9504 return LOAD_STATE_IDLE
;
9507 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9510 std::vector
<GURL
> resolved_
;
9512 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9515 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9517 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9518 : ProxyResolverFactory(false), resolver_(resolver
) {}
9520 int CreateProxyResolver(
9521 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9522 scoped_ptr
<ProxyResolver
>* resolver
,
9523 const net::CompletionCallback
& callback
,
9524 scoped_ptr
<Request
>* request
) override
{
9525 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9530 ProxyResolver
* resolver_
;
9533 TEST_P(HttpNetworkTransactionTest
,
9534 UseAlternateProtocolForTunneledNpnSpdy
) {
9535 session_deps_
.use_alternate_protocols
= true;
9536 session_deps_
.next_protos
= SpdyNextProtos();
9538 ProxyConfig proxy_config
;
9539 proxy_config
.set_auto_detect(true);
9540 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9542 CapturingProxyResolver capturing_proxy_resolver
;
9543 session_deps_
.proxy_service
.reset(new ProxyService(
9544 new ProxyConfigServiceFixed(proxy_config
),
9546 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9549 session_deps_
.net_log
= &net_log
;
9551 HttpRequestInfo request
;
9552 request
.method
= "GET";
9553 request
.url
= GURL("http://www.example.org/");
9554 request
.load_flags
= 0;
9556 std::string alternate_protocol_http_header
=
9557 GetAlternateProtocolHttpHeader();
9559 MockRead data_reads
[] = {
9560 MockRead("HTTP/1.1 200 OK\r\n"),
9561 MockRead(alternate_protocol_http_header
.c_str()),
9562 MockRead("hello world"),
9563 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9564 MockRead(ASYNC
, OK
),
9567 StaticSocketDataProvider
first_transaction(
9568 data_reads
, arraysize(data_reads
), NULL
, 0);
9569 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9571 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9572 ssl
.SetNextProto(GetParam());
9573 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9574 ASSERT_TRUE(ssl
.cert
.get());
9575 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9577 scoped_ptr
<SpdyFrame
> req(
9578 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9579 MockWrite spdy_writes
[] = {
9581 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9582 "Host: www.example.org\r\n"
9583 "Proxy-Connection: keep-alive\r\n\r\n"),
9584 CreateMockWrite(*req
, 2),
9587 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9589 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9590 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9591 MockRead spdy_reads
[] = {
9592 MockRead(ASYNC
, 1, kCONNECTResponse
),
9593 CreateMockRead(*resp
.get(), 3),
9594 CreateMockRead(*data
.get(), 4),
9595 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
9598 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9599 arraysize(spdy_writes
));
9600 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9602 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9603 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9605 hanging_non_alternate_protocol_socket
.set_connect_data(
9606 never_finishing_connect
);
9607 session_deps_
.socket_factory
->AddSocketDataProvider(
9608 &hanging_non_alternate_protocol_socket
);
9610 TestCompletionCallback callback
;
9612 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9613 scoped_ptr
<HttpTransaction
> trans(
9614 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9616 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9617 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9618 EXPECT_EQ(OK
, callback
.WaitForResult());
9620 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9621 ASSERT_TRUE(response
!= NULL
);
9622 ASSERT_TRUE(response
->headers
.get() != NULL
);
9623 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9624 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9625 EXPECT_FALSE(response
->was_npn_negotiated
);
9627 std::string response_data
;
9628 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9629 EXPECT_EQ("hello world", response_data
);
9631 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9633 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9634 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9635 EXPECT_EQ(OK
, callback
.WaitForResult());
9637 response
= trans
->GetResponseInfo();
9638 ASSERT_TRUE(response
!= NULL
);
9639 ASSERT_TRUE(response
->headers
.get() != NULL
);
9640 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9641 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9642 EXPECT_TRUE(response
->was_npn_negotiated
);
9644 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9645 EXPECT_EQ("hello!", response_data
);
9646 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9647 EXPECT_EQ("http://www.example.org/",
9648 capturing_proxy_resolver
.resolved()[0].spec());
9649 EXPECT_EQ("https://www.example.org/",
9650 capturing_proxy_resolver
.resolved()[1].spec());
9652 LoadTimingInfo load_timing_info
;
9653 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9654 TestLoadTimingNotReusedWithPac(load_timing_info
,
9655 CONNECT_TIMING_HAS_SSL_TIMES
);
9658 TEST_P(HttpNetworkTransactionTest
,
9659 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9660 session_deps_
.use_alternate_protocols
= true;
9661 session_deps_
.next_protos
= SpdyNextProtos();
9663 HttpRequestInfo request
;
9664 request
.method
= "GET";
9665 request
.url
= GURL("http://www.example.org/");
9666 request
.load_flags
= 0;
9668 std::string alternate_protocol_http_header
=
9669 GetAlternateProtocolHttpHeader();
9671 MockRead data_reads
[] = {
9672 MockRead("HTTP/1.1 200 OK\r\n"),
9673 MockRead(alternate_protocol_http_header
.c_str()),
9674 MockRead("hello world"),
9675 MockRead(ASYNC
, OK
),
9678 StaticSocketDataProvider
first_transaction(
9679 data_reads
, arraysize(data_reads
), NULL
, 0);
9680 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9682 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9683 ssl
.SetNextProto(GetParam());
9684 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9685 ASSERT_TRUE(ssl
.cert
.get());
9686 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9688 scoped_ptr
<SpdyFrame
> req(
9689 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9690 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9692 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9693 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9694 MockRead spdy_reads
[] = {
9695 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9698 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9699 arraysize(spdy_writes
));
9700 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9702 TestCompletionCallback callback
;
9704 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9706 scoped_ptr
<HttpTransaction
> trans(
9707 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9709 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9710 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9711 EXPECT_EQ(OK
, callback
.WaitForResult());
9713 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9714 ASSERT_TRUE(response
!= NULL
);
9715 ASSERT_TRUE(response
->headers
.get() != NULL
);
9716 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9718 std::string response_data
;
9719 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9720 EXPECT_EQ("hello world", response_data
);
9722 // Set up an initial SpdySession in the pool to reuse.
9723 HostPortPair
host_port_pair("www.example.org", 443);
9724 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9725 PRIVACY_MODE_DISABLED
);
9726 base::WeakPtr
<SpdySession
> spdy_session
=
9727 CreateSecureSpdySession(session
, key
, BoundNetLog());
9729 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9731 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9733 EXPECT_EQ(OK
, callback
.WaitForResult());
9735 response
= trans
->GetResponseInfo();
9736 ASSERT_TRUE(response
!= NULL
);
9737 ASSERT_TRUE(response
->headers
.get() != NULL
);
9738 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9739 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9740 EXPECT_TRUE(response
->was_npn_negotiated
);
9742 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9743 EXPECT_EQ("hello!", response_data
);
9746 // GenerateAuthToken is a mighty big test.
9747 // It tests all permutation of GenerateAuthToken behavior:
9748 // - Synchronous and Asynchronous completion.
9749 // - OK or error on completion.
9750 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9751 // - HTTP or HTTPS backend (to include proxy tunneling).
9752 // - Non-authenticating and authenticating backend.
9754 // In all, there are 44 reasonable permuations (for example, if there are
9755 // problems generating an auth token for an authenticating proxy, we don't
9756 // need to test all permutations of the backend server).
9758 // The test proceeds by going over each of the configuration cases, and
9759 // potentially running up to three rounds in each of the tests. The TestConfig
9760 // specifies both the configuration for the test as well as the expectations
9762 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9763 static const char kServer
[] = "http://www.example.com";
9764 static const char kSecureServer
[] = "https://www.example.com";
9765 static const char kProxy
[] = "myproxy:70";
9766 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9774 const MockWrite
kGet(
9775 "GET / HTTP/1.1\r\n"
9776 "Host: www.example.com\r\n"
9777 "Connection: keep-alive\r\n\r\n");
9778 const MockWrite
kGetProxy(
9779 "GET http://www.example.com/ HTTP/1.1\r\n"
9780 "Host: www.example.com\r\n"
9781 "Proxy-Connection: keep-alive\r\n\r\n");
9782 const MockWrite
kGetAuth(
9783 "GET / HTTP/1.1\r\n"
9784 "Host: www.example.com\r\n"
9785 "Connection: keep-alive\r\n"
9786 "Authorization: auth_token\r\n\r\n");
9787 const MockWrite
kGetProxyAuth(
9788 "GET http://www.example.com/ HTTP/1.1\r\n"
9789 "Host: www.example.com\r\n"
9790 "Proxy-Connection: keep-alive\r\n"
9791 "Proxy-Authorization: auth_token\r\n\r\n");
9792 const MockWrite
kGetAuthThroughProxy(
9793 "GET http://www.example.com/ HTTP/1.1\r\n"
9794 "Host: www.example.com\r\n"
9795 "Proxy-Connection: keep-alive\r\n"
9796 "Authorization: auth_token\r\n\r\n");
9797 const MockWrite
kGetAuthWithProxyAuth(
9798 "GET http://www.example.com/ HTTP/1.1\r\n"
9799 "Host: www.example.com\r\n"
9800 "Proxy-Connection: keep-alive\r\n"
9801 "Proxy-Authorization: auth_token\r\n"
9802 "Authorization: auth_token\r\n\r\n");
9803 const MockWrite
kConnect(
9804 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9805 "Host: www.example.com\r\n"
9806 "Proxy-Connection: keep-alive\r\n\r\n");
9807 const MockWrite
kConnectProxyAuth(
9808 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9809 "Host: www.example.com\r\n"
9810 "Proxy-Connection: keep-alive\r\n"
9811 "Proxy-Authorization: auth_token\r\n\r\n");
9813 const MockRead
kSuccess(
9814 "HTTP/1.1 200 OK\r\n"
9815 "Content-Type: text/html; charset=iso-8859-1\r\n"
9816 "Content-Length: 3\r\n\r\n"
9818 const MockRead
kFailure(
9819 "Should not be called.");
9820 const MockRead
kServerChallenge(
9821 "HTTP/1.1 401 Unauthorized\r\n"
9822 "WWW-Authenticate: Mock realm=server\r\n"
9823 "Content-Type: text/html; charset=iso-8859-1\r\n"
9824 "Content-Length: 14\r\n\r\n"
9825 "Unauthorized\r\n");
9826 const MockRead
kProxyChallenge(
9827 "HTTP/1.1 407 Unauthorized\r\n"
9828 "Proxy-Authenticate: Mock realm=proxy\r\n"
9829 "Proxy-Connection: close\r\n"
9830 "Content-Type: text/html; charset=iso-8859-1\r\n"
9831 "Content-Length: 14\r\n\r\n"
9832 "Unauthorized\r\n");
9833 const MockRead
kProxyConnected(
9834 "HTTP/1.1 200 Connection Established\r\n\r\n");
9836 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9837 // no constructors, but the C++ compiler on Windows warns about
9838 // unspecified data in compound literals. So, moved to using constructors,
9839 // and TestRound's created with the default constructor should not be used.
9842 : expected_rv(ERR_UNEXPECTED
),
9846 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9847 int expected_rv_arg
)
9850 expected_rv(expected_rv_arg
),
9854 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9855 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9856 const MockRead
* extra_read_arg
)
9859 expected_rv(expected_rv_arg
),
9860 extra_write(extra_write_arg
),
9861 extra_read(extra_read_arg
) {
9866 const MockWrite
* extra_write
;
9867 const MockRead
* extra_read
;
9870 static const int kNoSSL
= 500;
9873 const char* const proxy_url
;
9874 AuthTiming proxy_auth_timing
;
9876 const char* const server_url
;
9877 AuthTiming server_auth_timing
;
9879 int num_auth_rounds
;
9880 int first_ssl_round
;
9881 TestRound rounds
[3];
9882 } test_configs
[] = {
9883 // Non-authenticating HTTP server with a direct connection.
9884 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9885 { TestRound(kGet
, kSuccess
, OK
)}},
9886 // Authenticating HTTP server with a direct connection.
9887 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9888 { TestRound(kGet
, kServerChallenge
, OK
),
9889 TestRound(kGetAuth
, kSuccess
, OK
)}},
9890 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9891 { TestRound(kGet
, kServerChallenge
, OK
),
9892 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9893 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9894 { TestRound(kGet
, kServerChallenge
, OK
),
9895 TestRound(kGetAuth
, kSuccess
, OK
)}},
9896 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9897 { TestRound(kGet
, kServerChallenge
, OK
),
9898 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9899 // Non-authenticating HTTP server through a non-authenticating proxy.
9900 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9901 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9902 // Authenticating HTTP server through a non-authenticating proxy.
9903 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9904 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9905 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9906 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9907 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9908 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9909 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9910 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9911 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9912 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9913 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9914 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9915 // Non-authenticating HTTP server through an authenticating proxy.
9916 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9917 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9918 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9919 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9920 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9921 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9922 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9923 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9924 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9925 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9926 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9927 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9928 // Authenticating HTTP server through an authenticating proxy.
9929 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9930 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9931 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9932 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9933 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9934 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9935 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9936 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9937 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9938 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9939 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9940 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9941 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9942 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9943 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9944 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9945 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9946 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9947 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9948 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9949 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9950 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9951 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9952 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9953 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9954 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9955 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9956 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9957 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9958 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9959 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9960 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9961 // Non-authenticating HTTPS server with a direct connection.
9962 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9963 { TestRound(kGet
, kSuccess
, OK
)}},
9964 // Authenticating HTTPS server with a direct connection.
9965 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9966 { TestRound(kGet
, kServerChallenge
, OK
),
9967 TestRound(kGetAuth
, kSuccess
, OK
)}},
9968 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9969 { TestRound(kGet
, kServerChallenge
, OK
),
9970 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9971 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9972 { TestRound(kGet
, kServerChallenge
, OK
),
9973 TestRound(kGetAuth
, kSuccess
, OK
)}},
9974 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9975 { TestRound(kGet
, kServerChallenge
, OK
),
9976 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9977 // Non-authenticating HTTPS server with a non-authenticating proxy.
9978 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9979 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9980 // Authenticating HTTPS server through a non-authenticating proxy.
9981 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
9982 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9983 TestRound(kGetAuth
, kSuccess
, OK
)}},
9984 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
9985 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9986 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9987 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
9988 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9989 TestRound(kGetAuth
, kSuccess
, OK
)}},
9990 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
9991 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
9992 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9993 // Non-Authenticating HTTPS server through an authenticating proxy.
9994 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
9995 { TestRound(kConnect
, kProxyChallenge
, OK
),
9996 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
9997 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9998 { TestRound(kConnect
, kProxyChallenge
, OK
),
9999 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10000 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10001 { TestRound(kConnect
, kProxyChallenge
, OK
),
10002 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10003 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10004 { TestRound(kConnect
, kProxyChallenge
, OK
),
10005 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10006 // Authenticating HTTPS server through an authenticating proxy.
10007 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10008 { TestRound(kConnect
, kProxyChallenge
, OK
),
10009 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10010 &kGet
, &kServerChallenge
),
10011 TestRound(kGetAuth
, kSuccess
, OK
)}},
10012 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10013 { TestRound(kConnect
, kProxyChallenge
, OK
),
10014 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10015 &kGet
, &kServerChallenge
),
10016 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10017 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10018 { TestRound(kConnect
, kProxyChallenge
, OK
),
10019 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10020 &kGet
, &kServerChallenge
),
10021 TestRound(kGetAuth
, kSuccess
, OK
)}},
10022 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10023 { TestRound(kConnect
, kProxyChallenge
, OK
),
10024 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10025 &kGet
, &kServerChallenge
),
10026 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10027 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10028 { TestRound(kConnect
, kProxyChallenge
, OK
),
10029 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10030 &kGet
, &kServerChallenge
),
10031 TestRound(kGetAuth
, kSuccess
, OK
)}},
10032 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10033 { TestRound(kConnect
, kProxyChallenge
, OK
),
10034 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10035 &kGet
, &kServerChallenge
),
10036 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10037 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10038 { TestRound(kConnect
, kProxyChallenge
, OK
),
10039 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10040 &kGet
, &kServerChallenge
),
10041 TestRound(kGetAuth
, kSuccess
, OK
)}},
10042 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10043 { TestRound(kConnect
, kProxyChallenge
, OK
),
10044 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10045 &kGet
, &kServerChallenge
),
10046 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10049 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10050 HttpAuthHandlerMock::Factory
* auth_factory(
10051 new HttpAuthHandlerMock::Factory());
10052 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10053 const TestConfig
& test_config
= test_configs
[i
];
10055 // Set up authentication handlers as necessary.
10056 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10057 for (int n
= 0; n
< 2; n
++) {
10058 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10059 std::string auth_challenge
= "Mock realm=proxy";
10060 GURL
origin(test_config
.proxy_url
);
10061 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10062 auth_challenge
.end());
10063 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10064 origin
, BoundNetLog());
10065 auth_handler
->SetGenerateExpectation(
10066 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10067 test_config
.proxy_auth_rv
);
10068 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10071 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10072 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10073 std::string auth_challenge
= "Mock realm=server";
10074 GURL
origin(test_config
.server_url
);
10075 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10076 auth_challenge
.end());
10077 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10078 origin
, BoundNetLog());
10079 auth_handler
->SetGenerateExpectation(
10080 test_config
.server_auth_timing
== AUTH_ASYNC
,
10081 test_config
.server_auth_rv
);
10082 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10084 if (test_config
.proxy_url
) {
10085 session_deps_
.proxy_service
.reset(
10086 ProxyService::CreateFixed(test_config
.proxy_url
));
10088 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10091 HttpRequestInfo request
;
10092 request
.method
= "GET";
10093 request
.url
= GURL(test_config
.server_url
);
10094 request
.load_flags
= 0;
10096 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10097 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10099 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10101 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10102 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10103 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10104 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10106 // Set up expected reads and writes.
10107 mock_reads
.back().push_back(read_write_round
.read
);
10108 mock_writes
.back().push_back(read_write_round
.write
);
10110 // kProxyChallenge uses Proxy-Connection: close which means that the
10111 // socket is closed and a new one will be created for the next request.
10112 if (read_write_round
.read
.data
== kProxyChallenge
.data
&&
10113 read_write_round
.write
.data
!= kConnect
.data
) {
10114 mock_reads
.push_back(std::vector
<MockRead
>());
10115 mock_writes
.push_back(std::vector
<MockWrite
>());
10118 if (read_write_round
.extra_read
) {
10119 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10121 if (read_write_round
.extra_write
) {
10122 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10125 // Add an SSL sequence if necessary.
10126 if (round
>= test_config
.first_ssl_round
)
10127 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10128 &ssl_socket_data_provider
);
10131 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10132 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10133 data_providers
.push_back(new StaticSocketDataProvider(
10134 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10135 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10136 session_deps_
.socket_factory
->AddSocketDataProvider(
10137 data_providers
.back());
10140 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10141 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10142 // Start or restart the transaction.
10143 TestCompletionCallback callback
;
10146 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10148 rv
= trans
.RestartWithAuth(
10149 AuthCredentials(kFoo
, kBar
), callback
.callback());
10151 if (rv
== ERR_IO_PENDING
)
10152 rv
= callback
.WaitForResult();
10154 // Compare results with expected data.
10155 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10156 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10157 if (read_write_round
.expected_rv
!= OK
) {
10158 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10161 if (round
+ 1 < test_config
.num_auth_rounds
) {
10162 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10164 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10170 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10171 // Do multi-round authentication and make sure it works correctly.
10172 HttpAuthHandlerMock::Factory
* auth_factory(
10173 new HttpAuthHandlerMock::Factory());
10174 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10175 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10176 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10177 session_deps_
.host_resolver
->set_synchronous_mode(true);
10179 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10180 auth_handler
->set_connection_based(true);
10181 std::string auth_challenge
= "Mock realm=server";
10182 GURL
origin("http://www.example.com");
10183 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10184 auth_challenge
.end());
10185 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10186 origin
, BoundNetLog());
10187 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10190 const HttpResponseInfo
* response
= NULL
;
10191 HttpRequestInfo request
;
10192 request
.method
= "GET";
10193 request
.url
= origin
;
10194 request
.load_flags
= 0;
10196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10198 // Use a TCP Socket Pool with only one connection per group. This is used
10199 // to validate that the TCP socket is not released to the pool between
10200 // each round of multi-round authentication.
10201 HttpNetworkSessionPeer
session_peer(session
);
10202 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10203 50, // Max sockets for pool
10204 1, // Max sockets per group
10205 session_deps_
.host_resolver
.get(),
10206 session_deps_
.socket_factory
.get(),
10207 session_deps_
.net_log
);
10208 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10209 new MockClientSocketPoolManager
);
10210 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10211 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10213 scoped_ptr
<HttpTransaction
> trans(
10214 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10215 TestCompletionCallback callback
;
10217 const MockWrite
kGet(
10218 "GET / HTTP/1.1\r\n"
10219 "Host: www.example.com\r\n"
10220 "Connection: keep-alive\r\n\r\n");
10221 const MockWrite
kGetAuth(
10222 "GET / HTTP/1.1\r\n"
10223 "Host: www.example.com\r\n"
10224 "Connection: keep-alive\r\n"
10225 "Authorization: auth_token\r\n\r\n");
10227 const MockRead
kServerChallenge(
10228 "HTTP/1.1 401 Unauthorized\r\n"
10229 "WWW-Authenticate: Mock realm=server\r\n"
10230 "Content-Type: text/html; charset=iso-8859-1\r\n"
10231 "Content-Length: 14\r\n\r\n"
10232 "Unauthorized\r\n");
10233 const MockRead
kSuccess(
10234 "HTTP/1.1 200 OK\r\n"
10235 "Content-Type: text/html; charset=iso-8859-1\r\n"
10236 "Content-Length: 3\r\n\r\n"
10239 MockWrite writes
[] = {
10248 // Competing request
10251 MockRead reads
[] = {
10260 // Competing response
10263 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10264 writes
, arraysize(writes
));
10265 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10267 const char kSocketGroup
[] = "www.example.com:80";
10269 // First round of authentication.
10270 auth_handler
->SetGenerateExpectation(false, OK
);
10271 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10272 if (rv
== ERR_IO_PENDING
)
10273 rv
= callback
.WaitForResult();
10275 response
= trans
->GetResponseInfo();
10276 ASSERT_TRUE(response
!= NULL
);
10277 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10278 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10280 // In between rounds, another request comes in for the same domain.
10281 // It should not be able to grab the TCP socket that trans has already
10283 scoped_ptr
<HttpTransaction
> trans_compete(
10284 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10285 TestCompletionCallback callback_compete
;
10286 rv
= trans_compete
->Start(
10287 &request
, callback_compete
.callback(), BoundNetLog());
10288 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10289 // callback_compete.WaitForResult at this point would stall forever,
10290 // since the HttpNetworkTransaction does not release the request back to
10291 // the pool until after authentication completes.
10293 // Second round of authentication.
10294 auth_handler
->SetGenerateExpectation(false, OK
);
10295 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10296 if (rv
== ERR_IO_PENDING
)
10297 rv
= callback
.WaitForResult();
10299 response
= trans
->GetResponseInfo();
10300 ASSERT_TRUE(response
!= NULL
);
10301 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10302 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10304 // Third round of authentication.
10305 auth_handler
->SetGenerateExpectation(false, OK
);
10306 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10307 if (rv
== ERR_IO_PENDING
)
10308 rv
= callback
.WaitForResult();
10310 response
= trans
->GetResponseInfo();
10311 ASSERT_TRUE(response
!= NULL
);
10312 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10313 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10315 // Fourth round of authentication, which completes successfully.
10316 auth_handler
->SetGenerateExpectation(false, OK
);
10317 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10318 if (rv
== ERR_IO_PENDING
)
10319 rv
= callback
.WaitForResult();
10321 response
= trans
->GetResponseInfo();
10322 ASSERT_TRUE(response
!= NULL
);
10323 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10324 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10326 // Read the body since the fourth round was successful. This will also
10327 // release the socket back to the pool.
10328 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10329 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10330 if (rv
== ERR_IO_PENDING
)
10331 rv
= callback
.WaitForResult();
10333 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10335 // There are still 0 idle sockets, since the trans_compete transaction
10336 // will be handed it immediately after trans releases it to the group.
10337 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10339 // The competing request can now finish. Wait for the headers and then
10341 rv
= callback_compete
.WaitForResult();
10343 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10344 if (rv
== ERR_IO_PENDING
)
10345 rv
= callback
.WaitForResult();
10347 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10350 // Finally, the socket is released to the group.
10351 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10354 // This tests the case that a request is issued via http instead of spdy after
10355 // npn is negotiated.
10356 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10357 session_deps_
.use_alternate_protocols
= true;
10358 NextProtoVector next_protos
;
10359 next_protos
.push_back(kProtoHTTP11
);
10360 session_deps_
.next_protos
= next_protos
;
10362 HttpRequestInfo request
;
10363 request
.method
= "GET";
10364 request
.url
= GURL("https://www.example.org/");
10365 request
.load_flags
= 0;
10367 MockWrite data_writes
[] = {
10369 "GET / HTTP/1.1\r\n"
10370 "Host: www.example.org\r\n"
10371 "Connection: keep-alive\r\n\r\n"),
10374 std::string alternate_protocol_http_header
=
10375 GetAlternateProtocolHttpHeader();
10377 MockRead data_reads
[] = {
10378 MockRead("HTTP/1.1 200 OK\r\n"),
10379 MockRead(alternate_protocol_http_header
.c_str()),
10380 MockRead("hello world"),
10381 MockRead(SYNCHRONOUS
, OK
),
10384 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10385 ssl
.SetNextProto(kProtoHTTP11
);
10387 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10389 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10390 data_writes
, arraysize(data_writes
));
10391 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10393 TestCompletionCallback callback
;
10395 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10396 scoped_ptr
<HttpTransaction
> trans(
10397 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10399 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10401 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10402 EXPECT_EQ(OK
, callback
.WaitForResult());
10404 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10405 ASSERT_TRUE(response
!= NULL
);
10406 ASSERT_TRUE(response
->headers
.get() != NULL
);
10407 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10409 std::string response_data
;
10410 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10411 EXPECT_EQ("hello world", response_data
);
10413 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10414 EXPECT_TRUE(response
->was_npn_negotiated
);
10417 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10418 // Simulate the SSL handshake completing with an NPN negotiation
10419 // followed by an immediate server closing of the socket.
10420 // Fix crash: http://crbug.com/46369
10421 session_deps_
.use_alternate_protocols
= true;
10422 session_deps_
.next_protos
= SpdyNextProtos();
10424 HttpRequestInfo request
;
10425 request
.method
= "GET";
10426 request
.url
= GURL("https://www.example.org/");
10427 request
.load_flags
= 0;
10429 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10430 ssl
.SetNextProto(GetParam());
10431 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10433 scoped_ptr
<SpdyFrame
> req(
10434 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10435 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10437 MockRead spdy_reads
[] = {
10438 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10441 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10442 arraysize(spdy_writes
));
10443 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10445 TestCompletionCallback callback
;
10447 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10448 scoped_ptr
<HttpTransaction
> trans(
10449 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10451 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10452 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10453 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10456 // A subclass of HttpAuthHandlerMock that records the request URL when
10457 // it gets it. This is needed since the auth handler may get destroyed
10458 // before we get a chance to query it.
10459 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10461 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10463 ~UrlRecordingHttpAuthHandlerMock() override
{}
10466 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10467 const HttpRequestInfo
* request
,
10468 const CompletionCallback
& callback
,
10469 std::string
* auth_token
) override
{
10470 *url_
= request
->url
;
10471 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10472 credentials
, request
, callback
, auth_token
);
10479 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10480 // This test ensures that the URL passed into the proxy is upgraded
10481 // to https when doing an Alternate Protocol upgrade.
10482 session_deps_
.use_alternate_protocols
= true;
10483 session_deps_
.next_protos
= SpdyNextProtos();
10485 session_deps_
.proxy_service
.reset(
10486 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10487 TestNetLog net_log
;
10488 session_deps_
.net_log
= &net_log
;
10491 HttpAuthHandlerMock::Factory
* auth_factory
=
10492 new HttpAuthHandlerMock::Factory();
10493 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10494 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10495 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10496 auth_factory
->set_do_init_from_challenge(true);
10497 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10500 HttpRequestInfo request
;
10501 request
.method
= "GET";
10502 request
.url
= GURL("http://www.example.org");
10503 request
.load_flags
= 0;
10505 // First round goes unauthenticated through the proxy.
10506 MockWrite data_writes_1
[] = {
10508 "GET http://www.example.org/ HTTP/1.1\r\n"
10509 "Host: www.example.org\r\n"
10510 "Proxy-Connection: keep-alive\r\n"
10513 MockRead data_reads_1
[] = {
10514 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10515 MockRead("HTTP/1.1 200 OK\r\n"),
10516 MockRead("Alternate-Protocol: 443:"),
10517 MockRead(GetAlternateProtocolFromParam()),
10519 MockRead("Proxy-Connection: close\r\n"),
10522 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10523 data_writes_1
, arraysize(data_writes_1
));
10525 // Second round tries to tunnel to www.example.org due to the
10526 // Alternate-Protocol announcement in the first round. It fails due
10527 // to a proxy authentication challenge.
10528 // After the failure, a tunnel is established to www.example.org using
10529 // Proxy-Authorization headers. There is then a SPDY request round.
10531 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10532 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10533 // does a Disconnect and Connect on the same socket, rather than trying
10534 // to obtain a new one.
10536 // NOTE: Originally, the proxy response to the second CONNECT request
10537 // simply returned another 407 so the unit test could skip the SSL connection
10538 // establishment and SPDY framing issues. Alas, the
10539 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10540 // complicated to set up expectations for than the SPDY session.
10542 scoped_ptr
<SpdyFrame
> req(
10543 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10544 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10545 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10547 MockWrite data_writes_2
[] = {
10548 // First connection attempt without Proxy-Authorization.
10549 MockWrite(ASYNC
, 0,
10550 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10551 "Host: www.example.org\r\n"
10552 "Proxy-Connection: keep-alive\r\n"
10555 // Second connection attempt with Proxy-Authorization.
10556 MockWrite(ASYNC
, 2,
10557 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10558 "Host: www.example.org\r\n"
10559 "Proxy-Connection: keep-alive\r\n"
10560 "Proxy-Authorization: auth_token\r\n"
10564 CreateMockWrite(*req
, 4),
10566 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10567 "Proxy-Authenticate: Mock\r\n"
10568 "Proxy-Connection: close\r\n"
10570 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10571 MockRead data_reads_2
[] = {
10572 // First connection attempt fails
10573 MockRead(ASYNC
, kRejectConnectResponse
,
10574 arraysize(kRejectConnectResponse
) - 1, 1),
10576 // Second connection attempt passes
10577 MockRead(ASYNC
, kAcceptConnectResponse
,
10578 arraysize(kAcceptConnectResponse
) - 1, 3),
10581 CreateMockRead(*resp
.get(), 5),
10582 CreateMockRead(*data
.get(), 6),
10583 MockRead(ASYNC
, 0, 0, 7),
10585 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10586 data_writes_2
, arraysize(data_writes_2
));
10588 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10589 ssl
.SetNextProto(GetParam());
10590 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10591 ASSERT_TRUE(ssl
.cert
.get());
10593 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10594 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10596 hanging_non_alternate_protocol_socket
.set_connect_data(
10597 never_finishing_connect
);
10599 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10600 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10601 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10602 session_deps_
.socket_factory
->AddSocketDataProvider(
10603 &hanging_non_alternate_protocol_socket
);
10604 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10606 // First round should work and provide the Alternate-Protocol state.
10607 TestCompletionCallback callback_1
;
10608 scoped_ptr
<HttpTransaction
> trans_1(
10609 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10610 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10611 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10612 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10614 // Second round should attempt a tunnel connect and get an auth challenge.
10615 TestCompletionCallback callback_2
;
10616 scoped_ptr
<HttpTransaction
> trans_2(
10617 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10618 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10619 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10620 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10621 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10622 ASSERT_TRUE(response
!= NULL
);
10623 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10625 // Restart with auth. Tunnel should work and response received.
10626 TestCompletionCallback callback_3
;
10627 rv
= trans_2
->RestartWithAuth(
10628 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10629 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10630 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10632 // After all that work, these two lines (or actually, just the scheme) are
10633 // what this test is all about. Make sure it happens correctly.
10634 EXPECT_EQ("https", request_url
.scheme());
10635 EXPECT_EQ("www.example.org", request_url
.host());
10637 LoadTimingInfo load_timing_info
;
10638 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10639 TestLoadTimingNotReusedWithPac(load_timing_info
,
10640 CONNECT_TIMING_HAS_SSL_TIMES
);
10643 // Test that if we cancel the transaction as the connection is completing, that
10644 // everything tears down correctly.
10645 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10646 // Setup everything about the connection to complete synchronously, so that
10647 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10648 // for is the callback from the HttpStreamRequest.
10649 // Then cancel the transaction.
10650 // Verify that we don't crash.
10651 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10652 MockRead data_reads
[] = {
10653 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10654 MockRead(SYNCHRONOUS
, "hello world"),
10655 MockRead(SYNCHRONOUS
, OK
),
10658 HttpRequestInfo request
;
10659 request
.method
= "GET";
10660 request
.url
= GURL("http://www.example.org/");
10661 request
.load_flags
= 0;
10663 session_deps_
.host_resolver
->set_synchronous_mode(true);
10664 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10665 scoped_ptr
<HttpTransaction
> trans(
10666 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10668 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10669 data
.set_connect_data(mock_connect
);
10670 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10672 TestCompletionCallback callback
;
10674 BoundTestNetLog log
;
10675 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10676 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10677 trans
.reset(); // Cancel the transaction here.
10679 base::MessageLoop::current()->RunUntilIdle();
10682 // Test that if a transaction is cancelled after receiving the headers, the
10683 // stream is drained properly and added back to the socket pool. The main
10684 // purpose of this test is to make sure that an HttpStreamParser can be read
10685 // from after the HttpNetworkTransaction and the objects it owns have been
10687 // See http://crbug.com/368418
10688 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10689 MockRead data_reads
[] = {
10690 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10691 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10692 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10693 MockRead(ASYNC
, "1"),
10694 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10695 // HttpNetworkTransaction has been deleted.
10696 MockRead(ASYNC
, "2"),
10697 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10699 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10700 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10702 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10705 HttpRequestInfo request
;
10706 request
.method
= "GET";
10707 request
.url
= GURL("http://www.example.org/");
10708 request
.load_flags
= 0;
10710 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10711 TestCompletionCallback callback
;
10713 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10715 callback
.WaitForResult();
10717 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10718 ASSERT_TRUE(response
!= NULL
);
10719 EXPECT_TRUE(response
->headers
.get() != NULL
);
10720 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10722 // The transaction and HttpRequestInfo are deleted.
10725 // Let the HttpResponseBodyDrainer drain the socket.
10726 base::MessageLoop::current()->RunUntilIdle();
10728 // Socket should now be idle, waiting to be reused.
10729 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10732 // Test a basic GET request through a proxy.
10733 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10734 session_deps_
.proxy_service
.reset(
10735 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10736 BoundTestNetLog log
;
10737 session_deps_
.net_log
= log
.bound().net_log();
10738 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10740 HttpRequestInfo request
;
10741 request
.method
= "GET";
10742 request
.url
= GURL("http://www.example.org/");
10744 MockWrite data_writes1
[] = {
10746 "GET http://www.example.org/ HTTP/1.1\r\n"
10747 "Host: www.example.org\r\n"
10748 "Proxy-Connection: keep-alive\r\n\r\n"),
10751 MockRead data_reads1
[] = {
10752 MockRead("HTTP/1.1 200 OK\r\n"),
10753 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10754 MockRead("Content-Length: 100\r\n\r\n"),
10755 MockRead(SYNCHRONOUS
, OK
),
10758 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10759 data_writes1
, arraysize(data_writes1
));
10760 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10762 TestCompletionCallback callback1
;
10764 scoped_ptr
<HttpTransaction
> trans(
10765 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10766 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10767 trans
->SetBeforeProxyHeadersSentCallback(
10768 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10769 base::Unretained(&proxy_headers_handler
)));
10771 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10772 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10774 rv
= callback1
.WaitForResult();
10777 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10778 ASSERT_TRUE(response
!= NULL
);
10780 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10781 EXPECT_EQ(200, response
->headers
->response_code());
10782 EXPECT_EQ(100, response
->headers
->GetContentLength());
10783 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10785 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10786 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10787 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10788 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10790 LoadTimingInfo load_timing_info
;
10791 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10792 TestLoadTimingNotReusedWithPac(load_timing_info
,
10793 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10796 // Test a basic HTTPS GET request through a proxy.
10797 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10798 session_deps_
.proxy_service
.reset(
10799 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10800 BoundTestNetLog log
;
10801 session_deps_
.net_log
= log
.bound().net_log();
10802 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10804 HttpRequestInfo request
;
10805 request
.method
= "GET";
10806 request
.url
= GURL("https://www.example.org/");
10808 // Since we have proxy, should try to establish tunnel.
10809 MockWrite data_writes1
[] = {
10811 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10812 "Host: www.example.org\r\n"
10813 "Proxy-Connection: keep-alive\r\n\r\n"),
10816 "GET / HTTP/1.1\r\n"
10817 "Host: www.example.org\r\n"
10818 "Connection: keep-alive\r\n\r\n"),
10821 MockRead data_reads1
[] = {
10822 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10824 MockRead("HTTP/1.1 200 OK\r\n"),
10825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10826 MockRead("Content-Length: 100\r\n\r\n"),
10827 MockRead(SYNCHRONOUS
, OK
),
10830 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10831 data_writes1
, arraysize(data_writes1
));
10832 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10833 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10834 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10836 TestCompletionCallback callback1
;
10838 scoped_ptr
<HttpTransaction
> trans(
10839 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10841 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10844 rv
= callback1
.WaitForResult();
10846 TestNetLogEntry::List entries
;
10847 log
.GetEntries(&entries
);
10848 size_t pos
= ExpectLogContainsSomewhere(
10849 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10850 NetLog::PHASE_NONE
);
10851 ExpectLogContainsSomewhere(
10853 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10854 NetLog::PHASE_NONE
);
10856 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10857 ASSERT_TRUE(response
!= NULL
);
10859 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10860 EXPECT_EQ(200, response
->headers
->response_code());
10861 EXPECT_EQ(100, response
->headers
->GetContentLength());
10862 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10863 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10865 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10867 LoadTimingInfo load_timing_info
;
10868 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10869 TestLoadTimingNotReusedWithPac(load_timing_info
,
10870 CONNECT_TIMING_HAS_SSL_TIMES
);
10873 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10874 // while establishing the tunnel.
10875 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10876 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10877 BoundTestNetLog log
;
10878 session_deps_
.net_log
= log
.bound().net_log();
10879 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10881 HttpRequestInfo request
;
10882 request
.method
= "GET";
10883 request
.url
= GURL("https://www.example.org/");
10885 // Since we have proxy, should try to establish tunnel.
10886 MockWrite data_writes1
[] = {
10888 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10889 "Host: www.example.org\r\n"
10890 "Proxy-Connection: keep-alive\r\n\r\n"),
10893 "GET / HTTP/1.1\r\n"
10894 "Host: www.example.org\r\n"
10895 "Connection: keep-alive\r\n\r\n"),
10898 MockRead data_reads1
[] = {
10899 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10900 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10901 MockRead(ASYNC
, 0, 0), // EOF
10904 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10905 data_writes1
, arraysize(data_writes1
));
10906 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10907 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10908 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10910 TestCompletionCallback callback1
;
10912 scoped_ptr
<HttpTransaction
> trans(
10913 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10915 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10916 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10918 rv
= callback1
.WaitForResult();
10919 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10920 TestNetLogEntry::List entries
;
10921 log
.GetEntries(&entries
);
10922 size_t pos
= ExpectLogContainsSomewhere(
10923 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10924 NetLog::PHASE_NONE
);
10925 ExpectLogContainsSomewhere(
10927 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10928 NetLog::PHASE_NONE
);
10931 // Test for crbug.com/55424.
10932 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10933 scoped_ptr
<SpdyFrame
> req(
10934 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
10935 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
10937 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10938 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10939 MockRead spdy_reads
[] = {
10940 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
10943 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10944 arraysize(spdy_writes
));
10945 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10947 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10948 ssl
.SetNextProto(GetParam());
10949 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10951 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10953 // Set up an initial SpdySession in the pool to reuse.
10954 HostPortPair
host_port_pair("www.example.org", 443);
10955 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10956 PRIVACY_MODE_DISABLED
);
10957 base::WeakPtr
<SpdySession
> spdy_session
=
10958 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10960 HttpRequestInfo request
;
10961 request
.method
= "GET";
10962 request
.url
= GURL("https://www.example.org/");
10963 request
.load_flags
= 0;
10965 // This is the important line that marks this as a preconnect.
10966 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
10968 scoped_ptr
<HttpTransaction
> trans(
10969 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10971 TestCompletionCallback callback
;
10972 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10973 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10974 EXPECT_EQ(OK
, callback
.WaitForResult());
10977 // Given a net error, cause that error to be returned from the first Write()
10978 // call and verify that the HttpTransaction fails with that error.
10979 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
10980 int error
, IoMode mode
) {
10981 HttpRequestInfo request_info
;
10982 request_info
.url
= GURL("https://www.example.com/");
10983 request_info
.method
= "GET";
10984 request_info
.load_flags
= LOAD_NORMAL
;
10986 SSLSocketDataProvider
ssl_data(mode
, OK
);
10987 MockWrite data_writes
[] = {
10988 MockWrite(mode
, error
),
10990 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
10991 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10992 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
10994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10995 scoped_ptr
<HttpTransaction
> trans(
10996 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10998 TestCompletionCallback callback
;
10999 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11000 if (rv
== ERR_IO_PENDING
)
11001 rv
= callback
.WaitForResult();
11002 ASSERT_EQ(error
, rv
);
11005 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11006 // Just check a grab bag of cert errors.
11007 static const int kErrors
[] = {
11008 ERR_CERT_COMMON_NAME_INVALID
,
11009 ERR_CERT_AUTHORITY_INVALID
,
11010 ERR_CERT_DATE_INVALID
,
11012 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11013 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11014 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11018 // Ensure that a client certificate is removed from the SSL client auth
11020 // 1) No proxy is involved.
11021 // 2) TLS False Start is disabled.
11022 // 3) The initial TLS handshake requests a client certificate.
11023 // 4) The client supplies an invalid/unacceptable certificate.
11024 TEST_P(HttpNetworkTransactionTest
,
11025 ClientAuthCertCache_Direct_NoFalseStart
) {
11026 HttpRequestInfo request_info
;
11027 request_info
.url
= GURL("https://www.example.com/");
11028 request_info
.method
= "GET";
11029 request_info
.load_flags
= LOAD_NORMAL
;
11031 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11032 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11034 // [ssl_]data1 contains the data for the first SSL handshake. When a
11035 // CertificateRequest is received for the first time, the handshake will
11036 // be aborted to allow the caller to provide a certificate.
11037 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11038 ssl_data1
.cert_request_info
= cert_request
.get();
11039 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11040 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11041 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11043 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11044 // False Start is not being used, the result of the SSL handshake will be
11045 // returned as part of the SSLClientSocket::Connect() call. This test
11046 // matches the result of a server sending a handshake_failure alert,
11047 // rather than a Finished message, because it requires a client
11048 // certificate and none was supplied.
11049 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11050 ssl_data2
.cert_request_info
= cert_request
.get();
11051 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11052 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11053 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11055 // [ssl_]data3 contains the data for the third SSL handshake. When a
11056 // connection to a server fails during an SSL handshake,
11057 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11058 // connection was attempted with TLSv1.2. This is transparent to the caller
11059 // of the HttpNetworkTransaction. Because this test failure is due to
11060 // requiring a client certificate, this fallback handshake should also
11062 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11063 ssl_data3
.cert_request_info
= cert_request
.get();
11064 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11065 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11066 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11068 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11069 // connection to a server fails during an SSL handshake,
11070 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11071 // connection was attempted with TLSv1.1. This is transparent to the caller
11072 // of the HttpNetworkTransaction. Because this test failure is due to
11073 // requiring a client certificate, this fallback handshake should also
11075 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11076 ssl_data4
.cert_request_info
= cert_request
.get();
11077 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11078 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11079 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11081 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11082 scoped_ptr
<HttpTransaction
> trans(
11083 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11085 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11086 TestCompletionCallback callback
;
11087 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11088 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11090 // Complete the SSL handshake, which should abort due to requiring a
11091 // client certificate.
11092 rv
= callback
.WaitForResult();
11093 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11095 // Indicate that no certificate should be supplied. From the perspective
11096 // of SSLClientCertCache, NULL is just as meaningful as a real
11097 // certificate, so this is the same as supply a
11098 // legitimate-but-unacceptable certificate.
11099 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11100 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11102 // Ensure the certificate was added to the client auth cache before
11103 // allowing the connection to continue restarting.
11104 scoped_refptr
<X509Certificate
> client_cert
;
11105 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11106 HostPortPair("www.example.com", 443), &client_cert
));
11107 ASSERT_EQ(NULL
, client_cert
.get());
11109 // Restart the handshake. This will consume ssl_data2, which fails, and
11110 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11111 // The result code is checked against what ssl_data4 should return.
11112 rv
= callback
.WaitForResult();
11113 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11115 // Ensure that the client certificate is removed from the cache on a
11116 // handshake failure.
11117 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11118 HostPortPair("www.example.com", 443), &client_cert
));
11121 // Ensure that a client certificate is removed from the SSL client auth
11123 // 1) No proxy is involved.
11124 // 2) TLS False Start is enabled.
11125 // 3) The initial TLS handshake requests a client certificate.
11126 // 4) The client supplies an invalid/unacceptable certificate.
11127 TEST_P(HttpNetworkTransactionTest
,
11128 ClientAuthCertCache_Direct_FalseStart
) {
11129 HttpRequestInfo request_info
;
11130 request_info
.url
= GURL("https://www.example.com/");
11131 request_info
.method
= "GET";
11132 request_info
.load_flags
= LOAD_NORMAL
;
11134 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11135 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11137 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11138 // return successfully after reading up to the peer's Certificate message.
11139 // This is to allow the caller to call SSLClientSocket::Write(), which can
11140 // enqueue application data to be sent in the same packet as the
11141 // ChangeCipherSpec and Finished messages.
11142 // The actual handshake will be finished when SSLClientSocket::Read() is
11143 // called, which expects to process the peer's ChangeCipherSpec and
11144 // Finished messages. If there was an error negotiating with the peer,
11145 // such as due to the peer requiring a client certificate when none was
11146 // supplied, the alert sent by the peer won't be processed until Read() is
11149 // Like the non-False Start case, when a client certificate is requested by
11150 // the peer, the handshake is aborted during the Connect() call.
11151 // [ssl_]data1 represents the initial SSL handshake with the peer.
11152 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11153 ssl_data1
.cert_request_info
= cert_request
.get();
11154 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11155 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11156 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11158 // When a client certificate is supplied, Connect() will not be aborted
11159 // when the peer requests the certificate. Instead, the handshake will
11160 // artificially succeed, allowing the caller to write the HTTP request to
11161 // the socket. The handshake messages are not processed until Read() is
11162 // called, which then detects that the handshake was aborted, due to the
11163 // peer sending a handshake_failure because it requires a client
11165 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11166 ssl_data2
.cert_request_info
= cert_request
.get();
11167 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11168 MockRead data2_reads
[] = {
11169 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11171 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11172 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11174 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11175 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11176 // TLSv1. It has the same behaviour as [ssl_]data2.
11177 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11178 ssl_data3
.cert_request_info
= cert_request
.get();
11179 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11180 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11181 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11183 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11184 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11185 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11186 ssl_data4
.cert_request_info
= cert_request
.get();
11187 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11188 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11189 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11191 // Need one more if TLSv1.2 is enabled.
11192 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11193 ssl_data5
.cert_request_info
= cert_request
.get();
11194 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11195 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11196 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11198 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11199 scoped_ptr
<HttpTransaction
> trans(
11200 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11202 // Begin the initial SSL handshake.
11203 TestCompletionCallback callback
;
11204 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11205 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11207 // Complete the SSL handshake, which should abort due to requiring a
11208 // client certificate.
11209 rv
= callback
.WaitForResult();
11210 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11212 // Indicate that no certificate should be supplied. From the perspective
11213 // of SSLClientCertCache, NULL is just as meaningful as a real
11214 // certificate, so this is the same as supply a
11215 // legitimate-but-unacceptable certificate.
11216 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11217 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11219 // Ensure the certificate was added to the client auth cache before
11220 // allowing the connection to continue restarting.
11221 scoped_refptr
<X509Certificate
> client_cert
;
11222 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11223 HostPortPair("www.example.com", 443), &client_cert
));
11224 ASSERT_EQ(NULL
, client_cert
.get());
11226 // Restart the handshake. This will consume ssl_data2, which fails, and
11227 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11228 // The result code is checked against what ssl_data4 should return.
11229 rv
= callback
.WaitForResult();
11230 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11232 // Ensure that the client certificate is removed from the cache on a
11233 // handshake failure.
11234 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11235 HostPortPair("www.example.com", 443), &client_cert
));
11238 // Ensure that a client certificate is removed from the SSL client auth
11240 // 1) An HTTPS proxy is involved.
11241 // 3) The HTTPS proxy requests a client certificate.
11242 // 4) The client supplies an invalid/unacceptable certificate for the
11244 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11245 // then for connecting to an HTTP endpoint.
11246 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11247 session_deps_
.proxy_service
.reset(
11248 ProxyService::CreateFixed("https://proxy:70"));
11249 BoundTestNetLog log
;
11250 session_deps_
.net_log
= log
.bound().net_log();
11252 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11253 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11255 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11256 // [ssl_]data[1-3]. Rather than represending the endpoint
11257 // (www.example.com:443), they represent failures with the HTTPS proxy
11259 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11260 ssl_data1
.cert_request_info
= cert_request
.get();
11261 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11262 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11263 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11265 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11266 ssl_data2
.cert_request_info
= cert_request
.get();
11267 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11268 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11269 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11271 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11273 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11274 ssl_data3
.cert_request_info
= cert_request
.get();
11275 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11276 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11277 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11280 HttpRequestInfo requests
[2];
11281 requests
[0].url
= GURL("https://www.example.com/");
11282 requests
[0].method
= "GET";
11283 requests
[0].load_flags
= LOAD_NORMAL
;
11285 requests
[1].url
= GURL("http://www.example.com/");
11286 requests
[1].method
= "GET";
11287 requests
[1].load_flags
= LOAD_NORMAL
;
11289 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11290 session_deps_
.socket_factory
->ResetNextMockIndexes();
11291 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11292 scoped_ptr
<HttpNetworkTransaction
> trans(
11293 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11295 // Begin the SSL handshake with the proxy.
11296 TestCompletionCallback callback
;
11297 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11298 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11300 // Complete the SSL handshake, which should abort due to requiring a
11301 // client certificate.
11302 rv
= callback
.WaitForResult();
11303 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11305 // Indicate that no certificate should be supplied. From the perspective
11306 // of SSLClientCertCache, NULL is just as meaningful as a real
11307 // certificate, so this is the same as supply a
11308 // legitimate-but-unacceptable certificate.
11309 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11310 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11312 // Ensure the certificate was added to the client auth cache before
11313 // allowing the connection to continue restarting.
11314 scoped_refptr
<X509Certificate
> client_cert
;
11315 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11316 HostPortPair("proxy", 70), &client_cert
));
11317 ASSERT_EQ(NULL
, client_cert
.get());
11318 // Ensure the certificate was NOT cached for the endpoint. This only
11319 // applies to HTTPS requests, but is fine to check for HTTP requests.
11320 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11321 HostPortPair("www.example.com", 443), &client_cert
));
11323 // Restart the handshake. This will consume ssl_data2, which fails, and
11324 // then consume ssl_data3, which should also fail. The result code is
11325 // checked against what ssl_data3 should return.
11326 rv
= callback
.WaitForResult();
11327 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11329 // Now that the new handshake has failed, ensure that the client
11330 // certificate was removed from the client auth cache.
11331 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11332 HostPortPair("proxy", 70), &client_cert
));
11333 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11334 HostPortPair("www.example.com", 443), &client_cert
));
11338 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPooling
) {
11339 session_deps_
.use_alternate_protocols
= true;
11340 session_deps_
.next_protos
= SpdyNextProtos();
11342 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11343 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11344 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11345 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11346 pool_peer
.DisableDomainAuthenticationVerification();
11348 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11349 ssl
.SetNextProto(GetParam());
11350 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11352 scoped_ptr
<SpdyFrame
> host1_req(
11353 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11354 scoped_ptr
<SpdyFrame
> host2_req(
11355 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11356 MockWrite spdy_writes
[] = {
11357 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11359 scoped_ptr
<SpdyFrame
> host1_resp(
11360 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11361 scoped_ptr
<SpdyFrame
> host1_resp_body(
11362 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11363 scoped_ptr
<SpdyFrame
> host2_resp(
11364 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11365 scoped_ptr
<SpdyFrame
> host2_resp_body(
11366 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11367 MockRead spdy_reads
[] = {
11368 CreateMockRead(*host1_resp
, 1),
11369 CreateMockRead(*host1_resp_body
, 2),
11370 CreateMockRead(*host2_resp
, 4),
11371 CreateMockRead(*host2_resp_body
, 5),
11372 MockRead(ASYNC
, 0, 6),
11375 IPAddressNumber ip
;
11376 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11377 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11378 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11379 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11380 spdy_writes
, arraysize(spdy_writes
));
11381 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11383 TestCompletionCallback callback
;
11384 HttpRequestInfo request1
;
11385 request1
.method
= "GET";
11386 request1
.url
= GURL("https://www.example.org/");
11387 request1
.load_flags
= 0;
11388 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11390 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11391 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11392 EXPECT_EQ(OK
, callback
.WaitForResult());
11394 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11395 ASSERT_TRUE(response
!= NULL
);
11396 ASSERT_TRUE(response
->headers
.get() != NULL
);
11397 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11399 std::string response_data
;
11400 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11401 EXPECT_EQ("hello!", response_data
);
11403 // Preload www.gmail.com into HostCache.
11404 HostPortPair
host_port("www.gmail.com", 443);
11405 HostResolver::RequestInfo
resolve_info(host_port
);
11406 AddressList ignored
;
11407 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11410 callback
.callback(),
11413 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11414 rv
= callback
.WaitForResult();
11417 HttpRequestInfo request2
;
11418 request2
.method
= "GET";
11419 request2
.url
= GURL("https://www.gmail.com/");
11420 request2
.load_flags
= 0;
11421 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11423 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11425 EXPECT_EQ(OK
, callback
.WaitForResult());
11427 response
= trans2
.GetResponseInfo();
11428 ASSERT_TRUE(response
!= NULL
);
11429 ASSERT_TRUE(response
->headers
.get() != NULL
);
11430 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11431 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11432 EXPECT_TRUE(response
->was_npn_negotiated
);
11433 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11434 EXPECT_EQ("hello!", response_data
);
11437 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11438 session_deps_
.use_alternate_protocols
= true;
11439 session_deps_
.next_protos
= SpdyNextProtos();
11441 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11442 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11443 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11444 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11445 pool_peer
.DisableDomainAuthenticationVerification();
11447 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11448 ssl
.SetNextProto(GetParam());
11449 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11451 scoped_ptr
<SpdyFrame
> host1_req(
11452 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11453 scoped_ptr
<SpdyFrame
> host2_req(
11454 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11455 MockWrite spdy_writes
[] = {
11456 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11458 scoped_ptr
<SpdyFrame
> host1_resp(
11459 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11460 scoped_ptr
<SpdyFrame
> host1_resp_body(
11461 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11462 scoped_ptr
<SpdyFrame
> host2_resp(
11463 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11464 scoped_ptr
<SpdyFrame
> host2_resp_body(
11465 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11466 MockRead spdy_reads
[] = {
11467 CreateMockRead(*host1_resp
, 1),
11468 CreateMockRead(*host1_resp_body
, 2),
11469 CreateMockRead(*host2_resp
, 4),
11470 CreateMockRead(*host2_resp_body
, 5),
11471 MockRead(ASYNC
, 0, 6),
11474 IPAddressNumber ip
;
11475 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11476 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11477 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11478 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11479 spdy_writes
, arraysize(spdy_writes
));
11480 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11482 TestCompletionCallback callback
;
11483 HttpRequestInfo request1
;
11484 request1
.method
= "GET";
11485 request1
.url
= GURL("https://www.example.org/");
11486 request1
.load_flags
= 0;
11487 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11489 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11490 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11491 EXPECT_EQ(OK
, callback
.WaitForResult());
11493 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11494 ASSERT_TRUE(response
!= NULL
);
11495 ASSERT_TRUE(response
->headers
.get() != NULL
);
11496 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11498 std::string response_data
;
11499 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11500 EXPECT_EQ("hello!", response_data
);
11502 HttpRequestInfo request2
;
11503 request2
.method
= "GET";
11504 request2
.url
= GURL("https://www.gmail.com/");
11505 request2
.load_flags
= 0;
11506 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11508 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11509 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11510 EXPECT_EQ(OK
, callback
.WaitForResult());
11512 response
= trans2
.GetResponseInfo();
11513 ASSERT_TRUE(response
!= NULL
);
11514 ASSERT_TRUE(response
->headers
.get() != NULL
);
11515 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11516 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11517 EXPECT_TRUE(response
->was_npn_negotiated
);
11518 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11519 EXPECT_EQ("hello!", response_data
);
11522 class OneTimeCachingHostResolver
: public HostResolver
{
11524 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11525 : host_port_(host_port
) {}
11526 ~OneTimeCachingHostResolver() override
{}
11528 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11530 // HostResolver methods:
11531 int Resolve(const RequestInfo
& info
,
11532 RequestPriority priority
,
11533 AddressList
* addresses
,
11534 const CompletionCallback
& callback
,
11535 RequestHandle
* out_req
,
11536 const BoundNetLog
& net_log
) override
{
11537 return host_resolver_
.Resolve(
11538 info
, priority
, addresses
, callback
, out_req
, net_log
);
11541 int ResolveFromCache(const RequestInfo
& info
,
11542 AddressList
* addresses
,
11543 const BoundNetLog
& net_log
) override
{
11544 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11545 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11546 host_resolver_
.GetHostCache()->clear();
11550 void CancelRequest(RequestHandle req
) override
{
11551 host_resolver_
.CancelRequest(req
);
11554 MockCachingHostResolver
* GetMockHostResolver() {
11555 return &host_resolver_
;
11559 MockCachingHostResolver host_resolver_
;
11560 const HostPortPair host_port_
;
11563 TEST_P(HttpNetworkTransactionTest
,
11564 UseIPConnectionPoolingWithHostCacheExpiration
) {
11565 session_deps_
.use_alternate_protocols
= true;
11566 session_deps_
.next_protos
= SpdyNextProtos();
11568 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11569 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11570 HttpNetworkSession::Params params
=
11571 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11572 params
.host_resolver
= &host_resolver
;
11573 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11574 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11575 pool_peer
.DisableDomainAuthenticationVerification();
11577 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11578 ssl
.SetNextProto(GetParam());
11579 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11581 scoped_ptr
<SpdyFrame
> host1_req(
11582 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11583 scoped_ptr
<SpdyFrame
> host2_req(
11584 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11585 MockWrite spdy_writes
[] = {
11586 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11588 scoped_ptr
<SpdyFrame
> host1_resp(
11589 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11590 scoped_ptr
<SpdyFrame
> host1_resp_body(
11591 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11592 scoped_ptr
<SpdyFrame
> host2_resp(
11593 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11594 scoped_ptr
<SpdyFrame
> host2_resp_body(
11595 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11596 MockRead spdy_reads
[] = {
11597 CreateMockRead(*host1_resp
, 1),
11598 CreateMockRead(*host1_resp_body
, 2),
11599 CreateMockRead(*host2_resp
, 4),
11600 CreateMockRead(*host2_resp_body
, 5),
11601 MockRead(ASYNC
, 0, 6),
11604 IPAddressNumber ip
;
11605 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11606 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11607 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11608 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11609 spdy_writes
, arraysize(spdy_writes
));
11610 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11612 TestCompletionCallback callback
;
11613 HttpRequestInfo request1
;
11614 request1
.method
= "GET";
11615 request1
.url
= GURL("https://www.example.org/");
11616 request1
.load_flags
= 0;
11617 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11619 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11620 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11621 EXPECT_EQ(OK
, callback
.WaitForResult());
11623 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11624 ASSERT_TRUE(response
!= NULL
);
11625 ASSERT_TRUE(response
->headers
.get() != NULL
);
11626 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11628 std::string response_data
;
11629 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11630 EXPECT_EQ("hello!", response_data
);
11632 // Preload cache entries into HostCache.
11633 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11634 AddressList ignored
;
11635 rv
= host_resolver
.Resolve(resolve_info
,
11638 callback
.callback(),
11641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11642 rv
= callback
.WaitForResult();
11645 HttpRequestInfo request2
;
11646 request2
.method
= "GET";
11647 request2
.url
= GURL("https://www.gmail.com/");
11648 request2
.load_flags
= 0;
11649 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11651 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11652 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11653 EXPECT_EQ(OK
, callback
.WaitForResult());
11655 response
= trans2
.GetResponseInfo();
11656 ASSERT_TRUE(response
!= NULL
);
11657 ASSERT_TRUE(response
->headers
.get() != NULL
);
11658 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11659 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11660 EXPECT_TRUE(response
->was_npn_negotiated
);
11661 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11662 EXPECT_EQ("hello!", response_data
);
11665 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11666 const std::string https_url
= "https://www.example.org:8080/";
11667 const std::string http_url
= "http://www.example.org:8080/";
11669 // SPDY GET for HTTPS URL
11670 scoped_ptr
<SpdyFrame
> req1(
11671 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11673 MockWrite writes1
[] = {
11674 CreateMockWrite(*req1
, 0),
11677 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11678 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11679 MockRead reads1
[] = {
11680 CreateMockRead(*resp1
, 1),
11681 CreateMockRead(*body1
, 2),
11682 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11685 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
11686 arraysize(writes1
));
11687 MockConnect
connect_data1(ASYNC
, OK
);
11688 data1
.set_connect_data(connect_data1
);
11690 // HTTP GET for the HTTP URL
11691 MockWrite writes2
[] = {
11692 MockWrite(ASYNC
, 0,
11693 "GET / HTTP/1.1\r\n"
11694 "Host: www.example.org:8080\r\n"
11695 "Connection: keep-alive\r\n\r\n"),
11698 MockRead reads2
[] = {
11699 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11700 MockRead(ASYNC
, 2, "hello"),
11701 MockRead(ASYNC
, OK
, 3),
11704 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
11705 arraysize(writes2
));
11707 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11708 ssl
.SetNextProto(GetParam());
11709 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11710 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11711 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11713 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11715 // Start the first transaction to set up the SpdySession
11716 HttpRequestInfo request1
;
11717 request1
.method
= "GET";
11718 request1
.url
= GURL(https_url
);
11719 request1
.load_flags
= 0;
11720 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11721 TestCompletionCallback callback1
;
11722 EXPECT_EQ(ERR_IO_PENDING
,
11723 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11724 base::MessageLoop::current()->RunUntilIdle();
11726 EXPECT_EQ(OK
, callback1
.WaitForResult());
11727 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11729 // Now, start the HTTP request
11730 HttpRequestInfo request2
;
11731 request2
.method
= "GET";
11732 request2
.url
= GURL(http_url
);
11733 request2
.load_flags
= 0;
11734 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11735 TestCompletionCallback callback2
;
11736 EXPECT_EQ(ERR_IO_PENDING
,
11737 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11738 base::MessageLoop::current()->RunUntilIdle();
11740 EXPECT_EQ(OK
, callback2
.WaitForResult());
11741 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11744 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
11746 void Run(bool pooling
, bool valid
) {
11747 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
11749 HostPortPair
alternative("www.example.org", 443);
11751 base::FilePath certs_dir
= GetTestCertsDirectory();
11752 scoped_refptr
<X509Certificate
> cert(
11753 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
11754 ASSERT_TRUE(cert
.get());
11755 bool common_name_fallback_used
;
11757 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
11759 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
11760 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11761 ssl
.SetNextProto(GetParam());
11763 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11765 // If pooling, then start a request to alternative first to create a
11767 std::string url0
= "https://www.example.org:443";
11768 // Second request to origin, which has an alternative service, and could
11769 // open a connection to the alternative host or pool to the existing one.
11770 std::string
url1("https://");
11771 url1
.append(origin
.host());
11772 url1
.append(":443");
11774 scoped_ptr
<SpdyFrame
> req0
;
11775 scoped_ptr
<SpdyFrame
> req1
;
11776 scoped_ptr
<SpdyFrame
> resp0
;
11777 scoped_ptr
<SpdyFrame
> body0
;
11778 scoped_ptr
<SpdyFrame
> resp1
;
11779 scoped_ptr
<SpdyFrame
> body1
;
11780 std::vector
<MockWrite
> writes
;
11781 std::vector
<MockRead
> reads
;
11784 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
11785 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
11787 writes
.push_back(CreateMockWrite(*req0
, 0));
11788 writes
.push_back(CreateMockWrite(*req1
, 3));
11790 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11791 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11792 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11793 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11795 reads
.push_back(CreateMockRead(*resp0
, 1));
11796 reads
.push_back(CreateMockRead(*body0
, 2));
11797 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
11798 reads
.push_back(CreateMockRead(*resp1
, 5));
11799 reads
.push_back(CreateMockRead(*body1
, 6));
11800 reads
.push_back(MockRead(ASYNC
, OK
, 7));
11802 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
11804 writes
.push_back(CreateMockWrite(*req1
, 0));
11806 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11807 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11809 reads
.push_back(CreateMockRead(*resp1
, 1));
11810 reads
.push_back(CreateMockRead(*body1
, 2));
11811 reads
.push_back(MockRead(ASYNC
, OK
, 3));
11814 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
11815 vector_as_array(&writes
), writes
.size());
11816 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11818 // Connection to the origin fails.
11819 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11820 StaticSocketDataProvider data_refused
;
11821 data_refused
.set_connect_data(mock_connect
);
11822 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
11824 session_deps_
.use_alternate_protocols
= true;
11825 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11826 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
11827 session
->http_server_properties();
11828 AlternativeService
alternative_service(
11829 AlternateProtocolFromNextProto(GetParam()), alternative
);
11830 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
11833 // First request to alternative.
11835 scoped_ptr
<HttpTransaction
> trans0(
11836 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11837 HttpRequestInfo request0
;
11838 request0
.method
= "GET";
11839 request0
.url
= GURL(url0
);
11840 request0
.load_flags
= 0;
11841 TestCompletionCallback callback0
;
11843 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
11844 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11845 rv
= callback0
.WaitForResult();
11849 // Second request to origin.
11850 scoped_ptr
<HttpTransaction
> trans1(
11851 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11852 HttpRequestInfo request1
;
11853 request1
.method
= "GET";
11854 request1
.url
= GURL(url1
);
11855 request1
.load_flags
= 0;
11856 TestCompletionCallback callback1
;
11858 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
11859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11860 base::MessageLoop::current()->RunUntilIdle();
11861 if (data
.IsReadPaused()) {
11862 data
.CompleteRead();
11864 rv
= callback1
.WaitForResult();
11869 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11871 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
11877 INSTANTIATE_TEST_CASE_P(NextProto
,
11878 AltSvcCertificateVerificationTest
,
11879 testing::Values(kProtoSPDY31
,
11883 // The alternative service host must exhibit a certificate that is valid for the
11884 // origin host. Test that this is enforced when pooling to an existing
11886 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
11890 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
11894 // The alternative service host must exhibit a certificate that is valid for the
11895 // origin host. Test that this is enforced when opening a new connection.
11896 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
11900 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
11904 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
11905 // with the alternative server. That connection should not be used.
11906 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
11907 HostPortPair
origin("origin.example.org", 443);
11908 HostPortPair
alternative("alternative.example.org", 443);
11910 // Negotiate HTTP/1.1 with alternative.example.org.
11911 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11912 ssl
.SetNextProto(kProtoHTTP11
);
11913 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11915 // No data should be read from the alternative, because HTTP/1.1 is
11917 StaticSocketDataProvider data
;
11918 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11920 // This test documents that an alternate Job should not be used if HTTP/1.1 is
11921 // negotiated. In order to test this, a failed connection to the origin is
11922 // mocked. This way the request relies on the alternate Job.
11923 StaticSocketDataProvider data_refused
;
11924 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
11925 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
11927 // Set up alternative service for origin.
11928 session_deps_
.use_alternate_protocols
= true;
11929 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11930 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
11931 session
->http_server_properties();
11932 AlternativeService
alternative_service(
11933 AlternateProtocolFromNextProto(GetParam()), alternative
);
11934 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
11937 scoped_ptr
<HttpTransaction
> trans(
11938 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11939 HttpRequestInfo request
;
11940 request
.method
= "GET";
11941 request
.url
= GURL("https://origin.example.org:443");
11942 request
.load_flags
= 0;
11943 TestCompletionCallback callback
;
11945 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
11946 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
11947 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11948 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
11951 // A request to a server with an alternative service fires two Jobs: one to the
11952 // origin, and an alternate one to the alternative server. If the former
11953 // succeeds, the request should succeed, even if the latter fails because
11954 // HTTP/1.1 is negotiated which is insufficient for alternative service.
11955 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
11956 HostPortPair
origin("origin.example.org", 443);
11957 HostPortPair
alternative("alternative.example.org", 443);
11959 // Negotiate HTTP/1.1 with alternative.
11960 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
11961 alternative_ssl
.SetNextProto(kProtoHTTP11
);
11962 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
11964 // No data should be read from the alternative, because HTTP/1.1 is
11966 StaticSocketDataProvider data
;
11967 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11969 // Negotiate HTTP/1.1 with origin.
11970 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
11971 origin_ssl
.SetNextProto(kProtoHTTP11
);
11972 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
11974 MockWrite http_writes
[] = {
11976 "GET / HTTP/1.1\r\n"
11977 "Host: origin.example.org\r\n"
11978 "Connection: keep-alive\r\n\r\n"),
11980 "GET /second HTTP/1.1\r\n"
11981 "Host: origin.example.org\r\n"
11982 "Connection: keep-alive\r\n\r\n"),
11985 MockRead http_reads
[] = {
11986 MockRead("HTTP/1.1 200 OK\r\n"),
11987 MockRead("Content-Type: text/html\r\n"),
11988 MockRead("Content-Length: 6\r\n\r\n"),
11989 MockRead("foobar"),
11990 MockRead("HTTP/1.1 200 OK\r\n"),
11991 MockRead("Content-Type: text/html\r\n"),
11992 MockRead("Content-Length: 7\r\n\r\n"),
11993 MockRead("another"),
11995 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
11996 http_writes
, arraysize(http_writes
));
11997 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
11999 // Set up alternative service for origin.
12000 session_deps_
.use_alternate_protocols
= true;
12001 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12002 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12003 session
->http_server_properties();
12004 AlternativeService
alternative_service(
12005 AlternateProtocolFromNextProto(GetParam()), alternative
);
12006 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12009 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12010 HttpRequestInfo request1
;
12011 request1
.method
= "GET";
12012 request1
.url
= GURL("https://origin.example.org:443");
12013 request1
.load_flags
= 0;
12014 TestCompletionCallback callback1
;
12016 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12017 rv
= callback1
.GetResult(rv
);
12020 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12021 ASSERT_TRUE(response1
!= nullptr);
12022 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12023 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12025 std::string response_data1
;
12026 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12027 EXPECT_EQ("foobar", response_data1
);
12029 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12030 // for alternative service.
12032 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12034 // Since |alternative_service| is broken, a second transaction to origin
12035 // should not start an alternate Job. It should pool to existing connection
12037 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12038 HttpRequestInfo request2
;
12039 request2
.method
= "GET";
12040 request2
.url
= GURL("https://origin.example.org:443/second");
12041 request2
.load_flags
= 0;
12042 TestCompletionCallback callback2
;
12044 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12045 rv
= callback2
.GetResult(rv
);
12048 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12049 ASSERT_TRUE(response2
!= nullptr);
12050 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12051 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12053 std::string response_data2
;
12054 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12055 EXPECT_EQ("another", response_data2
);
12058 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12059 // HTTP/1.1 socket open to the alternative server. That socket should not be
12061 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12062 HostPortPair
origin("origin.example.org", 443);
12063 HostPortPair
alternative("alternative.example.org", 443);
12064 std::string origin_url
= "https://origin.example.org:443";
12065 std::string alternative_url
= "https://alternative.example.org:443";
12067 // Negotiate HTTP/1.1 with alternative.example.org.
12068 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12069 ssl
.SetNextProto(kProtoHTTP11
);
12070 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12072 // HTTP/1.1 data for |request1| and |request2|.
12073 MockWrite http_writes
[] = {
12075 "GET / HTTP/1.1\r\n"
12076 "Host: alternative.example.org\r\n"
12077 "Connection: keep-alive\r\n\r\n"),
12079 "GET / HTTP/1.1\r\n"
12080 "Host: alternative.example.org\r\n"
12081 "Connection: keep-alive\r\n\r\n"),
12084 MockRead http_reads
[] = {
12086 "HTTP/1.1 200 OK\r\n"
12087 "Content-Type: text/html; charset=iso-8859-1\r\n"
12088 "Content-Length: 40\r\n\r\n"
12089 "first HTTP/1.1 response from alternative"),
12091 "HTTP/1.1 200 OK\r\n"
12092 "Content-Type: text/html; charset=iso-8859-1\r\n"
12093 "Content-Length: 41\r\n\r\n"
12094 "second HTTP/1.1 response from alternative"),
12096 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12097 http_writes
, arraysize(http_writes
));
12098 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12100 // This test documents that an alternate Job should not pool to an already
12101 // existing HTTP/1.1 connection. In order to test this, a failed connection
12102 // to the origin is mocked. This way |request2| relies on the alternate Job.
12103 StaticSocketDataProvider data_refused
;
12104 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12105 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12107 // Set up alternative service for origin.
12108 session_deps_
.use_alternate_protocols
= true;
12109 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12110 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12111 session
->http_server_properties();
12112 AlternativeService
alternative_service(
12113 AlternateProtocolFromNextProto(GetParam()), alternative
);
12114 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12117 // First transaction to alternative to open an HTTP/1.1 socket.
12118 scoped_ptr
<HttpTransaction
> trans1(
12119 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12120 HttpRequestInfo request1
;
12121 request1
.method
= "GET";
12122 request1
.url
= GURL(alternative_url
);
12123 request1
.load_flags
= 0;
12124 TestCompletionCallback callback1
;
12126 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12127 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12128 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12129 ASSERT_TRUE(response1
);
12130 ASSERT_TRUE(response1
->headers
.get());
12131 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12132 EXPECT_TRUE(response1
->was_npn_negotiated
);
12133 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12134 std::string response_data1
;
12135 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12136 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12138 // Request for origin.example.org, which has an alternative service. This
12139 // will start two Jobs: the alternative looks for connections to pool to,
12140 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12141 // open other connections to alternative server. The Job to origin fails, so
12142 // this request fails.
12143 scoped_ptr
<HttpTransaction
> trans2(
12144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12145 HttpRequestInfo request2
;
12146 request2
.method
= "GET";
12147 request2
.url
= GURL(origin_url
);
12148 request2
.load_flags
= 0;
12149 TestCompletionCallback callback2
;
12151 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12152 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12154 // Another transaction to alternative. This is to test that the HTTP/1.1
12155 // socket is still open and in the pool.
12156 scoped_ptr
<HttpTransaction
> trans3(
12157 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12158 HttpRequestInfo request3
;
12159 request3
.method
= "GET";
12160 request3
.url
= GURL(alternative_url
);
12161 request3
.load_flags
= 0;
12162 TestCompletionCallback callback3
;
12164 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12165 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12166 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12167 ASSERT_TRUE(response3
);
12168 ASSERT_TRUE(response3
->headers
.get());
12169 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12170 EXPECT_TRUE(response3
->was_npn_negotiated
);
12171 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12172 std::string response_data3
;
12173 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12174 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12177 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12178 const std::string https_url
= "https://www.example.org:8080/";
12179 const std::string http_url
= "http://www.example.org:8080/";
12181 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12182 const HostPortPair
host_port_pair("www.example.org", 8080);
12183 scoped_ptr
<SpdyFrame
> connect(
12184 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12185 scoped_ptr
<SpdyFrame
> req1(
12186 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12187 scoped_ptr
<SpdyFrame
> wrapped_req1(
12188 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12190 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12191 SpdyHeaderBlock req2_block
;
12192 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12193 req2_block
[spdy_util_
.GetPathKey()] = "/";
12194 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12195 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12196 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12197 scoped_ptr
<SpdyFrame
> req2(
12198 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12200 MockWrite writes1
[] = {
12201 CreateMockWrite(*connect
, 0),
12202 CreateMockWrite(*wrapped_req1
, 2),
12203 CreateMockWrite(*req2
, 5),
12206 scoped_ptr
<SpdyFrame
> conn_resp(
12207 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12208 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12209 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12210 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12211 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12212 scoped_ptr
<SpdyFrame
> wrapped_body1(
12213 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12214 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12215 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12216 MockRead reads1
[] = {
12217 CreateMockRead(*conn_resp
, 1),
12218 CreateMockRead(*wrapped_resp1
, 3),
12219 CreateMockRead(*wrapped_body1
, 4),
12220 CreateMockRead(*resp2
, 6),
12221 CreateMockRead(*body2
, 7),
12222 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12225 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12226 writes1
, arraysize(writes1
));
12227 MockConnect
connect_data1(ASYNC
, OK
);
12228 data1
.set_connect_data(connect_data1
);
12230 session_deps_
.proxy_service
.reset(
12231 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12233 session_deps_
.net_log
= &log
;
12234 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12235 ssl1
.SetNextProto(GetParam());
12236 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12237 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12238 ssl2
.SetNextProto(GetParam());
12239 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12240 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12242 scoped_refptr
<HttpNetworkSession
> session(
12243 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12245 // Start the first transaction to set up the SpdySession
12246 HttpRequestInfo request1
;
12247 request1
.method
= "GET";
12248 request1
.url
= GURL(https_url
);
12249 request1
.load_flags
= 0;
12250 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12251 TestCompletionCallback callback1
;
12252 EXPECT_EQ(ERR_IO_PENDING
,
12253 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12254 base::MessageLoop::current()->RunUntilIdle();
12257 EXPECT_EQ(OK
, callback1
.WaitForResult());
12258 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12260 LoadTimingInfo load_timing_info1
;
12261 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12262 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12263 CONNECT_TIMING_HAS_SSL_TIMES
);
12265 // Now, start the HTTP request
12266 HttpRequestInfo request2
;
12267 request2
.method
= "GET";
12268 request2
.url
= GURL(http_url
);
12269 request2
.load_flags
= 0;
12270 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12271 TestCompletionCallback callback2
;
12272 EXPECT_EQ(ERR_IO_PENDING
,
12273 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12274 base::MessageLoop::current()->RunUntilIdle();
12277 EXPECT_EQ(OK
, callback2
.WaitForResult());
12278 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12280 LoadTimingInfo load_timing_info2
;
12281 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12282 // The established SPDY sessions is considered reused by the HTTP request.
12283 TestLoadTimingReusedWithPac(load_timing_info2
);
12284 // HTTP requests over a SPDY session should have a different connection
12285 // socket_log_id than requests over a tunnel.
12286 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12289 // Test that in the case where we have a SPDY session to a SPDY proxy
12290 // that we do not pool other origins that resolve to the same IP when
12291 // the certificate does not match the new origin.
12292 // http://crbug.com/134690
12293 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12294 const std::string url1
= "http://www.example.org/";
12295 const std::string url2
= "https://news.example.org/";
12296 const std::string ip_addr
= "1.2.3.4";
12298 // SPDY GET for HTTP URL (through SPDY proxy)
12299 scoped_ptr
<SpdyHeaderBlock
> headers(
12300 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12301 scoped_ptr
<SpdyFrame
> req1(
12302 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12304 MockWrite writes1
[] = {
12305 CreateMockWrite(*req1
, 0),
12308 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12309 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12310 MockRead reads1
[] = {
12311 CreateMockRead(*resp1
, 1),
12312 CreateMockRead(*body1
, 2),
12313 MockRead(ASYNC
, OK
, 3) // EOF
12316 scoped_ptr
<DeterministicSocketData
> data1(
12317 new DeterministicSocketData(reads1
, arraysize(reads1
),
12318 writes1
, arraysize(writes1
)));
12319 IPAddressNumber ip
;
12320 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12321 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12322 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12323 data1
->set_connect_data(connect_data1
);
12325 // SPDY GET for HTTPS URL (direct)
12326 scoped_ptr
<SpdyFrame
> req2(
12327 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12329 MockWrite writes2
[] = {
12330 CreateMockWrite(*req2
, 0),
12333 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12334 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12335 MockRead reads2
[] = {
12336 CreateMockRead(*resp2
, 1),
12337 CreateMockRead(*body2
, 2),
12338 MockRead(ASYNC
, OK
, 3) // EOF
12341 scoped_ptr
<DeterministicSocketData
> data2(
12342 new DeterministicSocketData(reads2
, arraysize(reads2
),
12343 writes2
, arraysize(writes2
)));
12344 MockConnect
connect_data2(ASYNC
, OK
);
12345 data2
->set_connect_data(connect_data2
);
12347 // Set up a proxy config that sends HTTP requests to a proxy, and
12348 // all others direct.
12349 ProxyConfig proxy_config
;
12350 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12351 session_deps_
.proxy_service
.reset(new ProxyService(
12352 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12354 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12355 ssl1
.SetNextProto(GetParam());
12356 // Load a valid cert. Note, that this does not need to
12357 // be valid for proxy because the MockSSLClientSocket does
12358 // not actually verify it. But SpdySession will use this
12359 // to see if it is valid for the new origin
12360 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12361 ASSERT_TRUE(ssl1
.cert
.get());
12362 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12363 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12366 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12367 ssl2
.SetNextProto(GetParam());
12368 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12369 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12372 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12373 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12374 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12376 scoped_refptr
<HttpNetworkSession
> session(
12377 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12379 // Start the first transaction to set up the SpdySession
12380 HttpRequestInfo request1
;
12381 request1
.method
= "GET";
12382 request1
.url
= GURL(url1
);
12383 request1
.load_flags
= 0;
12384 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12385 TestCompletionCallback callback1
;
12386 ASSERT_EQ(ERR_IO_PENDING
,
12387 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12390 ASSERT_TRUE(callback1
.have_result());
12391 EXPECT_EQ(OK
, callback1
.WaitForResult());
12392 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12394 // Now, start the HTTP request
12395 HttpRequestInfo request2
;
12396 request2
.method
= "GET";
12397 request2
.url
= GURL(url2
);
12398 request2
.load_flags
= 0;
12399 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12400 TestCompletionCallback callback2
;
12401 EXPECT_EQ(ERR_IO_PENDING
,
12402 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12403 base::MessageLoop::current()->RunUntilIdle();
12406 ASSERT_TRUE(callback2
.have_result());
12407 EXPECT_EQ(OK
, callback2
.WaitForResult());
12408 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12411 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12412 // error) in SPDY session, removes the socket from pool and closes the SPDY
12413 // session. Verify that new url's from the same HttpNetworkSession (and a new
12414 // SpdySession) do work. http://crbug.com/224701
12415 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12416 const std::string https_url
= "https://www.example.org/";
12418 MockRead reads1
[] = {
12419 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12422 SequencedSocketData
data1(reads1
, arraysize(reads1
), NULL
, 0);
12424 scoped_ptr
<SpdyFrame
> req2(
12425 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12426 MockWrite writes2
[] = {
12427 CreateMockWrite(*req2
, 0),
12430 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12431 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12432 MockRead reads2
[] = {
12433 CreateMockRead(*resp2
, 1),
12434 CreateMockRead(*body2
, 2),
12435 MockRead(ASYNC
, OK
, 3) // EOF
12438 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12439 arraysize(writes2
));
12441 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12442 ssl1
.SetNextProto(GetParam());
12443 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12444 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12446 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12447 ssl2
.SetNextProto(GetParam());
12448 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12449 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12451 scoped_refptr
<HttpNetworkSession
> session(
12452 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
12454 // Start the first transaction to set up the SpdySession and verify that
12455 // connection was closed.
12456 HttpRequestInfo request1
;
12457 request1
.method
= "GET";
12458 request1
.url
= GURL(https_url
);
12459 request1
.load_flags
= 0;
12460 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12461 TestCompletionCallback callback1
;
12462 EXPECT_EQ(ERR_IO_PENDING
,
12463 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12464 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12466 // Now, start the second request and make sure it succeeds.
12467 HttpRequestInfo request2
;
12468 request2
.method
= "GET";
12469 request2
.url
= GURL(https_url
);
12470 request2
.load_flags
= 0;
12471 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12472 TestCompletionCallback callback2
;
12473 EXPECT_EQ(ERR_IO_PENDING
,
12474 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12476 ASSERT_EQ(OK
, callback2
.WaitForResult());
12477 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12480 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12481 session_deps_
.next_protos
= SpdyNextProtos();
12482 ClientSocketPoolManager::set_max_sockets_per_group(
12483 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12484 ClientSocketPoolManager::set_max_sockets_per_pool(
12485 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12487 // Use two different hosts with different IPs so they don't get pooled.
12488 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12489 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12492 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12493 ssl1
.SetNextProto(GetParam());
12494 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12495 ssl2
.SetNextProto(GetParam());
12496 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12497 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12499 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12500 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12501 MockWrite spdy1_writes
[] = {
12502 CreateMockWrite(*host1_req
, 0),
12504 scoped_ptr
<SpdyFrame
> host1_resp(
12505 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12506 scoped_ptr
<SpdyFrame
> host1_resp_body(
12507 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12508 MockRead spdy1_reads
[] = {
12509 CreateMockRead(*host1_resp
, 1),
12510 CreateMockRead(*host1_resp_body
, 2),
12511 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12514 scoped_ptr
<SequencedSocketData
> spdy1_data(
12515 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12516 arraysize(spdy1_writes
)));
12517 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12519 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12520 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12521 MockWrite spdy2_writes
[] = {
12522 CreateMockWrite(*host2_req
, 0),
12524 scoped_ptr
<SpdyFrame
> host2_resp(
12525 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12526 scoped_ptr
<SpdyFrame
> host2_resp_body(
12527 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12528 MockRead spdy2_reads
[] = {
12529 CreateMockRead(*host2_resp
, 1),
12530 CreateMockRead(*host2_resp_body
, 2),
12531 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12534 scoped_ptr
<SequencedSocketData
> spdy2_data(
12535 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12536 arraysize(spdy2_writes
)));
12537 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12539 MockWrite http_write
[] = {
12540 MockWrite("GET / HTTP/1.1\r\n"
12541 "Host: www.a.com\r\n"
12542 "Connection: keep-alive\r\n\r\n"),
12545 MockRead http_read
[] = {
12546 MockRead("HTTP/1.1 200 OK\r\n"),
12547 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12548 MockRead("Content-Length: 6\r\n\r\n"),
12549 MockRead("hello!"),
12551 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12552 http_write
, arraysize(http_write
));
12553 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12555 HostPortPair
host_port_pair_a("www.a.com", 443);
12556 SpdySessionKey
spdy_session_key_a(
12557 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12559 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12561 TestCompletionCallback callback
;
12562 HttpRequestInfo request1
;
12563 request1
.method
= "GET";
12564 request1
.url
= GURL("https://www.a.com/");
12565 request1
.load_flags
= 0;
12566 scoped_ptr
<HttpNetworkTransaction
> trans(
12567 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12569 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12570 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12571 EXPECT_EQ(OK
, callback
.WaitForResult());
12573 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12574 ASSERT_TRUE(response
!= NULL
);
12575 ASSERT_TRUE(response
->headers
.get() != NULL
);
12576 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12577 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12578 EXPECT_TRUE(response
->was_npn_negotiated
);
12580 std::string response_data
;
12581 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12582 EXPECT_EQ("hello!", response_data
);
12585 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12587 HostPortPair
host_port_pair_b("www.b.com", 443);
12588 SpdySessionKey
spdy_session_key_b(
12589 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12591 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12592 HttpRequestInfo request2
;
12593 request2
.method
= "GET";
12594 request2
.url
= GURL("https://www.b.com/");
12595 request2
.load_flags
= 0;
12596 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12598 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12599 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12600 EXPECT_EQ(OK
, callback
.WaitForResult());
12602 response
= trans
->GetResponseInfo();
12603 ASSERT_TRUE(response
!= NULL
);
12604 ASSERT_TRUE(response
->headers
.get() != NULL
);
12605 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12606 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12607 EXPECT_TRUE(response
->was_npn_negotiated
);
12608 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12609 EXPECT_EQ("hello!", response_data
);
12611 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12613 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12615 HostPortPair
host_port_pair_a1("www.a.com", 80);
12616 SpdySessionKey
spdy_session_key_a1(
12617 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12619 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12620 HttpRequestInfo request3
;
12621 request3
.method
= "GET";
12622 request3
.url
= GURL("http://www.a.com/");
12623 request3
.load_flags
= 0;
12624 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12626 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12627 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12628 EXPECT_EQ(OK
, callback
.WaitForResult());
12630 response
= trans
->GetResponseInfo();
12631 ASSERT_TRUE(response
!= NULL
);
12632 ASSERT_TRUE(response
->headers
.get() != NULL
);
12633 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12634 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12635 EXPECT_FALSE(response
->was_npn_negotiated
);
12636 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12637 EXPECT_EQ("hello!", response_data
);
12639 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12641 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12644 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12645 HttpRequestInfo request
;
12646 request
.method
= "GET";
12647 request
.url
= GURL("http://www.example.org/");
12648 request
.load_flags
= 0;
12650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12651 scoped_ptr
<HttpTransaction
> trans(
12652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12654 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12655 StaticSocketDataProvider data
;
12656 data
.set_connect_data(mock_connect
);
12657 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12659 TestCompletionCallback callback
;
12661 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12662 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12664 rv
= callback
.WaitForResult();
12665 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12667 // We don't care whether this succeeds or fails, but it shouldn't crash.
12668 HttpRequestHeaders request_headers
;
12669 trans
->GetFullRequestHeaders(&request_headers
);
12671 ConnectionAttempts attempts
;
12672 trans
->GetConnectionAttempts(&attempts
);
12673 ASSERT_EQ(1u, attempts
.size());
12674 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12677 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12678 HttpRequestInfo request
;
12679 request
.method
= "GET";
12680 request
.url
= GURL("http://www.example.org/");
12681 request
.load_flags
= 0;
12683 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12684 scoped_ptr
<HttpTransaction
> trans(
12685 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12687 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12688 StaticSocketDataProvider data
;
12689 data
.set_connect_data(mock_connect
);
12690 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12692 TestCompletionCallback callback
;
12694 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12697 rv
= callback
.WaitForResult();
12698 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12700 // We don't care whether this succeeds or fails, but it shouldn't crash.
12701 HttpRequestHeaders request_headers
;
12702 trans
->GetFullRequestHeaders(&request_headers
);
12704 ConnectionAttempts attempts
;
12705 trans
->GetConnectionAttempts(&attempts
);
12706 ASSERT_EQ(1u, attempts
.size());
12707 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12710 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12711 HttpRequestInfo request
;
12712 request
.method
= "GET";
12713 request
.url
= GURL("http://www.example.org/");
12714 request
.load_flags
= 0;
12716 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12717 scoped_ptr
<HttpTransaction
> trans(
12718 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12720 MockWrite data_writes
[] = {
12721 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12723 MockRead data_reads
[] = {
12724 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12727 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12728 data_writes
, arraysize(data_writes
));
12729 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12731 TestCompletionCallback callback
;
12733 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12734 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12736 rv
= callback
.WaitForResult();
12737 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12739 HttpRequestHeaders request_headers
;
12740 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12741 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12744 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12745 HttpRequestInfo request
;
12746 request
.method
= "GET";
12747 request
.url
= GURL("http://www.example.org/");
12748 request
.load_flags
= 0;
12750 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12751 scoped_ptr
<HttpTransaction
> trans(
12752 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12754 MockWrite data_writes
[] = {
12755 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12757 MockRead data_reads
[] = {
12758 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12761 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12762 data_writes
, arraysize(data_writes
));
12763 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12765 TestCompletionCallback callback
;
12767 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12768 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12770 rv
= callback
.WaitForResult();
12771 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12773 HttpRequestHeaders request_headers
;
12774 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12775 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12778 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12779 HttpRequestInfo request
;
12780 request
.method
= "GET";
12781 request
.url
= GURL("http://www.example.org/");
12782 request
.load_flags
= 0;
12784 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12785 scoped_ptr
<HttpTransaction
> trans(
12786 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12788 MockWrite data_writes
[] = {
12790 "GET / HTTP/1.1\r\n"
12791 "Host: www.example.org\r\n"
12792 "Connection: keep-alive\r\n\r\n"),
12794 MockRead data_reads
[] = {
12795 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12798 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12799 data_writes
, arraysize(data_writes
));
12800 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12802 TestCompletionCallback callback
;
12804 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12805 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12807 rv
= callback
.WaitForResult();
12808 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12810 HttpRequestHeaders request_headers
;
12811 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12812 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12815 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12816 HttpRequestInfo request
;
12817 request
.method
= "GET";
12818 request
.url
= GURL("http://www.example.org/");
12819 request
.load_flags
= 0;
12821 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12822 scoped_ptr
<HttpTransaction
> trans(
12823 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12825 MockWrite data_writes
[] = {
12827 "GET / HTTP/1.1\r\n"
12828 "Host: www.example.org\r\n"
12829 "Connection: keep-alive\r\n\r\n"),
12831 MockRead data_reads
[] = {
12832 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12835 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12836 data_writes
, arraysize(data_writes
));
12837 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12839 TestCompletionCallback callback
;
12841 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12844 rv
= callback
.WaitForResult();
12845 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12847 HttpRequestHeaders request_headers
;
12848 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12849 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12852 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12853 HttpRequestInfo request
;
12854 request
.method
= "GET";
12855 request
.url
= GURL("http://www.example.org/");
12856 request
.load_flags
= 0;
12857 request
.extra_headers
.SetHeader("X-Foo", "bar");
12859 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12860 scoped_ptr
<HttpTransaction
> trans(
12861 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12863 MockWrite data_writes
[] = {
12865 "GET / HTTP/1.1\r\n"
12866 "Host: www.example.org\r\n"
12867 "Connection: keep-alive\r\n"
12868 "X-Foo: bar\r\n\r\n"),
12870 MockRead data_reads
[] = {
12871 MockRead("HTTP/1.1 200 OK\r\n"
12872 "Content-Length: 5\r\n\r\n"
12874 MockRead(ASYNC
, ERR_UNEXPECTED
),
12877 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12878 data_writes
, arraysize(data_writes
));
12879 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12881 TestCompletionCallback callback
;
12883 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12884 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12886 rv
= callback
.WaitForResult();
12889 HttpRequestHeaders request_headers
;
12890 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12892 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12893 EXPECT_EQ("bar", foo
);
12898 // Fake HttpStream that simply records calls to SetPriority().
12899 class FakeStream
: public HttpStream
,
12900 public base::SupportsWeakPtr
<FakeStream
> {
12902 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12903 ~FakeStream() override
{}
12905 RequestPriority
priority() const { return priority_
; }
12907 int InitializeStream(const HttpRequestInfo
* request_info
,
12908 RequestPriority priority
,
12909 const BoundNetLog
& net_log
,
12910 const CompletionCallback
& callback
) override
{
12911 return ERR_IO_PENDING
;
12914 int SendRequest(const HttpRequestHeaders
& request_headers
,
12915 HttpResponseInfo
* response
,
12916 const CompletionCallback
& callback
) override
{
12918 return ERR_UNEXPECTED
;
12921 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12923 return ERR_UNEXPECTED
;
12926 int ReadResponseBody(IOBuffer
* buf
,
12928 const CompletionCallback
& callback
) override
{
12930 return ERR_UNEXPECTED
;
12933 void Close(bool not_reusable
) override
{}
12935 bool IsResponseBodyComplete() const override
{
12940 bool CanFindEndOfResponse() const override
{ return false; }
12942 bool IsConnectionReused() const override
{
12947 void SetConnectionReused() override
{ ADD_FAILURE(); }
12949 bool IsConnectionReusable() const override
{
12954 int64
GetTotalReceivedBytes() const override
{
12959 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12964 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
12966 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12970 bool IsSpdyHttpStream() const override
{
12975 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
12977 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12979 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
12981 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
12984 RequestPriority priority_
;
12986 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12989 // Fake HttpStreamRequest that simply records calls to SetPriority()
12990 // and vends FakeStreams with its current priority.
12991 class FakeStreamRequest
: public HttpStreamRequest
,
12992 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12994 FakeStreamRequest(RequestPriority priority
,
12995 HttpStreamRequest::Delegate
* delegate
)
12996 : priority_(priority
),
12997 delegate_(delegate
),
12998 websocket_stream_create_helper_(NULL
) {}
13000 FakeStreamRequest(RequestPriority priority
,
13001 HttpStreamRequest::Delegate
* delegate
,
13002 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13003 : priority_(priority
),
13004 delegate_(delegate
),
13005 websocket_stream_create_helper_(create_helper
) {}
13007 ~FakeStreamRequest() override
{}
13009 RequestPriority
priority() const { return priority_
; }
13011 const WebSocketHandshakeStreamBase::CreateHelper
*
13012 websocket_stream_create_helper() const {
13013 return websocket_stream_create_helper_
;
13016 // Create a new FakeStream and pass it to the request's
13017 // delegate. Returns a weak pointer to the FakeStream.
13018 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13019 FakeStream
* fake_stream
= new FakeStream(priority_
);
13020 // Do this before calling OnStreamReady() as OnStreamReady() may
13021 // immediately delete |fake_stream|.
13022 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13023 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13024 return weak_stream
;
13027 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13029 return ERR_UNEXPECTED
;
13032 LoadState
GetLoadState() const override
{
13034 return LoadState();
13037 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13039 bool was_npn_negotiated() const override
{ return false; }
13041 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13043 bool using_spdy() const override
{ return false; }
13045 const ConnectionAttempts
& connection_attempts() const override
{
13046 static ConnectionAttempts no_attempts
;
13047 return no_attempts
;
13051 RequestPriority priority_
;
13052 HttpStreamRequest::Delegate
* const delegate_
;
13053 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13055 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13058 // Fake HttpStreamFactory that vends FakeStreamRequests.
13059 class FakeStreamFactory
: public HttpStreamFactory
{
13061 FakeStreamFactory() {}
13062 ~FakeStreamFactory() override
{}
13064 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13065 // RequestStream() (which may be NULL if it was destroyed already).
13066 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13067 return last_stream_request_
;
13070 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13071 RequestPriority priority
,
13072 const SSLConfig
& server_ssl_config
,
13073 const SSLConfig
& proxy_ssl_config
,
13074 HttpStreamRequest::Delegate
* delegate
,
13075 const BoundNetLog
& net_log
) override
{
13076 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13077 last_stream_request_
= fake_request
->AsWeakPtr();
13078 return fake_request
;
13081 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13082 const HttpRequestInfo
& info
,
13083 RequestPriority priority
,
13084 const SSLConfig
& server_ssl_config
,
13085 const SSLConfig
& proxy_ssl_config
,
13086 HttpStreamRequest::Delegate
* delegate
,
13087 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13088 const BoundNetLog
& net_log
) override
{
13089 FakeStreamRequest
* fake_request
=
13090 new FakeStreamRequest(priority
, delegate
, create_helper
);
13091 last_stream_request_
= fake_request
->AsWeakPtr();
13092 return fake_request
;
13095 void PreconnectStreams(int num_streams
,
13096 const HttpRequestInfo
& info
,
13097 const SSLConfig
& server_ssl_config
,
13098 const SSLConfig
& proxy_ssl_config
) override
{
13102 const HostMappingRules
* GetHostMappingRules() const override
{
13108 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13110 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13113 // TODO(ricea): Maybe unify this with the one in
13114 // url_request_http_job_unittest.cc ?
13115 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13117 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13119 : state_(connection
.release(), using_proxy
) {}
13121 // Fake implementation of HttpStreamBase methods.
13122 // This ends up being quite "real" because this object has to really send data
13123 // on the mock socket. It might be easier to use the real implementation, but
13124 // the fact that the WebSocket code is not compiled on iOS makes that
13126 int InitializeStream(const HttpRequestInfo
* request_info
,
13127 RequestPriority priority
,
13128 const BoundNetLog
& net_log
,
13129 const CompletionCallback
& callback
) override
{
13130 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13134 int SendRequest(const HttpRequestHeaders
& request_headers
,
13135 HttpResponseInfo
* response
,
13136 const CompletionCallback
& callback
) override
{
13137 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13138 response
, callback
);
13141 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13142 return parser()->ReadResponseHeaders(callback
);
13145 int ReadResponseBody(IOBuffer
* buf
,
13147 const CompletionCallback
& callback
) override
{
13149 return ERR_IO_PENDING
;
13152 void Close(bool not_reusable
) override
{
13154 parser()->Close(true);
13157 bool IsResponseBodyComplete() const override
{
13162 bool CanFindEndOfResponse() const override
{
13163 return parser()->CanFindEndOfResponse();
13166 bool IsConnectionReused() const override
{
13170 void SetConnectionReused() override
{ NOTREACHED(); }
13172 bool IsConnectionReusable() const override
{
13177 int64
GetTotalReceivedBytes() const override
{
13182 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13187 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13189 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13193 bool IsSpdyHttpStream() const override
{
13198 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13200 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13202 UploadProgress
GetUploadProgress() const override
{
13204 return UploadProgress();
13207 HttpStream
* RenewStreamForAuth() override
{
13212 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13213 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13215 return scoped_ptr
<WebSocketStream
>();
13219 HttpStreamParser
* parser() const { return state_
.parser(); }
13220 HttpBasicState state_
;
13222 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13225 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13227 class FakeWebSocketStreamCreateHelper
:
13228 public WebSocketHandshakeStreamBase::CreateHelper
{
13230 WebSocketHandshakeStreamBase
* CreateBasicStream(
13231 scoped_ptr
<ClientSocketHandle
> connection
,
13232 bool using_proxy
) override
{
13233 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13237 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13238 const base::WeakPtr
<SpdySession
>& session
,
13239 bool use_relative_url
) override
{
13244 ~FakeWebSocketStreamCreateHelper() override
{}
13246 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13248 return scoped_ptr
<WebSocketStream
>();
13254 // Make sure that HttpNetworkTransaction passes on its priority to its
13255 // stream request on start.
13256 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13257 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13258 HttpNetworkSessionPeer
peer(session
);
13259 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13260 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13262 HttpNetworkTransaction
trans(LOW
, session
.get());
13264 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13266 HttpRequestInfo request
;
13267 TestCompletionCallback callback
;
13268 EXPECT_EQ(ERR_IO_PENDING
,
13269 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13271 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13272 fake_factory
->last_stream_request();
13273 ASSERT_TRUE(fake_request
!= NULL
);
13274 EXPECT_EQ(LOW
, fake_request
->priority());
13277 // Make sure that HttpNetworkTransaction passes on its priority
13278 // updates to its stream request.
13279 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13280 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13281 HttpNetworkSessionPeer
peer(session
);
13282 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13283 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13285 HttpNetworkTransaction
trans(LOW
, session
.get());
13287 HttpRequestInfo request
;
13288 TestCompletionCallback callback
;
13289 EXPECT_EQ(ERR_IO_PENDING
,
13290 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13292 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13293 fake_factory
->last_stream_request();
13294 ASSERT_TRUE(fake_request
!= NULL
);
13295 EXPECT_EQ(LOW
, fake_request
->priority());
13297 trans
.SetPriority(LOWEST
);
13298 ASSERT_TRUE(fake_request
!= NULL
);
13299 EXPECT_EQ(LOWEST
, fake_request
->priority());
13302 // Make sure that HttpNetworkTransaction passes on its priority
13303 // updates to its stream.
13304 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13305 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13306 HttpNetworkSessionPeer
peer(session
);
13307 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13308 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13310 HttpNetworkTransaction
trans(LOW
, session
.get());
13312 HttpRequestInfo request
;
13313 TestCompletionCallback callback
;
13314 EXPECT_EQ(ERR_IO_PENDING
,
13315 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13317 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13318 fake_factory
->last_stream_request();
13319 ASSERT_TRUE(fake_request
!= NULL
);
13320 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13321 ASSERT_TRUE(fake_stream
!= NULL
);
13322 EXPECT_EQ(LOW
, fake_stream
->priority());
13324 trans
.SetPriority(LOWEST
);
13325 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13328 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13329 // The same logic needs to be tested for both ws: and wss: schemes, but this
13330 // test is already parameterised on NextProto, so it uses a loop to verify
13331 // that the different schemes work.
13332 std::string test_cases
[] = {"ws://www.example.org/",
13333 "wss://www.example.org/"};
13334 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13335 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13336 HttpNetworkSessionPeer
peer(session
);
13337 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13338 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13339 peer
.SetHttpStreamFactoryForWebSocket(
13340 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13342 HttpNetworkTransaction
trans(LOW
, session
.get());
13343 trans
.SetWebSocketHandshakeStreamCreateHelper(
13344 &websocket_stream_create_helper
);
13346 HttpRequestInfo request
;
13347 TestCompletionCallback callback
;
13348 request
.method
= "GET";
13349 request
.url
= GURL(test_cases
[i
]);
13351 EXPECT_EQ(ERR_IO_PENDING
,
13352 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13354 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13355 fake_factory
->last_stream_request();
13356 ASSERT_TRUE(fake_request
!= NULL
);
13357 EXPECT_EQ(&websocket_stream_create_helper
,
13358 fake_request
->websocket_stream_create_helper());
13362 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13363 // if the transport socket pool is stalled on the global socket limit.
13364 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13365 ClientSocketPoolManager::set_max_sockets_per_group(
13366 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13367 ClientSocketPoolManager::set_max_sockets_per_pool(
13368 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13370 // Set up SSL request.
13372 HttpRequestInfo ssl_request
;
13373 ssl_request
.method
= "GET";
13374 ssl_request
.url
= GURL("https://www.example.org/");
13376 MockWrite ssl_writes
[] = {
13378 "GET / HTTP/1.1\r\n"
13379 "Host: www.example.org\r\n"
13380 "Connection: keep-alive\r\n\r\n"),
13382 MockRead ssl_reads
[] = {
13383 MockRead("HTTP/1.1 200 OK\r\n"),
13384 MockRead("Content-Length: 11\r\n\r\n"),
13385 MockRead("hello world"),
13386 MockRead(SYNCHRONOUS
, OK
),
13388 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13389 ssl_writes
, arraysize(ssl_writes
));
13390 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13392 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13393 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13395 // Set up HTTP request.
13397 HttpRequestInfo http_request
;
13398 http_request
.method
= "GET";
13399 http_request
.url
= GURL("http://www.example.org/");
13401 MockWrite http_writes
[] = {
13403 "GET / HTTP/1.1\r\n"
13404 "Host: www.example.org\r\n"
13405 "Connection: keep-alive\r\n\r\n"),
13407 MockRead http_reads
[] = {
13408 MockRead("HTTP/1.1 200 OK\r\n"),
13409 MockRead("Content-Length: 7\r\n\r\n"),
13410 MockRead("falafel"),
13411 MockRead(SYNCHRONOUS
, OK
),
13413 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13414 http_writes
, arraysize(http_writes
));
13415 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13417 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13419 // Start the SSL request.
13420 TestCompletionCallback ssl_callback
;
13421 scoped_ptr
<HttpTransaction
> ssl_trans(
13422 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13423 ASSERT_EQ(ERR_IO_PENDING
,
13424 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13427 // Start the HTTP request. Pool should stall.
13428 TestCompletionCallback http_callback
;
13429 scoped_ptr
<HttpTransaction
> http_trans(
13430 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13431 ASSERT_EQ(ERR_IO_PENDING
,
13432 http_trans
->Start(&http_request
, http_callback
.callback(),
13434 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13436 // Wait for response from SSL request.
13437 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13438 std::string response_data
;
13439 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13440 EXPECT_EQ("hello world", response_data
);
13442 // The SSL socket should automatically be closed, so the HTTP request can
13444 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13445 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13447 // The HTTP request can now complete.
13448 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13449 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13450 EXPECT_EQ("falafel", response_data
);
13452 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13455 // Tests that when a SSL connection is established but there's no corresponding
13456 // request that needs it, the new socket is closed if the transport socket pool
13457 // is stalled on the global socket limit.
13458 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13459 ClientSocketPoolManager::set_max_sockets_per_group(
13460 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13461 ClientSocketPoolManager::set_max_sockets_per_pool(
13462 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13464 // Set up an ssl request.
13466 HttpRequestInfo ssl_request
;
13467 ssl_request
.method
= "GET";
13468 ssl_request
.url
= GURL("https://www.foopy.com/");
13470 // No data will be sent on the SSL socket.
13471 StaticSocketDataProvider ssl_data
;
13472 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13474 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13475 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13477 // Set up HTTP request.
13479 HttpRequestInfo http_request
;
13480 http_request
.method
= "GET";
13481 http_request
.url
= GURL("http://www.example.org/");
13483 MockWrite http_writes
[] = {
13485 "GET / HTTP/1.1\r\n"
13486 "Host: www.example.org\r\n"
13487 "Connection: keep-alive\r\n\r\n"),
13489 MockRead http_reads
[] = {
13490 MockRead("HTTP/1.1 200 OK\r\n"),
13491 MockRead("Content-Length: 7\r\n\r\n"),
13492 MockRead("falafel"),
13493 MockRead(SYNCHRONOUS
, OK
),
13495 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13496 http_writes
, arraysize(http_writes
));
13497 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13499 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13501 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13502 // cancelled when a normal transaction is cancelled.
13503 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13504 SSLConfig ssl_config
;
13505 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13506 http_stream_factory
->PreconnectStreams(1, ssl_request
, ssl_config
,
13508 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13510 // Start the HTTP request. Pool should stall.
13511 TestCompletionCallback http_callback
;
13512 scoped_ptr
<HttpTransaction
> http_trans(
13513 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13514 ASSERT_EQ(ERR_IO_PENDING
,
13515 http_trans
->Start(&http_request
, http_callback
.callback(),
13517 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13519 // The SSL connection will automatically be closed once the connection is
13520 // established, to let the HTTP request start.
13521 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13522 std::string response_data
;
13523 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13524 EXPECT_EQ("falafel", response_data
);
13526 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13529 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13530 ScopedVector
<UploadElementReader
> element_readers
;
13531 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13532 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13534 HttpRequestInfo request
;
13535 request
.method
= "POST";
13536 request
.url
= GURL("http://www.foo.com/");
13537 request
.upload_data_stream
= &upload_data_stream
;
13538 request
.load_flags
= 0;
13540 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13541 scoped_ptr
<HttpTransaction
> trans(
13542 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13543 // Send headers successfully, but get an error while sending the body.
13544 MockWrite data_writes
[] = {
13545 MockWrite("POST / HTTP/1.1\r\n"
13546 "Host: www.foo.com\r\n"
13547 "Connection: keep-alive\r\n"
13548 "Content-Length: 3\r\n\r\n"),
13549 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13552 MockRead data_reads
[] = {
13553 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13554 MockRead("hello world"),
13555 MockRead(SYNCHRONOUS
, OK
),
13557 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13558 arraysize(data_writes
));
13559 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13561 TestCompletionCallback callback
;
13563 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13564 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13566 rv
= callback
.WaitForResult();
13569 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13570 ASSERT_TRUE(response
!= NULL
);
13572 EXPECT_TRUE(response
->headers
.get() != NULL
);
13573 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13575 std::string response_data
;
13576 rv
= ReadTransaction(trans
.get(), &response_data
);
13578 EXPECT_EQ("hello world", response_data
);
13581 // This test makes sure the retry logic doesn't trigger when reading an error
13582 // response from a server that rejected a POST with a CONNECTION_RESET.
13583 TEST_P(HttpNetworkTransactionTest
,
13584 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13585 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13586 MockWrite data_writes
[] = {
13587 MockWrite("GET / HTTP/1.1\r\n"
13588 "Host: www.foo.com\r\n"
13589 "Connection: keep-alive\r\n\r\n"),
13590 MockWrite("POST / HTTP/1.1\r\n"
13591 "Host: www.foo.com\r\n"
13592 "Connection: keep-alive\r\n"
13593 "Content-Length: 3\r\n\r\n"),
13594 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13597 MockRead data_reads
[] = {
13598 MockRead("HTTP/1.1 200 Peachy\r\n"
13599 "Content-Length: 14\r\n\r\n"),
13600 MockRead("first response"),
13601 MockRead("HTTP/1.1 400 Not OK\r\n"
13602 "Content-Length: 15\r\n\r\n"),
13603 MockRead("second response"),
13604 MockRead(SYNCHRONOUS
, OK
),
13606 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13607 arraysize(data_writes
));
13608 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13610 TestCompletionCallback callback
;
13611 HttpRequestInfo request1
;
13612 request1
.method
= "GET";
13613 request1
.url
= GURL("http://www.foo.com/");
13614 request1
.load_flags
= 0;
13616 scoped_ptr
<HttpTransaction
> trans1(
13617 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13618 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13619 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13621 rv
= callback
.WaitForResult();
13624 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13625 ASSERT_TRUE(response1
!= NULL
);
13627 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13628 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13630 std::string response_data1
;
13631 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13633 EXPECT_EQ("first response", response_data1
);
13634 // Delete the transaction to release the socket back into the socket pool.
13637 ScopedVector
<UploadElementReader
> element_readers
;
13638 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13639 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13641 HttpRequestInfo request2
;
13642 request2
.method
= "POST";
13643 request2
.url
= GURL("http://www.foo.com/");
13644 request2
.upload_data_stream
= &upload_data_stream
;
13645 request2
.load_flags
= 0;
13647 scoped_ptr
<HttpTransaction
> trans2(
13648 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13649 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13650 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13652 rv
= callback
.WaitForResult();
13655 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13656 ASSERT_TRUE(response2
!= NULL
);
13658 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13659 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13661 std::string response_data2
;
13662 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13664 EXPECT_EQ("second response", response_data2
);
13667 TEST_P(HttpNetworkTransactionTest
,
13668 PostReadsErrorResponseAfterResetPartialBodySent
) {
13669 ScopedVector
<UploadElementReader
> element_readers
;
13670 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13671 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13673 HttpRequestInfo request
;
13674 request
.method
= "POST";
13675 request
.url
= GURL("http://www.foo.com/");
13676 request
.upload_data_stream
= &upload_data_stream
;
13677 request
.load_flags
= 0;
13679 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13680 scoped_ptr
<HttpTransaction
> trans(
13681 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13682 // Send headers successfully, but get an error while sending the body.
13683 MockWrite data_writes
[] = {
13684 MockWrite("POST / HTTP/1.1\r\n"
13685 "Host: www.foo.com\r\n"
13686 "Connection: keep-alive\r\n"
13687 "Content-Length: 3\r\n\r\n"
13689 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13692 MockRead data_reads
[] = {
13693 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13694 MockRead("hello world"),
13695 MockRead(SYNCHRONOUS
, OK
),
13697 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13698 arraysize(data_writes
));
13699 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13701 TestCompletionCallback callback
;
13703 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13706 rv
= callback
.WaitForResult();
13709 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13710 ASSERT_TRUE(response
!= NULL
);
13712 EXPECT_TRUE(response
->headers
.get() != NULL
);
13713 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13715 std::string response_data
;
13716 rv
= ReadTransaction(trans
.get(), &response_data
);
13718 EXPECT_EQ("hello world", response_data
);
13721 // This tests the more common case than the previous test, where headers and
13722 // body are not merged into a single request.
13723 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13724 ScopedVector
<UploadElementReader
> element_readers
;
13725 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13726 ChunkedUploadDataStream
upload_data_stream(0);
13728 HttpRequestInfo request
;
13729 request
.method
= "POST";
13730 request
.url
= GURL("http://www.foo.com/");
13731 request
.upload_data_stream
= &upload_data_stream
;
13732 request
.load_flags
= 0;
13734 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13735 scoped_ptr
<HttpTransaction
> trans(
13736 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13737 // Send headers successfully, but get an error while sending the body.
13738 MockWrite data_writes
[] = {
13739 MockWrite("POST / HTTP/1.1\r\n"
13740 "Host: www.foo.com\r\n"
13741 "Connection: keep-alive\r\n"
13742 "Transfer-Encoding: chunked\r\n\r\n"),
13743 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13746 MockRead data_reads
[] = {
13747 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13748 MockRead("hello world"),
13749 MockRead(SYNCHRONOUS
, OK
),
13751 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13752 arraysize(data_writes
));
13753 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13755 TestCompletionCallback callback
;
13757 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13758 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13759 // Make sure the headers are sent before adding a chunk. This ensures that
13760 // they can't be merged with the body in a single send. Not currently
13761 // necessary since a chunked body is never merged with headers, but this makes
13762 // the test more future proof.
13763 base::RunLoop().RunUntilIdle();
13765 upload_data_stream
.AppendData("last chunk", 10, true);
13767 rv
= callback
.WaitForResult();
13770 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13771 ASSERT_TRUE(response
!= NULL
);
13773 EXPECT_TRUE(response
->headers
.get() != NULL
);
13774 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13776 std::string response_data
;
13777 rv
= ReadTransaction(trans
.get(), &response_data
);
13779 EXPECT_EQ("hello world", response_data
);
13782 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13783 ScopedVector
<UploadElementReader
> element_readers
;
13784 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13785 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13787 HttpRequestInfo request
;
13788 request
.method
= "POST";
13789 request
.url
= GURL("http://www.foo.com/");
13790 request
.upload_data_stream
= &upload_data_stream
;
13791 request
.load_flags
= 0;
13793 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13794 scoped_ptr
<HttpTransaction
> trans(
13795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13797 MockWrite data_writes
[] = {
13798 MockWrite("POST / HTTP/1.1\r\n"
13799 "Host: www.foo.com\r\n"
13800 "Connection: keep-alive\r\n"
13801 "Content-Length: 3\r\n\r\n"),
13802 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13805 MockRead data_reads
[] = {
13806 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13807 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13808 MockRead("hello world"),
13809 MockRead(SYNCHRONOUS
, OK
),
13811 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13812 arraysize(data_writes
));
13813 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13815 TestCompletionCallback callback
;
13817 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13818 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13820 rv
= callback
.WaitForResult();
13823 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13824 ASSERT_TRUE(response
!= NULL
);
13826 EXPECT_TRUE(response
->headers
.get() != NULL
);
13827 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13829 std::string response_data
;
13830 rv
= ReadTransaction(trans
.get(), &response_data
);
13832 EXPECT_EQ("hello world", response_data
);
13835 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13836 ScopedVector
<UploadElementReader
> element_readers
;
13837 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13838 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13840 HttpRequestInfo request
;
13841 request
.method
= "POST";
13842 request
.url
= GURL("http://www.foo.com/");
13843 request
.upload_data_stream
= &upload_data_stream
;
13844 request
.load_flags
= 0;
13846 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13847 scoped_ptr
<HttpTransaction
> trans(
13848 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13849 // Send headers successfully, but get an error while sending the body.
13850 MockWrite data_writes
[] = {
13851 MockWrite("POST / HTTP/1.1\r\n"
13852 "Host: www.foo.com\r\n"
13853 "Connection: keep-alive\r\n"
13854 "Content-Length: 3\r\n\r\n"),
13855 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13858 MockRead data_reads
[] = {
13859 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13860 MockRead("hello world"),
13861 MockRead(SYNCHRONOUS
, OK
),
13863 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13864 arraysize(data_writes
));
13865 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13867 TestCompletionCallback callback
;
13869 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13870 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13872 rv
= callback
.WaitForResult();
13873 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13876 TEST_P(HttpNetworkTransactionTest
,
13877 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13878 ScopedVector
<UploadElementReader
> element_readers
;
13879 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13880 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13882 HttpRequestInfo request
;
13883 request
.method
= "POST";
13884 request
.url
= GURL("http://www.foo.com/");
13885 request
.upload_data_stream
= &upload_data_stream
;
13886 request
.load_flags
= 0;
13888 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13889 scoped_ptr
<HttpTransaction
> trans(
13890 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13891 // Send headers successfully, but get an error while sending the body.
13892 MockWrite data_writes
[] = {
13893 MockWrite("POST / HTTP/1.1\r\n"
13894 "Host: www.foo.com\r\n"
13895 "Connection: keep-alive\r\n"
13896 "Content-Length: 3\r\n\r\n"),
13897 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13900 MockRead data_reads
[] = {
13901 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13902 MockRead("HTTP/1.0 302 Redirect\r\n"),
13903 MockRead("Location: http://somewhere-else.com/\r\n"),
13904 MockRead("Content-Length: 0\r\n\r\n"),
13905 MockRead(SYNCHRONOUS
, OK
),
13907 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13908 arraysize(data_writes
));
13909 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13911 TestCompletionCallback callback
;
13913 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13914 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13916 rv
= callback
.WaitForResult();
13917 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13920 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13921 ScopedVector
<UploadElementReader
> element_readers
;
13922 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13923 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13925 HttpRequestInfo request
;
13926 request
.method
= "POST";
13927 request
.url
= GURL("http://www.foo.com/");
13928 request
.upload_data_stream
= &upload_data_stream
;
13929 request
.load_flags
= 0;
13931 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13932 scoped_ptr
<HttpTransaction
> trans(
13933 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13934 // Send headers successfully, but get an error while sending the body.
13935 MockWrite data_writes
[] = {
13936 MockWrite("POST / HTTP/1.1\r\n"
13937 "Host: www.foo.com\r\n"
13938 "Connection: keep-alive\r\n"
13939 "Content-Length: 3\r\n\r\n"),
13940 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13943 MockRead data_reads
[] = {
13944 MockRead("HTTP 0.9 rocks!"),
13945 MockRead(SYNCHRONOUS
, OK
),
13947 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13948 arraysize(data_writes
));
13949 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13951 TestCompletionCallback callback
;
13953 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13954 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13956 rv
= callback
.WaitForResult();
13957 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13960 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13961 ScopedVector
<UploadElementReader
> element_readers
;
13962 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13963 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13965 HttpRequestInfo request
;
13966 request
.method
= "POST";
13967 request
.url
= GURL("http://www.foo.com/");
13968 request
.upload_data_stream
= &upload_data_stream
;
13969 request
.load_flags
= 0;
13971 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13972 scoped_ptr
<HttpTransaction
> trans(
13973 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13974 // Send headers successfully, but get an error while sending the body.
13975 MockWrite data_writes
[] = {
13976 MockWrite("POST / HTTP/1.1\r\n"
13977 "Host: www.foo.com\r\n"
13978 "Connection: keep-alive\r\n"
13979 "Content-Length: 3\r\n\r\n"),
13980 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13983 MockRead data_reads
[] = {
13984 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13985 MockRead(SYNCHRONOUS
, OK
),
13987 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13988 arraysize(data_writes
));
13989 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13991 TestCompletionCallback callback
;
13993 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13994 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13996 rv
= callback
.WaitForResult();
13997 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14000 // Verify that proxy headers are not sent to the destination server when
14001 // establishing a tunnel for a secure WebSocket connection.
14002 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14003 HttpRequestInfo request
;
14004 request
.method
= "GET";
14005 request
.url
= GURL("wss://www.example.org/");
14006 AddWebSocketHeaders(&request
.extra_headers
);
14008 // Configure against proxy server "myproxy:70".
14009 session_deps_
.proxy_service
.reset(
14010 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14012 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14014 // Since a proxy is configured, try to establish a tunnel.
14015 MockWrite data_writes
[] = {
14017 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14018 "Host: www.example.org\r\n"
14019 "Proxy-Connection: keep-alive\r\n\r\n"),
14021 // After calling trans->RestartWithAuth(), this is the request we should
14022 // be issuing -- the final header line contains the credentials.
14024 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14025 "Host: www.example.org\r\n"
14026 "Proxy-Connection: keep-alive\r\n"
14027 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14030 "GET / HTTP/1.1\r\n"
14031 "Host: www.example.org\r\n"
14032 "Connection: Upgrade\r\n"
14033 "Upgrade: websocket\r\n"
14034 "Origin: http://www.example.org\r\n"
14035 "Sec-WebSocket-Version: 13\r\n"
14036 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14039 // The proxy responds to the connect with a 407, using a persistent
14041 MockRead data_reads
[] = {
14043 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14044 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14045 MockRead("Proxy-Connection: close\r\n\r\n"),
14047 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14049 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14050 MockRead("Upgrade: websocket\r\n"),
14051 MockRead("Connection: Upgrade\r\n"),
14052 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14055 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14056 arraysize(data_writes
));
14057 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14058 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14059 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14061 scoped_ptr
<HttpTransaction
> trans(
14062 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14063 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14064 trans
->SetWebSocketHandshakeStreamCreateHelper(
14065 &websocket_stream_create_helper
);
14068 TestCompletionCallback callback
;
14070 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14071 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14073 rv
= callback
.WaitForResult();
14077 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14078 ASSERT_TRUE(response
);
14079 ASSERT_TRUE(response
->headers
.get());
14080 EXPECT_EQ(407, response
->headers
->response_code());
14083 TestCompletionCallback callback
;
14085 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14086 callback
.callback());
14087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14089 rv
= callback
.WaitForResult();
14093 response
= trans
->GetResponseInfo();
14094 ASSERT_TRUE(response
);
14095 ASSERT_TRUE(response
->headers
.get());
14097 EXPECT_EQ(101, response
->headers
->response_code());
14100 session
->CloseAllConnections();
14103 // Verify that proxy headers are not sent to the destination server when
14104 // establishing a tunnel for an insecure WebSocket connection.
14105 // This requires the authentication info to be injected into the auth cache
14106 // due to crbug.com/395064
14107 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14108 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14109 HttpRequestInfo request
;
14110 request
.method
= "GET";
14111 request
.url
= GURL("ws://www.example.org/");
14112 AddWebSocketHeaders(&request
.extra_headers
);
14114 // Configure against proxy server "myproxy:70".
14115 session_deps_
.proxy_service
.reset(
14116 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14118 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14120 MockWrite data_writes
[] = {
14121 // Try to establish a tunnel for the WebSocket connection, with
14122 // credentials. Because WebSockets have a separate set of socket pools,
14123 // they cannot and will not use the same TCP/IP connection as the
14124 // preflight HTTP request.
14126 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14127 "Host: www.example.org:80\r\n"
14128 "Proxy-Connection: keep-alive\r\n"
14129 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14132 "GET / HTTP/1.1\r\n"
14133 "Host: www.example.org\r\n"
14134 "Connection: Upgrade\r\n"
14135 "Upgrade: websocket\r\n"
14136 "Origin: http://www.example.org\r\n"
14137 "Sec-WebSocket-Version: 13\r\n"
14138 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14141 MockRead data_reads
[] = {
14142 // HTTP CONNECT with credentials.
14143 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14145 // WebSocket connection established inside tunnel.
14146 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14147 MockRead("Upgrade: websocket\r\n"),
14148 MockRead("Connection: Upgrade\r\n"),
14149 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14152 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14153 arraysize(data_writes
));
14154 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14156 session
->http_auth_cache()->Add(
14157 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14158 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14160 scoped_ptr
<HttpTransaction
> trans(
14161 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14162 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14163 trans
->SetWebSocketHandshakeStreamCreateHelper(
14164 &websocket_stream_create_helper
);
14166 TestCompletionCallback callback
;
14168 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14169 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14171 rv
= callback
.WaitForResult();
14174 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14175 ASSERT_TRUE(response
);
14176 ASSERT_TRUE(response
->headers
.get());
14178 EXPECT_EQ(101, response
->headers
->response_code());
14181 session
->CloseAllConnections();