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 std::string
GetAlternativeServiceHttpHeader() {
292 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
293 "=\"www.example.com:443\"\r\n";
296 std::string
GetAlternateProtocolHttpHeader() {
297 return std::string("Alternate-Protocol: 443:") +
298 GetAlternateProtocolFromParam() + "\r\n";
301 // Either |write_failure| specifies a write failure or |read_failure|
302 // specifies a read failure when using a reused socket. In either case, the
303 // failure should cause the network transaction to resend the request, and the
304 // other argument should be NULL.
305 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
306 const MockRead
* read_failure
);
308 // Either |write_failure| specifies a write failure or |read_failure|
309 // specifies a read failure when using a reused socket. In either case, the
310 // failure should cause the network transaction to resend the request, and the
311 // other argument should be NULL.
312 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
313 const MockRead
* read_failure
,
316 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
318 SimpleGetHelperResult out
;
320 HttpRequestInfo request
;
321 request
.method
= "GET";
322 request
.url
= GURL("http://www.example.org/");
323 request
.load_flags
= 0;
326 session_deps_
.net_log
= log
.bound().net_log();
327 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
328 scoped_ptr
<HttpTransaction
> trans(
329 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
331 for (size_t i
= 0; i
< data_count
; ++i
) {
332 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
335 TestCompletionCallback callback
;
337 EXPECT_TRUE(log
.bound().IsCapturing());
338 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
341 out
.rv
= callback
.WaitForResult();
343 // Even in the failure cases that use this function, connections are always
344 // successfully established before the error.
345 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
346 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
351 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
352 // Can't use ASSERT_* inside helper functions like this, so
354 if (response
== NULL
|| response
->headers
.get() == NULL
) {
355 out
.rv
= ERR_UNEXPECTED
;
358 out
.status_line
= response
->headers
->GetStatusLine();
360 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
361 EXPECT_EQ(80, response
->socket_address
.port());
363 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
366 TestNetLogEntry::List entries
;
367 log
.GetEntries(&entries
);
368 size_t pos
= ExpectLogContainsSomewhere(
369 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
371 ExpectLogContainsSomewhere(
373 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
377 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
378 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
380 HttpRequestHeaders request_headers
;
381 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
383 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
384 EXPECT_EQ("www.example.org", value
);
385 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
386 EXPECT_EQ("keep-alive", value
);
388 std::string response_headers
;
389 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
390 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
393 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
394 trans
->GetConnectionAttempts(&out
.connection_attempts
);
398 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
399 size_t reads_count
) {
400 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
401 StaticSocketDataProvider
* data
[] = { &reads
};
402 return SimpleGetHelperForData(data
, 1);
405 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
407 for (size_t i
= 0; i
< reads_count
; ++i
)
408 size
+= data_reads
[i
].data_len
;
412 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
413 int expected_status
);
415 void ConnectStatusHelper(const MockRead
& status
);
417 void BypassHostCacheOnRefreshHelper(int load_flags
);
419 void CheckErrorIsPassedBack(int error
, IoMode mode
);
421 SpdyTestUtil spdy_util_
;
422 SpdySessionDependencies session_deps_
;
424 // Original socket limits. Some tests set these. Safest to always restore
425 // them once each test has been run.
426 int old_max_group_sockets_
;
427 int old_max_pool_sockets_
;
430 INSTANTIATE_TEST_CASE_P(NextProto
,
431 HttpNetworkTransactionTest
,
432 testing::Values(kProtoSPDY31
,
437 class BeforeNetworkStartHandler
{
439 explicit BeforeNetworkStartHandler(bool defer
)
440 : defer_on_before_network_start_(defer
),
441 observed_before_network_start_(false) {}
443 void OnBeforeNetworkStart(bool* defer
) {
444 *defer
= defer_on_before_network_start_
;
445 observed_before_network_start_
= true;
448 bool observed_before_network_start() const {
449 return observed_before_network_start_
;
453 const bool defer_on_before_network_start_
;
454 bool observed_before_network_start_
;
456 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
459 class BeforeProxyHeadersSentHandler
{
461 BeforeProxyHeadersSentHandler()
462 : observed_before_proxy_headers_sent_(false) {}
464 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
465 HttpRequestHeaders
* request_headers
) {
466 observed_before_proxy_headers_sent_
= true;
467 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
470 bool observed_before_proxy_headers_sent() const {
471 return observed_before_proxy_headers_sent_
;
474 std::string
observed_proxy_server_uri() const {
475 return observed_proxy_server_uri_
;
479 bool observed_before_proxy_headers_sent_
;
480 std::string observed_proxy_server_uri_
;
482 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
485 // Fill |str| with a long header list that consumes >= |size| bytes.
486 void FillLargeHeadersString(std::string
* str
, int size
) {
488 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
489 const int sizeof_row
= strlen(row
);
490 const int num_rows
= static_cast<int>(
491 ceil(static_cast<float>(size
) / sizeof_row
));
492 const int sizeof_data
= num_rows
* sizeof_row
;
493 DCHECK(sizeof_data
>= size
);
494 str
->reserve(sizeof_data
);
496 for (int i
= 0; i
< num_rows
; ++i
)
497 str
->append(row
, sizeof_row
);
500 #if defined(NTLM_PORTABLE)
501 // Alternative functions that eliminate randomness and dependency on the local
502 // host name so that the generated NTLM messages are reproducible.
503 void MockGenerateRandom1(uint8
* output
, size_t n
) {
504 static const uint8 bytes
[] = {
505 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
507 static size_t current_byte
= 0;
508 for (size_t i
= 0; i
< n
; ++i
) {
509 output
[i
] = bytes
[current_byte
++];
510 current_byte
%= arraysize(bytes
);
514 void MockGenerateRandom2(uint8
* output
, size_t n
) {
515 static const uint8 bytes
[] = {
516 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
517 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
519 static size_t current_byte
= 0;
520 for (size_t i
= 0; i
< n
; ++i
) {
521 output
[i
] = bytes
[current_byte
++];
522 current_byte
%= arraysize(bytes
);
526 std::string
MockGetHostName() {
529 #endif // defined(NTLM_PORTABLE)
531 template<typename ParentPool
>
532 class CaptureGroupNameSocketPool
: public ParentPool
{
534 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
535 CertVerifier
* cert_verifier
);
537 const std::string
last_group_name_received() const {
538 return last_group_name_
;
541 int RequestSocket(const std::string
& group_name
,
542 const void* socket_params
,
543 RequestPriority priority
,
544 ClientSocketHandle
* handle
,
545 const CompletionCallback
& callback
,
546 const BoundNetLog
& net_log
) override
{
547 last_group_name_
= group_name
;
548 return ERR_IO_PENDING
;
550 void CancelRequest(const std::string
& group_name
,
551 ClientSocketHandle
* handle
) override
{}
552 void ReleaseSocket(const std::string
& group_name
,
553 scoped_ptr
<StreamSocket
> socket
,
555 void CloseIdleSockets() override
{}
556 int IdleSocketCount() const override
{ return 0; }
557 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
560 LoadState
GetLoadState(const std::string
& group_name
,
561 const ClientSocketHandle
* handle
) const override
{
562 return LOAD_STATE_IDLE
;
564 base::TimeDelta
ConnectionTimeout() const override
{
565 return base::TimeDelta();
569 std::string last_group_name_
;
572 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
573 CaptureGroupNameTransportSocketPool
;
574 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
575 CaptureGroupNameHttpProxySocketPool
;
576 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
577 CaptureGroupNameSOCKSSocketPool
;
578 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
579 CaptureGroupNameSSLSocketPool
;
581 template <typename ParentPool
>
582 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
583 HostResolver
* host_resolver
,
584 CertVerifier
* /* cert_verifier */)
585 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
589 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
590 HostResolver
* /* host_resolver */,
591 CertVerifier
* /* cert_verifier */)
592 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
596 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
597 HostResolver
* /* host_resolver */,
598 CertVerifier
* cert_verifier
)
599 : SSLClientSocketPool(0,
615 //-----------------------------------------------------------------------------
617 // Helper functions for validating that AuthChallengeInfo's are correctly
618 // configured for common cases.
619 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
622 EXPECT_FALSE(auth_challenge
->is_proxy
);
623 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
624 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
625 EXPECT_EQ("basic", auth_challenge
->scheme
);
629 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
632 EXPECT_TRUE(auth_challenge
->is_proxy
);
633 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
634 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
635 EXPECT_EQ("basic", auth_challenge
->scheme
);
639 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
642 EXPECT_FALSE(auth_challenge
->is_proxy
);
643 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
644 EXPECT_EQ("digestive", auth_challenge
->realm
);
645 EXPECT_EQ("digest", auth_challenge
->scheme
);
649 #if defined(NTLM_PORTABLE)
650 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
653 EXPECT_FALSE(auth_challenge
->is_proxy
);
654 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
655 EXPECT_EQ(std::string(), auth_challenge
->realm
);
656 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
659 #endif // defined(NTLM_PORTABLE)
663 TEST_P(HttpNetworkTransactionTest
, Basic
) {
664 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
665 scoped_ptr
<HttpTransaction
> trans(
666 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
669 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
670 MockRead data_reads
[] = {
671 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
672 MockRead("hello world"),
673 MockRead(SYNCHRONOUS
, OK
),
675 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
676 arraysize(data_reads
));
677 EXPECT_EQ(OK
, out
.rv
);
678 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
679 EXPECT_EQ("hello world", out
.response_data
);
680 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
681 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
682 EXPECT_EQ(0u, out
.connection_attempts
.size());
685 // Response with no status line.
686 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
687 MockRead data_reads
[] = {
688 MockRead("hello world"),
689 MockRead(SYNCHRONOUS
, OK
),
691 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
692 arraysize(data_reads
));
693 EXPECT_EQ(OK
, out
.rv
);
694 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
695 EXPECT_EQ("hello world", out
.response_data
);
696 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
697 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
700 // Allow up to 4 bytes of junk to precede status line.
701 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
702 MockRead data_reads
[] = {
703 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
704 MockRead(SYNCHRONOUS
, OK
),
706 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
707 arraysize(data_reads
));
708 EXPECT_EQ(OK
, out
.rv
);
709 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
710 EXPECT_EQ("DATA", out
.response_data
);
711 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
712 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
715 // Allow up to 4 bytes of junk to precede status line.
716 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
717 MockRead data_reads
[] = {
718 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
719 MockRead(SYNCHRONOUS
, OK
),
721 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
722 arraysize(data_reads
));
723 EXPECT_EQ(OK
, out
.rv
);
724 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
725 EXPECT_EQ("DATA", out
.response_data
);
726 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
727 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
730 // Beyond 4 bytes of slop and it should fail to find a status line.
731 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
732 MockRead data_reads
[] = {
733 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
734 MockRead(SYNCHRONOUS
, OK
),
736 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
737 arraysize(data_reads
));
738 EXPECT_EQ(OK
, out
.rv
);
739 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
740 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
741 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
742 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
745 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
746 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
747 MockRead data_reads
[] = {
752 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
753 MockRead(SYNCHRONOUS
, OK
),
755 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
756 arraysize(data_reads
));
757 EXPECT_EQ(OK
, out
.rv
);
758 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
759 EXPECT_EQ("DATA", out
.response_data
);
760 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
761 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
764 // Close the connection before enough bytes to have a status line.
765 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
766 MockRead data_reads
[] = {
768 MockRead(SYNCHRONOUS
, OK
),
770 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
771 arraysize(data_reads
));
772 EXPECT_EQ(OK
, out
.rv
);
773 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
774 EXPECT_EQ("HTT", out
.response_data
);
775 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
776 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
779 // Simulate a 204 response, lacking a Content-Length header, sent over a
780 // persistent connection. The response should still terminate since a 204
781 // cannot have a response body.
782 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
783 char junk
[] = "junk";
784 MockRead data_reads
[] = {
785 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
786 MockRead(junk
), // Should not be read!!
787 MockRead(SYNCHRONOUS
, OK
),
789 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
790 arraysize(data_reads
));
791 EXPECT_EQ(OK
, out
.rv
);
792 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
793 EXPECT_EQ("", out
.response_data
);
794 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
795 int64 response_size
= reads_size
- strlen(junk
);
796 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
799 // A simple request using chunked encoding with some extra data after.
800 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
801 std::string final_chunk
= "0\r\n\r\n";
802 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
803 std::string last_read
= final_chunk
+ extra_data
;
804 MockRead data_reads
[] = {
805 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
806 MockRead("5\r\nHello\r\n"),
809 MockRead("5\r\nworld\r\n"),
810 MockRead(last_read
.data()),
811 MockRead(SYNCHRONOUS
, OK
),
813 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
814 arraysize(data_reads
));
815 EXPECT_EQ(OK
, out
.rv
);
816 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
817 EXPECT_EQ("Hello world", out
.response_data
);
818 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
819 int64 response_size
= reads_size
- extra_data
.size();
820 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
823 // Next tests deal with http://crbug.com/56344.
825 TEST_P(HttpNetworkTransactionTest
,
826 MultipleContentLengthHeadersNoTransferEncoding
) {
827 MockRead data_reads
[] = {
828 MockRead("HTTP/1.1 200 OK\r\n"),
829 MockRead("Content-Length: 10\r\n"),
830 MockRead("Content-Length: 5\r\n\r\n"),
832 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
833 arraysize(data_reads
));
834 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
837 TEST_P(HttpNetworkTransactionTest
,
838 DuplicateContentLengthHeadersNoTransferEncoding
) {
839 MockRead data_reads
[] = {
840 MockRead("HTTP/1.1 200 OK\r\n"),
841 MockRead("Content-Length: 5\r\n"),
842 MockRead("Content-Length: 5\r\n\r\n"),
845 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
846 arraysize(data_reads
));
847 EXPECT_EQ(OK
, out
.rv
);
848 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
849 EXPECT_EQ("Hello", out
.response_data
);
852 TEST_P(HttpNetworkTransactionTest
,
853 ComplexContentLengthHeadersNoTransferEncoding
) {
854 // More than 2 dupes.
856 MockRead data_reads
[] = {
857 MockRead("HTTP/1.1 200 OK\r\n"),
858 MockRead("Content-Length: 5\r\n"),
859 MockRead("Content-Length: 5\r\n"),
860 MockRead("Content-Length: 5\r\n\r\n"),
863 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
864 arraysize(data_reads
));
865 EXPECT_EQ(OK
, out
.rv
);
866 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
867 EXPECT_EQ("Hello", out
.response_data
);
871 MockRead data_reads
[] = {
872 MockRead("HTTP/1.0 200 OK\r\n"),
873 MockRead("Content-Length: 5\r\n"),
874 MockRead("Content-Length: 5\r\n"),
875 MockRead("Content-Length: 5\r\n\r\n"),
878 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
879 arraysize(data_reads
));
880 EXPECT_EQ(OK
, out
.rv
);
881 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
882 EXPECT_EQ("Hello", out
.response_data
);
884 // 2 dupes and one mismatched.
886 MockRead data_reads
[] = {
887 MockRead("HTTP/1.1 200 OK\r\n"),
888 MockRead("Content-Length: 10\r\n"),
889 MockRead("Content-Length: 10\r\n"),
890 MockRead("Content-Length: 5\r\n\r\n"),
892 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
893 arraysize(data_reads
));
894 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
898 TEST_P(HttpNetworkTransactionTest
,
899 MultipleContentLengthHeadersTransferEncoding
) {
900 MockRead data_reads
[] = {
901 MockRead("HTTP/1.1 200 OK\r\n"),
902 MockRead("Content-Length: 666\r\n"),
903 MockRead("Content-Length: 1337\r\n"),
904 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
905 MockRead("5\r\nHello\r\n"),
908 MockRead("5\r\nworld\r\n"),
909 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
910 MockRead(SYNCHRONOUS
, OK
),
912 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
913 arraysize(data_reads
));
914 EXPECT_EQ(OK
, out
.rv
);
915 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
916 EXPECT_EQ("Hello world", out
.response_data
);
919 // Next tests deal with http://crbug.com/98895.
921 // Checks that a single Content-Disposition header results in no error.
922 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
923 MockRead data_reads
[] = {
924 MockRead("HTTP/1.1 200 OK\r\n"),
925 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
926 MockRead("Content-Length: 5\r\n\r\n"),
929 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
930 arraysize(data_reads
));
931 EXPECT_EQ(OK
, out
.rv
);
932 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
933 EXPECT_EQ("Hello", out
.response_data
);
936 // Checks that two identical Content-Disposition headers result in no error.
937 TEST_P(HttpNetworkTransactionTest
,
938 TwoIdenticalContentDispositionHeaders
) {
939 MockRead data_reads
[] = {
940 MockRead("HTTP/1.1 200 OK\r\n"),
941 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
942 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
943 MockRead("Content-Length: 5\r\n\r\n"),
946 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
947 arraysize(data_reads
));
948 EXPECT_EQ(OK
, out
.rv
);
949 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
950 EXPECT_EQ("Hello", out
.response_data
);
953 // Checks that two distinct Content-Disposition headers result in an error.
954 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
955 MockRead data_reads
[] = {
956 MockRead("HTTP/1.1 200 OK\r\n"),
957 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
958 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
959 MockRead("Content-Length: 5\r\n\r\n"),
962 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
963 arraysize(data_reads
));
964 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
967 // Checks that two identical Location headers result in no error.
968 // Also tests Location header behavior.
969 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
970 MockRead data_reads
[] = {
971 MockRead("HTTP/1.1 302 Redirect\r\n"),
972 MockRead("Location: http://good.com/\r\n"),
973 MockRead("Location: http://good.com/\r\n"),
974 MockRead("Content-Length: 0\r\n\r\n"),
975 MockRead(SYNCHRONOUS
, OK
),
978 HttpRequestInfo request
;
979 request
.method
= "GET";
980 request
.url
= GURL("http://redirect.com/");
981 request
.load_flags
= 0;
983 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
984 scoped_ptr
<HttpTransaction
> trans(
985 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
987 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
988 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
990 TestCompletionCallback callback
;
992 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
993 EXPECT_EQ(ERR_IO_PENDING
, rv
);
995 EXPECT_EQ(OK
, callback
.WaitForResult());
997 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
998 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
999 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
1001 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
1002 EXPECT_EQ("http://good.com/", url
);
1003 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1006 // Checks that two distinct Location headers result in an error.
1007 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
1008 MockRead data_reads
[] = {
1009 MockRead("HTTP/1.1 302 Redirect\r\n"),
1010 MockRead("Location: http://good.com/\r\n"),
1011 MockRead("Location: http://evil.com/\r\n"),
1012 MockRead("Content-Length: 0\r\n\r\n"),
1013 MockRead(SYNCHRONOUS
, OK
),
1015 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1016 arraysize(data_reads
));
1017 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1020 // Do a request using the HEAD method. Verify that we don't try to read the
1021 // message body (since HEAD has none).
1022 TEST_P(HttpNetworkTransactionTest
, Head
) {
1023 HttpRequestInfo request
;
1024 request
.method
= "HEAD";
1025 request
.url
= GURL("http://www.example.org/");
1026 request
.load_flags
= 0;
1028 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1029 scoped_ptr
<HttpTransaction
> trans(
1030 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1031 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1032 trans
->SetBeforeProxyHeadersSentCallback(
1033 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1034 base::Unretained(&proxy_headers_handler
)));
1036 MockWrite data_writes1
[] = {
1037 MockWrite("HEAD / HTTP/1.1\r\n"
1038 "Host: www.example.org\r\n"
1039 "Connection: keep-alive\r\n\r\n"),
1041 MockRead data_reads1
[] = {
1042 MockRead("HTTP/1.1 404 Not Found\r\n"),
1043 MockRead("Server: Blah\r\n"),
1044 MockRead("Content-Length: 1234\r\n\r\n"),
1046 // No response body because the test stops reading here.
1047 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1050 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1051 data_writes1
, arraysize(data_writes1
));
1052 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1054 TestCompletionCallback callback1
;
1056 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1057 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1059 rv
= callback1
.WaitForResult();
1062 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1063 ASSERT_TRUE(response
!= NULL
);
1065 // Check that the headers got parsed.
1066 EXPECT_TRUE(response
->headers
.get() != NULL
);
1067 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1068 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1069 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1070 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1072 std::string server_header
;
1074 bool has_server_header
= response
->headers
->EnumerateHeader(
1075 &iter
, "Server", &server_header
);
1076 EXPECT_TRUE(has_server_header
);
1077 EXPECT_EQ("Blah", server_header
);
1079 // Reading should give EOF right away, since there is no message body
1080 // (despite non-zero content-length).
1081 std::string response_data
;
1082 rv
= ReadTransaction(trans
.get(), &response_data
);
1084 EXPECT_EQ("", response_data
);
1087 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1088 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1090 MockRead data_reads
[] = {
1091 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1093 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1095 MockRead(SYNCHRONOUS
, OK
),
1097 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1098 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1100 const char* const kExpectedResponseData
[] = {
1104 for (int i
= 0; i
< 2; ++i
) {
1105 HttpRequestInfo request
;
1106 request
.method
= "GET";
1107 request
.url
= GURL("http://www.example.org/");
1108 request
.load_flags
= 0;
1110 scoped_ptr
<HttpTransaction
> trans(
1111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1113 TestCompletionCallback callback
;
1115 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1118 rv
= callback
.WaitForResult();
1121 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1122 ASSERT_TRUE(response
!= NULL
);
1124 EXPECT_TRUE(response
->headers
.get() != NULL
);
1125 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1126 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1128 std::string response_data
;
1129 rv
= ReadTransaction(trans
.get(), &response_data
);
1131 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1135 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1136 ScopedVector
<UploadElementReader
> element_readers
;
1137 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1138 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1140 HttpRequestInfo request
;
1141 request
.method
= "POST";
1142 request
.url
= GURL("http://www.foo.com/");
1143 request
.upload_data_stream
= &upload_data_stream
;
1144 request
.load_flags
= 0;
1146 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1147 scoped_ptr
<HttpTransaction
> trans(
1148 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1150 MockRead data_reads
[] = {
1151 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1152 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1153 MockRead("hello world"),
1154 MockRead(SYNCHRONOUS
, OK
),
1156 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1157 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1159 TestCompletionCallback callback
;
1161 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1162 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1164 rv
= callback
.WaitForResult();
1167 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1168 ASSERT_TRUE(response
!= NULL
);
1170 EXPECT_TRUE(response
->headers
.get() != NULL
);
1171 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1173 std::string response_data
;
1174 rv
= ReadTransaction(trans
.get(), &response_data
);
1176 EXPECT_EQ("hello world", response_data
);
1179 // This test is almost the same as Ignores100 above, but the response contains
1180 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1181 // HTTP/1.1 and the two status headers are read in one read.
1182 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1183 HttpRequestInfo request
;
1184 request
.method
= "GET";
1185 request
.url
= GURL("http://www.foo.com/");
1186 request
.load_flags
= 0;
1188 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1189 scoped_ptr
<HttpTransaction
> trans(
1190 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1192 MockRead data_reads
[] = {
1193 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1194 "HTTP/1.1 200 OK\r\n\r\n"),
1195 MockRead("hello world"),
1196 MockRead(SYNCHRONOUS
, OK
),
1198 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1199 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1201 TestCompletionCallback callback
;
1203 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1204 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1206 rv
= callback
.WaitForResult();
1209 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1210 ASSERT_TRUE(response
!= NULL
);
1212 EXPECT_TRUE(response
->headers
.get() != NULL
);
1213 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1215 std::string response_data
;
1216 rv
= ReadTransaction(trans
.get(), &response_data
);
1218 EXPECT_EQ("hello world", response_data
);
1221 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1222 HttpRequestInfo request
;
1223 request
.method
= "POST";
1224 request
.url
= GURL("http://www.foo.com/");
1225 request
.load_flags
= 0;
1227 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1228 scoped_ptr
<HttpTransaction
> trans(
1229 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1231 MockRead data_reads
[] = {
1232 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1235 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1236 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1238 TestCompletionCallback callback
;
1240 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1241 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1243 rv
= callback
.WaitForResult();
1246 std::string response_data
;
1247 rv
= ReadTransaction(trans
.get(), &response_data
);
1249 EXPECT_EQ("", response_data
);
1252 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1253 HttpRequestInfo request
;
1254 request
.method
= "POST";
1255 request
.url
= GURL("http://www.foo.com/");
1256 request
.load_flags
= 0;
1258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1259 scoped_ptr
<HttpTransaction
> trans(
1260 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1262 MockRead data_reads
[] = {
1265 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1266 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1268 TestCompletionCallback callback
;
1270 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1271 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1273 rv
= callback
.WaitForResult();
1274 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1277 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1278 const MockWrite
* write_failure
,
1279 const MockRead
* read_failure
) {
1280 HttpRequestInfo request
;
1281 request
.method
= "GET";
1282 request
.url
= GURL("http://www.foo.com/");
1283 request
.load_flags
= 0;
1286 session_deps_
.net_log
= &net_log
;
1287 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1289 // Written data for successfully sending both requests.
1290 MockWrite data1_writes
[] = {
1291 MockWrite("GET / HTTP/1.1\r\n"
1292 "Host: www.foo.com\r\n"
1293 "Connection: keep-alive\r\n\r\n"),
1294 MockWrite("GET / HTTP/1.1\r\n"
1295 "Host: www.foo.com\r\n"
1296 "Connection: keep-alive\r\n\r\n")
1299 // Read results for the first request.
1300 MockRead data1_reads
[] = {
1301 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1303 MockRead(ASYNC
, OK
),
1306 if (write_failure
) {
1307 ASSERT_FALSE(read_failure
);
1308 data1_writes
[1] = *write_failure
;
1310 ASSERT_TRUE(read_failure
);
1311 data1_reads
[2] = *read_failure
;
1314 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1315 data1_writes
, arraysize(data1_writes
));
1316 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1318 MockRead data2_reads
[] = {
1319 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1321 MockRead(ASYNC
, OK
),
1323 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1324 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1326 const char* const kExpectedResponseData
[] = {
1330 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1331 for (int i
= 0; i
< 2; ++i
) {
1332 TestCompletionCallback callback
;
1334 scoped_ptr
<HttpTransaction
> trans(
1335 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1337 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1338 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1340 rv
= callback
.WaitForResult();
1343 LoadTimingInfo load_timing_info
;
1344 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1345 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1347 first_socket_log_id
= load_timing_info
.socket_log_id
;
1349 // The second request should be using a new socket.
1350 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1353 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1354 ASSERT_TRUE(response
!= NULL
);
1356 EXPECT_TRUE(response
->headers
.get() != NULL
);
1357 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1359 std::string response_data
;
1360 rv
= ReadTransaction(trans
.get(), &response_data
);
1362 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1366 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1367 const MockWrite
* write_failure
,
1368 const MockRead
* read_failure
,
1370 HttpRequestInfo request
;
1371 request
.method
= "GET";
1372 request
.url
= GURL("https://www.foo.com/");
1373 request
.load_flags
= 0;
1376 session_deps_
.net_log
= &net_log
;
1377 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1379 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1380 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1382 ssl1
.SetNextProto(GetParam());
1383 ssl2
.SetNextProto(GetParam());
1385 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1386 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1388 // SPDY versions of the request and response.
1389 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1390 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1391 scoped_ptr
<SpdyFrame
> spdy_response(
1392 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1393 scoped_ptr
<SpdyFrame
> spdy_data(
1394 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1396 // HTTP/1.1 versions of the request and response.
1397 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1398 "Host: www.foo.com\r\n"
1399 "Connection: keep-alive\r\n\r\n";
1400 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1401 const char kHttpData
[] = "hello";
1403 std::vector
<MockRead
> data1_reads
;
1404 std::vector
<MockWrite
> data1_writes
;
1405 if (write_failure
) {
1406 ASSERT_FALSE(read_failure
);
1407 data1_writes
.push_back(*write_failure
);
1408 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1410 ASSERT_TRUE(read_failure
);
1412 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1414 data1_writes
.push_back(MockWrite(kHttpRequest
));
1416 data1_reads
.push_back(*read_failure
);
1419 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1420 &data1_writes
[0], data1_writes
.size());
1421 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1423 std::vector
<MockRead
> data2_reads
;
1424 std::vector
<MockWrite
> data2_writes
;
1427 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1429 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1430 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1431 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1433 data2_writes
.push_back(
1434 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1436 data2_reads
.push_back(
1437 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1438 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1439 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1441 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1442 &data2_writes
[0], data2_writes
.size());
1443 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1445 // Preconnect a socket.
1446 SSLConfig ssl_config
;
1447 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1448 session
->GetNextProtos(&ssl_config
.next_protos
);
1449 session
->http_stream_factory()->PreconnectStreams(1, request
, ssl_config
,
1451 // Wait for the preconnect to complete.
1452 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1453 base::RunLoop().RunUntilIdle();
1454 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1456 // Make the request.
1457 TestCompletionCallback callback
;
1459 scoped_ptr
<HttpTransaction
> trans(
1460 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1462 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1463 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1465 rv
= callback
.WaitForResult();
1468 LoadTimingInfo load_timing_info
;
1469 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1470 TestLoadTimingNotReused(
1472 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1474 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1475 ASSERT_TRUE(response
!= NULL
);
1477 EXPECT_TRUE(response
->headers
.get() != NULL
);
1478 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1480 std::string response_data
;
1481 rv
= ReadTransaction(trans
.get(), &response_data
);
1483 EXPECT_EQ(kHttpData
, response_data
);
1486 TEST_P(HttpNetworkTransactionTest
,
1487 KeepAliveConnectionNotConnectedOnWrite
) {
1488 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1489 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1492 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1493 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1494 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1497 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1498 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1499 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1502 // Make sure that on a 408 response (Request Timeout), the request is retried,
1503 // if the socket was a reused keep alive socket.
1504 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1505 MockRead
read_failure(SYNCHRONOUS
,
1506 "HTTP/1.1 408 Request Timeout\r\n"
1507 "Connection: Keep-Alive\r\n"
1508 "Content-Length: 6\r\n\r\n"
1510 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1513 TEST_P(HttpNetworkTransactionTest
,
1514 PreconnectErrorNotConnectedOnWrite
) {
1515 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1516 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1519 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1520 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1521 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1524 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1525 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1526 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1529 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1530 MockRead
read_failure(ASYNC
, OK
); // EOF
1531 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1534 // Make sure that on a 408 response (Request Timeout), the request is retried,
1535 // if the socket was a preconnected (UNUSED_IDLE) socket.
1536 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1537 MockRead
read_failure(SYNCHRONOUS
,
1538 "HTTP/1.1 408 Request Timeout\r\n"
1539 "Connection: Keep-Alive\r\n"
1540 "Content-Length: 6\r\n\r\n"
1542 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1543 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1546 TEST_P(HttpNetworkTransactionTest
,
1547 SpdyPreconnectErrorNotConnectedOnWrite
) {
1548 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1549 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1552 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1553 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1554 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1557 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1558 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1559 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1562 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1563 MockRead
read_failure(ASYNC
, OK
); // EOF
1564 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1567 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1568 HttpRequestInfo request
;
1569 request
.method
= "GET";
1570 request
.url
= GURL("http://www.example.org/");
1571 request
.load_flags
= 0;
1573 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1574 scoped_ptr
<HttpTransaction
> trans(
1575 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1577 MockRead data_reads
[] = {
1578 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1579 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1580 MockRead("hello world"),
1581 MockRead(SYNCHRONOUS
, OK
),
1583 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1584 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1586 TestCompletionCallback callback
;
1588 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1591 rv
= callback
.WaitForResult();
1592 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1595 // What do various browsers do when the server closes a non-keepalive
1596 // connection without sending any response header or body?
1599 // Safari 3.1.2 (Windows): error page
1600 // Firefox 3.0.1: blank page
1601 // Opera 9.52: after five attempts, blank page
1602 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1603 // Us: error page (EMPTY_RESPONSE)
1604 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1605 MockRead data_reads
[] = {
1606 MockRead(SYNCHRONOUS
, OK
), // EOF
1607 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1608 MockRead("hello world"),
1609 MockRead(SYNCHRONOUS
, OK
),
1611 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1612 arraysize(data_reads
));
1613 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1616 // Test that network access can be deferred and resumed.
1617 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1618 HttpRequestInfo request
;
1619 request
.method
= "GET";
1620 request
.url
= GURL("http://www.example.org/");
1621 request
.load_flags
= 0;
1623 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1624 scoped_ptr
<HttpTransaction
> trans(
1625 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1627 // Defer on OnBeforeNetworkStart.
1628 BeforeNetworkStartHandler
net_start_handler(true); // defer
1629 trans
->SetBeforeNetworkStartCallback(
1630 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1631 base::Unretained(&net_start_handler
)));
1633 MockRead data_reads
[] = {
1634 MockRead("HTTP/1.0 200 OK\r\n"),
1635 MockRead("Content-Length: 5\r\n\r\n"),
1637 MockRead(SYNCHRONOUS
, 0),
1639 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1640 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1642 TestCompletionCallback callback
;
1644 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1645 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1646 base::MessageLoop::current()->RunUntilIdle();
1648 // Should have deferred for network start.
1649 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1650 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1652 trans
->ResumeNetworkStart();
1653 rv
= callback
.WaitForResult();
1655 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1657 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1658 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1659 if (rv
== ERR_IO_PENDING
)
1660 rv
= callback
.WaitForResult();
1665 // Test that network use can be deferred and canceled.
1666 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1667 HttpRequestInfo request
;
1668 request
.method
= "GET";
1669 request
.url
= GURL("http://www.example.org/");
1670 request
.load_flags
= 0;
1672 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1673 scoped_ptr
<HttpTransaction
> trans(
1674 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1676 // Defer on OnBeforeNetworkStart.
1677 BeforeNetworkStartHandler
net_start_handler(true); // defer
1678 trans
->SetBeforeNetworkStartCallback(
1679 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1680 base::Unretained(&net_start_handler
)));
1682 TestCompletionCallback callback
;
1684 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1685 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1686 base::MessageLoop::current()->RunUntilIdle();
1688 // Should have deferred for network start.
1689 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1690 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1693 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1694 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1695 // destructor in such situations.
1696 // See http://crbug.com/154712 and http://crbug.com/156609.
1697 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1698 HttpRequestInfo request
;
1699 request
.method
= "GET";
1700 request
.url
= GURL("http://www.example.org/");
1701 request
.load_flags
= 0;
1703 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1704 scoped_ptr
<HttpTransaction
> trans(
1705 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1707 MockRead data_reads
[] = {
1708 MockRead("HTTP/1.0 200 OK\r\n"),
1709 MockRead("Connection: keep-alive\r\n"),
1710 MockRead("Content-Length: 100\r\n\r\n"),
1712 MockRead(SYNCHRONOUS
, 0),
1714 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1715 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1717 TestCompletionCallback callback
;
1719 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1720 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1722 rv
= callback
.WaitForResult();
1725 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1726 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1727 if (rv
== ERR_IO_PENDING
)
1728 rv
= callback
.WaitForResult();
1730 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1731 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1734 base::MessageLoop::current()->RunUntilIdle();
1735 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1738 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1739 HttpRequestInfo request
;
1740 request
.method
= "GET";
1741 request
.url
= GURL("http://www.example.org/");
1742 request
.load_flags
= 0;
1744 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1745 scoped_ptr
<HttpTransaction
> trans(
1746 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1748 MockRead data_reads
[] = {
1749 MockRead("HTTP/1.0 200 OK\r\n"),
1750 MockRead("Connection: keep-alive\r\n"),
1751 MockRead("Content-Length: 100\r\n\r\n"),
1752 MockRead(SYNCHRONOUS
, 0),
1754 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1755 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1757 TestCompletionCallback callback
;
1759 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1760 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1762 rv
= callback
.WaitForResult();
1765 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1766 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1767 if (rv
== ERR_IO_PENDING
)
1768 rv
= callback
.WaitForResult();
1769 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1772 base::MessageLoop::current()->RunUntilIdle();
1773 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1776 // Test that we correctly reuse a keep-alive connection after not explicitly
1777 // reading the body.
1778 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1779 HttpRequestInfo request
;
1780 request
.method
= "GET";
1781 request
.url
= GURL("http://www.foo.com/");
1782 request
.load_flags
= 0;
1785 session_deps_
.net_log
= &net_log
;
1786 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1788 // Note that because all these reads happen in the same
1789 // StaticSocketDataProvider, it shows that the same socket is being reused for
1790 // all transactions.
1791 MockRead data1_reads
[] = {
1792 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1793 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1794 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1795 MockRead("HTTP/1.1 302 Found\r\n"
1796 "Content-Length: 0\r\n\r\n"),
1797 MockRead("HTTP/1.1 302 Found\r\n"
1798 "Content-Length: 5\r\n\r\n"
1800 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1801 "Content-Length: 0\r\n\r\n"),
1802 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1803 "Content-Length: 5\r\n\r\n"
1805 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1808 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1809 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1811 MockRead data2_reads
[] = {
1812 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1814 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1815 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1817 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1818 std::string response_lines
[kNumUnreadBodies
];
1820 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1821 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1822 TestCompletionCallback callback
;
1824 scoped_ptr
<HttpTransaction
> trans(
1825 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1827 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1828 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1830 rv
= callback
.WaitForResult();
1833 LoadTimingInfo load_timing_info
;
1834 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1836 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1837 first_socket_log_id
= load_timing_info
.socket_log_id
;
1839 TestLoadTimingReused(load_timing_info
);
1840 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1843 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1844 ASSERT_TRUE(response
!= NULL
);
1846 ASSERT_TRUE(response
->headers
.get() != NULL
);
1847 response_lines
[i
] = response
->headers
->GetStatusLine();
1849 // We intentionally don't read the response bodies.
1852 const char* const kStatusLines
[] = {
1853 "HTTP/1.1 204 No Content",
1854 "HTTP/1.1 205 Reset Content",
1855 "HTTP/1.1 304 Not Modified",
1856 "HTTP/1.1 302 Found",
1857 "HTTP/1.1 302 Found",
1858 "HTTP/1.1 301 Moved Permanently",
1859 "HTTP/1.1 301 Moved Permanently",
1862 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1863 "forgot to update kStatusLines");
1865 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1866 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1868 TestCompletionCallback callback
;
1869 scoped_ptr
<HttpTransaction
> trans(
1870 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1871 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1872 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1873 rv
= callback
.WaitForResult();
1875 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1876 ASSERT_TRUE(response
!= NULL
);
1877 ASSERT_TRUE(response
->headers
.get() != NULL
);
1878 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1879 std::string response_data
;
1880 rv
= ReadTransaction(trans
.get(), &response_data
);
1882 EXPECT_EQ("hello", response_data
);
1885 // Test the request-challenge-retry sequence for basic auth.
1886 // (basic auth is the easiest to mock, because it has no randomness).
1887 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1888 HttpRequestInfo request
;
1889 request
.method
= "GET";
1890 request
.url
= GURL("http://www.example.org/");
1891 request
.load_flags
= 0;
1894 session_deps_
.net_log
= &log
;
1895 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1896 scoped_ptr
<HttpTransaction
> trans(
1897 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1899 MockWrite data_writes1
[] = {
1901 "GET / HTTP/1.1\r\n"
1902 "Host: www.example.org\r\n"
1903 "Connection: keep-alive\r\n\r\n"),
1906 MockRead data_reads1
[] = {
1907 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1908 // Give a couple authenticate options (only the middle one is actually
1910 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1911 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1912 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1913 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1914 // Large content-length -- won't matter, as connection will be reset.
1915 MockRead("Content-Length: 10000\r\n\r\n"),
1916 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1919 // After calling trans->RestartWithAuth(), this is the request we should
1920 // be issuing -- the final header line contains the credentials.
1921 MockWrite data_writes2
[] = {
1923 "GET / HTTP/1.1\r\n"
1924 "Host: www.example.org\r\n"
1925 "Connection: keep-alive\r\n"
1926 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1929 // Lastly, the server responds with the actual content.
1930 MockRead data_reads2
[] = {
1931 MockRead("HTTP/1.0 200 OK\r\n"),
1932 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1933 MockRead("Content-Length: 100\r\n\r\n"),
1934 MockRead(SYNCHRONOUS
, OK
),
1937 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1938 data_writes1
, arraysize(data_writes1
));
1939 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1940 data_writes2
, arraysize(data_writes2
));
1941 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1942 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1944 TestCompletionCallback callback1
;
1946 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1947 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1949 rv
= callback1
.WaitForResult();
1952 LoadTimingInfo load_timing_info1
;
1953 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1954 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1956 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1957 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1959 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1960 ASSERT_TRUE(response
!= NULL
);
1961 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1963 TestCompletionCallback callback2
;
1965 rv
= trans
->RestartWithAuth(
1966 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1967 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1969 rv
= callback2
.WaitForResult();
1972 LoadTimingInfo load_timing_info2
;
1973 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1974 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1975 // The load timing after restart should have a new socket ID, and times after
1976 // those of the first load timing.
1977 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1978 load_timing_info2
.connect_timing
.connect_start
);
1979 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1981 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1982 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1984 response
= trans
->GetResponseInfo();
1985 ASSERT_TRUE(response
!= NULL
);
1986 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1987 EXPECT_EQ(100, response
->headers
->GetContentLength());
1990 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1991 HttpRequestInfo request
;
1992 request
.method
= "GET";
1993 request
.url
= GURL("http://www.example.org/");
1994 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1996 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1997 scoped_ptr
<HttpTransaction
> trans(
1998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2000 MockWrite data_writes
[] = {
2002 "GET / HTTP/1.1\r\n"
2003 "Host: www.example.org\r\n"
2004 "Connection: keep-alive\r\n\r\n"),
2007 MockRead data_reads
[] = {
2008 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2009 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2010 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2011 // Large content-length -- won't matter, as connection will be reset.
2012 MockRead("Content-Length: 10000\r\n\r\n"),
2013 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2016 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2017 data_writes
, arraysize(data_writes
));
2018 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2019 TestCompletionCallback callback
;
2021 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2022 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2024 rv
= callback
.WaitForResult();
2027 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2028 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2030 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2031 ASSERT_TRUE(response
!= NULL
);
2032 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2035 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2037 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2038 HttpRequestInfo request
;
2039 request
.method
= "GET";
2040 request
.url
= GURL("http://www.example.org/");
2041 request
.load_flags
= 0;
2044 session_deps_
.net_log
= &log
;
2045 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2047 MockWrite data_writes1
[] = {
2049 "GET / HTTP/1.1\r\n"
2050 "Host: www.example.org\r\n"
2051 "Connection: keep-alive\r\n\r\n"),
2053 // After calling trans->RestartWithAuth(), this is the request we should
2054 // be issuing -- the final header line contains the credentials.
2056 "GET / HTTP/1.1\r\n"
2057 "Host: www.example.org\r\n"
2058 "Connection: keep-alive\r\n"
2059 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2062 MockRead data_reads1
[] = {
2063 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2064 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2065 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2066 MockRead("Content-Length: 14\r\n\r\n"),
2067 MockRead("Unauthorized\r\n"),
2069 // Lastly, the server responds with the actual content.
2070 MockRead("HTTP/1.1 200 OK\r\n"),
2071 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2072 MockRead("Content-Length: 5\r\n\r\n"),
2076 // If there is a regression where we disconnect a Keep-Alive
2077 // connection during an auth roundtrip, we'll end up reading this.
2078 MockRead data_reads2
[] = {
2079 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2082 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2083 data_writes1
, arraysize(data_writes1
));
2084 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2086 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2087 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2089 TestCompletionCallback callback1
;
2091 scoped_ptr
<HttpTransaction
> trans(
2092 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2093 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2094 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2096 rv
= callback1
.WaitForResult();
2099 LoadTimingInfo load_timing_info1
;
2100 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2101 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2103 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2104 ASSERT_TRUE(response
!= NULL
);
2105 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2107 TestCompletionCallback callback2
;
2109 rv
= trans
->RestartWithAuth(
2110 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2111 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2113 rv
= callback2
.WaitForResult();
2116 LoadTimingInfo load_timing_info2
;
2117 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2118 TestLoadTimingReused(load_timing_info2
);
2119 // The load timing after restart should have the same socket ID, and times
2120 // those of the first load timing.
2121 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2122 load_timing_info2
.send_start
);
2123 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2125 response
= trans
->GetResponseInfo();
2126 ASSERT_TRUE(response
!= NULL
);
2127 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2128 EXPECT_EQ(5, response
->headers
->GetContentLength());
2130 std::string response_data
;
2131 rv
= ReadTransaction(trans
.get(), &response_data
);
2133 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2134 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2137 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2138 // connection and with no response body to drain.
2139 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2140 HttpRequestInfo request
;
2141 request
.method
= "GET";
2142 request
.url
= GURL("http://www.example.org/");
2143 request
.load_flags
= 0;
2145 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2147 MockWrite data_writes1
[] = {
2149 "GET / HTTP/1.1\r\n"
2150 "Host: www.example.org\r\n"
2151 "Connection: keep-alive\r\n\r\n"),
2153 // After calling trans->RestartWithAuth(), this is the request we should
2154 // be issuing -- the final header line contains the credentials.
2156 "GET / HTTP/1.1\r\n"
2157 "Host: www.example.org\r\n"
2158 "Connection: keep-alive\r\n"
2159 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2162 MockRead data_reads1
[] = {
2163 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2164 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2165 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2167 // Lastly, the server responds with the actual content.
2168 MockRead("HTTP/1.1 200 OK\r\n"),
2169 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2170 MockRead("Content-Length: 5\r\n\r\n"),
2174 // An incorrect reconnect would cause this to be read.
2175 MockRead data_reads2
[] = {
2176 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2179 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2180 data_writes1
, arraysize(data_writes1
));
2181 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2183 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2184 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2186 TestCompletionCallback callback1
;
2188 scoped_ptr
<HttpTransaction
> trans(
2189 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2190 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2191 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2193 rv
= callback1
.WaitForResult();
2196 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2197 ASSERT_TRUE(response
!= NULL
);
2198 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2200 TestCompletionCallback callback2
;
2202 rv
= trans
->RestartWithAuth(
2203 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2204 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2206 rv
= callback2
.WaitForResult();
2209 response
= trans
->GetResponseInfo();
2210 ASSERT_TRUE(response
!= NULL
);
2211 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2212 EXPECT_EQ(5, response
->headers
->GetContentLength());
2215 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2216 // connection and with a large response body to drain.
2217 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2218 HttpRequestInfo request
;
2219 request
.method
= "GET";
2220 request
.url
= GURL("http://www.example.org/");
2221 request
.load_flags
= 0;
2223 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2225 MockWrite data_writes1
[] = {
2227 "GET / HTTP/1.1\r\n"
2228 "Host: www.example.org\r\n"
2229 "Connection: keep-alive\r\n\r\n"),
2231 // After calling trans->RestartWithAuth(), this is the request we should
2232 // be issuing -- the final header line contains the credentials.
2234 "GET / HTTP/1.1\r\n"
2235 "Host: www.example.org\r\n"
2236 "Connection: keep-alive\r\n"
2237 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2240 // Respond with 5 kb of response body.
2241 std::string
large_body_string("Unauthorized");
2242 large_body_string
.append(5 * 1024, ' ');
2243 large_body_string
.append("\r\n");
2245 MockRead data_reads1
[] = {
2246 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2247 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2249 // 5134 = 12 + 5 * 1024 + 2
2250 MockRead("Content-Length: 5134\r\n\r\n"),
2251 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2253 // Lastly, the server responds with the actual content.
2254 MockRead("HTTP/1.1 200 OK\r\n"),
2255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2256 MockRead("Content-Length: 5\r\n\r\n"),
2260 // An incorrect reconnect would cause this to be read.
2261 MockRead data_reads2
[] = {
2262 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2265 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2266 data_writes1
, arraysize(data_writes1
));
2267 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2269 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2270 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2272 TestCompletionCallback callback1
;
2274 scoped_ptr
<HttpTransaction
> trans(
2275 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2276 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2277 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2279 rv
= callback1
.WaitForResult();
2282 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2283 ASSERT_TRUE(response
!= NULL
);
2284 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2286 TestCompletionCallback callback2
;
2288 rv
= trans
->RestartWithAuth(
2289 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2290 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2292 rv
= callback2
.WaitForResult();
2295 response
= trans
->GetResponseInfo();
2296 ASSERT_TRUE(response
!= NULL
);
2297 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2298 EXPECT_EQ(5, response
->headers
->GetContentLength());
2301 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2302 // connection, but the server gets impatient and closes the connection.
2303 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2304 HttpRequestInfo request
;
2305 request
.method
= "GET";
2306 request
.url
= GURL("http://www.example.org/");
2307 request
.load_flags
= 0;
2309 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2311 MockWrite data_writes1
[] = {
2313 "GET / HTTP/1.1\r\n"
2314 "Host: www.example.org\r\n"
2315 "Connection: keep-alive\r\n\r\n"),
2316 // This simulates the seemingly successful write to a closed connection
2317 // if the bug is not fixed.
2319 "GET / HTTP/1.1\r\n"
2320 "Host: www.example.org\r\n"
2321 "Connection: keep-alive\r\n"
2322 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2325 MockRead data_reads1
[] = {
2326 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2327 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2328 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2329 MockRead("Content-Length: 14\r\n\r\n"),
2330 // Tell MockTCPClientSocket to simulate the server closing the connection.
2331 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2332 MockRead("Unauthorized\r\n"),
2333 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2336 // After calling trans->RestartWithAuth(), this is the request we should
2337 // be issuing -- the final header line contains the credentials.
2338 MockWrite data_writes2
[] = {
2340 "GET / HTTP/1.1\r\n"
2341 "Host: www.example.org\r\n"
2342 "Connection: keep-alive\r\n"
2343 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2346 // Lastly, the server responds with the actual content.
2347 MockRead data_reads2
[] = {
2348 MockRead("HTTP/1.1 200 OK\r\n"),
2349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2350 MockRead("Content-Length: 5\r\n\r\n"),
2354 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2355 data_writes1
, arraysize(data_writes1
));
2356 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2357 data_writes2
, arraysize(data_writes2
));
2358 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2359 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2361 TestCompletionCallback callback1
;
2363 scoped_ptr
<HttpTransaction
> trans(
2364 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2365 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2366 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2368 rv
= callback1
.WaitForResult();
2371 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2372 ASSERT_TRUE(response
!= NULL
);
2373 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2375 TestCompletionCallback callback2
;
2377 rv
= trans
->RestartWithAuth(
2378 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2379 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2381 rv
= callback2
.WaitForResult();
2384 response
= trans
->GetResponseInfo();
2385 ASSERT_TRUE(response
!= NULL
);
2386 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2387 EXPECT_EQ(5, response
->headers
->GetContentLength());
2390 // Test the request-challenge-retry sequence for basic auth, over a connection
2391 // that requires a restart when setting up an SSL tunnel.
2392 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2393 HttpRequestInfo request
;
2394 request
.method
= "GET";
2395 request
.url
= GURL("https://www.example.org/");
2396 // when the no authentication data flag is set.
2397 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2399 // Configure against proxy server "myproxy:70".
2400 session_deps_
.proxy_service
.reset(
2401 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2402 BoundTestNetLog log
;
2403 session_deps_
.net_log
= log
.bound().net_log();
2404 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2406 // Since we have proxy, should try to establish tunnel.
2407 MockWrite data_writes1
[] = {
2408 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2409 "Host: www.example.org\r\n"
2410 "Proxy-Connection: keep-alive\r\n\r\n"),
2413 // The proxy responds to the connect with a 407, using a non-persistent
2415 MockRead data_reads1
[] = {
2417 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2418 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2421 // Since the first connection couldn't be reused, need to establish another
2422 // once given credentials.
2423 MockWrite data_writes2
[] = {
2424 // After calling trans->RestartWithAuth(), this is the request we should
2425 // be issuing -- the final header line contains the credentials.
2426 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2427 "Host: www.example.org\r\n"
2428 "Proxy-Connection: keep-alive\r\n"
2429 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2431 MockWrite("GET / HTTP/1.1\r\n"
2432 "Host: www.example.org\r\n"
2433 "Connection: keep-alive\r\n\r\n"),
2436 MockRead data_reads2
[] = {
2437 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2439 MockRead("HTTP/1.1 200 OK\r\n"),
2440 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2441 MockRead("Content-Length: 5\r\n\r\n"),
2442 MockRead(SYNCHRONOUS
, "hello"),
2445 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2446 data_writes1
, arraysize(data_writes1
));
2447 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2448 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2449 data_writes2
, arraysize(data_writes2
));
2450 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2451 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2452 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2454 TestCompletionCallback callback1
;
2456 scoped_ptr
<HttpTransaction
> trans(
2457 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2459 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2460 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2462 rv
= callback1
.WaitForResult();
2464 TestNetLogEntry::List entries
;
2465 log
.GetEntries(&entries
);
2466 size_t pos
= ExpectLogContainsSomewhere(
2467 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2468 NetLog::PHASE_NONE
);
2469 ExpectLogContainsSomewhere(
2470 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2471 NetLog::PHASE_NONE
);
2473 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2474 ASSERT_TRUE(response
!= NULL
);
2475 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2476 ASSERT_FALSE(response
->headers
.get() == NULL
);
2477 EXPECT_EQ(407, response
->headers
->response_code());
2478 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2479 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2481 LoadTimingInfo load_timing_info
;
2482 // CONNECT requests and responses are handled at the connect job level, so
2483 // the transaction does not yet have a connection.
2484 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2486 TestCompletionCallback callback2
;
2489 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2490 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2492 rv
= callback2
.WaitForResult();
2495 response
= trans
->GetResponseInfo();
2496 ASSERT_TRUE(response
!= NULL
);
2498 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2499 EXPECT_EQ(200, response
->headers
->response_code());
2500 EXPECT_EQ(5, response
->headers
->GetContentLength());
2501 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2503 // The password prompt info should not be set.
2504 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2506 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2507 TestLoadTimingNotReusedWithPac(load_timing_info
,
2508 CONNECT_TIMING_HAS_SSL_TIMES
);
2511 session
->CloseAllConnections();
2514 // Test the request-challenge-retry sequence for basic auth, over a connection
2515 // that requires a restart when setting up an SSL tunnel.
2516 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2517 HttpRequestInfo request
;
2518 request
.method
= "GET";
2519 request
.url
= GURL("https://www.example.org/");
2520 // when the no authentication data flag is set.
2521 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2523 // Configure against proxy server "myproxy:70".
2524 session_deps_
.proxy_service
.reset(
2525 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2526 BoundTestNetLog log
;
2527 session_deps_
.net_log
= log
.bound().net_log();
2528 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2530 // Since we have proxy, should try to establish tunnel.
2531 MockWrite data_writes1
[] = {
2532 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2533 "Host: www.example.org\r\n"
2534 "Proxy-Connection: keep-alive\r\n\r\n"),
2537 // The proxy responds to the connect with a 407, using a non-persistent
2539 MockRead data_reads1
[] = {
2541 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2542 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2543 MockRead("Proxy-Connection: close\r\n\r\n"),
2546 MockWrite data_writes2
[] = {
2547 // After calling trans->RestartWithAuth(), this is the request we should
2548 // be issuing -- the final header line contains the credentials.
2549 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2550 "Host: www.example.org\r\n"
2551 "Proxy-Connection: keep-alive\r\n"
2552 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2554 MockWrite("GET / HTTP/1.1\r\n"
2555 "Host: www.example.org\r\n"
2556 "Connection: keep-alive\r\n\r\n"),
2559 MockRead data_reads2
[] = {
2560 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2562 MockRead("HTTP/1.1 200 OK\r\n"),
2563 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2564 MockRead("Content-Length: 5\r\n\r\n"),
2565 MockRead(SYNCHRONOUS
, "hello"),
2568 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2569 data_writes1
, arraysize(data_writes1
));
2570 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2571 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2572 data_writes2
, arraysize(data_writes2
));
2573 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2574 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2575 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2577 TestCompletionCallback callback1
;
2579 scoped_ptr
<HttpTransaction
> trans(
2580 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2582 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2583 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2585 rv
= callback1
.WaitForResult();
2587 TestNetLogEntry::List entries
;
2588 log
.GetEntries(&entries
);
2589 size_t pos
= ExpectLogContainsSomewhere(
2590 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2591 NetLog::PHASE_NONE
);
2592 ExpectLogContainsSomewhere(
2594 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2595 NetLog::PHASE_NONE
);
2597 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2598 ASSERT_TRUE(response
!= NULL
);
2599 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2600 ASSERT_FALSE(response
->headers
.get() == NULL
);
2601 EXPECT_EQ(407, response
->headers
->response_code());
2602 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2603 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2605 LoadTimingInfo load_timing_info
;
2606 // CONNECT requests and responses are handled at the connect job level, so
2607 // the transaction does not yet have a connection.
2608 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2610 TestCompletionCallback callback2
;
2612 rv
= trans
->RestartWithAuth(
2613 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2614 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2616 rv
= callback2
.WaitForResult();
2619 response
= trans
->GetResponseInfo();
2620 ASSERT_TRUE(response
!= NULL
);
2622 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2623 EXPECT_EQ(200, response
->headers
->response_code());
2624 EXPECT_EQ(5, response
->headers
->GetContentLength());
2625 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2627 // The password prompt info should not be set.
2628 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2630 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2631 TestLoadTimingNotReusedWithPac(load_timing_info
,
2632 CONNECT_TIMING_HAS_SSL_TIMES
);
2635 session
->CloseAllConnections();
2638 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2639 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2640 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2641 HttpRequestInfo request
;
2642 request
.method
= "GET";
2643 request
.url
= GURL("https://www.example.org/");
2644 // Ensure that proxy authentication is attempted even
2645 // when the no authentication data flag is set.
2646 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2648 // Configure against proxy server "myproxy:70".
2649 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2650 BoundTestNetLog log
;
2651 session_deps_
.net_log
= log
.bound().net_log();
2652 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2654 scoped_ptr
<HttpTransaction
> trans(
2655 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2657 // Since we have proxy, should try to establish tunnel.
2658 MockWrite data_writes1
[] = {
2660 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2661 "Host: www.example.org\r\n"
2662 "Proxy-Connection: keep-alive\r\n\r\n"),
2664 // After calling trans->RestartWithAuth(), this is the request we should
2665 // be issuing -- the final header line contains the credentials.
2667 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2668 "Host: www.example.org\r\n"
2669 "Proxy-Connection: keep-alive\r\n"
2670 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2673 // The proxy responds to the connect with a 407, using a persistent
2674 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2675 MockRead data_reads1
[] = {
2677 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2679 MockRead("Proxy-Connection: keep-alive\r\n"),
2680 MockRead("Content-Length: 10\r\n\r\n"),
2681 MockRead("0123456789"),
2683 // Wrong credentials (wrong password).
2684 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2685 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2686 MockRead("Proxy-Connection: keep-alive\r\n"),
2687 MockRead("Content-Length: 10\r\n\r\n"),
2688 // No response body because the test stops reading here.
2689 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2692 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2693 data_writes1
, arraysize(data_writes1
));
2694 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2696 TestCompletionCallback callback1
;
2698 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2699 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2701 rv
= callback1
.WaitForResult();
2703 TestNetLogEntry::List entries
;
2704 log
.GetEntries(&entries
);
2705 size_t pos
= ExpectLogContainsSomewhere(
2706 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2707 NetLog::PHASE_NONE
);
2708 ExpectLogContainsSomewhere(
2709 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2710 NetLog::PHASE_NONE
);
2712 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2713 ASSERT_TRUE(response
);
2714 ASSERT_TRUE(response
->headers
);
2715 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2716 EXPECT_EQ(407, response
->headers
->response_code());
2717 EXPECT_EQ(10, response
->headers
->GetContentLength());
2718 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2719 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2721 TestCompletionCallback callback2
;
2723 // Wrong password (should be "bar").
2725 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2726 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2728 rv
= callback2
.WaitForResult();
2731 response
= trans
->GetResponseInfo();
2732 ASSERT_TRUE(response
);
2733 ASSERT_TRUE(response
->headers
);
2734 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2735 EXPECT_EQ(407, response
->headers
->response_code());
2736 EXPECT_EQ(10, response
->headers
->GetContentLength());
2737 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2738 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2740 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2742 session
->CloseAllConnections();
2745 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2746 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2747 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2748 HttpRequestInfo request
;
2749 request
.method
= "GET";
2750 request
.url
= GURL("https://www.example.org/");
2751 // Ensure that proxy authentication is attempted even
2752 // when the no authentication data flag is set.
2753 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2755 // Configure against proxy server "myproxy:70".
2756 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2757 BoundTestNetLog log
;
2758 session_deps_
.net_log
= log
.bound().net_log();
2759 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2761 scoped_ptr
<HttpTransaction
> trans(
2762 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2764 // Since we have proxy, should try to establish tunnel.
2765 MockWrite data_writes1
[] = {
2767 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2768 "Host: www.example.org\r\n"
2769 "Proxy-Connection: keep-alive\r\n\r\n"),
2771 // After calling trans->RestartWithAuth(), this is the request we should
2772 // be issuing -- the final header line contains the credentials.
2774 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2775 "Host: www.example.org\r\n"
2776 "Proxy-Connection: keep-alive\r\n"
2777 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2780 // The proxy responds to the connect with a 407, using a persistent
2782 MockRead data_reads1
[] = {
2784 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2785 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2786 MockRead("Content-Length: 10\r\n\r\n"),
2787 MockRead("0123456789"),
2789 // Wrong credentials (wrong password).
2790 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2791 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2792 MockRead("Content-Length: 10\r\n\r\n"),
2793 // No response body because the test stops reading here.
2794 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2797 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2798 data_writes1
, arraysize(data_writes1
));
2799 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2801 TestCompletionCallback callback1
;
2803 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2804 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2806 rv
= callback1
.WaitForResult();
2808 TestNetLogEntry::List entries
;
2809 log
.GetEntries(&entries
);
2810 size_t pos
= ExpectLogContainsSomewhere(
2811 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2812 NetLog::PHASE_NONE
);
2813 ExpectLogContainsSomewhere(
2815 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2816 NetLog::PHASE_NONE
);
2818 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2819 ASSERT_TRUE(response
);
2820 ASSERT_TRUE(response
->headers
);
2821 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2822 EXPECT_EQ(407, response
->headers
->response_code());
2823 EXPECT_EQ(10, response
->headers
->GetContentLength());
2824 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2825 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2827 TestCompletionCallback callback2
;
2829 // Wrong password (should be "bar").
2830 rv
= trans
->RestartWithAuth(
2831 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2832 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2834 rv
= callback2
.WaitForResult();
2837 response
= trans
->GetResponseInfo();
2838 ASSERT_TRUE(response
);
2839 ASSERT_TRUE(response
->headers
);
2840 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2841 EXPECT_EQ(407, response
->headers
->response_code());
2842 EXPECT_EQ(10, response
->headers
->GetContentLength());
2843 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2844 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2846 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2848 session
->CloseAllConnections();
2851 // Test the case a proxy closes a socket while the challenge body is being
2853 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHangupDuringBody
) {
2854 HttpRequestInfo request
;
2855 request
.method
= "GET";
2856 request
.url
= GURL("https://www.example.org/");
2857 // Ensure that proxy authentication is attempted even
2858 // when the no authentication data flag is set.
2859 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2861 // Configure against proxy server "myproxy:70".
2862 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2863 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2865 scoped_ptr
<HttpTransaction
> trans(
2866 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2868 // Since we have proxy, should try to establish tunnel.
2869 MockWrite data_writes1
[] = {
2870 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2871 "Host: www.example.org\r\n"
2872 "Proxy-Connection: keep-alive\r\n\r\n"),
2875 // The proxy responds to the connect with a 407, using a persistent
2877 MockRead data_reads1
[] = {
2879 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2880 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2881 MockRead("Content-Length: 10\r\n\r\n"), MockRead("spam!"),
2882 // Server hands up in the middle of the body.
2883 MockRead(ASYNC
, ERR_CONNECTION_CLOSED
),
2886 MockWrite data_writes2
[] = {
2887 // After calling trans->RestartWithAuth(), this is the request we should
2888 // be issuing -- the final header line contains the credentials.
2889 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
2890 "Host: www.example.org\r\n"
2891 "Proxy-Connection: keep-alive\r\n"
2892 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2894 MockWrite("GET / HTTP/1.1\r\n"
2895 "Host: www.example.org\r\n"
2896 "Connection: keep-alive\r\n\r\n"),
2899 MockRead data_reads2
[] = {
2900 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2902 MockRead("HTTP/1.1 200 OK\r\n"),
2903 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2904 MockRead("Content-Length: 5\r\n\r\n"),
2905 MockRead(SYNCHRONOUS
, "hello"),
2908 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2909 data_writes1
, arraysize(data_writes1
));
2910 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2911 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2912 data_writes2
, arraysize(data_writes2
));
2913 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2914 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2915 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2917 TestCompletionCallback callback
;
2919 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2920 EXPECT_EQ(OK
, callback
.GetResult(rv
));
2922 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2923 ASSERT_TRUE(response
);
2924 ASSERT_TRUE(response
->headers
);
2925 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2926 EXPECT_EQ(407, response
->headers
->response_code());
2927 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2929 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
2930 EXPECT_EQ(OK
, callback
.GetResult(rv
));
2932 response
= trans
->GetResponseInfo();
2933 ASSERT_TRUE(response
);
2934 ASSERT_TRUE(response
->headers
);
2935 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2936 EXPECT_EQ(200, response
->headers
->response_code());
2938 EXPECT_EQ(OK
, ReadTransaction(trans
.get(), &body
));
2939 EXPECT_EQ("hello", body
);
2942 // Test that we don't read the response body when we fail to establish a tunnel,
2943 // even if the user cancels the proxy's auth attempt.
2944 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2945 HttpRequestInfo request
;
2946 request
.method
= "GET";
2947 request
.url
= GURL("https://www.example.org/");
2948 request
.load_flags
= 0;
2950 // Configure against proxy server "myproxy:70".
2951 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2953 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2955 scoped_ptr
<HttpTransaction
> trans(
2956 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2958 // Since we have proxy, should try to establish tunnel.
2959 MockWrite data_writes
[] = {
2961 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2962 "Host: www.example.org\r\n"
2963 "Proxy-Connection: keep-alive\r\n\r\n"),
2966 // The proxy responds to the connect with a 407.
2967 MockRead data_reads
[] = {
2968 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2969 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2970 MockRead("Content-Length: 10\r\n\r\n"),
2971 MockRead("0123456789"), // Should not be reached.
2972 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2975 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2976 data_writes
, arraysize(data_writes
));
2977 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2979 TestCompletionCallback callback
;
2981 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2982 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2984 rv
= callback
.WaitForResult();
2987 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2988 ASSERT_TRUE(response
);
2989 ASSERT_TRUE(response
->headers
);
2990 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2991 EXPECT_EQ(407, response
->headers
->response_code());
2992 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2994 std::string response_data
;
2995 rv
= ReadTransaction(trans
.get(), &response_data
);
2996 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2998 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2999 session
->CloseAllConnections();
3002 // Test that we don't pass extraneous headers from the proxy's response to the
3003 // caller when the proxy responds to CONNECT with 407.
3004 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
3005 HttpRequestInfo request
;
3006 request
.method
= "GET";
3007 request
.url
= GURL("https://www.example.org/");
3008 request
.load_flags
= 0;
3010 // Configure against proxy server "myproxy:70".
3011 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3013 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3015 scoped_ptr
<HttpTransaction
> trans(
3016 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3018 // Since we have proxy, should try to establish tunnel.
3019 MockWrite data_writes
[] = {
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 // The proxy responds to the connect with a 407.
3027 MockRead data_reads
[] = {
3028 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3029 MockRead("X-Foo: bar\r\n"),
3030 MockRead("Set-Cookie: foo=bar\r\n"),
3031 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3032 MockRead("Content-Length: 10\r\n\r\n"),
3033 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
3036 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
3037 arraysize(data_writes
));
3038 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3040 TestCompletionCallback callback
;
3042 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3045 rv
= callback
.WaitForResult();
3048 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3049 ASSERT_TRUE(response
);
3050 ASSERT_TRUE(response
->headers
);
3051 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3052 EXPECT_EQ(407, response
->headers
->response_code());
3053 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3054 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
3055 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
3057 std::string response_data
;
3058 rv
= ReadTransaction(trans
.get(), &response_data
);
3059 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3061 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
3062 session
->CloseAllConnections();
3065 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
3066 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
3067 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
3068 HttpRequestInfo request
;
3069 request
.method
= "GET";
3070 request
.url
= GURL("http://www.example.org/");
3071 request
.load_flags
= 0;
3073 // We are using a DIRECT connection (i.e. no proxy) for this session.
3074 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3075 scoped_ptr
<HttpTransaction
> trans(
3076 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3078 MockWrite data_writes1
[] = {
3080 "GET / HTTP/1.1\r\n"
3081 "Host: www.example.org\r\n"
3082 "Connection: keep-alive\r\n\r\n"),
3085 MockRead data_reads1
[] = {
3086 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
3087 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3088 // Large content-length -- won't matter, as connection will be reset.
3089 MockRead("Content-Length: 10000\r\n\r\n"),
3090 MockRead(SYNCHRONOUS
, ERR_FAILED
),
3093 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3094 data_writes1
, arraysize(data_writes1
));
3095 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3097 TestCompletionCallback callback
;
3099 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3100 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3102 rv
= callback
.WaitForResult();
3103 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3106 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3107 // through a non-authenticating proxy. The request should fail with
3108 // ERR_UNEXPECTED_PROXY_AUTH.
3109 // Note that it is impossible to detect if an HTTP server returns a 407 through
3110 // a non-authenticating proxy - there is nothing to indicate whether the
3111 // response came from the proxy or the server, so it is treated as if the proxy
3112 // issued the challenge.
3113 TEST_P(HttpNetworkTransactionTest
,
3114 HttpsServerRequestsProxyAuthThroughProxy
) {
3115 HttpRequestInfo request
;
3116 request
.method
= "GET";
3117 request
.url
= GURL("https://www.example.org/");
3119 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3120 BoundTestNetLog log
;
3121 session_deps_
.net_log
= log
.bound().net_log();
3122 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3124 // Since we have proxy, should try to establish tunnel.
3125 MockWrite data_writes1
[] = {
3127 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3128 "Host: www.example.org\r\n"
3129 "Proxy-Connection: keep-alive\r\n\r\n"),
3132 "GET / HTTP/1.1\r\n"
3133 "Host: www.example.org\r\n"
3134 "Connection: keep-alive\r\n\r\n"),
3137 MockRead data_reads1
[] = {
3138 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3140 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3141 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3143 MockRead(SYNCHRONOUS
, OK
),
3146 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3147 data_writes1
, arraysize(data_writes1
));
3148 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3149 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3150 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3152 TestCompletionCallback callback1
;
3154 scoped_ptr
<HttpTransaction
> trans(
3155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3157 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3158 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3160 rv
= callback1
.WaitForResult();
3161 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3162 TestNetLogEntry::List entries
;
3163 log
.GetEntries(&entries
);
3164 size_t pos
= ExpectLogContainsSomewhere(
3165 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3166 NetLog::PHASE_NONE
);
3167 ExpectLogContainsSomewhere(
3169 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3170 NetLog::PHASE_NONE
);
3173 // Test the load timing for HTTPS requests with an HTTP proxy.
3174 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3175 HttpRequestInfo request1
;
3176 request1
.method
= "GET";
3177 request1
.url
= GURL("https://www.example.org/1");
3179 HttpRequestInfo request2
;
3180 request2
.method
= "GET";
3181 request2
.url
= GURL("https://www.example.org/2");
3183 // Configure against proxy server "myproxy:70".
3184 session_deps_
.proxy_service
.reset(
3185 ProxyService::CreateFixed("PROXY myproxy:70"));
3186 BoundTestNetLog log
;
3187 session_deps_
.net_log
= log
.bound().net_log();
3188 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3190 // Since we have proxy, should try to establish tunnel.
3191 MockWrite data_writes1
[] = {
3193 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3194 "Host: www.example.org\r\n"
3195 "Proxy-Connection: keep-alive\r\n\r\n"),
3198 "GET /1 HTTP/1.1\r\n"
3199 "Host: www.example.org\r\n"
3200 "Connection: keep-alive\r\n\r\n"),
3203 "GET /2 HTTP/1.1\r\n"
3204 "Host: www.example.org\r\n"
3205 "Connection: keep-alive\r\n\r\n"),
3208 // The proxy responds to the connect with a 407, using a persistent
3210 MockRead data_reads1
[] = {
3211 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3213 MockRead("HTTP/1.1 200 OK\r\n"),
3214 MockRead("Content-Length: 1\r\n\r\n"),
3215 MockRead(SYNCHRONOUS
, "1"),
3217 MockRead("HTTP/1.1 200 OK\r\n"),
3218 MockRead("Content-Length: 2\r\n\r\n"),
3219 MockRead(SYNCHRONOUS
, "22"),
3222 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3223 data_writes1
, arraysize(data_writes1
));
3224 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3225 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3226 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3228 TestCompletionCallback callback1
;
3229 scoped_ptr
<HttpTransaction
> trans1(
3230 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3232 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3233 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3235 rv
= callback1
.WaitForResult();
3238 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3239 ASSERT_TRUE(response1
!= NULL
);
3240 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3241 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3243 LoadTimingInfo load_timing_info1
;
3244 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3245 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3249 TestCompletionCallback callback2
;
3250 scoped_ptr
<HttpTransaction
> trans2(
3251 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3253 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3256 rv
= callback2
.WaitForResult();
3259 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3260 ASSERT_TRUE(response2
!= NULL
);
3261 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3262 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3264 LoadTimingInfo load_timing_info2
;
3265 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3266 TestLoadTimingReused(load_timing_info2
);
3268 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3271 session
->CloseAllConnections();
3274 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3275 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3276 HttpRequestInfo request1
;
3277 request1
.method
= "GET";
3278 request1
.url
= GURL("https://www.example.org/1");
3280 HttpRequestInfo request2
;
3281 request2
.method
= "GET";
3282 request2
.url
= GURL("https://www.example.org/2");
3284 // Configure against proxy server "myproxy:70".
3285 session_deps_
.proxy_service
.reset(
3286 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3287 BoundTestNetLog log
;
3288 session_deps_
.net_log
= log
.bound().net_log();
3289 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3291 // Since we have proxy, should try to establish tunnel.
3292 MockWrite data_writes1
[] = {
3294 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3295 "Host: www.example.org\r\n"
3296 "Proxy-Connection: keep-alive\r\n\r\n"),
3299 "GET /1 HTTP/1.1\r\n"
3300 "Host: www.example.org\r\n"
3301 "Connection: keep-alive\r\n\r\n"),
3304 "GET /2 HTTP/1.1\r\n"
3305 "Host: www.example.org\r\n"
3306 "Connection: keep-alive\r\n\r\n"),
3309 // The proxy responds to the connect with a 407, using a persistent
3311 MockRead data_reads1
[] = {
3312 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3314 MockRead("HTTP/1.1 200 OK\r\n"),
3315 MockRead("Content-Length: 1\r\n\r\n"),
3316 MockRead(SYNCHRONOUS
, "1"),
3318 MockRead("HTTP/1.1 200 OK\r\n"),
3319 MockRead("Content-Length: 2\r\n\r\n"),
3320 MockRead(SYNCHRONOUS
, "22"),
3323 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3324 data_writes1
, arraysize(data_writes1
));
3325 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3326 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3327 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3329 TestCompletionCallback callback1
;
3330 scoped_ptr
<HttpTransaction
> trans1(
3331 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3333 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3336 rv
= callback1
.WaitForResult();
3339 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3340 ASSERT_TRUE(response1
!= NULL
);
3341 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3342 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3344 LoadTimingInfo load_timing_info1
;
3345 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3346 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3347 CONNECT_TIMING_HAS_SSL_TIMES
);
3351 TestCompletionCallback callback2
;
3352 scoped_ptr
<HttpTransaction
> trans2(
3353 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3355 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3358 rv
= callback2
.WaitForResult();
3361 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3362 ASSERT_TRUE(response2
!= NULL
);
3363 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3364 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3366 LoadTimingInfo load_timing_info2
;
3367 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3368 TestLoadTimingReusedWithPac(load_timing_info2
);
3370 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3373 session
->CloseAllConnections();
3376 // Test a simple get through an HTTPS Proxy.
3377 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3378 HttpRequestInfo request
;
3379 request
.method
= "GET";
3380 request
.url
= GURL("http://www.example.org/");
3382 // Configure against https proxy server "proxy:70".
3383 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3384 "https://proxy:70"));
3385 BoundTestNetLog log
;
3386 session_deps_
.net_log
= log
.bound().net_log();
3387 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3389 // Since we have proxy, should use full url
3390 MockWrite data_writes1
[] = {
3392 "GET http://www.example.org/ HTTP/1.1\r\n"
3393 "Host: www.example.org\r\n"
3394 "Proxy-Connection: keep-alive\r\n\r\n"),
3397 MockRead data_reads1
[] = {
3398 MockRead("HTTP/1.1 200 OK\r\n"),
3399 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3400 MockRead("Content-Length: 100\r\n\r\n"),
3401 MockRead(SYNCHRONOUS
, OK
),
3404 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3405 data_writes1
, arraysize(data_writes1
));
3406 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3407 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3408 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3410 TestCompletionCallback callback1
;
3412 scoped_ptr
<HttpTransaction
> trans(
3413 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3415 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3416 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3418 rv
= callback1
.WaitForResult();
3421 LoadTimingInfo load_timing_info
;
3422 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3423 TestLoadTimingNotReused(load_timing_info
,
3424 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3426 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3427 ASSERT_TRUE(response
!= NULL
);
3429 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3430 EXPECT_EQ(200, response
->headers
->response_code());
3431 EXPECT_EQ(100, response
->headers
->GetContentLength());
3432 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3434 // The password prompt info should not be set.
3435 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3438 // Test a SPDY get through an HTTPS Proxy.
3439 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3440 HttpRequestInfo request
;
3441 request
.method
= "GET";
3442 request
.url
= GURL("http://www.example.org/");
3443 request
.load_flags
= 0;
3445 // Configure against https proxy server "proxy:70".
3446 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3447 "https://proxy:70"));
3448 BoundTestNetLog log
;
3449 session_deps_
.net_log
= log
.bound().net_log();
3450 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3452 // fetch http://www.example.org/ via SPDY
3453 scoped_ptr
<SpdyFrame
> req(
3454 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3455 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3457 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3458 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3459 MockRead spdy_reads
[] = {
3460 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3463 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3464 arraysize(spdy_writes
));
3465 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3467 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3468 ssl
.SetNextProto(GetParam());
3469 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3471 TestCompletionCallback callback1
;
3473 scoped_ptr
<HttpTransaction
> trans(
3474 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3476 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3477 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3479 rv
= callback1
.WaitForResult();
3482 LoadTimingInfo load_timing_info
;
3483 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3484 TestLoadTimingNotReused(load_timing_info
,
3485 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3487 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3488 ASSERT_TRUE(response
!= NULL
);
3489 ASSERT_TRUE(response
->headers
.get() != NULL
);
3490 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3492 std::string response_data
;
3493 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3494 EXPECT_EQ(kUploadData
, response_data
);
3497 // Verifies that a session which races and wins against the owning transaction
3498 // (completing prior to host resolution), doesn't fail the transaction.
3499 // Regression test for crbug.com/334413.
3500 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3501 HttpRequestInfo request
;
3502 request
.method
= "GET";
3503 request
.url
= GURL("http://www.example.org/");
3504 request
.load_flags
= 0;
3506 // Configure SPDY proxy server "proxy:70".
3507 session_deps_
.proxy_service
.reset(
3508 ProxyService::CreateFixed("https://proxy:70"));
3509 BoundTestNetLog log
;
3510 session_deps_
.net_log
= log
.bound().net_log();
3511 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3513 // Fetch http://www.example.org/ through the SPDY proxy.
3514 scoped_ptr
<SpdyFrame
> req(
3515 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3516 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3518 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3519 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3520 MockRead spdy_reads
[] = {
3521 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3524 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3525 arraysize(spdy_writes
));
3526 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3528 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3529 ssl
.SetNextProto(GetParam());
3530 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3532 TestCompletionCallback callback1
;
3534 scoped_ptr
<HttpTransaction
> trans(
3535 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3537 // Stall the hostname resolution begun by the transaction.
3538 session_deps_
.host_resolver
->set_synchronous_mode(false);
3539 session_deps_
.host_resolver
->set_ondemand_mode(true);
3541 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3542 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3544 // Race a session to the proxy, which completes first.
3545 session_deps_
.host_resolver
->set_ondemand_mode(false);
3547 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3548 base::WeakPtr
<SpdySession
> spdy_session
=
3549 CreateSecureSpdySession(session
, key
, log
.bound());
3551 // Unstall the resolution begun by the transaction.
3552 session_deps_
.host_resolver
->set_ondemand_mode(true);
3553 session_deps_
.host_resolver
->ResolveAllPending();
3555 EXPECT_FALSE(callback1
.have_result());
3556 rv
= callback1
.WaitForResult();
3559 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3560 ASSERT_TRUE(response
!= NULL
);
3561 ASSERT_TRUE(response
->headers
.get() != NULL
);
3562 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3564 std::string response_data
;
3565 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3566 EXPECT_EQ(kUploadData
, response_data
);
3569 // Test a SPDY get through an HTTPS Proxy.
3570 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3571 HttpRequestInfo request
;
3572 request
.method
= "GET";
3573 request
.url
= GURL("http://www.example.org/");
3574 request
.load_flags
= 0;
3576 // Configure against https proxy server "myproxy:70".
3577 session_deps_
.proxy_service
.reset(
3578 ProxyService::CreateFixed("https://myproxy:70"));
3579 BoundTestNetLog log
;
3580 session_deps_
.net_log
= log
.bound().net_log();
3581 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3583 // The first request will be a bare GET, the second request will be a
3584 // GET with a Proxy-Authorization header.
3585 scoped_ptr
<SpdyFrame
> req_get(
3586 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3587 const char* const kExtraAuthorizationHeaders
[] = {
3588 "proxy-authorization", "Basic Zm9vOmJhcg=="
3590 scoped_ptr
<SpdyFrame
> req_get_authorization(
3591 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3592 arraysize(kExtraAuthorizationHeaders
) / 2,
3597 MockWrite spdy_writes
[] = {
3598 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3601 // The first response is a 407 proxy authentication challenge, and the second
3602 // response will be a 200 response since the second request includes a valid
3603 // Authorization header.
3604 const char* const kExtraAuthenticationHeaders
[] = {
3605 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3607 scoped_ptr
<SpdyFrame
> resp_authentication(
3608 spdy_util_
.ConstructSpdySynReplyError(
3609 "407 Proxy Authentication Required",
3610 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3612 scoped_ptr
<SpdyFrame
> body_authentication(
3613 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3614 scoped_ptr
<SpdyFrame
> resp_data(
3615 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3616 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3617 MockRead spdy_reads
[] = {
3618 CreateMockRead(*resp_authentication
, 1),
3619 CreateMockRead(*body_authentication
, 2),
3620 CreateMockRead(*resp_data
, 4),
3621 CreateMockRead(*body_data
, 5),
3622 MockRead(ASYNC
, 0, 6),
3625 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3626 arraysize(spdy_writes
));
3627 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3629 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3630 ssl
.SetNextProto(GetParam());
3631 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3633 TestCompletionCallback callback1
;
3635 scoped_ptr
<HttpTransaction
> trans(
3636 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3638 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3641 rv
= callback1
.WaitForResult();
3644 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3646 ASSERT_TRUE(response
!= NULL
);
3647 ASSERT_TRUE(response
->headers
.get() != NULL
);
3648 EXPECT_EQ(407, response
->headers
->response_code());
3649 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3650 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3652 TestCompletionCallback callback2
;
3654 rv
= trans
->RestartWithAuth(
3655 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3656 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3658 rv
= callback2
.WaitForResult();
3661 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3663 ASSERT_TRUE(response_restart
!= NULL
);
3664 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3665 EXPECT_EQ(200, response_restart
->headers
->response_code());
3666 // The password prompt info should not be set.
3667 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3670 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3671 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3672 HttpRequestInfo request
;
3673 request
.method
= "GET";
3674 request
.url
= GURL("https://www.example.org/");
3675 request
.load_flags
= 0;
3677 // Configure against https proxy server "proxy:70".
3678 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3679 "https://proxy:70"));
3680 BoundTestNetLog log
;
3681 session_deps_
.net_log
= log
.bound().net_log();
3682 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3684 scoped_ptr
<HttpTransaction
> trans(
3685 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3687 // CONNECT to www.example.org:443 via SPDY
3688 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3689 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3690 // fetch https://www.example.org/ via HTTP
3693 "GET / HTTP/1.1\r\n"
3694 "Host: www.example.org\r\n"
3695 "Connection: keep-alive\r\n\r\n";
3696 scoped_ptr
<SpdyFrame
> wrapped_get(
3697 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3698 scoped_ptr
<SpdyFrame
> conn_resp(
3699 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3700 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3701 "Content-Length: 10\r\n\r\n";
3702 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3703 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3704 scoped_ptr
<SpdyFrame
> wrapped_body(
3705 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3706 scoped_ptr
<SpdyFrame
> window_update(
3707 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3709 MockWrite spdy_writes
[] = {
3710 CreateMockWrite(*connect
, 0),
3711 CreateMockWrite(*wrapped_get
, 2),
3712 CreateMockWrite(*window_update
, 6),
3715 MockRead spdy_reads
[] = {
3716 CreateMockRead(*conn_resp
, 1, ASYNC
),
3717 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3718 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3719 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3720 MockRead(ASYNC
, 0, 7),
3723 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3724 arraysize(spdy_writes
));
3725 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3727 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3728 ssl
.SetNextProto(GetParam());
3729 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3730 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3731 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3733 TestCompletionCallback callback1
;
3735 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3736 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3738 rv
= callback1
.WaitForResult();
3741 LoadTimingInfo load_timing_info
;
3742 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3743 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3745 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3746 ASSERT_TRUE(response
!= NULL
);
3747 ASSERT_TRUE(response
->headers
.get() != NULL
);
3748 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3750 std::string response_data
;
3751 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3752 EXPECT_EQ("1234567890", response_data
);
3755 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3756 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3757 HttpRequestInfo request
;
3758 request
.method
= "GET";
3759 request
.url
= GURL("https://www.example.org/");
3760 request
.load_flags
= 0;
3762 // Configure against https proxy server "proxy:70".
3763 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3764 "https://proxy:70"));
3765 BoundTestNetLog log
;
3766 session_deps_
.net_log
= log
.bound().net_log();
3767 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3769 scoped_ptr
<HttpTransaction
> trans(
3770 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3772 // CONNECT to www.example.org:443 via SPDY
3773 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3774 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3775 // fetch https://www.example.org/ via SPDY
3776 const char kMyUrl
[] = "https://www.example.org/";
3777 scoped_ptr
<SpdyFrame
> get(
3778 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3779 scoped_ptr
<SpdyFrame
> wrapped_get(
3780 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3781 scoped_ptr
<SpdyFrame
> conn_resp(
3782 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3783 scoped_ptr
<SpdyFrame
> get_resp(
3784 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3785 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3786 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3787 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3788 scoped_ptr
<SpdyFrame
> wrapped_body(
3789 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3790 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3791 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3792 scoped_ptr
<SpdyFrame
> window_update_body(
3793 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3795 MockWrite spdy_writes
[] = {
3796 CreateMockWrite(*connect
, 0),
3797 CreateMockWrite(*wrapped_get
, 2),
3798 CreateMockWrite(*window_update_get_resp
, 6),
3799 CreateMockWrite(*window_update_body
, 7),
3802 MockRead spdy_reads
[] = {
3803 CreateMockRead(*conn_resp
, 1, ASYNC
),
3804 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3805 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3806 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3807 MockRead(ASYNC
, 0, 8),
3810 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3811 arraysize(spdy_writes
));
3812 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3814 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3815 ssl
.SetNextProto(GetParam());
3816 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3817 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3818 ssl2
.SetNextProto(GetParam());
3819 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3821 TestCompletionCallback callback1
;
3823 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3824 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3826 // Allow the SpdyProxyClientSocket's write callback to complete.
3827 base::MessageLoop::current()->RunUntilIdle();
3828 // Now allow the read of the response to complete.
3829 spdy_data
.CompleteRead();
3830 rv
= callback1
.WaitForResult();
3833 LoadTimingInfo load_timing_info
;
3834 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3835 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3837 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3838 ASSERT_TRUE(response
!= NULL
);
3839 ASSERT_TRUE(response
->headers
.get() != NULL
);
3840 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3842 std::string response_data
;
3843 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3844 EXPECT_EQ(kUploadData
, response_data
);
3847 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3848 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3849 HttpRequestInfo request
;
3850 request
.method
= "GET";
3851 request
.url
= GURL("https://www.example.org/");
3852 request
.load_flags
= 0;
3854 // Configure against https proxy server "proxy:70".
3855 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3856 "https://proxy:70"));
3857 BoundTestNetLog log
;
3858 session_deps_
.net_log
= log
.bound().net_log();
3859 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3861 scoped_ptr
<HttpTransaction
> trans(
3862 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3864 // CONNECT to www.example.org:443 via SPDY
3865 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3866 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3867 scoped_ptr
<SpdyFrame
> get(
3868 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3870 MockWrite spdy_writes
[] = {
3871 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3874 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3875 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3876 MockRead spdy_reads
[] = {
3877 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3880 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3881 arraysize(spdy_writes
));
3882 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3884 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3885 ssl
.SetNextProto(GetParam());
3886 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3887 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3888 ssl2
.SetNextProto(GetParam());
3889 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3891 TestCompletionCallback callback1
;
3893 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3894 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3896 rv
= callback1
.WaitForResult();
3897 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3899 // TODO(ttuttle): Anything else to check here?
3902 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3903 // HTTPS Proxy to different servers.
3904 TEST_P(HttpNetworkTransactionTest
,
3905 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3906 // Configure against https proxy server "proxy:70".
3907 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3908 "https://proxy:70"));
3909 BoundTestNetLog log
;
3910 session_deps_
.net_log
= log
.bound().net_log();
3911 scoped_refptr
<HttpNetworkSession
> session(
3912 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3914 HttpRequestInfo request1
;
3915 request1
.method
= "GET";
3916 request1
.url
= GURL("https://www.example.org/");
3917 request1
.load_flags
= 0;
3919 HttpRequestInfo request2
;
3920 request2
.method
= "GET";
3921 request2
.url
= GURL("https://mail.example.org/");
3922 request2
.load_flags
= 0;
3924 // CONNECT to www.example.org:443 via SPDY.
3925 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3926 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3927 scoped_ptr
<SpdyFrame
> conn_resp1(
3928 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3930 // Fetch https://www.example.org/ via HTTP.
3932 "GET / HTTP/1.1\r\n"
3933 "Host: www.example.org\r\n"
3934 "Connection: keep-alive\r\n\r\n";
3935 scoped_ptr
<SpdyFrame
> wrapped_get1(
3936 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3937 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3938 "Content-Length: 1\r\n\r\n";
3939 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3940 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3941 scoped_ptr
<SpdyFrame
> wrapped_body1(
3942 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3943 scoped_ptr
<SpdyFrame
> window_update(
3944 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3946 // CONNECT to mail.example.org:443 via SPDY.
3947 SpdyHeaderBlock connect2_block
;
3948 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3949 if (GetParam() >= kProtoHTTP2MinimumVersion
) {
3950 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org:443";
3952 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3953 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3955 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3956 scoped_ptr
<SpdyFrame
> connect2(
3957 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3959 scoped_ptr
<SpdyFrame
> conn_resp2(
3960 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3962 // Fetch https://mail.example.org/ via HTTP.
3964 "GET / HTTP/1.1\r\n"
3965 "Host: mail.example.org\r\n"
3966 "Connection: keep-alive\r\n\r\n";
3967 scoped_ptr
<SpdyFrame
> wrapped_get2(
3968 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3969 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3970 "Content-Length: 2\r\n\r\n";
3971 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3972 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3973 scoped_ptr
<SpdyFrame
> wrapped_body2(
3974 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3976 MockWrite spdy_writes
[] = {
3977 CreateMockWrite(*connect1
, 0),
3978 CreateMockWrite(*wrapped_get1
, 2),
3979 CreateMockWrite(*connect2
, 5),
3980 CreateMockWrite(*wrapped_get2
, 7),
3983 MockRead spdy_reads
[] = {
3984 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3985 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3986 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3987 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3988 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3989 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3990 MockRead(ASYNC
, 0, 10),
3993 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3994 arraysize(spdy_writes
));
3995 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3997 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3998 ssl
.SetNextProto(GetParam());
3999 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4000 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4001 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4002 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
4003 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl3
);
4005 TestCompletionCallback callback
;
4007 scoped_ptr
<HttpTransaction
> trans(
4008 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4009 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4010 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4012 LoadTimingInfo load_timing_info
;
4013 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4014 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4016 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4017 ASSERT_TRUE(response
!= NULL
);
4018 ASSERT_TRUE(response
->headers
.get() != NULL
);
4019 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4021 std::string response_data
;
4022 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4023 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4024 EXPECT_EQ(1, callback
.GetResult(rv
));
4026 scoped_ptr
<HttpTransaction
> trans2(
4027 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4028 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4029 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4031 LoadTimingInfo load_timing_info2
;
4032 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4033 // Even though the SPDY connection is reused, a new tunnelled connection has
4034 // to be created, so the socket's load timing looks like a fresh connection.
4035 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
4037 // The requests should have different IDs, since they each are using their own
4039 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4041 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4042 EXPECT_EQ(2, callback
.GetResult(rv
));
4045 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
4046 // HTTPS Proxy to the same server.
4047 TEST_P(HttpNetworkTransactionTest
,
4048 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
4049 // Configure against https proxy server "proxy:70".
4050 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4051 "https://proxy:70"));
4052 BoundTestNetLog log
;
4053 session_deps_
.net_log
= log
.bound().net_log();
4054 scoped_refptr
<HttpNetworkSession
> session(
4055 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4057 HttpRequestInfo request1
;
4058 request1
.method
= "GET";
4059 request1
.url
= GURL("https://www.example.org/");
4060 request1
.load_flags
= 0;
4062 HttpRequestInfo request2
;
4063 request2
.method
= "GET";
4064 request2
.url
= GURL("https://www.example.org/2");
4065 request2
.load_flags
= 0;
4067 // CONNECT to www.example.org:443 via SPDY.
4068 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
4069 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
4070 scoped_ptr
<SpdyFrame
> conn_resp1(
4071 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4073 // Fetch https://www.example.org/ via HTTP.
4075 "GET / HTTP/1.1\r\n"
4076 "Host: www.example.org\r\n"
4077 "Connection: keep-alive\r\n\r\n";
4078 scoped_ptr
<SpdyFrame
> wrapped_get1(
4079 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
4080 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
4081 "Content-Length: 1\r\n\r\n";
4082 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
4083 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
4084 scoped_ptr
<SpdyFrame
> wrapped_body1(
4085 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
4086 scoped_ptr
<SpdyFrame
> window_update(
4087 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
4089 // Fetch https://www.example.org/2 via HTTP.
4091 "GET /2 HTTP/1.1\r\n"
4092 "Host: www.example.org\r\n"
4093 "Connection: keep-alive\r\n\r\n";
4094 scoped_ptr
<SpdyFrame
> wrapped_get2(
4095 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
4096 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
4097 "Content-Length: 2\r\n\r\n";
4098 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
4099 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4100 scoped_ptr
<SpdyFrame
> wrapped_body2(
4101 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4103 MockWrite spdy_writes
[] = {
4104 CreateMockWrite(*connect1
, 0),
4105 CreateMockWrite(*wrapped_get1
, 2),
4106 CreateMockWrite(*wrapped_get2
, 5),
4109 MockRead spdy_reads
[] = {
4110 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4111 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4112 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4113 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4114 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4115 MockRead(ASYNC
, 0, 8),
4118 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4119 arraysize(spdy_writes
));
4120 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4122 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4123 ssl
.SetNextProto(GetParam());
4124 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4125 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4126 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4128 TestCompletionCallback callback
;
4130 scoped_ptr
<HttpTransaction
> trans(
4131 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4132 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4135 rv
= callback
.WaitForResult();
4138 LoadTimingInfo load_timing_info
;
4139 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4140 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4142 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4143 ASSERT_TRUE(response
!= NULL
);
4144 ASSERT_TRUE(response
->headers
.get() != NULL
);
4145 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4147 std::string response_data
;
4148 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4149 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4152 scoped_ptr
<HttpTransaction
> trans2(
4153 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4154 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4155 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4157 rv
= callback
.WaitForResult();
4160 LoadTimingInfo load_timing_info2
;
4161 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4162 TestLoadTimingReused(load_timing_info2
);
4164 // The requests should have the same ID.
4165 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4167 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4170 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4171 // Proxy to different servers.
4172 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4173 // Configure against https proxy server "proxy:70".
4174 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4175 "https://proxy:70"));
4176 BoundTestNetLog log
;
4177 session_deps_
.net_log
= log
.bound().net_log();
4178 scoped_refptr
<HttpNetworkSession
> session(
4179 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4181 HttpRequestInfo request1
;
4182 request1
.method
= "GET";
4183 request1
.url
= GURL("http://www.example.org/");
4184 request1
.load_flags
= 0;
4186 HttpRequestInfo request2
;
4187 request2
.method
= "GET";
4188 request2
.url
= GURL("http://mail.example.org/");
4189 request2
.load_flags
= 0;
4191 // http://www.example.org/
4192 scoped_ptr
<SpdyHeaderBlock
> headers(
4193 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4194 scoped_ptr
<SpdyFrame
> get1(
4195 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4196 scoped_ptr
<SpdyFrame
> get_resp1(
4197 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4198 scoped_ptr
<SpdyFrame
> body1(
4199 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4201 // http://mail.example.org/
4202 scoped_ptr
<SpdyHeaderBlock
> headers2(
4203 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4204 scoped_ptr
<SpdyFrame
> get2(
4205 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4206 scoped_ptr
<SpdyFrame
> get_resp2(
4207 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4208 scoped_ptr
<SpdyFrame
> body2(
4209 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4211 MockWrite spdy_writes
[] = {
4212 CreateMockWrite(*get1
, 0),
4213 CreateMockWrite(*get2
, 3),
4216 MockRead spdy_reads
[] = {
4217 CreateMockRead(*get_resp1
, 1, ASYNC
),
4218 CreateMockRead(*body1
, 2, ASYNC
),
4219 CreateMockRead(*get_resp2
, 4, ASYNC
),
4220 CreateMockRead(*body2
, 5, ASYNC
),
4221 MockRead(ASYNC
, 0, 6),
4224 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4225 arraysize(spdy_writes
));
4226 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4228 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4229 ssl
.SetNextProto(GetParam());
4230 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4232 TestCompletionCallback callback
;
4234 scoped_ptr
<HttpTransaction
> trans(
4235 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4236 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4237 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4239 LoadTimingInfo load_timing_info
;
4240 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4241 TestLoadTimingNotReused(load_timing_info
,
4242 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4244 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4245 ASSERT_TRUE(response
!= NULL
);
4246 ASSERT_TRUE(response
->headers
.get() != NULL
);
4247 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4249 std::string response_data
;
4250 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4251 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4252 EXPECT_EQ(1, callback
.GetResult(rv
));
4253 // Delete the first request, so the second one can reuse the socket.
4256 scoped_ptr
<HttpTransaction
> trans2(
4257 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4258 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4259 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4261 LoadTimingInfo load_timing_info2
;
4262 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4263 TestLoadTimingReused(load_timing_info2
);
4265 // The requests should have the same ID.
4266 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4268 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4269 EXPECT_EQ(2, callback
.GetResult(rv
));
4272 // Test the challenge-response-retry sequence through an HTTPS Proxy
4273 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4274 HttpRequestInfo request
;
4275 request
.method
= "GET";
4276 request
.url
= GURL("http://www.example.org/");
4277 // when the no authentication data flag is set.
4278 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4280 // Configure against https proxy server "myproxy:70".
4281 session_deps_
.proxy_service
.reset(
4282 ProxyService::CreateFixed("https://myproxy:70"));
4283 BoundTestNetLog log
;
4284 session_deps_
.net_log
= log
.bound().net_log();
4285 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4287 // Since we have proxy, should use full url
4288 MockWrite data_writes1
[] = {
4290 "GET http://www.example.org/ HTTP/1.1\r\n"
4291 "Host: www.example.org\r\n"
4292 "Proxy-Connection: keep-alive\r\n\r\n"),
4294 // After calling trans->RestartWithAuth(), this is the request we should
4295 // be issuing -- the final header line contains the credentials.
4297 "GET http://www.example.org/ HTTP/1.1\r\n"
4298 "Host: www.example.org\r\n"
4299 "Proxy-Connection: keep-alive\r\n"
4300 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4303 // The proxy responds to the GET with a 407, using a persistent
4305 MockRead data_reads1
[] = {
4307 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4308 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4309 MockRead("Proxy-Connection: keep-alive\r\n"),
4310 MockRead("Content-Length: 0\r\n\r\n"),
4312 MockRead("HTTP/1.1 200 OK\r\n"),
4313 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4314 MockRead("Content-Length: 100\r\n\r\n"),
4315 MockRead(SYNCHRONOUS
, OK
),
4318 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4319 data_writes1
, arraysize(data_writes1
));
4320 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4321 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4322 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4324 TestCompletionCallback callback1
;
4326 scoped_ptr
<HttpTransaction
> trans(
4327 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4329 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4330 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4332 rv
= callback1
.WaitForResult();
4335 LoadTimingInfo load_timing_info
;
4336 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4337 TestLoadTimingNotReused(load_timing_info
,
4338 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4340 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4341 ASSERT_TRUE(response
!= NULL
);
4342 ASSERT_FALSE(response
->headers
.get() == NULL
);
4343 EXPECT_EQ(407, response
->headers
->response_code());
4344 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4345 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4347 TestCompletionCallback callback2
;
4349 rv
= trans
->RestartWithAuth(
4350 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4351 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4353 rv
= callback2
.WaitForResult();
4356 load_timing_info
= LoadTimingInfo();
4357 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4358 // Retrying with HTTP AUTH is considered to be reusing a socket.
4359 TestLoadTimingReused(load_timing_info
);
4361 response
= trans
->GetResponseInfo();
4362 ASSERT_TRUE(response
!= NULL
);
4364 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4365 EXPECT_EQ(200, response
->headers
->response_code());
4366 EXPECT_EQ(100, response
->headers
->GetContentLength());
4367 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4369 // The password prompt info should not be set.
4370 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4373 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4374 const MockRead
& status
, int expected_status
) {
4375 HttpRequestInfo request
;
4376 request
.method
= "GET";
4377 request
.url
= GURL("https://www.example.org/");
4378 request
.load_flags
= 0;
4380 // Configure against proxy server "myproxy:70".
4381 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4382 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4384 // Since we have proxy, should try to establish tunnel.
4385 MockWrite data_writes
[] = {
4387 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4388 "Host: www.example.org\r\n"
4389 "Proxy-Connection: keep-alive\r\n\r\n"),
4392 MockRead data_reads
[] = {
4394 MockRead("Content-Length: 10\r\n\r\n"),
4395 // No response body because the test stops reading here.
4396 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4399 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4400 data_writes
, arraysize(data_writes
));
4401 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4403 TestCompletionCallback callback
;
4405 scoped_ptr
<HttpTransaction
> trans(
4406 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4408 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4409 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4411 rv
= callback
.WaitForResult();
4412 EXPECT_EQ(expected_status
, rv
);
4415 void HttpNetworkTransactionTest::ConnectStatusHelper(
4416 const MockRead
& status
) {
4417 ConnectStatusHelperWithExpectedStatus(
4418 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4421 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4422 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4425 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4426 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4429 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4430 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4433 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4434 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4437 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4438 ConnectStatusHelper(
4439 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4442 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4443 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4446 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4447 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4450 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4451 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4454 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4455 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4458 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4459 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4462 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4463 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4466 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4467 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4470 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4471 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4474 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4475 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4478 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4479 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4482 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4483 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4486 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4487 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4490 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4491 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4494 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4495 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4498 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4499 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4502 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4503 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4506 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4507 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4510 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4511 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4514 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4515 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4518 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4519 ConnectStatusHelperWithExpectedStatus(
4520 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4521 ERR_PROXY_AUTH_UNSUPPORTED
);
4524 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4525 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4528 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4529 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4532 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4533 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4536 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4537 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4540 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4541 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4544 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4545 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4548 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4549 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4552 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4553 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4556 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4557 ConnectStatusHelper(
4558 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4561 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4562 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4565 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4566 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4569 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4570 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4573 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4574 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4577 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4578 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4581 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4582 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4585 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4586 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4589 // Test the flow when both the proxy server AND origin server require
4590 // authentication. Again, this uses basic auth for both since that is
4591 // the simplest to mock.
4592 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4593 HttpRequestInfo request
;
4594 request
.method
= "GET";
4595 request
.url
= GURL("http://www.example.org/");
4596 request
.load_flags
= 0;
4598 // Configure against proxy server "myproxy:70".
4599 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4600 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4602 scoped_ptr
<HttpTransaction
> trans(
4603 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4605 MockWrite data_writes1
[] = {
4607 "GET http://www.example.org/ HTTP/1.1\r\n"
4608 "Host: www.example.org\r\n"
4609 "Proxy-Connection: keep-alive\r\n\r\n"),
4612 MockRead data_reads1
[] = {
4613 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4614 // Give a couple authenticate options (only the middle one is actually
4616 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4617 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4618 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4619 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4620 // Large content-length -- won't matter, as connection will be reset.
4621 MockRead("Content-Length: 10000\r\n\r\n"),
4622 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4625 // After calling trans->RestartWithAuth() the first time, this is the
4626 // request we should be issuing -- the final header line contains the
4627 // proxy's credentials.
4628 MockWrite data_writes2
[] = {
4630 "GET http://www.example.org/ HTTP/1.1\r\n"
4631 "Host: www.example.org\r\n"
4632 "Proxy-Connection: keep-alive\r\n"
4633 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4636 // Now the proxy server lets the request pass through to origin server.
4637 // The origin server responds with a 401.
4638 MockRead data_reads2
[] = {
4639 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4640 // Note: We are using the same realm-name as the proxy server. This is
4641 // completely valid, as realms are unique across hosts.
4642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4643 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4644 MockRead("Content-Length: 2000\r\n\r\n"),
4645 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4648 // After calling trans->RestartWithAuth() the second time, we should send
4649 // the credentials for both the proxy and origin server.
4650 MockWrite data_writes3
[] = {
4652 "GET http://www.example.org/ HTTP/1.1\r\n"
4653 "Host: www.example.org\r\n"
4654 "Proxy-Connection: keep-alive\r\n"
4655 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4656 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4659 // Lastly we get the desired content.
4660 MockRead data_reads3
[] = {
4661 MockRead("HTTP/1.0 200 OK\r\n"),
4662 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4663 MockRead("Content-Length: 100\r\n\r\n"),
4664 MockRead(SYNCHRONOUS
, OK
),
4667 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4668 data_writes1
, arraysize(data_writes1
));
4669 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4670 data_writes2
, arraysize(data_writes2
));
4671 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4672 data_writes3
, arraysize(data_writes3
));
4673 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4674 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4675 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4677 TestCompletionCallback callback1
;
4679 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4682 rv
= callback1
.WaitForResult();
4685 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4686 ASSERT_TRUE(response
!= NULL
);
4687 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4689 TestCompletionCallback callback2
;
4691 rv
= trans
->RestartWithAuth(
4692 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4693 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4695 rv
= callback2
.WaitForResult();
4698 response
= trans
->GetResponseInfo();
4699 ASSERT_TRUE(response
!= NULL
);
4700 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4702 TestCompletionCallback callback3
;
4704 rv
= trans
->RestartWithAuth(
4705 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4706 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4708 rv
= callback3
.WaitForResult();
4711 response
= trans
->GetResponseInfo();
4712 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4713 EXPECT_EQ(100, response
->headers
->GetContentLength());
4716 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4717 // can't hook into its internals to cause it to generate predictable NTLM
4718 // authorization headers.
4719 #if defined(NTLM_PORTABLE)
4720 // The NTLM authentication unit tests were generated by capturing the HTTP
4721 // requests and responses using Fiddler 2 and inspecting the generated random
4722 // bytes in the debugger.
4724 // Enter the correct password and authenticate successfully.
4725 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4726 HttpRequestInfo request
;
4727 request
.method
= "GET";
4728 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4730 // Ensure load is not disrupted by flags which suppress behaviour specific
4731 // to other auth schemes.
4732 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4734 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4736 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4738 MockWrite data_writes1
[] = {
4739 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4740 "Host: 172.22.68.17\r\n"
4741 "Connection: keep-alive\r\n\r\n"),
4744 MockRead data_reads1
[] = {
4745 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4746 // Negotiate and NTLM are often requested together. However, we only want
4747 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4748 // the header that requests Negotiate for this test.
4749 MockRead("WWW-Authenticate: NTLM\r\n"),
4750 MockRead("Connection: close\r\n"),
4751 MockRead("Content-Length: 42\r\n"),
4752 MockRead("Content-Type: text/html\r\n\r\n"),
4753 // Missing content -- won't matter, as connection will be reset.
4754 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4757 MockWrite data_writes2
[] = {
4758 // After restarting with a null identity, this is the
4759 // request we should be issuing -- the final header line contains a Type
4761 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4762 "Host: 172.22.68.17\r\n"
4763 "Connection: keep-alive\r\n"
4764 "Authorization: NTLM "
4765 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4767 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4768 // (the credentials for the origin server). The second request continues
4769 // on the same connection.
4770 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4771 "Host: 172.22.68.17\r\n"
4772 "Connection: keep-alive\r\n"
4773 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4774 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4775 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4776 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4777 "ahlhx5I=\r\n\r\n"),
4780 MockRead data_reads2
[] = {
4781 // The origin server responds with a Type 2 message.
4782 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4783 MockRead("WWW-Authenticate: NTLM "
4784 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4785 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4786 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4787 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4788 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4789 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4791 MockRead("Content-Length: 42\r\n"),
4792 MockRead("Content-Type: text/html\r\n\r\n"),
4793 MockRead("You are not authorized to view this page\r\n"),
4795 // Lastly we get the desired content.
4796 MockRead("HTTP/1.1 200 OK\r\n"),
4797 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4798 MockRead("Content-Length: 13\r\n\r\n"),
4799 MockRead("Please Login\r\n"),
4800 MockRead(SYNCHRONOUS
, OK
),
4803 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4804 data_writes1
, arraysize(data_writes1
));
4805 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4806 data_writes2
, arraysize(data_writes2
));
4807 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4808 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4810 TestCompletionCallback callback1
;
4812 scoped_ptr
<HttpTransaction
> trans(
4813 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4815 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4816 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4818 rv
= callback1
.WaitForResult();
4821 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4823 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4824 ASSERT_FALSE(response
== NULL
);
4825 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4827 TestCompletionCallback callback2
;
4829 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4830 callback2
.callback());
4831 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4833 rv
= callback2
.WaitForResult();
4836 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4838 response
= trans
->GetResponseInfo();
4839 ASSERT_TRUE(response
!= NULL
);
4840 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4842 TestCompletionCallback callback3
;
4844 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4845 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4847 rv
= callback3
.WaitForResult();
4850 response
= trans
->GetResponseInfo();
4851 ASSERT_TRUE(response
!= NULL
);
4852 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4853 EXPECT_EQ(13, response
->headers
->GetContentLength());
4856 // Enter a wrong password, and then the correct one.
4857 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4858 HttpRequestInfo request
;
4859 request
.method
= "GET";
4860 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4861 request
.load_flags
= 0;
4863 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4865 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4867 MockWrite data_writes1
[] = {
4868 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4869 "Host: 172.22.68.17\r\n"
4870 "Connection: keep-alive\r\n\r\n"),
4873 MockRead data_reads1
[] = {
4874 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4875 // Negotiate and NTLM are often requested together. However, we only want
4876 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4877 // the header that requests Negotiate for this test.
4878 MockRead("WWW-Authenticate: NTLM\r\n"),
4879 MockRead("Connection: close\r\n"),
4880 MockRead("Content-Length: 42\r\n"),
4881 MockRead("Content-Type: text/html\r\n\r\n"),
4882 // Missing content -- won't matter, as connection will be reset.
4883 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4886 MockWrite data_writes2
[] = {
4887 // After restarting with a null identity, this is the
4888 // request we should be issuing -- the final header line contains a Type
4890 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4891 "Host: 172.22.68.17\r\n"
4892 "Connection: keep-alive\r\n"
4893 "Authorization: NTLM "
4894 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4896 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4897 // (the credentials for the origin server). The second request continues
4898 // on the same connection.
4899 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4900 "Host: 172.22.68.17\r\n"
4901 "Connection: keep-alive\r\n"
4902 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4903 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4904 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4905 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4906 "4Ww7b7E=\r\n\r\n"),
4909 MockRead data_reads2
[] = {
4910 // The origin server responds with a Type 2 message.
4911 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4912 MockRead("WWW-Authenticate: NTLM "
4913 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4914 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4915 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4916 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4917 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4918 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4920 MockRead("Content-Length: 42\r\n"),
4921 MockRead("Content-Type: text/html\r\n\r\n"),
4922 MockRead("You are not authorized to view this page\r\n"),
4925 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4926 MockRead("WWW-Authenticate: NTLM\r\n"),
4927 MockRead("Connection: close\r\n"),
4928 MockRead("Content-Length: 42\r\n"),
4929 MockRead("Content-Type: text/html\r\n\r\n"),
4930 // Missing content -- won't matter, as connection will be reset.
4931 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4934 MockWrite data_writes3
[] = {
4935 // After restarting with a null identity, this is the
4936 // request we should be issuing -- the final header line contains a Type
4938 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4939 "Host: 172.22.68.17\r\n"
4940 "Connection: keep-alive\r\n"
4941 "Authorization: NTLM "
4942 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4944 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4945 // (the credentials for the origin server). The second request continues
4946 // on the same connection.
4947 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4948 "Host: 172.22.68.17\r\n"
4949 "Connection: keep-alive\r\n"
4950 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4951 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4952 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4953 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4954 "+4MUm7c=\r\n\r\n"),
4957 MockRead data_reads3
[] = {
4958 // The origin server responds with a Type 2 message.
4959 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4960 MockRead("WWW-Authenticate: NTLM "
4961 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4962 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4963 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4964 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4965 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4966 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4968 MockRead("Content-Length: 42\r\n"),
4969 MockRead("Content-Type: text/html\r\n\r\n"),
4970 MockRead("You are not authorized to view this page\r\n"),
4972 // Lastly we get the desired content.
4973 MockRead("HTTP/1.1 200 OK\r\n"),
4974 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4975 MockRead("Content-Length: 13\r\n\r\n"),
4976 MockRead("Please Login\r\n"),
4977 MockRead(SYNCHRONOUS
, OK
),
4980 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4981 data_writes1
, arraysize(data_writes1
));
4982 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4983 data_writes2
, arraysize(data_writes2
));
4984 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4985 data_writes3
, arraysize(data_writes3
));
4986 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4987 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4988 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4990 TestCompletionCallback callback1
;
4992 scoped_ptr
<HttpTransaction
> trans(
4993 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4995 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4996 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4998 rv
= callback1
.WaitForResult();
5001 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5003 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5004 ASSERT_TRUE(response
!= NULL
);
5005 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
5007 TestCompletionCallback callback2
;
5009 // Enter the wrong password.
5010 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
5011 callback2
.callback());
5012 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5014 rv
= callback2
.WaitForResult();
5017 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5018 TestCompletionCallback callback3
;
5019 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
5020 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5021 rv
= callback3
.WaitForResult();
5023 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5025 response
= trans
->GetResponseInfo();
5026 ASSERT_FALSE(response
== NULL
);
5027 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
5029 TestCompletionCallback callback4
;
5031 // Now enter the right password.
5032 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
5033 callback4
.callback());
5034 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5036 rv
= callback4
.WaitForResult();
5039 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5041 TestCompletionCallback callback5
;
5043 // One more roundtrip
5044 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
5045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5047 rv
= callback5
.WaitForResult();
5050 response
= trans
->GetResponseInfo();
5051 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5052 EXPECT_EQ(13, response
->headers
->GetContentLength());
5054 #endif // NTLM_PORTABLE
5056 // Test reading a server response which has only headers, and no body.
5057 // After some maximum number of bytes is consumed, the transaction should
5058 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
5059 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
5060 HttpRequestInfo request
;
5061 request
.method
= "GET";
5062 request
.url
= GURL("http://www.example.org/");
5063 request
.load_flags
= 0;
5065 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5066 scoped_ptr
<HttpTransaction
> trans(
5067 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5069 // Respond with 300 kb of headers (we should fail after 256 kb).
5070 std::string large_headers_string
;
5071 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
5073 MockRead data_reads
[] = {
5074 MockRead("HTTP/1.0 200 OK\r\n"),
5075 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
5076 MockRead("\r\nBODY"),
5077 MockRead(SYNCHRONOUS
, OK
),
5079 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5080 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5082 TestCompletionCallback callback
;
5084 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5087 rv
= callback
.WaitForResult();
5088 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5091 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5092 // establish tunnel.
5093 // http://code.google.com/p/chromium/issues/detail?id=3772
5094 TEST_P(HttpNetworkTransactionTest
,
5095 DontRecycleTransportSocketForSSLTunnel
) {
5096 HttpRequestInfo request
;
5097 request
.method
= "GET";
5098 request
.url
= GURL("https://www.example.org/");
5099 request
.load_flags
= 0;
5101 // Configure against proxy server "myproxy:70".
5102 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5104 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5106 scoped_ptr
<HttpTransaction
> trans(
5107 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5109 // Since we have proxy, should try to establish tunnel.
5110 MockWrite data_writes1
[] = {
5112 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5113 "Host: www.example.org\r\n"
5114 "Proxy-Connection: keep-alive\r\n\r\n"),
5117 // The proxy responds to the connect with a 404, using a persistent
5118 // connection. Usually a proxy would return 501 (not implemented),
5119 // or 200 (tunnel established).
5120 MockRead data_reads1
[] = {
5121 MockRead("HTTP/1.1 404 Not Found\r\n"),
5122 MockRead("Content-Length: 10\r\n\r\n"),
5123 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5126 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5127 data_writes1
, arraysize(data_writes1
));
5128 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5130 TestCompletionCallback callback1
;
5132 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5135 rv
= callback1
.WaitForResult();
5136 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5138 // Empty the current queue. This is necessary because idle sockets are
5139 // added to the connection pool asynchronously with a PostTask.
5140 base::MessageLoop::current()->RunUntilIdle();
5142 // We now check to make sure the TCPClientSocket was not added back to
5144 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5146 base::MessageLoop::current()->RunUntilIdle();
5147 // Make sure that the socket didn't get recycled after calling the destructor.
5148 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5151 // Make sure that we recycle a socket after reading all of the response body.
5152 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5153 HttpRequestInfo request
;
5154 request
.method
= "GET";
5155 request
.url
= GURL("http://www.example.org/");
5156 request
.load_flags
= 0;
5158 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5160 scoped_ptr
<HttpTransaction
> trans(
5161 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5163 MockRead data_reads
[] = {
5164 // A part of the response body is received with the response headers.
5165 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5166 // The rest of the response body is received in two parts.
5169 MockRead("junk"), // Should not be read!!
5170 MockRead(SYNCHRONOUS
, OK
),
5173 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5174 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5176 TestCompletionCallback callback
;
5178 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5181 rv
= callback
.WaitForResult();
5184 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5185 ASSERT_TRUE(response
!= NULL
);
5187 EXPECT_TRUE(response
->headers
.get() != NULL
);
5188 std::string status_line
= response
->headers
->GetStatusLine();
5189 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5191 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5193 std::string response_data
;
5194 rv
= ReadTransaction(trans
.get(), &response_data
);
5196 EXPECT_EQ("hello world", response_data
);
5198 // Empty the current queue. This is necessary because idle sockets are
5199 // added to the connection pool asynchronously with a PostTask.
5200 base::MessageLoop::current()->RunUntilIdle();
5202 // We now check to make sure the socket was added back to the pool.
5203 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5206 // Make sure that we recycle a SSL socket after reading all of the response
5208 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5209 HttpRequestInfo request
;
5210 request
.method
= "GET";
5211 request
.url
= GURL("https://www.example.org/");
5212 request
.load_flags
= 0;
5214 MockWrite data_writes
[] = {
5216 "GET / HTTP/1.1\r\n"
5217 "Host: www.example.org\r\n"
5218 "Connection: keep-alive\r\n\r\n"),
5221 MockRead data_reads
[] = {
5222 MockRead("HTTP/1.1 200 OK\r\n"),
5223 MockRead("Content-Length: 11\r\n\r\n"),
5224 MockRead("hello world"),
5225 MockRead(SYNCHRONOUS
, OK
),
5228 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5229 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5231 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5232 data_writes
, arraysize(data_writes
));
5233 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5235 TestCompletionCallback callback
;
5237 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5238 scoped_ptr
<HttpTransaction
> trans(
5239 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5241 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5244 EXPECT_EQ(OK
, callback
.WaitForResult());
5246 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5247 ASSERT_TRUE(response
!= NULL
);
5248 ASSERT_TRUE(response
->headers
.get() != NULL
);
5249 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5251 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5253 std::string response_data
;
5254 rv
= ReadTransaction(trans
.get(), &response_data
);
5256 EXPECT_EQ("hello world", response_data
);
5258 // Empty the current queue. This is necessary because idle sockets are
5259 // added to the connection pool asynchronously with a PostTask.
5260 base::MessageLoop::current()->RunUntilIdle();
5262 // We now check to make sure the socket was added back to the pool.
5263 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5266 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5267 // from the pool and make sure that we recover okay.
5268 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5269 HttpRequestInfo request
;
5270 request
.method
= "GET";
5271 request
.url
= GURL("https://www.example.org/");
5272 request
.load_flags
= 0;
5274 MockWrite data_writes
[] = {
5276 "GET / HTTP/1.1\r\n"
5277 "Host: www.example.org\r\n"
5278 "Connection: keep-alive\r\n\r\n"),
5280 "GET / HTTP/1.1\r\n"
5281 "Host: www.example.org\r\n"
5282 "Connection: keep-alive\r\n\r\n"),
5285 MockRead data_reads
[] = {
5286 MockRead("HTTP/1.1 200 OK\r\n"),
5287 MockRead("Content-Length: 11\r\n\r\n"),
5288 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5289 MockRead("hello world"),
5290 MockRead(ASYNC
, 0, 0) // EOF
5293 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5294 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5295 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5296 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5298 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5299 data_writes
, arraysize(data_writes
));
5300 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5301 data_writes
, arraysize(data_writes
));
5302 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5303 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5305 TestCompletionCallback callback
;
5307 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5308 scoped_ptr
<HttpTransaction
> trans(
5309 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5311 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5313 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5314 EXPECT_EQ(OK
, callback
.WaitForResult());
5316 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5317 ASSERT_TRUE(response
!= NULL
);
5318 ASSERT_TRUE(response
->headers
.get() != NULL
);
5319 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5321 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5323 std::string response_data
;
5324 rv
= ReadTransaction(trans
.get(), &response_data
);
5326 EXPECT_EQ("hello world", response_data
);
5328 // Empty the current queue. This is necessary because idle sockets are
5329 // added to the connection pool asynchronously with a PostTask.
5330 base::MessageLoop::current()->RunUntilIdle();
5332 // We now check to make sure the socket was added back to the pool.
5333 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5335 // Now start the second transaction, which should reuse the previous socket.
5337 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5339 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5341 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5342 EXPECT_EQ(OK
, callback
.WaitForResult());
5344 response
= trans
->GetResponseInfo();
5345 ASSERT_TRUE(response
!= NULL
);
5346 ASSERT_TRUE(response
->headers
.get() != NULL
);
5347 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5349 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5351 rv
= ReadTransaction(trans
.get(), &response_data
);
5353 EXPECT_EQ("hello world", response_data
);
5355 // Empty the current queue. This is necessary because idle sockets are
5356 // added to the connection pool asynchronously with a PostTask.
5357 base::MessageLoop::current()->RunUntilIdle();
5359 // We now check to make sure the socket was added back to the pool.
5360 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5363 // Make sure that we recycle a socket after a zero-length response.
5364 // http://crbug.com/9880
5365 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5366 HttpRequestInfo request
;
5367 request
.method
= "GET";
5369 "http://www.example.org/csi?v=3&s=web&action=&"
5370 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5371 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5372 "rt=prt.2642,ol.2649,xjs.2951");
5373 request
.load_flags
= 0;
5375 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5377 scoped_ptr
<HttpTransaction
> trans(
5378 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5380 MockRead data_reads
[] = {
5381 MockRead("HTTP/1.1 204 No Content\r\n"
5382 "Content-Length: 0\r\n"
5383 "Content-Type: text/html\r\n\r\n"),
5384 MockRead("junk"), // Should not be read!!
5385 MockRead(SYNCHRONOUS
, OK
),
5388 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5389 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5391 TestCompletionCallback callback
;
5393 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5394 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5396 rv
= callback
.WaitForResult();
5399 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5400 ASSERT_TRUE(response
!= NULL
);
5402 EXPECT_TRUE(response
->headers
.get() != NULL
);
5403 std::string status_line
= response
->headers
->GetStatusLine();
5404 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5406 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5408 std::string response_data
;
5409 rv
= ReadTransaction(trans
.get(), &response_data
);
5411 EXPECT_EQ("", response_data
);
5413 // Empty the current queue. This is necessary because idle sockets are
5414 // added to the connection pool asynchronously with a PostTask.
5415 base::MessageLoop::current()->RunUntilIdle();
5417 // We now check to make sure the socket was added back to the pool.
5418 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5421 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5422 ScopedVector
<UploadElementReader
> element_readers
;
5423 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5424 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5426 HttpRequestInfo request
[2];
5427 // Transaction 1: a GET request that succeeds. The socket is recycled
5429 request
[0].method
= "GET";
5430 request
[0].url
= GURL("http://www.google.com/");
5431 request
[0].load_flags
= 0;
5432 // Transaction 2: a POST request. Reuses the socket kept alive from
5433 // transaction 1. The first attempts fails when writing the POST data.
5434 // This causes the transaction to retry with a new socket. The second
5435 // attempt succeeds.
5436 request
[1].method
= "POST";
5437 request
[1].url
= GURL("http://www.google.com/login.cgi");
5438 request
[1].upload_data_stream
= &upload_data_stream
;
5439 request
[1].load_flags
= 0;
5441 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5443 // The first socket is used for transaction 1 and the first attempt of
5446 // The response of transaction 1.
5447 MockRead data_reads1
[] = {
5448 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5449 MockRead("hello world"),
5450 MockRead(SYNCHRONOUS
, OK
),
5452 // The mock write results of transaction 1 and the first attempt of
5454 MockWrite data_writes1
[] = {
5455 MockWrite(SYNCHRONOUS
, 64), // GET
5456 MockWrite(SYNCHRONOUS
, 93), // POST
5457 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5459 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5460 data_writes1
, arraysize(data_writes1
));
5462 // The second socket is used for the second attempt of transaction 2.
5464 // The response of transaction 2.
5465 MockRead data_reads2
[] = {
5466 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5467 MockRead("welcome"),
5468 MockRead(SYNCHRONOUS
, OK
),
5470 // The mock write results of the second attempt of transaction 2.
5471 MockWrite data_writes2
[] = {
5472 MockWrite(SYNCHRONOUS
, 93), // POST
5473 MockWrite(SYNCHRONOUS
, 3), // POST data
5475 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5476 data_writes2
, arraysize(data_writes2
));
5478 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5479 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5481 const char* const kExpectedResponseData
[] = {
5482 "hello world", "welcome"
5485 for (int i
= 0; i
< 2; ++i
) {
5486 scoped_ptr
<HttpTransaction
> trans(
5487 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5489 TestCompletionCallback callback
;
5491 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5492 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5494 rv
= callback
.WaitForResult();
5497 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5498 ASSERT_TRUE(response
!= NULL
);
5500 EXPECT_TRUE(response
->headers
.get() != NULL
);
5501 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5503 std::string response_data
;
5504 rv
= ReadTransaction(trans
.get(), &response_data
);
5506 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5510 // Test the request-challenge-retry sequence for basic auth when there is
5511 // an identity in the URL. The request should be sent as normal, but when
5512 // it fails the identity from the URL is used to answer the challenge.
5513 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5514 HttpRequestInfo request
;
5515 request
.method
= "GET";
5516 request
.url
= GURL("http://foo:b@r@www.example.org/");
5517 request
.load_flags
= LOAD_NORMAL
;
5519 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5520 scoped_ptr
<HttpTransaction
> trans(
5521 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5523 // The password contains an escaped character -- for this test to pass it
5524 // will need to be unescaped by HttpNetworkTransaction.
5525 EXPECT_EQ("b%40r", request
.url
.password());
5527 MockWrite data_writes1
[] = {
5529 "GET / HTTP/1.1\r\n"
5530 "Host: www.example.org\r\n"
5531 "Connection: keep-alive\r\n\r\n"),
5534 MockRead data_reads1
[] = {
5535 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5536 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5537 MockRead("Content-Length: 10\r\n\r\n"),
5538 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5541 // After the challenge above, the transaction will be restarted using the
5542 // identity from the url (foo, b@r) to answer the challenge.
5543 MockWrite data_writes2
[] = {
5545 "GET / HTTP/1.1\r\n"
5546 "Host: www.example.org\r\n"
5547 "Connection: keep-alive\r\n"
5548 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5551 MockRead data_reads2
[] = {
5552 MockRead("HTTP/1.0 200 OK\r\n"),
5553 MockRead("Content-Length: 100\r\n\r\n"),
5554 MockRead(SYNCHRONOUS
, OK
),
5557 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5558 data_writes1
, arraysize(data_writes1
));
5559 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5560 data_writes2
, arraysize(data_writes2
));
5561 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5562 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5564 TestCompletionCallback callback1
;
5565 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5566 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5567 rv
= callback1
.WaitForResult();
5569 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5571 TestCompletionCallback callback2
;
5572 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5573 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5574 rv
= callback2
.WaitForResult();
5576 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5578 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5579 ASSERT_TRUE(response
!= NULL
);
5581 // There is no challenge info, since the identity in URL worked.
5582 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5584 EXPECT_EQ(100, response
->headers
->GetContentLength());
5586 // Empty the current queue.
5587 base::MessageLoop::current()->RunUntilIdle();
5590 // Test the request-challenge-retry sequence for basic auth when there is an
5591 // incorrect identity in the URL. The identity from the URL should be used only
5593 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5594 HttpRequestInfo request
;
5595 request
.method
= "GET";
5596 // Note: the URL has a username:password in it. The password "baz" is
5597 // wrong (should be "bar").
5598 request
.url
= GURL("http://foo:baz@www.example.org/");
5600 request
.load_flags
= LOAD_NORMAL
;
5602 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5603 scoped_ptr
<HttpTransaction
> trans(
5604 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5606 MockWrite data_writes1
[] = {
5608 "GET / HTTP/1.1\r\n"
5609 "Host: www.example.org\r\n"
5610 "Connection: keep-alive\r\n\r\n"),
5613 MockRead data_reads1
[] = {
5614 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5615 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5616 MockRead("Content-Length: 10\r\n\r\n"),
5617 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5620 // After the challenge above, the transaction will be restarted using the
5621 // identity from the url (foo, baz) to answer the challenge.
5622 MockWrite data_writes2
[] = {
5624 "GET / HTTP/1.1\r\n"
5625 "Host: www.example.org\r\n"
5626 "Connection: keep-alive\r\n"
5627 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5630 MockRead data_reads2
[] = {
5631 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5632 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5633 MockRead("Content-Length: 10\r\n\r\n"),
5634 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5637 // After the challenge above, the transaction will be restarted using the
5638 // identity supplied by the user (foo, bar) to answer the challenge.
5639 MockWrite data_writes3
[] = {
5641 "GET / HTTP/1.1\r\n"
5642 "Host: www.example.org\r\n"
5643 "Connection: keep-alive\r\n"
5644 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5647 MockRead data_reads3
[] = {
5648 MockRead("HTTP/1.0 200 OK\r\n"),
5649 MockRead("Content-Length: 100\r\n\r\n"),
5650 MockRead(SYNCHRONOUS
, OK
),
5653 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5654 data_writes1
, arraysize(data_writes1
));
5655 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5656 data_writes2
, arraysize(data_writes2
));
5657 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5658 data_writes3
, arraysize(data_writes3
));
5659 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5660 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5661 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5663 TestCompletionCallback callback1
;
5665 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5666 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5668 rv
= callback1
.WaitForResult();
5671 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5672 TestCompletionCallback callback2
;
5673 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5674 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5675 rv
= callback2
.WaitForResult();
5677 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5679 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5680 ASSERT_TRUE(response
!= NULL
);
5681 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5683 TestCompletionCallback callback3
;
5684 rv
= trans
->RestartWithAuth(
5685 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5687 rv
= callback3
.WaitForResult();
5689 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5691 response
= trans
->GetResponseInfo();
5692 ASSERT_TRUE(response
!= NULL
);
5694 // There is no challenge info, since the identity worked.
5695 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5697 EXPECT_EQ(100, response
->headers
->GetContentLength());
5699 // Empty the current queue.
5700 base::MessageLoop::current()->RunUntilIdle();
5704 // Test the request-challenge-retry sequence for basic auth when there is a
5705 // correct identity in the URL, but its use is being suppressed. The identity
5706 // from the URL should never be used.
5707 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5708 HttpRequestInfo request
;
5709 request
.method
= "GET";
5710 request
.url
= GURL("http://foo:bar@www.example.org/");
5711 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5713 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5714 scoped_ptr
<HttpTransaction
> trans(
5715 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5717 MockWrite data_writes1
[] = {
5719 "GET / HTTP/1.1\r\n"
5720 "Host: www.example.org\r\n"
5721 "Connection: keep-alive\r\n\r\n"),
5724 MockRead data_reads1
[] = {
5725 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5726 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5727 MockRead("Content-Length: 10\r\n\r\n"),
5728 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5731 // After the challenge above, the transaction will be restarted using the
5732 // identity supplied by the user, not the one in the URL, to answer the
5734 MockWrite data_writes3
[] = {
5736 "GET / HTTP/1.1\r\n"
5737 "Host: www.example.org\r\n"
5738 "Connection: keep-alive\r\n"
5739 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5742 MockRead data_reads3
[] = {
5743 MockRead("HTTP/1.0 200 OK\r\n"),
5744 MockRead("Content-Length: 100\r\n\r\n"),
5745 MockRead(SYNCHRONOUS
, OK
),
5748 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5749 data_writes1
, arraysize(data_writes1
));
5750 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5751 data_writes3
, arraysize(data_writes3
));
5752 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5753 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5755 TestCompletionCallback callback1
;
5756 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5757 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5758 rv
= callback1
.WaitForResult();
5760 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5762 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5763 ASSERT_TRUE(response
!= NULL
);
5764 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5766 TestCompletionCallback callback3
;
5767 rv
= trans
->RestartWithAuth(
5768 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5769 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5770 rv
= callback3
.WaitForResult();
5772 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5774 response
= trans
->GetResponseInfo();
5775 ASSERT_TRUE(response
!= NULL
);
5777 // There is no challenge info, since the identity worked.
5778 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5779 EXPECT_EQ(100, response
->headers
->GetContentLength());
5781 // Empty the current queue.
5782 base::MessageLoop::current()->RunUntilIdle();
5785 // Test that previously tried username/passwords for a realm get re-used.
5786 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5787 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5789 // Transaction 1: authenticate (foo, bar) on MyRealm1
5791 HttpRequestInfo request
;
5792 request
.method
= "GET";
5793 request
.url
= GURL("http://www.example.org/x/y/z");
5794 request
.load_flags
= 0;
5796 scoped_ptr
<HttpTransaction
> trans(
5797 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5799 MockWrite data_writes1
[] = {
5801 "GET /x/y/z HTTP/1.1\r\n"
5802 "Host: www.example.org\r\n"
5803 "Connection: keep-alive\r\n\r\n"),
5806 MockRead data_reads1
[] = {
5807 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5808 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5809 MockRead("Content-Length: 10000\r\n\r\n"),
5810 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5813 // Resend with authorization (username=foo, password=bar)
5814 MockWrite data_writes2
[] = {
5816 "GET /x/y/z HTTP/1.1\r\n"
5817 "Host: www.example.org\r\n"
5818 "Connection: keep-alive\r\n"
5819 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5822 // Sever accepts the authorization.
5823 MockRead data_reads2
[] = {
5824 MockRead("HTTP/1.0 200 OK\r\n"),
5825 MockRead("Content-Length: 100\r\n\r\n"),
5826 MockRead(SYNCHRONOUS
, OK
),
5829 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5830 data_writes1
, arraysize(data_writes1
));
5831 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5832 data_writes2
, arraysize(data_writes2
));
5833 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5834 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5836 TestCompletionCallback callback1
;
5838 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5839 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5841 rv
= callback1
.WaitForResult();
5844 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5845 ASSERT_TRUE(response
!= NULL
);
5846 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5848 TestCompletionCallback callback2
;
5850 rv
= trans
->RestartWithAuth(
5851 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5852 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5854 rv
= callback2
.WaitForResult();
5857 response
= trans
->GetResponseInfo();
5858 ASSERT_TRUE(response
!= NULL
);
5859 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5860 EXPECT_EQ(100, response
->headers
->GetContentLength());
5863 // ------------------------------------------------------------------------
5865 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5867 HttpRequestInfo request
;
5868 request
.method
= "GET";
5869 // Note that Transaction 1 was at /x/y/z, so this is in the same
5870 // protection space as MyRealm1.
5871 request
.url
= GURL("http://www.example.org/x/y/a/b");
5872 request
.load_flags
= 0;
5874 scoped_ptr
<HttpTransaction
> trans(
5875 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5877 MockWrite data_writes1
[] = {
5879 "GET /x/y/a/b HTTP/1.1\r\n"
5880 "Host: www.example.org\r\n"
5881 "Connection: keep-alive\r\n"
5882 // Send preemptive authorization for MyRealm1
5883 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5886 // The server didn't like the preemptive authorization, and
5887 // challenges us for a different realm (MyRealm2).
5888 MockRead data_reads1
[] = {
5889 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5890 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5891 MockRead("Content-Length: 10000\r\n\r\n"),
5892 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5895 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5896 MockWrite data_writes2
[] = {
5898 "GET /x/y/a/b HTTP/1.1\r\n"
5899 "Host: www.example.org\r\n"
5900 "Connection: keep-alive\r\n"
5901 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5904 // Sever accepts the authorization.
5905 MockRead data_reads2
[] = {
5906 MockRead("HTTP/1.0 200 OK\r\n"),
5907 MockRead("Content-Length: 100\r\n\r\n"),
5908 MockRead(SYNCHRONOUS
, OK
),
5911 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5912 data_writes1
, arraysize(data_writes1
));
5913 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5914 data_writes2
, arraysize(data_writes2
));
5915 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5916 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5918 TestCompletionCallback callback1
;
5920 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5923 rv
= callback1
.WaitForResult();
5926 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5927 ASSERT_TRUE(response
!= NULL
);
5928 ASSERT_TRUE(response
->auth_challenge
.get());
5929 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5930 EXPECT_EQ("www.example.org:80",
5931 response
->auth_challenge
->challenger
.ToString());
5932 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5933 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5935 TestCompletionCallback callback2
;
5937 rv
= trans
->RestartWithAuth(
5938 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5939 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5941 rv
= callback2
.WaitForResult();
5944 response
= trans
->GetResponseInfo();
5945 ASSERT_TRUE(response
!= NULL
);
5946 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5947 EXPECT_EQ(100, response
->headers
->GetContentLength());
5950 // ------------------------------------------------------------------------
5952 // Transaction 3: Resend a request in MyRealm's protection space --
5953 // succeed with preemptive authorization.
5955 HttpRequestInfo request
;
5956 request
.method
= "GET";
5957 request
.url
= GURL("http://www.example.org/x/y/z2");
5958 request
.load_flags
= 0;
5960 scoped_ptr
<HttpTransaction
> trans(
5961 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5963 MockWrite data_writes1
[] = {
5965 "GET /x/y/z2 HTTP/1.1\r\n"
5966 "Host: www.example.org\r\n"
5967 "Connection: keep-alive\r\n"
5968 // The authorization for MyRealm1 gets sent preemptively
5969 // (since the url is in the same protection space)
5970 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5973 // Sever accepts the preemptive authorization
5974 MockRead data_reads1
[] = {
5975 MockRead("HTTP/1.0 200 OK\r\n"),
5976 MockRead("Content-Length: 100\r\n\r\n"),
5977 MockRead(SYNCHRONOUS
, OK
),
5980 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5981 data_writes1
, arraysize(data_writes1
));
5982 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5984 TestCompletionCallback callback1
;
5986 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5987 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5989 rv
= callback1
.WaitForResult();
5992 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5993 ASSERT_TRUE(response
!= NULL
);
5995 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5996 EXPECT_EQ(100, response
->headers
->GetContentLength());
5999 // ------------------------------------------------------------------------
6001 // Transaction 4: request another URL in MyRealm (however the
6002 // url is not known to belong to the protection space, so no pre-auth).
6004 HttpRequestInfo request
;
6005 request
.method
= "GET";
6006 request
.url
= GURL("http://www.example.org/x/1");
6007 request
.load_flags
= 0;
6009 scoped_ptr
<HttpTransaction
> trans(
6010 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6012 MockWrite data_writes1
[] = {
6014 "GET /x/1 HTTP/1.1\r\n"
6015 "Host: www.example.org\r\n"
6016 "Connection: keep-alive\r\n\r\n"),
6019 MockRead data_reads1
[] = {
6020 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6021 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6022 MockRead("Content-Length: 10000\r\n\r\n"),
6023 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6026 // Resend with authorization from MyRealm's cache.
6027 MockWrite data_writes2
[] = {
6029 "GET /x/1 HTTP/1.1\r\n"
6030 "Host: www.example.org\r\n"
6031 "Connection: keep-alive\r\n"
6032 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6035 // Sever accepts the authorization.
6036 MockRead data_reads2
[] = {
6037 MockRead("HTTP/1.0 200 OK\r\n"),
6038 MockRead("Content-Length: 100\r\n\r\n"),
6039 MockRead(SYNCHRONOUS
, OK
),
6042 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6043 data_writes1
, arraysize(data_writes1
));
6044 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6045 data_writes2
, arraysize(data_writes2
));
6046 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6047 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6049 TestCompletionCallback callback1
;
6051 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6054 rv
= callback1
.WaitForResult();
6057 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6058 TestCompletionCallback callback2
;
6059 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6060 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6061 rv
= callback2
.WaitForResult();
6063 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6065 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6066 ASSERT_TRUE(response
!= NULL
);
6067 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6068 EXPECT_EQ(100, response
->headers
->GetContentLength());
6071 // ------------------------------------------------------------------------
6073 // Transaction 5: request a URL in MyRealm, but the server rejects the
6074 // cached identity. Should invalidate and re-prompt.
6076 HttpRequestInfo request
;
6077 request
.method
= "GET";
6078 request
.url
= GURL("http://www.example.org/p/q/t");
6079 request
.load_flags
= 0;
6081 scoped_ptr
<HttpTransaction
> trans(
6082 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6084 MockWrite data_writes1
[] = {
6086 "GET /p/q/t HTTP/1.1\r\n"
6087 "Host: www.example.org\r\n"
6088 "Connection: keep-alive\r\n\r\n"),
6091 MockRead data_reads1
[] = {
6092 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6093 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6094 MockRead("Content-Length: 10000\r\n\r\n"),
6095 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6098 // Resend with authorization from cache for MyRealm.
6099 MockWrite data_writes2
[] = {
6101 "GET /p/q/t HTTP/1.1\r\n"
6102 "Host: www.example.org\r\n"
6103 "Connection: keep-alive\r\n"
6104 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6107 // Sever rejects the authorization.
6108 MockRead data_reads2
[] = {
6109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6110 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6111 MockRead("Content-Length: 10000\r\n\r\n"),
6112 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6115 // At this point we should prompt for new credentials for MyRealm.
6116 // Restart with username=foo3, password=foo4.
6117 MockWrite data_writes3
[] = {
6119 "GET /p/q/t HTTP/1.1\r\n"
6120 "Host: www.example.org\r\n"
6121 "Connection: keep-alive\r\n"
6122 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6125 // Sever accepts the authorization.
6126 MockRead data_reads3
[] = {
6127 MockRead("HTTP/1.0 200 OK\r\n"),
6128 MockRead("Content-Length: 100\r\n\r\n"),
6129 MockRead(SYNCHRONOUS
, OK
),
6132 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6133 data_writes1
, arraysize(data_writes1
));
6134 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6135 data_writes2
, arraysize(data_writes2
));
6136 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6137 data_writes3
, arraysize(data_writes3
));
6138 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6139 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6140 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6142 TestCompletionCallback callback1
;
6144 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6145 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6147 rv
= callback1
.WaitForResult();
6150 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6151 TestCompletionCallback callback2
;
6152 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6153 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6154 rv
= callback2
.WaitForResult();
6156 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6158 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6159 ASSERT_TRUE(response
!= NULL
);
6160 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6162 TestCompletionCallback callback3
;
6164 rv
= trans
->RestartWithAuth(
6165 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6168 rv
= callback3
.WaitForResult();
6171 response
= trans
->GetResponseInfo();
6172 ASSERT_TRUE(response
!= NULL
);
6173 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6174 EXPECT_EQ(100, response
->headers
->GetContentLength());
6178 // Tests that nonce count increments when multiple auth attempts
6179 // are started with the same nonce.
6180 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6181 HttpAuthHandlerDigest::Factory
* digest_factory
=
6182 new HttpAuthHandlerDigest::Factory();
6183 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6184 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6185 digest_factory
->set_nonce_generator(nonce_generator
);
6186 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6187 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6189 // Transaction 1: authenticate (foo, bar) on MyRealm1
6191 HttpRequestInfo request
;
6192 request
.method
= "GET";
6193 request
.url
= GURL("http://www.example.org/x/y/z");
6194 request
.load_flags
= 0;
6196 scoped_ptr
<HttpTransaction
> trans(
6197 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6199 MockWrite data_writes1
[] = {
6201 "GET /x/y/z HTTP/1.1\r\n"
6202 "Host: www.example.org\r\n"
6203 "Connection: keep-alive\r\n\r\n"),
6206 MockRead data_reads1
[] = {
6207 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6208 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6209 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6210 MockRead(SYNCHRONOUS
, OK
),
6213 // Resend with authorization (username=foo, password=bar)
6214 MockWrite data_writes2
[] = {
6216 "GET /x/y/z HTTP/1.1\r\n"
6217 "Host: www.example.org\r\n"
6218 "Connection: keep-alive\r\n"
6219 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6220 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6221 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6222 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6225 // Sever accepts the authorization.
6226 MockRead data_reads2
[] = {
6227 MockRead("HTTP/1.0 200 OK\r\n"),
6228 MockRead(SYNCHRONOUS
, OK
),
6231 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6232 data_writes1
, arraysize(data_writes1
));
6233 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6234 data_writes2
, arraysize(data_writes2
));
6235 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6236 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6238 TestCompletionCallback callback1
;
6240 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6241 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6243 rv
= callback1
.WaitForResult();
6246 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6247 ASSERT_TRUE(response
!= NULL
);
6248 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6250 TestCompletionCallback callback2
;
6252 rv
= trans
->RestartWithAuth(
6253 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6256 rv
= callback2
.WaitForResult();
6259 response
= trans
->GetResponseInfo();
6260 ASSERT_TRUE(response
!= NULL
);
6261 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6264 // ------------------------------------------------------------------------
6266 // Transaction 2: Request another resource in digestive's protection space.
6267 // This will preemptively add an Authorization header which should have an
6268 // "nc" value of 2 (as compared to 1 in the first use.
6270 HttpRequestInfo request
;
6271 request
.method
= "GET";
6272 // Note that Transaction 1 was at /x/y/z, so this is in the same
6273 // protection space as digest.
6274 request
.url
= GURL("http://www.example.org/x/y/a/b");
6275 request
.load_flags
= 0;
6277 scoped_ptr
<HttpTransaction
> trans(
6278 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6280 MockWrite data_writes1
[] = {
6282 "GET /x/y/a/b HTTP/1.1\r\n"
6283 "Host: www.example.org\r\n"
6284 "Connection: keep-alive\r\n"
6285 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6286 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6287 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6288 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6291 // Sever accepts the authorization.
6292 MockRead data_reads1
[] = {
6293 MockRead("HTTP/1.0 200 OK\r\n"),
6294 MockRead("Content-Length: 100\r\n\r\n"),
6295 MockRead(SYNCHRONOUS
, OK
),
6298 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6299 data_writes1
, arraysize(data_writes1
));
6300 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6302 TestCompletionCallback callback1
;
6304 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6307 rv
= callback1
.WaitForResult();
6310 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6311 ASSERT_TRUE(response
!= NULL
);
6312 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6316 // Test the ResetStateForRestart() private method.
6317 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6318 // Create a transaction (the dependencies aren't important).
6319 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6320 scoped_ptr
<HttpNetworkTransaction
> trans(
6321 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6323 // Setup some state (which we expect ResetStateForRestart() will clear).
6324 trans
->read_buf_
= new IOBuffer(15);
6325 trans
->read_buf_len_
= 15;
6326 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6328 // Setup state in response_
6329 HttpResponseInfo
* response
= &trans
->response_
;
6330 response
->auth_challenge
= new AuthChallengeInfo();
6331 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6332 response
->response_time
= base::Time::Now();
6333 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6335 { // Setup state for response_.vary_data
6336 HttpRequestInfo request
;
6337 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6338 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6339 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6340 request
.extra_headers
.SetHeader("Foo", "1");
6341 request
.extra_headers
.SetHeader("bar", "23");
6342 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6345 // Cause the above state to be reset.
6346 trans
->ResetStateForRestart();
6348 // Verify that the state that needed to be reset, has been reset.
6349 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6350 EXPECT_EQ(0, trans
->read_buf_len_
);
6351 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6352 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6353 EXPECT_TRUE(response
->headers
.get() == NULL
);
6354 EXPECT_FALSE(response
->was_cached
);
6355 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6356 EXPECT_FALSE(response
->vary_data
.is_valid());
6359 // Test HTTPS connections to a site with a bad certificate
6360 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6361 HttpRequestInfo request
;
6362 request
.method
= "GET";
6363 request
.url
= GURL("https://www.example.org/");
6364 request
.load_flags
= 0;
6366 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6367 scoped_ptr
<HttpTransaction
> trans(
6368 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6370 MockWrite data_writes
[] = {
6372 "GET / HTTP/1.1\r\n"
6373 "Host: www.example.org\r\n"
6374 "Connection: keep-alive\r\n\r\n"),
6377 MockRead data_reads
[] = {
6378 MockRead("HTTP/1.0 200 OK\r\n"),
6379 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6380 MockRead("Content-Length: 100\r\n\r\n"),
6381 MockRead(SYNCHRONOUS
, OK
),
6384 StaticSocketDataProvider ssl_bad_certificate
;
6385 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6386 data_writes
, arraysize(data_writes
));
6387 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6388 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6390 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6391 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6392 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6393 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6395 TestCompletionCallback callback
;
6397 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6398 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6400 rv
= callback
.WaitForResult();
6401 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6403 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6404 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6406 rv
= callback
.WaitForResult();
6409 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6411 ASSERT_TRUE(response
!= NULL
);
6412 EXPECT_EQ(100, response
->headers
->GetContentLength());
6415 // Test HTTPS connections to a site with a bad certificate, going through a
6417 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6418 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6420 HttpRequestInfo request
;
6421 request
.method
= "GET";
6422 request
.url
= GURL("https://www.example.org/");
6423 request
.load_flags
= 0;
6425 MockWrite proxy_writes
[] = {
6427 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6428 "Host: www.example.org\r\n"
6429 "Proxy-Connection: keep-alive\r\n\r\n"),
6432 MockRead proxy_reads
[] = {
6433 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6434 MockRead(SYNCHRONOUS
, OK
)
6437 MockWrite data_writes
[] = {
6439 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6440 "Host: www.example.org\r\n"
6441 "Proxy-Connection: keep-alive\r\n\r\n"),
6443 "GET / HTTP/1.1\r\n"
6444 "Host: www.example.org\r\n"
6445 "Connection: keep-alive\r\n\r\n"),
6448 MockRead data_reads
[] = {
6449 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6450 MockRead("HTTP/1.0 200 OK\r\n"),
6451 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6452 MockRead("Content-Length: 100\r\n\r\n"),
6453 MockRead(SYNCHRONOUS
, OK
),
6456 StaticSocketDataProvider
ssl_bad_certificate(
6457 proxy_reads
, arraysize(proxy_reads
),
6458 proxy_writes
, arraysize(proxy_writes
));
6459 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6460 data_writes
, arraysize(data_writes
));
6461 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6462 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6464 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6465 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6466 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6467 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6469 TestCompletionCallback callback
;
6471 for (int i
= 0; i
< 2; i
++) {
6472 session_deps_
.socket_factory
->ResetNextMockIndexes();
6474 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6475 scoped_ptr
<HttpTransaction
> trans(
6476 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6478 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6479 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6481 rv
= callback
.WaitForResult();
6482 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6484 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6485 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6487 rv
= callback
.WaitForResult();
6490 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6492 ASSERT_TRUE(response
!= NULL
);
6493 EXPECT_EQ(100, response
->headers
->GetContentLength());
6498 // Test HTTPS connections to a site, going through an HTTPS proxy
6499 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6500 session_deps_
.proxy_service
.reset(
6501 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6503 session_deps_
.net_log
= &net_log
;
6505 HttpRequestInfo request
;
6506 request
.method
= "GET";
6507 request
.url
= GURL("https://www.example.org/");
6508 request
.load_flags
= 0;
6510 MockWrite data_writes
[] = {
6512 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6513 "Host: www.example.org\r\n"
6514 "Proxy-Connection: keep-alive\r\n\r\n"),
6516 "GET / HTTP/1.1\r\n"
6517 "Host: www.example.org\r\n"
6518 "Connection: keep-alive\r\n\r\n"),
6521 MockRead data_reads
[] = {
6522 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6523 MockRead("HTTP/1.1 200 OK\r\n"),
6524 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6525 MockRead("Content-Length: 100\r\n\r\n"),
6526 MockRead(SYNCHRONOUS
, OK
),
6529 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6530 data_writes
, arraysize(data_writes
));
6531 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6532 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6534 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6535 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6536 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6538 TestCompletionCallback callback
;
6540 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6541 scoped_ptr
<HttpTransaction
> trans(
6542 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6544 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6545 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6547 rv
= callback
.WaitForResult();
6549 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6551 ASSERT_TRUE(response
!= NULL
);
6553 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6554 EXPECT_EQ(200, response
->headers
->response_code());
6555 EXPECT_EQ(100, response
->headers
->GetContentLength());
6556 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6558 LoadTimingInfo load_timing_info
;
6559 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6560 TestLoadTimingNotReusedWithPac(load_timing_info
,
6561 CONNECT_TIMING_HAS_SSL_TIMES
);
6564 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6565 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6566 session_deps_
.proxy_service
.reset(
6567 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6569 session_deps_
.net_log
= &net_log
;
6571 HttpRequestInfo request
;
6572 request
.method
= "GET";
6573 request
.url
= GURL("https://www.example.org/");
6574 request
.load_flags
= 0;
6576 MockWrite data_writes
[] = {
6578 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6579 "Host: www.example.org\r\n"
6580 "Proxy-Connection: keep-alive\r\n\r\n"),
6583 MockRead data_reads
[] = {
6584 MockRead("HTTP/1.1 302 Redirect\r\n"),
6585 MockRead("Location: http://login.example.com/\r\n"),
6586 MockRead("Content-Length: 0\r\n\r\n"),
6587 MockRead(SYNCHRONOUS
, OK
),
6590 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6591 data_writes
, arraysize(data_writes
));
6592 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6594 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6595 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6597 TestCompletionCallback callback
;
6599 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6600 scoped_ptr
<HttpTransaction
> trans(
6601 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6603 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6604 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6606 rv
= callback
.WaitForResult();
6608 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6610 ASSERT_TRUE(response
!= NULL
);
6612 EXPECT_EQ(302, response
->headers
->response_code());
6614 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6615 EXPECT_EQ("http://login.example.com/", url
);
6617 // In the case of redirects from proxies, HttpNetworkTransaction returns
6618 // timing for the proxy connection instead of the connection to the host,
6619 // and no send / receive times.
6620 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6621 LoadTimingInfo load_timing_info
;
6622 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6624 EXPECT_FALSE(load_timing_info
.socket_reused
);
6625 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6627 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6628 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6629 load_timing_info
.proxy_resolve_end
);
6630 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6631 load_timing_info
.connect_timing
.connect_start
);
6632 ExpectConnectTimingHasTimes(
6633 load_timing_info
.connect_timing
,
6634 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6636 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6637 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6638 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6641 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6642 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6643 session_deps_
.proxy_service
.reset(
6644 ProxyService::CreateFixed("https://proxy:70"));
6646 HttpRequestInfo request
;
6647 request
.method
= "GET";
6648 request
.url
= GURL("https://www.example.org/");
6649 request
.load_flags
= 0;
6651 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6652 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6653 scoped_ptr
<SpdyFrame
> goaway(
6654 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6655 MockWrite data_writes
[] = {
6656 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6657 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6660 static const char* const kExtraHeaders
[] = {
6662 "http://login.example.com/",
6664 scoped_ptr
<SpdyFrame
> resp(
6665 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6666 arraysize(kExtraHeaders
)/2, 1));
6667 MockRead data_reads
[] = {
6668 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6671 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6672 arraysize(data_writes
));
6673 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6674 proxy_ssl
.SetNextProto(GetParam());
6676 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6677 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6679 TestCompletionCallback callback
;
6681 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6682 scoped_ptr
<HttpTransaction
> trans(
6683 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6685 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6688 rv
= callback
.WaitForResult();
6690 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6692 ASSERT_TRUE(response
!= NULL
);
6694 EXPECT_EQ(302, response
->headers
->response_code());
6696 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6697 EXPECT_EQ("http://login.example.com/", url
);
6700 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6701 TEST_P(HttpNetworkTransactionTest
,
6702 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6703 session_deps_
.proxy_service
.reset(
6704 ProxyService::CreateFixed("https://proxy:70"));
6706 HttpRequestInfo request
;
6707 request
.method
= "GET";
6708 request
.url
= GURL("https://www.example.org/");
6709 request
.load_flags
= 0;
6711 MockWrite data_writes
[] = {
6713 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6714 "Host: www.example.org\r\n"
6715 "Proxy-Connection: keep-alive\r\n\r\n"),
6718 MockRead data_reads
[] = {
6719 MockRead("HTTP/1.1 404 Not Found\r\n"),
6720 MockRead("Content-Length: 23\r\n\r\n"),
6721 MockRead("The host does not exist"),
6722 MockRead(SYNCHRONOUS
, OK
),
6725 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6726 data_writes
, arraysize(data_writes
));
6727 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6729 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6730 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6732 TestCompletionCallback callback
;
6734 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6735 scoped_ptr
<HttpTransaction
> trans(
6736 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6738 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6741 rv
= callback
.WaitForResult();
6742 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6744 // TODO(ttuttle): Anything else to check here?
6747 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6748 TEST_P(HttpNetworkTransactionTest
,
6749 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6750 session_deps_
.proxy_service
.reset(
6751 ProxyService::CreateFixed("https://proxy:70"));
6753 HttpRequestInfo request
;
6754 request
.method
= "GET";
6755 request
.url
= GURL("https://www.example.org/");
6756 request
.load_flags
= 0;
6758 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6759 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6760 scoped_ptr
<SpdyFrame
> rst(
6761 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6762 MockWrite data_writes
[] = {
6763 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6766 static const char* const kExtraHeaders
[] = {
6768 "http://login.example.com/",
6770 scoped_ptr
<SpdyFrame
> resp(
6771 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6772 arraysize(kExtraHeaders
)/2, 1));
6773 scoped_ptr
<SpdyFrame
> body(
6774 spdy_util_
.ConstructSpdyBodyFrame(
6775 1, "The host does not exist", 23, true));
6776 MockRead data_reads
[] = {
6777 CreateMockRead(*resp
.get(), 1),
6778 CreateMockRead(*body
.get(), 2),
6779 MockRead(ASYNC
, 0, 4), // EOF
6782 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6783 arraysize(data_writes
));
6784 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6785 proxy_ssl
.SetNextProto(GetParam());
6787 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6788 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6790 TestCompletionCallback callback
;
6792 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6793 scoped_ptr
<HttpTransaction
> trans(
6794 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6796 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6797 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6799 rv
= callback
.WaitForResult();
6800 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6802 // TODO(ttuttle): Anything else to check here?
6805 // Test the request-challenge-retry sequence for basic auth, through
6806 // a SPDY proxy over a single SPDY session.
6807 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6808 HttpRequestInfo request
;
6809 request
.method
= "GET";
6810 request
.url
= GURL("https://www.example.org/");
6811 // when the no authentication data flag is set.
6812 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6814 // Configure against https proxy server "myproxy:70".
6815 session_deps_
.proxy_service
.reset(
6816 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6817 BoundTestNetLog log
;
6818 session_deps_
.net_log
= log
.bound().net_log();
6819 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6821 // Since we have proxy, should try to establish tunnel.
6822 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6823 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6824 scoped_ptr
<SpdyFrame
> rst(
6825 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6827 // After calling trans->RestartWithAuth(), this is the request we should
6828 // be issuing -- the final header line contains the credentials.
6829 const char* const kAuthCredentials
[] = {
6830 "proxy-authorization", "Basic Zm9vOmJhcg==",
6832 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6833 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6834 HostPortPair("www.example.org", 443)));
6835 // fetch https://www.example.org/ via HTTP
6837 "GET / HTTP/1.1\r\n"
6838 "Host: www.example.org\r\n"
6839 "Connection: keep-alive\r\n\r\n";
6840 scoped_ptr
<SpdyFrame
> wrapped_get(
6841 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6843 MockWrite spdy_writes
[] = {
6844 CreateMockWrite(*req
, 0, ASYNC
),
6845 CreateMockWrite(*rst
, 2, ASYNC
),
6846 CreateMockWrite(*connect2
, 3),
6847 CreateMockWrite(*wrapped_get
, 5),
6850 // The proxy responds to the connect with a 407, using a persistent
6852 const char kAuthStatus
[] = "407";
6853 const char* const kAuthChallenge
[] = {
6854 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6856 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6857 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6859 scoped_ptr
<SpdyFrame
> conn_resp(
6860 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6861 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6862 "Content-Length: 5\r\n\r\n";
6864 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6865 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6866 scoped_ptr
<SpdyFrame
> wrapped_body(
6867 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6868 MockRead spdy_reads
[] = {
6869 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6870 CreateMockRead(*conn_resp
, 4, ASYNC
),
6871 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6872 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6873 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6876 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6877 arraysize(spdy_writes
));
6878 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6879 // Negotiate SPDY to the proxy
6880 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6881 proxy
.SetNextProto(GetParam());
6882 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6883 // Vanilla SSL to the server
6884 SSLSocketDataProvider
server(ASYNC
, OK
);
6885 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6887 TestCompletionCallback callback1
;
6889 scoped_ptr
<HttpTransaction
> trans(
6890 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6892 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6893 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6895 rv
= callback1
.WaitForResult();
6897 TestNetLogEntry::List entries
;
6898 log
.GetEntries(&entries
);
6899 size_t pos
= ExpectLogContainsSomewhere(
6900 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6901 NetLog::PHASE_NONE
);
6902 ExpectLogContainsSomewhere(
6904 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6905 NetLog::PHASE_NONE
);
6907 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6908 ASSERT_TRUE(response
!= NULL
);
6909 ASSERT_FALSE(response
->headers
.get() == NULL
);
6910 EXPECT_EQ(407, response
->headers
->response_code());
6911 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6912 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6913 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6915 TestCompletionCallback callback2
;
6917 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6918 callback2
.callback());
6919 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6921 rv
= callback2
.WaitForResult();
6924 response
= trans
->GetResponseInfo();
6925 ASSERT_TRUE(response
!= NULL
);
6927 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6928 EXPECT_EQ(200, response
->headers
->response_code());
6929 EXPECT_EQ(5, response
->headers
->GetContentLength());
6930 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6932 // The password prompt info should not be set.
6933 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6935 LoadTimingInfo load_timing_info
;
6936 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6937 TestLoadTimingNotReusedWithPac(load_timing_info
,
6938 CONNECT_TIMING_HAS_SSL_TIMES
);
6941 session
->CloseAllConnections();
6944 // Test that an explicitly trusted SPDY proxy can push a resource from an
6945 // origin that is different from that of its associated resource.
6946 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6947 HttpRequestInfo request
;
6948 HttpRequestInfo push_request
;
6950 request
.method
= "GET";
6951 request
.url
= GURL("http://www.example.org/");
6952 push_request
.method
= "GET";
6953 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6955 // Configure against https proxy server "myproxy:70".
6956 session_deps_
.proxy_service
.reset(
6957 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6958 BoundTestNetLog log
;
6959 session_deps_
.net_log
= log
.bound().net_log();
6961 // Enable cross-origin push.
6962 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6964 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6966 scoped_ptr
<SpdyFrame
> stream1_syn(
6967 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6969 MockWrite spdy_writes
[] = {
6970 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6973 scoped_ptr
<SpdyFrame
>
6974 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6976 scoped_ptr
<SpdyFrame
>
6977 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6979 scoped_ptr
<SpdyFrame
>
6980 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6984 "http://www.another-origin.com/foo.dat"));
6985 const char kPushedData
[] = "pushed";
6986 scoped_ptr
<SpdyFrame
> stream2_body(
6987 spdy_util_
.ConstructSpdyBodyFrame(
6988 2, kPushedData
, strlen(kPushedData
), true));
6990 MockRead spdy_reads
[] = {
6991 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6992 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6993 CreateMockRead(*stream1_body
, 3, ASYNC
),
6994 CreateMockRead(*stream2_body
, 4, ASYNC
),
6995 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
6998 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6999 arraysize(spdy_writes
));
7000 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7001 // Negotiate SPDY to the proxy
7002 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7003 proxy
.SetNextProto(GetParam());
7004 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7006 scoped_ptr
<HttpTransaction
> trans(
7007 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7008 TestCompletionCallback callback
;
7009 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7010 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7012 rv
= callback
.WaitForResult();
7014 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7016 scoped_ptr
<HttpTransaction
> push_trans(
7017 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7018 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
7019 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7021 rv
= callback
.WaitForResult();
7023 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
7025 ASSERT_TRUE(response
!= NULL
);
7026 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7028 EXPECT_EQ(200, response
->headers
->response_code());
7029 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7031 std::string response_data
;
7032 rv
= ReadTransaction(trans
.get(), &response_data
);
7034 EXPECT_EQ("hello!", response_data
);
7036 LoadTimingInfo load_timing_info
;
7037 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7038 TestLoadTimingNotReusedWithPac(load_timing_info
,
7039 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7041 // Verify the pushed stream.
7042 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
7043 EXPECT_EQ(200, push_response
->headers
->response_code());
7045 rv
= ReadTransaction(push_trans
.get(), &response_data
);
7047 EXPECT_EQ("pushed", response_data
);
7049 LoadTimingInfo push_load_timing_info
;
7050 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
7051 TestLoadTimingReusedWithPac(push_load_timing_info
);
7052 // The transactions should share a socket ID, despite being for different
7054 EXPECT_EQ(load_timing_info
.socket_log_id
,
7055 push_load_timing_info
.socket_log_id
);
7059 session
->CloseAllConnections();
7062 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7063 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
7064 HttpRequestInfo request
;
7066 request
.method
= "GET";
7067 request
.url
= GURL("http://www.example.org/");
7069 // Configure against https proxy server "myproxy:70".
7070 session_deps_
.proxy_service
.reset(
7071 ProxyService::CreateFixed("https://myproxy:70"));
7072 BoundTestNetLog log
;
7073 session_deps_
.net_log
= log
.bound().net_log();
7075 // Enable cross-origin push.
7076 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
7078 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7080 scoped_ptr
<SpdyFrame
> stream1_syn(
7081 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
7083 scoped_ptr
<SpdyFrame
> push_rst(
7084 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7086 MockWrite spdy_writes
[] = {
7087 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
7090 scoped_ptr
<SpdyFrame
>
7091 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7093 scoped_ptr
<SpdyFrame
>
7094 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7096 scoped_ptr
<SpdyFrame
>
7097 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7101 "https://www.another-origin.com/foo.dat"));
7103 MockRead spdy_reads
[] = {
7104 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7105 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7106 CreateMockRead(*stream1_body
, 4, ASYNC
),
7107 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7110 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7111 arraysize(spdy_writes
));
7112 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7113 // Negotiate SPDY to the proxy
7114 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7115 proxy
.SetNextProto(GetParam());
7116 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7118 scoped_ptr
<HttpTransaction
> trans(
7119 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7120 TestCompletionCallback callback
;
7121 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7122 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7124 rv
= callback
.WaitForResult();
7126 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7128 ASSERT_TRUE(response
!= NULL
);
7129 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7131 EXPECT_EQ(200, response
->headers
->response_code());
7132 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7134 std::string response_data
;
7135 rv
= ReadTransaction(trans
.get(), &response_data
);
7137 EXPECT_EQ("hello!", response_data
);
7140 session
->CloseAllConnections();
7143 // Test HTTPS connections to a site with a bad certificate, going through an
7145 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7146 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7147 "https://proxy:70"));
7149 HttpRequestInfo request
;
7150 request
.method
= "GET";
7151 request
.url
= GURL("https://www.example.org/");
7152 request
.load_flags
= 0;
7154 // Attempt to fetch the URL from a server with a bad cert
7155 MockWrite bad_cert_writes
[] = {
7157 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7158 "Host: www.example.org\r\n"
7159 "Proxy-Connection: keep-alive\r\n\r\n"),
7162 MockRead bad_cert_reads
[] = {
7163 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7164 MockRead(SYNCHRONOUS
, OK
)
7167 // Attempt to fetch the URL with a good cert
7168 MockWrite good_data_writes
[] = {
7170 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7171 "Host: www.example.org\r\n"
7172 "Proxy-Connection: keep-alive\r\n\r\n"),
7174 "GET / HTTP/1.1\r\n"
7175 "Host: www.example.org\r\n"
7176 "Connection: keep-alive\r\n\r\n"),
7179 MockRead good_cert_reads
[] = {
7180 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7181 MockRead("HTTP/1.0 200 OK\r\n"),
7182 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7183 MockRead("Content-Length: 100\r\n\r\n"),
7184 MockRead(SYNCHRONOUS
, OK
),
7187 StaticSocketDataProvider
ssl_bad_certificate(
7188 bad_cert_reads
, arraysize(bad_cert_reads
),
7189 bad_cert_writes
, arraysize(bad_cert_writes
));
7190 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7191 good_data_writes
, arraysize(good_data_writes
));
7192 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7193 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7195 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7196 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7197 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7198 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7200 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7201 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7202 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7203 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7205 TestCompletionCallback callback
;
7207 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7208 scoped_ptr
<HttpTransaction
> trans(
7209 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7211 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7212 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7214 rv
= callback
.WaitForResult();
7215 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7217 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7218 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7220 rv
= callback
.WaitForResult();
7223 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7225 ASSERT_TRUE(response
!= NULL
);
7226 EXPECT_EQ(100, response
->headers
->GetContentLength());
7229 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7230 HttpRequestInfo request
;
7231 request
.method
= "GET";
7232 request
.url
= GURL("http://www.example.org/");
7233 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7234 "Chromium Ultra Awesome X Edition");
7236 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7237 scoped_ptr
<HttpTransaction
> trans(
7238 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7240 MockWrite data_writes
[] = {
7242 "GET / HTTP/1.1\r\n"
7243 "Host: www.example.org\r\n"
7244 "Connection: keep-alive\r\n"
7245 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7248 // Lastly, the server responds with the actual content.
7249 MockRead data_reads
[] = {
7250 MockRead("HTTP/1.0 200 OK\r\n"),
7251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7252 MockRead("Content-Length: 100\r\n\r\n"),
7253 MockRead(SYNCHRONOUS
, OK
),
7256 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7257 data_writes
, arraysize(data_writes
));
7258 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7260 TestCompletionCallback callback
;
7262 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7263 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7265 rv
= callback
.WaitForResult();
7269 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7270 HttpRequestInfo request
;
7271 request
.method
= "GET";
7272 request
.url
= GURL("https://www.example.org/");
7273 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7274 "Chromium Ultra Awesome X Edition");
7276 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7277 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7278 scoped_ptr
<HttpTransaction
> trans(
7279 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7281 MockWrite data_writes
[] = {
7283 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7284 "Host: www.example.org\r\n"
7285 "Proxy-Connection: keep-alive\r\n"
7286 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7288 MockRead data_reads
[] = {
7289 // Return an error, so the transaction stops here (this test isn't
7290 // interested in the rest).
7291 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7292 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7293 MockRead("Proxy-Connection: close\r\n\r\n"),
7296 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7297 data_writes
, arraysize(data_writes
));
7298 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7300 TestCompletionCallback callback
;
7302 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7303 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7305 rv
= callback
.WaitForResult();
7309 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7310 HttpRequestInfo request
;
7311 request
.method
= "GET";
7312 request
.url
= GURL("http://www.example.org/");
7313 request
.load_flags
= 0;
7314 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7315 "http://the.previous.site.com/");
7317 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7318 scoped_ptr
<HttpTransaction
> trans(
7319 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7321 MockWrite data_writes
[] = {
7323 "GET / HTTP/1.1\r\n"
7324 "Host: www.example.org\r\n"
7325 "Connection: keep-alive\r\n"
7326 "Referer: http://the.previous.site.com/\r\n\r\n"),
7329 // Lastly, the server responds with the actual content.
7330 MockRead data_reads
[] = {
7331 MockRead("HTTP/1.0 200 OK\r\n"),
7332 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7333 MockRead("Content-Length: 100\r\n\r\n"),
7334 MockRead(SYNCHRONOUS
, OK
),
7337 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7338 data_writes
, arraysize(data_writes
));
7339 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7341 TestCompletionCallback callback
;
7343 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7344 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7346 rv
= callback
.WaitForResult();
7350 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7351 HttpRequestInfo request
;
7352 request
.method
= "POST";
7353 request
.url
= GURL("http://www.example.org/");
7355 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7356 scoped_ptr
<HttpTransaction
> trans(
7357 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7359 MockWrite data_writes
[] = {
7361 "POST / HTTP/1.1\r\n"
7362 "Host: www.example.org\r\n"
7363 "Connection: keep-alive\r\n"
7364 "Content-Length: 0\r\n\r\n"),
7367 // Lastly, the server responds with the actual content.
7368 MockRead data_reads
[] = {
7369 MockRead("HTTP/1.0 200 OK\r\n"),
7370 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7371 MockRead("Content-Length: 100\r\n\r\n"),
7372 MockRead(SYNCHRONOUS
, OK
),
7375 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7376 data_writes
, arraysize(data_writes
));
7377 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7379 TestCompletionCallback callback
;
7381 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7382 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7384 rv
= callback
.WaitForResult();
7388 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7389 HttpRequestInfo request
;
7390 request
.method
= "PUT";
7391 request
.url
= GURL("http://www.example.org/");
7393 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7394 scoped_ptr
<HttpTransaction
> trans(
7395 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7397 MockWrite data_writes
[] = {
7399 "PUT / HTTP/1.1\r\n"
7400 "Host: www.example.org\r\n"
7401 "Connection: keep-alive\r\n"
7402 "Content-Length: 0\r\n\r\n"),
7405 // Lastly, the server responds with the actual content.
7406 MockRead data_reads
[] = {
7407 MockRead("HTTP/1.0 200 OK\r\n"),
7408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7409 MockRead("Content-Length: 100\r\n\r\n"),
7410 MockRead(SYNCHRONOUS
, OK
),
7413 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7414 data_writes
, arraysize(data_writes
));
7415 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7417 TestCompletionCallback callback
;
7419 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7420 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7422 rv
= callback
.WaitForResult();
7426 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7427 HttpRequestInfo request
;
7428 request
.method
= "HEAD";
7429 request
.url
= GURL("http://www.example.org/");
7431 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7432 scoped_ptr
<HttpTransaction
> trans(
7433 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7435 MockWrite data_writes
[] = {
7436 MockWrite("HEAD / HTTP/1.1\r\n"
7437 "Host: www.example.org\r\n"
7438 "Connection: keep-alive\r\n\r\n"),
7441 // Lastly, the server responds with the actual content.
7442 MockRead data_reads
[] = {
7443 MockRead("HTTP/1.0 200 OK\r\n"),
7444 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7445 MockRead("Content-Length: 100\r\n\r\n"),
7446 MockRead(SYNCHRONOUS
, OK
),
7449 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7450 data_writes
, arraysize(data_writes
));
7451 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7453 TestCompletionCallback callback
;
7455 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7456 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7458 rv
= callback
.WaitForResult();
7462 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7463 HttpRequestInfo request
;
7464 request
.method
= "GET";
7465 request
.url
= GURL("http://www.example.org/");
7466 request
.load_flags
= LOAD_BYPASS_CACHE
;
7468 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7469 scoped_ptr
<HttpTransaction
> trans(
7470 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7472 MockWrite data_writes
[] = {
7474 "GET / HTTP/1.1\r\n"
7475 "Host: www.example.org\r\n"
7476 "Connection: keep-alive\r\n"
7477 "Pragma: no-cache\r\n"
7478 "Cache-Control: no-cache\r\n\r\n"),
7481 // Lastly, the server responds with the actual content.
7482 MockRead data_reads
[] = {
7483 MockRead("HTTP/1.0 200 OK\r\n"),
7484 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7485 MockRead("Content-Length: 100\r\n\r\n"),
7486 MockRead(SYNCHRONOUS
, OK
),
7489 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7490 data_writes
, arraysize(data_writes
));
7491 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7493 TestCompletionCallback callback
;
7495 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7496 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7498 rv
= callback
.WaitForResult();
7502 TEST_P(HttpNetworkTransactionTest
,
7503 BuildRequest_CacheControlValidateCache
) {
7504 HttpRequestInfo request
;
7505 request
.method
= "GET";
7506 request
.url
= GURL("http://www.example.org/");
7507 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7509 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7510 scoped_ptr
<HttpTransaction
> trans(
7511 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7513 MockWrite data_writes
[] = {
7515 "GET / HTTP/1.1\r\n"
7516 "Host: www.example.org\r\n"
7517 "Connection: keep-alive\r\n"
7518 "Cache-Control: max-age=0\r\n\r\n"),
7521 // Lastly, the server responds with the actual content.
7522 MockRead data_reads
[] = {
7523 MockRead("HTTP/1.0 200 OK\r\n"),
7524 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7525 MockRead("Content-Length: 100\r\n\r\n"),
7526 MockRead(SYNCHRONOUS
, OK
),
7529 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7530 data_writes
, arraysize(data_writes
));
7531 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7533 TestCompletionCallback callback
;
7535 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7536 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7538 rv
= callback
.WaitForResult();
7542 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7543 HttpRequestInfo request
;
7544 request
.method
= "GET";
7545 request
.url
= GURL("http://www.example.org/");
7546 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7548 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7549 scoped_ptr
<HttpTransaction
> trans(
7550 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7552 MockWrite data_writes
[] = {
7554 "GET / HTTP/1.1\r\n"
7555 "Host: www.example.org\r\n"
7556 "Connection: keep-alive\r\n"
7557 "FooHeader: Bar\r\n\r\n"),
7560 // Lastly, the server responds with the actual content.
7561 MockRead data_reads
[] = {
7562 MockRead("HTTP/1.0 200 OK\r\n"),
7563 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7564 MockRead("Content-Length: 100\r\n\r\n"),
7565 MockRead(SYNCHRONOUS
, OK
),
7568 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7569 data_writes
, arraysize(data_writes
));
7570 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7572 TestCompletionCallback callback
;
7574 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7575 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7577 rv
= callback
.WaitForResult();
7581 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7582 HttpRequestInfo request
;
7583 request
.method
= "GET";
7584 request
.url
= GURL("http://www.example.org/");
7585 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7586 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7587 request
.extra_headers
.SetHeader("FoO", "bar");
7589 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7590 scoped_ptr
<HttpTransaction
> trans(
7591 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7593 MockWrite data_writes
[] = {
7595 "GET / HTTP/1.1\r\n"
7596 "Host: www.example.org\r\n"
7597 "Connection: keep-alive\r\n"
7598 "referer: www.foo.com\r\n"
7600 "FoO: bar\r\n\r\n"),
7603 // Lastly, the server responds with the actual content.
7604 MockRead data_reads
[] = {
7605 MockRead("HTTP/1.0 200 OK\r\n"),
7606 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7607 MockRead("Content-Length: 100\r\n\r\n"),
7608 MockRead(SYNCHRONOUS
, OK
),
7611 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7612 data_writes
, arraysize(data_writes
));
7613 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7615 TestCompletionCallback callback
;
7617 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7618 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7620 rv
= callback
.WaitForResult();
7624 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7625 HttpRequestInfo request
;
7626 request
.method
= "GET";
7627 request
.url
= GURL("http://www.example.org/");
7628 request
.load_flags
= 0;
7630 session_deps_
.proxy_service
.reset(
7631 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7633 session_deps_
.net_log
= &net_log
;
7635 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7636 scoped_ptr
<HttpTransaction
> trans(
7637 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7639 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7640 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7642 MockWrite data_writes
[] = {
7643 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7645 "GET / HTTP/1.1\r\n"
7646 "Host: www.example.org\r\n"
7647 "Connection: keep-alive\r\n\r\n")};
7649 MockRead data_reads
[] = {
7650 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7651 MockRead("HTTP/1.0 200 OK\r\n"),
7652 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7653 MockRead("Payload"),
7654 MockRead(SYNCHRONOUS
, OK
)
7657 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7658 data_writes
, arraysize(data_writes
));
7659 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7661 TestCompletionCallback callback
;
7663 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7664 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7666 rv
= callback
.WaitForResult();
7669 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7670 ASSERT_TRUE(response
!= NULL
);
7672 LoadTimingInfo load_timing_info
;
7673 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7674 TestLoadTimingNotReusedWithPac(load_timing_info
,
7675 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7677 std::string response_text
;
7678 rv
= ReadTransaction(trans
.get(), &response_text
);
7680 EXPECT_EQ("Payload", response_text
);
7683 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7684 HttpRequestInfo request
;
7685 request
.method
= "GET";
7686 request
.url
= GURL("https://www.example.org/");
7687 request
.load_flags
= 0;
7689 session_deps_
.proxy_service
.reset(
7690 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7692 session_deps_
.net_log
= &net_log
;
7694 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7695 scoped_ptr
<HttpTransaction
> trans(
7696 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7698 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7699 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7701 MockWrite data_writes
[] = {
7702 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7703 arraysize(write_buffer
)),
7705 "GET / HTTP/1.1\r\n"
7706 "Host: www.example.org\r\n"
7707 "Connection: keep-alive\r\n\r\n")};
7709 MockRead data_reads
[] = {
7710 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7711 arraysize(read_buffer
)),
7712 MockRead("HTTP/1.0 200 OK\r\n"),
7713 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7714 MockRead("Payload"),
7715 MockRead(SYNCHRONOUS
, OK
)
7718 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7719 data_writes
, arraysize(data_writes
));
7720 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7722 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7723 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7725 TestCompletionCallback callback
;
7727 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7728 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7730 rv
= callback
.WaitForResult();
7733 LoadTimingInfo load_timing_info
;
7734 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7735 TestLoadTimingNotReusedWithPac(load_timing_info
,
7736 CONNECT_TIMING_HAS_SSL_TIMES
);
7738 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7739 ASSERT_TRUE(response
!= NULL
);
7741 std::string response_text
;
7742 rv
= ReadTransaction(trans
.get(), &response_text
);
7744 EXPECT_EQ("Payload", response_text
);
7747 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7748 HttpRequestInfo request
;
7749 request
.method
= "GET";
7750 request
.url
= GURL("http://www.example.org/");
7751 request
.load_flags
= 0;
7753 session_deps_
.proxy_service
.reset(
7754 ProxyService::CreateFixed("socks4://myproxy:1080"));
7756 session_deps_
.net_log
= &net_log
;
7758 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7759 scoped_ptr
<HttpTransaction
> trans(
7760 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7762 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7763 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7765 MockWrite data_writes
[] = {
7766 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7768 "GET / HTTP/1.1\r\n"
7769 "Host: www.example.org\r\n"
7770 "Connection: keep-alive\r\n\r\n")};
7772 MockRead data_reads
[] = {
7773 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7774 MockRead("HTTP/1.0 200 OK\r\n"),
7775 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7776 MockRead("Payload"),
7777 MockRead(SYNCHRONOUS
, OK
)
7780 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7781 data_writes
, arraysize(data_writes
));
7782 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7784 TestCompletionCallback callback
;
7786 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7789 rv
= callback
.WaitForResult();
7792 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7793 ASSERT_TRUE(response
!= NULL
);
7795 LoadTimingInfo load_timing_info
;
7796 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7797 TestLoadTimingNotReused(load_timing_info
,
7798 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7800 std::string response_text
;
7801 rv
= ReadTransaction(trans
.get(), &response_text
);
7803 EXPECT_EQ("Payload", response_text
);
7806 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7807 HttpRequestInfo request
;
7808 request
.method
= "GET";
7809 request
.url
= GURL("http://www.example.org/");
7810 request
.load_flags
= 0;
7812 session_deps_
.proxy_service
.reset(
7813 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7815 session_deps_
.net_log
= &net_log
;
7817 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7818 scoped_ptr
<HttpTransaction
> trans(
7819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7821 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7822 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7823 const char kSOCKS5OkRequest
[] = {
7825 0x01, // Command (CONNECT)
7827 0x03, // Address type (DOMAINNAME).
7828 0x0F, // Length of domain (15)
7829 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7830 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7832 const char kSOCKS5OkResponse
[] =
7833 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7835 MockWrite data_writes
[] = {
7836 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7837 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7839 "GET / HTTP/1.1\r\n"
7840 "Host: www.example.org\r\n"
7841 "Connection: keep-alive\r\n\r\n")};
7843 MockRead data_reads
[] = {
7844 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7845 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7846 MockRead("HTTP/1.0 200 OK\r\n"),
7847 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7848 MockRead("Payload"),
7849 MockRead(SYNCHRONOUS
, OK
)
7852 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7853 data_writes
, arraysize(data_writes
));
7854 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7856 TestCompletionCallback callback
;
7858 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7861 rv
= callback
.WaitForResult();
7864 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7865 ASSERT_TRUE(response
!= NULL
);
7867 LoadTimingInfo load_timing_info
;
7868 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7869 TestLoadTimingNotReusedWithPac(load_timing_info
,
7870 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7872 std::string response_text
;
7873 rv
= ReadTransaction(trans
.get(), &response_text
);
7875 EXPECT_EQ("Payload", response_text
);
7878 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7879 HttpRequestInfo request
;
7880 request
.method
= "GET";
7881 request
.url
= GURL("https://www.example.org/");
7882 request
.load_flags
= 0;
7884 session_deps_
.proxy_service
.reset(
7885 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7887 session_deps_
.net_log
= &net_log
;
7889 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7890 scoped_ptr
<HttpTransaction
> trans(
7891 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7893 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7894 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7895 const unsigned char kSOCKS5OkRequest
[] = {
7897 0x01, // Command (CONNECT)
7899 0x03, // Address type (DOMAINNAME).
7900 0x0F, // Length of domain (15)
7901 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7902 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7905 const char kSOCKS5OkResponse
[] =
7906 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7908 MockWrite data_writes
[] = {
7909 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7910 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7911 arraysize(kSOCKS5OkRequest
)),
7913 "GET / HTTP/1.1\r\n"
7914 "Host: www.example.org\r\n"
7915 "Connection: keep-alive\r\n\r\n")};
7917 MockRead data_reads
[] = {
7918 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7919 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7920 MockRead("HTTP/1.0 200 OK\r\n"),
7921 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7922 MockRead("Payload"),
7923 MockRead(SYNCHRONOUS
, OK
)
7926 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7927 data_writes
, arraysize(data_writes
));
7928 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7930 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7931 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7933 TestCompletionCallback callback
;
7935 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7938 rv
= callback
.WaitForResult();
7941 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7942 ASSERT_TRUE(response
!= NULL
);
7944 LoadTimingInfo load_timing_info
;
7945 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7946 TestLoadTimingNotReusedWithPac(load_timing_info
,
7947 CONNECT_TIMING_HAS_SSL_TIMES
);
7949 std::string response_text
;
7950 rv
= ReadTransaction(trans
.get(), &response_text
);
7952 EXPECT_EQ("Payload", response_text
);
7957 // Tests that for connection endpoints the group names are correctly set.
7959 struct GroupNameTest
{
7960 std::string proxy_server
;
7962 std::string expected_group_name
;
7966 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7967 NextProto next_proto
,
7968 SpdySessionDependencies
* session_deps_
) {
7969 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7971 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7972 session
->http_server_properties();
7973 AlternativeService
alternative_service(
7974 AlternateProtocolFromNextProto(next_proto
), "", 443);
7975 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
7976 http_server_properties
->SetAlternativeService(
7977 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0,
7983 int GroupNameTransactionHelper(
7984 const std::string
& url
,
7985 const scoped_refptr
<HttpNetworkSession
>& session
) {
7986 HttpRequestInfo request
;
7987 request
.method
= "GET";
7988 request
.url
= GURL(url
);
7989 request
.load_flags
= 0;
7991 scoped_ptr
<HttpTransaction
> trans(
7992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7994 TestCompletionCallback callback
;
7996 // We do not complete this request, the dtor will clean the transaction up.
7997 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
8002 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
8003 const GroupNameTest tests
[] = {
8006 "http://www.example.org/direct",
8007 "www.example.org:80",
8012 "http://[2001:1418:13:1::25]/direct",
8013 "[2001:1418:13:1::25]:80",
8020 "https://www.example.org/direct_ssl",
8021 "ssl/www.example.org:443",
8026 "https://[2001:1418:13:1::25]/direct",
8027 "ssl/[2001:1418:13:1::25]:443",
8032 "http://host.with.alternate/direct",
8033 "ssl/host.with.alternate:443",
8038 session_deps_
.use_alternative_services
= true;
8040 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8041 session_deps_
.proxy_service
.reset(
8042 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8043 scoped_refptr
<HttpNetworkSession
> session(
8044 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8046 HttpNetworkSessionPeer
peer(session
);
8047 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
8048 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
8049 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8050 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8051 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8052 new MockClientSocketPoolManager
);
8053 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
8054 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
8055 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8057 EXPECT_EQ(ERR_IO_PENDING
,
8058 GroupNameTransactionHelper(tests
[i
].url
, session
));
8060 EXPECT_EQ(tests
[i
].expected_group_name
,
8061 ssl_conn_pool
->last_group_name_received());
8063 EXPECT_EQ(tests
[i
].expected_group_name
,
8064 transport_conn_pool
->last_group_name_received());
8068 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
8069 const GroupNameTest tests
[] = {
8072 "http://www.example.org/http_proxy_normal",
8073 "www.example.org:80",
8080 "https://www.example.org/http_connect_ssl",
8081 "ssl/www.example.org:443",
8087 "http://host.with.alternate/direct",
8088 "ssl/host.with.alternate:443",
8094 "ftp://ftp.google.com/http_proxy_normal",
8095 "ftp/ftp.google.com:21",
8100 session_deps_
.use_alternative_services
= true;
8102 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8103 session_deps_
.proxy_service
.reset(
8104 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8105 scoped_refptr
<HttpNetworkSession
> session(
8106 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8108 HttpNetworkSessionPeer
peer(session
);
8110 HostPortPair
proxy_host("http_proxy", 80);
8111 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8112 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8113 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8114 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8116 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8117 new MockClientSocketPoolManager
);
8118 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8119 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8120 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8122 EXPECT_EQ(ERR_IO_PENDING
,
8123 GroupNameTransactionHelper(tests
[i
].url
, session
));
8125 EXPECT_EQ(tests
[i
].expected_group_name
,
8126 ssl_conn_pool
->last_group_name_received());
8128 EXPECT_EQ(tests
[i
].expected_group_name
,
8129 http_proxy_pool
->last_group_name_received());
8133 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8134 const GroupNameTest tests
[] = {
8136 "socks4://socks_proxy:1080",
8137 "http://www.example.org/socks4_direct",
8138 "socks4/www.example.org:80",
8142 "socks5://socks_proxy:1080",
8143 "http://www.example.org/socks5_direct",
8144 "socks5/www.example.org:80",
8150 "socks4://socks_proxy:1080",
8151 "https://www.example.org/socks4_ssl",
8152 "socks4/ssl/www.example.org:443",
8156 "socks5://socks_proxy:1080",
8157 "https://www.example.org/socks5_ssl",
8158 "socks5/ssl/www.example.org:443",
8163 "socks4://socks_proxy:1080",
8164 "http://host.with.alternate/direct",
8165 "socks4/ssl/host.with.alternate:443",
8170 session_deps_
.use_alternative_services
= true;
8172 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8173 session_deps_
.proxy_service
.reset(
8174 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8175 scoped_refptr
<HttpNetworkSession
> session(
8176 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8178 HttpNetworkSessionPeer
peer(session
);
8180 HostPortPair
proxy_host("socks_proxy", 1080);
8181 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8182 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8183 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8184 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8186 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8187 new MockClientSocketPoolManager
);
8188 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8189 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8190 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8192 scoped_ptr
<HttpTransaction
> trans(
8193 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8195 EXPECT_EQ(ERR_IO_PENDING
,
8196 GroupNameTransactionHelper(tests
[i
].url
, session
));
8198 EXPECT_EQ(tests
[i
].expected_group_name
,
8199 ssl_conn_pool
->last_group_name_received());
8201 EXPECT_EQ(tests
[i
].expected_group_name
,
8202 socks_conn_pool
->last_group_name_received());
8206 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8207 HttpRequestInfo request
;
8208 request
.method
= "GET";
8209 request
.url
= GURL("http://www.example.org/");
8211 session_deps_
.proxy_service
.reset(
8212 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8214 // This simulates failure resolving all hostnames; that means we will fail
8215 // connecting to both proxies (myproxy:70 and foobar:80).
8216 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8218 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8219 scoped_ptr
<HttpTransaction
> trans(
8220 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8222 TestCompletionCallback callback
;
8224 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8225 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8227 rv
= callback
.WaitForResult();
8228 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8231 // Base test to make sure that when the load flags for a request specify to
8232 // bypass the cache, the DNS cache is not used.
8233 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8235 // Issue a request, asking to bypass the cache(s).
8236 HttpRequestInfo request
;
8237 request
.method
= "GET";
8238 request
.load_flags
= load_flags
;
8239 request
.url
= GURL("http://www.example.org/");
8241 // Select a host resolver that does caching.
8242 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8244 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8245 scoped_ptr
<HttpTransaction
> trans(
8246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8248 // Warm up the host cache so it has an entry for "www.example.org".
8249 AddressList addrlist
;
8250 TestCompletionCallback callback
;
8251 int rv
= session_deps_
.host_resolver
->Resolve(
8252 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8253 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8255 rv
= callback
.WaitForResult();
8258 // Verify that it was added to host cache, by doing a subsequent async lookup
8259 // and confirming it completes synchronously.
8260 rv
= session_deps_
.host_resolver
->Resolve(
8261 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8262 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8265 // Inject a failure the next time that "www.example.org" is resolved. This way
8266 // we can tell if the next lookup hit the cache, or the "network".
8267 // (cache --> success, "network" --> failure).
8268 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8270 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8271 // first read -- this won't be reached as the host resolution will fail first.
8272 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8273 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8274 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8277 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8278 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8279 rv
= callback
.WaitForResult();
8281 // If we bypassed the cache, we would have gotten a failure while resolving
8282 // "www.example.org".
8283 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8286 // There are multiple load flags that should trigger the host cache bypass.
8287 // Test each in isolation:
8288 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8289 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8292 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8293 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8296 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8297 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8300 // Make sure we can handle an error when writing the request.
8301 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8302 HttpRequestInfo request
;
8303 request
.method
= "GET";
8304 request
.url
= GURL("http://www.foo.com/");
8305 request
.load_flags
= 0;
8307 MockWrite write_failure
[] = {
8308 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8310 StaticSocketDataProvider
data(NULL
, 0,
8311 write_failure
, arraysize(write_failure
));
8312 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8313 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8315 TestCompletionCallback callback
;
8317 scoped_ptr
<HttpTransaction
> trans(
8318 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8320 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8321 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8323 rv
= callback
.WaitForResult();
8324 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8327 // Check that a connection closed after the start of the headers finishes ok.
8328 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8329 HttpRequestInfo request
;
8330 request
.method
= "GET";
8331 request
.url
= GURL("http://www.foo.com/");
8332 request
.load_flags
= 0;
8334 MockRead data_reads
[] = {
8335 MockRead("HTTP/1."),
8336 MockRead(SYNCHRONOUS
, OK
),
8339 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8340 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8341 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8343 TestCompletionCallback callback
;
8345 scoped_ptr
<HttpTransaction
> trans(
8346 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8348 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8349 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8351 rv
= callback
.WaitForResult();
8354 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8355 ASSERT_TRUE(response
!= NULL
);
8357 EXPECT_TRUE(response
->headers
.get() != NULL
);
8358 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8360 std::string response_data
;
8361 rv
= ReadTransaction(trans
.get(), &response_data
);
8363 EXPECT_EQ("", response_data
);
8366 // Make sure that a dropped connection while draining the body for auth
8367 // restart does the right thing.
8368 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8369 HttpRequestInfo request
;
8370 request
.method
= "GET";
8371 request
.url
= GURL("http://www.example.org/");
8372 request
.load_flags
= 0;
8374 MockWrite data_writes1
[] = {
8376 "GET / HTTP/1.1\r\n"
8377 "Host: www.example.org\r\n"
8378 "Connection: keep-alive\r\n\r\n"),
8381 MockRead data_reads1
[] = {
8382 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8383 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8384 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8385 MockRead("Content-Length: 14\r\n\r\n"),
8387 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8390 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8391 data_writes1
, arraysize(data_writes1
));
8392 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8394 // After calling trans->RestartWithAuth(), this is the request we should
8395 // be issuing -- the final header line contains the credentials.
8396 MockWrite data_writes2
[] = {
8398 "GET / HTTP/1.1\r\n"
8399 "Host: www.example.org\r\n"
8400 "Connection: keep-alive\r\n"
8401 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8404 // Lastly, the server responds with the actual content.
8405 MockRead data_reads2
[] = {
8406 MockRead("HTTP/1.1 200 OK\r\n"),
8407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8408 MockRead("Content-Length: 100\r\n\r\n"),
8409 MockRead(SYNCHRONOUS
, OK
),
8412 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8413 data_writes2
, arraysize(data_writes2
));
8414 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8415 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8417 TestCompletionCallback callback1
;
8419 scoped_ptr
<HttpTransaction
> trans(
8420 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8422 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8425 rv
= callback1
.WaitForResult();
8428 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8429 ASSERT_TRUE(response
!= NULL
);
8430 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8432 TestCompletionCallback callback2
;
8434 rv
= trans
->RestartWithAuth(
8435 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8438 rv
= callback2
.WaitForResult();
8441 response
= trans
->GetResponseInfo();
8442 ASSERT_TRUE(response
!= NULL
);
8443 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8444 EXPECT_EQ(100, response
->headers
->GetContentLength());
8447 // Test HTTPS connections going through a proxy that sends extra data.
8448 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8449 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8451 HttpRequestInfo request
;
8452 request
.method
= "GET";
8453 request
.url
= GURL("https://www.example.org/");
8454 request
.load_flags
= 0;
8456 MockRead proxy_reads
[] = {
8457 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8458 MockRead(SYNCHRONOUS
, OK
)
8461 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8462 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8464 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8465 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8467 TestCompletionCallback callback
;
8469 session_deps_
.socket_factory
->ResetNextMockIndexes();
8471 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8472 scoped_ptr
<HttpTransaction
> trans(
8473 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8475 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8476 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8478 rv
= callback
.WaitForResult();
8479 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8482 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8483 HttpRequestInfo request
;
8484 request
.method
= "GET";
8485 request
.url
= GURL("http://www.example.org/");
8486 request
.load_flags
= 0;
8488 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8489 scoped_ptr
<HttpTransaction
> trans(
8490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8492 MockRead data_reads
[] = {
8493 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8494 MockRead(SYNCHRONOUS
, OK
),
8497 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8498 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8500 TestCompletionCallback callback
;
8502 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8505 EXPECT_EQ(OK
, callback
.WaitForResult());
8507 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8508 ASSERT_TRUE(response
!= NULL
);
8510 EXPECT_TRUE(response
->headers
.get() != NULL
);
8511 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8513 std::string response_data
;
8514 rv
= ReadTransaction(trans
.get(), &response_data
);
8515 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8518 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8519 base::FilePath temp_file_path
;
8520 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8521 const uint64 kFakeSize
= 100000; // file is actually blank
8522 UploadFileElementReader::ScopedOverridingContentLengthForTests
8523 overriding_content_length(kFakeSize
);
8525 ScopedVector
<UploadElementReader
> element_readers
;
8526 element_readers
.push_back(
8527 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8528 temp_file_path
, 0, kuint64max
, base::Time()));
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 MockRead data_reads
[] = {
8542 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8543 MockRead("hello world"),
8544 MockRead(SYNCHRONOUS
, OK
),
8546 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8547 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8549 TestCompletionCallback callback
;
8551 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8552 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8554 rv
= callback
.WaitForResult();
8557 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8558 ASSERT_TRUE(response
!= NULL
);
8560 EXPECT_TRUE(response
->headers
.get() != NULL
);
8561 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8563 std::string response_data
;
8564 rv
= ReadTransaction(trans
.get(), &response_data
);
8566 EXPECT_EQ("hello world", response_data
);
8568 base::DeleteFile(temp_file_path
, false);
8571 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8572 base::FilePath temp_file
;
8573 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8574 std::string
temp_file_content("Unreadable file.");
8575 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8576 temp_file_content
.length()));
8577 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8579 ScopedVector
<UploadElementReader
> element_readers
;
8580 element_readers
.push_back(
8581 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8582 temp_file
, 0, kuint64max
, base::Time()));
8583 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8585 HttpRequestInfo request
;
8586 request
.method
= "POST";
8587 request
.url
= GURL("http://www.example.org/upload");
8588 request
.upload_data_stream
= &upload_data_stream
;
8589 request
.load_flags
= 0;
8591 // If we try to upload an unreadable file, the transaction should fail.
8592 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8593 scoped_ptr
<HttpTransaction
> trans(
8594 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8596 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8597 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8599 TestCompletionCallback callback
;
8601 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8602 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8604 rv
= callback
.WaitForResult();
8605 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8607 base::DeleteFile(temp_file
, false);
8610 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8611 class FakeUploadElementReader
: public UploadElementReader
{
8613 FakeUploadElementReader() {}
8614 ~FakeUploadElementReader() override
{}
8616 const CompletionCallback
& callback() const { return callback_
; }
8618 // UploadElementReader overrides:
8619 int Init(const CompletionCallback
& callback
) override
{
8620 callback_
= callback
;
8621 return ERR_IO_PENDING
;
8623 uint64
GetContentLength() const override
{ return 0; }
8624 uint64
BytesRemaining() const override
{ return 0; }
8625 int Read(IOBuffer
* buf
,
8627 const CompletionCallback
& callback
) override
{
8632 CompletionCallback callback_
;
8635 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8636 ScopedVector
<UploadElementReader
> element_readers
;
8637 element_readers
.push_back(fake_reader
);
8638 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8640 HttpRequestInfo request
;
8641 request
.method
= "POST";
8642 request
.url
= GURL("http://www.example.org/upload");
8643 request
.upload_data_stream
= &upload_data_stream
;
8644 request
.load_flags
= 0;
8646 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8647 scoped_ptr
<HttpTransaction
> trans(
8648 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8650 StaticSocketDataProvider data
;
8651 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8653 TestCompletionCallback callback
;
8654 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8655 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8656 base::MessageLoop::current()->RunUntilIdle();
8658 // Transaction is pending on request body initialization.
8659 ASSERT_FALSE(fake_reader
->callback().is_null());
8661 // Return Init()'s result after the transaction gets destroyed.
8663 fake_reader
->callback().Run(OK
); // Should not crash.
8666 // Tests that changes to Auth realms are treated like auth rejections.
8667 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8668 HttpRequestInfo request
;
8669 request
.method
= "GET";
8670 request
.url
= GURL("http://www.example.org/");
8671 request
.load_flags
= 0;
8673 // First transaction will request a resource and receive a Basic challenge
8674 // with realm="first_realm".
8675 MockWrite data_writes1
[] = {
8677 "GET / HTTP/1.1\r\n"
8678 "Host: www.example.org\r\n"
8679 "Connection: keep-alive\r\n"
8682 MockRead data_reads1
[] = {
8683 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8684 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8688 // After calling trans->RestartWithAuth(), provide an Authentication header
8689 // for first_realm. The server will reject and provide a challenge with
8691 MockWrite data_writes2
[] = {
8693 "GET / HTTP/1.1\r\n"
8694 "Host: www.example.org\r\n"
8695 "Connection: keep-alive\r\n"
8696 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8699 MockRead data_reads2
[] = {
8700 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8701 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8705 // This again fails, and goes back to first_realm. Make sure that the
8706 // entry is removed from cache.
8707 MockWrite data_writes3
[] = {
8709 "GET / HTTP/1.1\r\n"
8710 "Host: www.example.org\r\n"
8711 "Connection: keep-alive\r\n"
8712 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8715 MockRead data_reads3
[] = {
8716 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8717 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8721 // Try one last time (with the correct password) and get the resource.
8722 MockWrite data_writes4
[] = {
8724 "GET / HTTP/1.1\r\n"
8725 "Host: www.example.org\r\n"
8726 "Connection: keep-alive\r\n"
8727 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8730 MockRead data_reads4
[] = {
8731 MockRead("HTTP/1.1 200 OK\r\n"
8732 "Content-Type: text/html; charset=iso-8859-1\r\n"
8733 "Content-Length: 5\r\n"
8738 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8739 data_writes1
, arraysize(data_writes1
));
8740 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8741 data_writes2
, arraysize(data_writes2
));
8742 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8743 data_writes3
, arraysize(data_writes3
));
8744 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8745 data_writes4
, arraysize(data_writes4
));
8746 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8747 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8748 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8749 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8751 TestCompletionCallback callback1
;
8753 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8754 scoped_ptr
<HttpTransaction
> trans(
8755 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8757 // Issue the first request with Authorize headers. There should be a
8758 // password prompt for first_realm waiting to be filled in after the
8759 // transaction completes.
8760 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8761 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8762 rv
= callback1
.WaitForResult();
8764 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8765 ASSERT_TRUE(response
!= NULL
);
8766 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8767 ASSERT_FALSE(challenge
== NULL
);
8768 EXPECT_FALSE(challenge
->is_proxy
);
8769 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8770 EXPECT_EQ("first_realm", challenge
->realm
);
8771 EXPECT_EQ("basic", challenge
->scheme
);
8773 // Issue the second request with an incorrect password. There should be a
8774 // password prompt for second_realm waiting to be filled in after the
8775 // transaction completes.
8776 TestCompletionCallback callback2
;
8777 rv
= trans
->RestartWithAuth(
8778 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8780 rv
= callback2
.WaitForResult();
8782 response
= trans
->GetResponseInfo();
8783 ASSERT_TRUE(response
!= NULL
);
8784 challenge
= response
->auth_challenge
.get();
8785 ASSERT_FALSE(challenge
== NULL
);
8786 EXPECT_FALSE(challenge
->is_proxy
);
8787 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8788 EXPECT_EQ("second_realm", challenge
->realm
);
8789 EXPECT_EQ("basic", challenge
->scheme
);
8791 // Issue the third request with another incorrect password. There should be
8792 // a password prompt for first_realm waiting to be filled in. If the password
8793 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8794 // first_realm was not correctly removed.
8795 TestCompletionCallback callback3
;
8796 rv
= trans
->RestartWithAuth(
8797 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8798 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8799 rv
= callback3
.WaitForResult();
8801 response
= trans
->GetResponseInfo();
8802 ASSERT_TRUE(response
!= NULL
);
8803 challenge
= response
->auth_challenge
.get();
8804 ASSERT_FALSE(challenge
== NULL
);
8805 EXPECT_FALSE(challenge
->is_proxy
);
8806 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8807 EXPECT_EQ("first_realm", challenge
->realm
);
8808 EXPECT_EQ("basic", challenge
->scheme
);
8810 // Issue the fourth request with the correct password and username.
8811 TestCompletionCallback callback4
;
8812 rv
= trans
->RestartWithAuth(
8813 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8814 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8815 rv
= callback4
.WaitForResult();
8817 response
= trans
->GetResponseInfo();
8818 ASSERT_TRUE(response
!= NULL
);
8819 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8822 TEST_P(HttpNetworkTransactionTest
, HonorAlternativeServiceHeader
) {
8823 session_deps_
.next_protos
= SpdyNextProtos();
8824 session_deps_
.use_alternative_services
= true;
8826 std::string alternative_service_http_header
=
8827 GetAlternativeServiceHttpHeader();
8829 MockRead data_reads
[] = {
8830 MockRead("HTTP/1.1 200 OK\r\n"),
8831 MockRead(alternative_service_http_header
.c_str()),
8833 MockRead("hello world"),
8834 MockRead(SYNCHRONOUS
, OK
),
8837 HttpRequestInfo request
;
8838 request
.method
= "GET";
8839 request
.url
= GURL("http://www.example.org/");
8840 request
.load_flags
= 0;
8842 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8844 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8846 TestCompletionCallback callback
;
8848 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8849 scoped_ptr
<HttpTransaction
> trans(
8850 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8852 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8853 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8855 HostPortPair
http_host_port_pair("www.example.org", 80);
8856 HttpServerProperties
& http_server_properties
=
8857 *session
->http_server_properties();
8858 AlternativeServiceVector alternative_service_vector
=
8859 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8860 EXPECT_TRUE(alternative_service_vector
.empty());
8862 EXPECT_EQ(OK
, callback
.WaitForResult());
8864 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8865 ASSERT_TRUE(response
!= NULL
);
8866 ASSERT_TRUE(response
->headers
.get() != NULL
);
8867 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8868 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8869 EXPECT_FALSE(response
->was_npn_negotiated
);
8871 std::string response_data
;
8872 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8873 EXPECT_EQ("hello world", response_data
);
8875 alternative_service_vector
=
8876 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8877 ASSERT_EQ(1u, alternative_service_vector
.size());
8878 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8879 alternative_service_vector
[0].protocol
);
8880 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8881 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8884 // Alternative Service headers must be ignored when |use_alternative_services|
8886 TEST_P(HttpNetworkTransactionTest
, DoNotHonorAlternativeServiceHeader
) {
8887 session_deps_
.next_protos
= SpdyNextProtos();
8888 session_deps_
.use_alternative_services
= false;
8890 std::string alternative_service_http_header
=
8891 GetAlternativeServiceHttpHeader();
8893 MockRead data_reads
[] = {
8894 MockRead("HTTP/1.1 200 OK\r\n"),
8895 MockRead(alternative_service_http_header
.c_str()),
8897 MockRead("hello world"),
8898 MockRead(SYNCHRONOUS
, OK
),
8901 HttpRequestInfo request
;
8902 request
.method
= "GET";
8903 request
.url
= GURL("http://www.example.org/");
8904 request
.load_flags
= 0;
8906 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), nullptr, 0);
8908 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8910 TestCompletionCallback callback
;
8912 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8913 scoped_ptr
<HttpTransaction
> trans(
8914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8916 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8917 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8919 HostPortPair
http_host_port_pair("www.example.org", 80);
8920 HttpServerProperties
& http_server_properties
=
8921 *session
->http_server_properties();
8922 AlternativeServiceVector alternative_service_vector
=
8923 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8924 EXPECT_TRUE(alternative_service_vector
.empty());
8926 EXPECT_EQ(OK
, callback
.WaitForResult());
8928 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8929 ASSERT_TRUE(response
!= nullptr);
8930 ASSERT_TRUE(response
->headers
.get() != nullptr);
8931 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8932 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8933 EXPECT_FALSE(response
->was_npn_negotiated
);
8935 std::string response_data
;
8936 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8937 EXPECT_EQ("hello world", response_data
);
8939 alternative_service_vector
=
8940 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8941 EXPECT_TRUE(alternative_service_vector
.empty());
8944 TEST_P(HttpNetworkTransactionTest
, HonorMultipleAlternativeServiceHeader
) {
8945 session_deps_
.next_protos
= SpdyNextProtos();
8946 session_deps_
.use_alternative_services
= true;
8948 MockRead data_reads
[] = {
8949 MockRead("HTTP/1.1 200 OK\r\n"),
8950 MockRead("Alt-Svc: "),
8951 MockRead(GetAlternateProtocolFromParam()),
8952 MockRead("=\"www.example.com:443\";p=1.0,"),
8953 MockRead("quic=\":1234\"\r\n\r\n"),
8954 MockRead("hello world"),
8955 MockRead(SYNCHRONOUS
, OK
),
8958 HttpRequestInfo request
;
8959 request
.method
= "GET";
8960 request
.url
= GURL("http://www.example.org/");
8961 request
.load_flags
= 0;
8963 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8965 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8967 TestCompletionCallback callback
;
8969 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8970 scoped_ptr
<HttpTransaction
> trans(
8971 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8973 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8974 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8976 HostPortPair
http_host_port_pair("www.example.org", 80);
8977 HttpServerProperties
& http_server_properties
=
8978 *session
->http_server_properties();
8979 AlternativeServiceVector alternative_service_vector
=
8980 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8981 EXPECT_TRUE(alternative_service_vector
.empty());
8983 EXPECT_EQ(OK
, callback
.WaitForResult());
8985 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8986 ASSERT_TRUE(response
!= NULL
);
8987 ASSERT_TRUE(response
->headers
.get() != NULL
);
8988 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8989 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8990 EXPECT_FALSE(response
->was_npn_negotiated
);
8992 std::string response_data
;
8993 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8994 EXPECT_EQ("hello world", response_data
);
8996 alternative_service_vector
=
8997 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8998 ASSERT_EQ(2u, alternative_service_vector
.size());
8999 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9000 alternative_service_vector
[0].protocol
);
9001 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9002 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9003 EXPECT_EQ(QUIC
, alternative_service_vector
[1].protocol
);
9004 EXPECT_EQ("www.example.org", alternative_service_vector
[1].host
);
9005 EXPECT_EQ(1234, alternative_service_vector
[1].port
);
9008 // Alternate Protocol headers must be honored even if |use_alternative_services|
9010 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
9011 session_deps_
.next_protos
= SpdyNextProtos();
9012 session_deps_
.use_alternative_services
= false;
9014 std::string alternate_protocol_http_header
=
9015 GetAlternateProtocolHttpHeader();
9017 MockRead data_reads
[] = {
9018 MockRead("HTTP/1.1 200 OK\r\n"),
9019 MockRead(alternate_protocol_http_header
.c_str()),
9021 MockRead("hello world"),
9022 MockRead(SYNCHRONOUS
, OK
),
9025 HttpRequestInfo request
;
9026 request
.method
= "GET";
9027 request
.url
= GURL("http://www.example.org/");
9028 request
.load_flags
= 0;
9030 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9032 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9034 TestCompletionCallback callback
;
9036 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9037 scoped_ptr
<HttpTransaction
> trans(
9038 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9040 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9041 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9043 HostPortPair
http_host_port_pair("www.example.org", 80);
9044 HttpServerProperties
& http_server_properties
=
9045 *session
->http_server_properties();
9046 AlternativeServiceVector alternative_service_vector
=
9047 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9048 EXPECT_TRUE(alternative_service_vector
.empty());
9050 EXPECT_EQ(OK
, callback
.WaitForResult());
9052 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9053 ASSERT_TRUE(response
!= NULL
);
9054 ASSERT_TRUE(response
->headers
.get() != NULL
);
9055 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9056 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9057 EXPECT_FALSE(response
->was_npn_negotiated
);
9059 std::string response_data
;
9060 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9061 EXPECT_EQ("hello world", response_data
);
9063 alternative_service_vector
=
9064 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9065 ASSERT_EQ(1u, alternative_service_vector
.size());
9066 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9067 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9068 alternative_service_vector
[0].protocol
);
9071 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
9072 session_deps_
.next_protos
= SpdyNextProtos();
9073 session_deps_
.use_alternative_services
= true;
9075 MockRead data_reads
[] = {
9076 MockRead("HTTP/1.1 200 OK\r\n"),
9077 MockRead("Alternate-Protocol: \r\n\r\n"),
9078 MockRead("hello world"),
9079 MockRead(SYNCHRONOUS
, OK
),
9082 HttpRequestInfo request
;
9083 request
.method
= "GET";
9084 request
.url
= GURL("http://www.example.org/");
9085 request
.load_flags
= 0;
9087 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9089 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9091 TestCompletionCallback callback
;
9093 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9095 HostPortPair
http_host_port_pair("www.example.org", 80);
9096 HttpServerProperties
& http_server_properties
=
9097 *session
->http_server_properties();
9098 AlternativeService
alternative_service(QUIC
, "", 80);
9099 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9100 http_server_properties
.SetAlternativeService(
9101 http_host_port_pair
, alternative_service
, 1.0, expiration
);
9103 AlternativeServiceVector alternative_service_vector
=
9104 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9105 ASSERT_EQ(1u, alternative_service_vector
.size());
9106 EXPECT_EQ(QUIC
, alternative_service_vector
[0].protocol
);
9108 scoped_ptr
<HttpTransaction
> trans(
9109 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9111 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9112 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9114 EXPECT_EQ(OK
, callback
.WaitForResult());
9116 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9117 ASSERT_TRUE(response
!= NULL
);
9118 ASSERT_TRUE(response
->headers
.get() != NULL
);
9119 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9120 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9121 EXPECT_FALSE(response
->was_npn_negotiated
);
9123 std::string response_data
;
9124 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9125 EXPECT_EQ("hello world", response_data
);
9127 alternative_service_vector
=
9128 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9129 EXPECT_TRUE(alternative_service_vector
.empty());
9132 TEST_P(HttpNetworkTransactionTest
, AltSvcOverwritesAlternateProtocol
) {
9133 session_deps_
.next_protos
= SpdyNextProtos();
9134 session_deps_
.use_alternative_services
= true;
9136 std::string alternative_service_http_header
=
9137 GetAlternativeServiceHttpHeader();
9138 std::string alternate_protocol_http_header
= GetAlternateProtocolHttpHeader();
9140 MockRead data_reads
[] = {
9141 MockRead("HTTP/1.1 200 OK\r\n"),
9142 MockRead(alternative_service_http_header
.c_str()),
9143 MockRead(alternate_protocol_http_header
.c_str()),
9145 MockRead("hello world"),
9146 MockRead(SYNCHRONOUS
, OK
),
9149 HttpRequestInfo request
;
9150 request
.method
= "GET";
9151 request
.url
= GURL("http://www.example.org/");
9152 request
.load_flags
= 0;
9154 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9156 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9158 TestCompletionCallback callback
;
9160 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9161 scoped_ptr
<HttpTransaction
> trans(
9162 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9164 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9167 HostPortPair
http_host_port_pair("www.example.org", 80);
9168 HttpServerProperties
& http_server_properties
=
9169 *session
->http_server_properties();
9170 AlternativeServiceVector alternative_service_vector
=
9171 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9172 EXPECT_TRUE(alternative_service_vector
.empty());
9174 EXPECT_EQ(OK
, callback
.WaitForResult());
9176 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9177 ASSERT_TRUE(response
!= NULL
);
9178 ASSERT_TRUE(response
->headers
.get() != NULL
);
9179 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9180 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9181 EXPECT_FALSE(response
->was_npn_negotiated
);
9183 std::string response_data
;
9184 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9185 EXPECT_EQ("hello world", response_data
);
9187 alternative_service_vector
=
9188 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9189 ASSERT_EQ(1u, alternative_service_vector
.size());
9190 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9191 alternative_service_vector
[0].protocol
);
9192 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9193 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9196 // When |use_alternative_services| is false, do not observe alternative service
9197 // entries that point to a different host.
9198 TEST_P(HttpNetworkTransactionTest
, DisableAlternativeServiceToDifferentHost
) {
9199 session_deps_
.use_alternative_services
= false;
9201 HttpRequestInfo request
;
9202 request
.method
= "GET";
9203 request
.url
= GURL("http://www.example.org/");
9204 request
.load_flags
= 0;
9206 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9207 StaticSocketDataProvider first_data
;
9208 first_data
.set_connect_data(mock_connect
);
9209 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9211 MockRead data_reads
[] = {
9212 MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"),
9213 MockRead(ASYNC
, OK
),
9215 StaticSocketDataProvider
second_data(data_reads
, arraysize(data_reads
),
9217 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9219 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9221 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9222 session
->http_server_properties();
9223 AlternativeService
alternative_service(
9224 AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80);
9225 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9226 http_server_properties
->SetAlternativeService(
9227 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9229 scoped_ptr
<HttpTransaction
> trans(
9230 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9231 TestCompletionCallback callback
;
9233 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9234 // The connetion to origin was refused, and the alternative service should not
9235 // be used (even though mock data are there), therefore the request should
9237 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.GetResult(rv
));
9240 TEST_P(HttpNetworkTransactionTest
,
9241 MarkBrokenAlternateProtocolAndFallback
) {
9242 session_deps_
.use_alternative_services
= true;
9244 HttpRequestInfo request
;
9245 request
.method
= "GET";
9246 request
.url
= GURL("http://www.example.org/");
9247 request
.load_flags
= 0;
9249 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9250 StaticSocketDataProvider first_data
;
9251 first_data
.set_connect_data(mock_connect
);
9252 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9254 MockRead data_reads
[] = {
9255 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9256 MockRead("hello world"),
9257 MockRead(ASYNC
, OK
),
9259 StaticSocketDataProvider
second_data(
9260 data_reads
, arraysize(data_reads
), NULL
, 0);
9261 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9263 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9265 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9266 session
->http_server_properties();
9267 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
9268 // Port must be < 1024, or the header will be ignored (since initial port was
9269 // port 80 (another restricted port).
9270 const AlternativeService
alternative_service(
9271 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9272 666); // Port is ignored by MockConnect anyway.
9273 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9274 http_server_properties
->SetAlternativeService(
9275 host_port_pair
, alternative_service
, 1.0, expiration
);
9277 scoped_ptr
<HttpTransaction
> trans(
9278 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9279 TestCompletionCallback callback
;
9281 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9283 EXPECT_EQ(OK
, callback
.WaitForResult());
9285 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9286 ASSERT_TRUE(response
!= NULL
);
9287 ASSERT_TRUE(response
->headers
.get() != NULL
);
9288 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9290 std::string response_data
;
9291 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9292 EXPECT_EQ("hello world", response_data
);
9294 const AlternativeServiceVector alternative_service_vector
=
9295 http_server_properties
->GetAlternativeServices(host_port_pair
);
9296 ASSERT_EQ(1u, alternative_service_vector
.size());
9297 EXPECT_EQ(alternative_service
, alternative_service_vector
[0]);
9298 EXPECT_TRUE(http_server_properties
->IsAlternativeServiceBroken(
9299 alternative_service_vector
[0]));
9302 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9303 // to an unrestricted (port >= 1024) when the original traffic was on a
9304 // restricted port (port < 1024). Ensure that we can redirect in all other
9306 TEST_P(HttpNetworkTransactionTest
,
9307 AlternateProtocolPortRestrictedBlocked
) {
9308 session_deps_
.use_alternative_services
= true;
9310 HttpRequestInfo restricted_port_request
;
9311 restricted_port_request
.method
= "GET";
9312 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9313 restricted_port_request
.load_flags
= 0;
9315 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9316 StaticSocketDataProvider first_data
;
9317 first_data
.set_connect_data(mock_connect
);
9318 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9320 MockRead data_reads
[] = {
9321 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9322 MockRead("hello world"),
9323 MockRead(ASYNC
, OK
),
9325 StaticSocketDataProvider
second_data(
9326 data_reads
, arraysize(data_reads
), NULL
, 0);
9327 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9329 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9331 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9332 session
->http_server_properties();
9333 const int kUnrestrictedAlternatePort
= 1024;
9334 AlternativeService
alternative_service(
9335 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9336 kUnrestrictedAlternatePort
);
9337 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9338 http_server_properties
->SetAlternativeService(
9339 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9342 scoped_ptr
<HttpTransaction
> trans(
9343 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9344 TestCompletionCallback callback
;
9346 int rv
= trans
->Start(
9347 &restricted_port_request
,
9348 callback
.callback(), BoundNetLog());
9349 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9350 // Invalid change to unrestricted port should fail.
9351 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9354 // Ensure that we are allowed to redirect traffic via an alternate protocol to
9355 // an unrestricted (port >= 1024) when the original traffic was on a restricted
9356 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
9357 TEST_P(HttpNetworkTransactionTest
,
9358 AlternateProtocolPortRestrictedPermitted
) {
9359 session_deps_
.use_alternative_services
= true;
9360 session_deps_
.enable_user_alternate_protocol_ports
= true;
9362 HttpRequestInfo restricted_port_request
;
9363 restricted_port_request
.method
= "GET";
9364 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9365 restricted_port_request
.load_flags
= 0;
9367 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9368 StaticSocketDataProvider first_data
;
9369 first_data
.set_connect_data(mock_connect
);
9370 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9372 MockRead data_reads
[] = {
9373 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9374 MockRead("hello world"),
9375 MockRead(ASYNC
, OK
),
9377 StaticSocketDataProvider
second_data(
9378 data_reads
, arraysize(data_reads
), NULL
, 0);
9379 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9381 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9383 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9384 session
->http_server_properties();
9385 const int kUnrestrictedAlternatePort
= 1024;
9386 AlternativeService
alternative_service(
9387 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9388 kUnrestrictedAlternatePort
);
9389 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9390 http_server_properties
->SetAlternativeService(
9391 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9394 scoped_ptr
<HttpTransaction
> trans(
9395 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9396 TestCompletionCallback callback
;
9398 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9399 &restricted_port_request
,
9400 callback
.callback(), BoundNetLog()));
9401 // Change to unrestricted port should succeed.
9402 EXPECT_EQ(OK
, callback
.WaitForResult());
9405 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9406 // to an unrestricted (port >= 1024) when the original traffic was on a
9407 // restricted port (port < 1024). Ensure that we can redirect in all other
9409 TEST_P(HttpNetworkTransactionTest
,
9410 AlternateProtocolPortRestrictedAllowed
) {
9411 session_deps_
.use_alternative_services
= true;
9413 HttpRequestInfo restricted_port_request
;
9414 restricted_port_request
.method
= "GET";
9415 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9416 restricted_port_request
.load_flags
= 0;
9418 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9419 StaticSocketDataProvider first_data
;
9420 first_data
.set_connect_data(mock_connect
);
9421 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9423 MockRead data_reads
[] = {
9424 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9425 MockRead("hello world"),
9426 MockRead(ASYNC
, OK
),
9428 StaticSocketDataProvider
second_data(
9429 data_reads
, arraysize(data_reads
), NULL
, 0);
9430 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9432 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9434 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9435 session
->http_server_properties();
9436 const int kRestrictedAlternatePort
= 80;
9437 AlternativeService
alternative_service(
9438 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9439 kRestrictedAlternatePort
);
9440 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9441 http_server_properties
->SetAlternativeService(
9442 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9445 scoped_ptr
<HttpTransaction
> trans(
9446 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9447 TestCompletionCallback callback
;
9449 int rv
= trans
->Start(
9450 &restricted_port_request
,
9451 callback
.callback(), BoundNetLog());
9452 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9453 // Valid change to restricted port should pass.
9454 EXPECT_EQ(OK
, callback
.WaitForResult());
9457 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9458 // to an unrestricted (port >= 1024) when the original traffic was on a
9459 // restricted port (port < 1024). Ensure that we can redirect in all other
9461 TEST_P(HttpNetworkTransactionTest
,
9462 AlternateProtocolPortUnrestrictedAllowed1
) {
9463 session_deps_
.use_alternative_services
= true;
9465 HttpRequestInfo unrestricted_port_request
;
9466 unrestricted_port_request
.method
= "GET";
9467 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9468 unrestricted_port_request
.load_flags
= 0;
9470 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9471 StaticSocketDataProvider first_data
;
9472 first_data
.set_connect_data(mock_connect
);
9473 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9475 MockRead data_reads
[] = {
9476 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9477 MockRead("hello world"),
9478 MockRead(ASYNC
, OK
),
9480 StaticSocketDataProvider
second_data(
9481 data_reads
, arraysize(data_reads
), NULL
, 0);
9482 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9484 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9486 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9487 session
->http_server_properties();
9488 const int kRestrictedAlternatePort
= 80;
9489 AlternativeService
alternative_service(
9490 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9491 kRestrictedAlternatePort
);
9492 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9493 http_server_properties
->SetAlternativeService(
9494 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9497 scoped_ptr
<HttpTransaction
> trans(
9498 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9499 TestCompletionCallback callback
;
9501 int rv
= trans
->Start(
9502 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9504 // Valid change to restricted port should pass.
9505 EXPECT_EQ(OK
, callback
.WaitForResult());
9508 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9509 // to an unrestricted (port >= 1024) when the original traffic was on a
9510 // restricted port (port < 1024). Ensure that we can redirect in all other
9512 TEST_P(HttpNetworkTransactionTest
,
9513 AlternateProtocolPortUnrestrictedAllowed2
) {
9514 session_deps_
.use_alternative_services
= true;
9516 HttpRequestInfo unrestricted_port_request
;
9517 unrestricted_port_request
.method
= "GET";
9518 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9519 unrestricted_port_request
.load_flags
= 0;
9521 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9522 StaticSocketDataProvider first_data
;
9523 first_data
.set_connect_data(mock_connect
);
9524 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9526 MockRead data_reads
[] = {
9527 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9528 MockRead("hello world"),
9529 MockRead(ASYNC
, OK
),
9531 StaticSocketDataProvider
second_data(
9532 data_reads
, arraysize(data_reads
), NULL
, 0);
9533 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9535 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9537 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9538 session
->http_server_properties();
9539 const int kUnrestrictedAlternatePort
= 1025;
9540 AlternativeService
alternative_service(
9541 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9542 kUnrestrictedAlternatePort
);
9543 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9544 http_server_properties
->SetAlternativeService(
9545 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9548 scoped_ptr
<HttpTransaction
> trans(
9549 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9550 TestCompletionCallback callback
;
9552 int rv
= trans
->Start(
9553 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9554 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9555 // Valid change to an unrestricted port should pass.
9556 EXPECT_EQ(OK
, callback
.WaitForResult());
9559 // Ensure that we are not allowed to redirect traffic via an alternate protocol
9560 // to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job
9561 // once the alternate protocol request fails.
9562 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9563 session_deps_
.use_alternative_services
= true;
9565 HttpRequestInfo request
;
9566 request
.method
= "GET";
9567 request
.url
= GURL("http://www.example.org/");
9568 request
.load_flags
= 0;
9570 // The alternate protocol request will error out before we attempt to connect,
9571 // so only the standard HTTP request will try to connect.
9572 MockRead data_reads
[] = {
9573 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9574 MockRead("hello world"),
9575 MockRead(ASYNC
, OK
),
9577 StaticSocketDataProvider
data(
9578 data_reads
, arraysize(data_reads
), NULL
, 0);
9579 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9581 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9583 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9584 session
->http_server_properties();
9585 const int kUnsafePort
= 7;
9586 AlternativeService
alternative_service(
9587 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9589 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9590 http_server_properties
->SetAlternativeService(
9591 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9593 scoped_ptr
<HttpTransaction
> trans(
9594 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9595 TestCompletionCallback callback
;
9597 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9598 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9599 // The HTTP request should succeed.
9600 EXPECT_EQ(OK
, callback
.WaitForResult());
9602 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9603 ASSERT_TRUE(response
!= NULL
);
9604 ASSERT_TRUE(response
->headers
.get() != NULL
);
9605 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9607 std::string response_data
;
9608 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9609 EXPECT_EQ("hello world", response_data
);
9612 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9613 session_deps_
.use_alternative_services
= true;
9614 session_deps_
.next_protos
= SpdyNextProtos();
9616 HttpRequestInfo request
;
9617 request
.method
= "GET";
9618 request
.url
= GURL("http://www.example.org/");
9619 request
.load_flags
= 0;
9621 std::string alternate_protocol_http_header
=
9622 GetAlternateProtocolHttpHeader();
9624 MockRead data_reads
[] = {
9625 MockRead("HTTP/1.1 200 OK\r\n"),
9626 MockRead(alternate_protocol_http_header
.c_str()),
9628 MockRead("hello world"),
9629 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9630 MockRead(ASYNC
, OK
)};
9632 StaticSocketDataProvider
first_transaction(
9633 data_reads
, arraysize(data_reads
), NULL
, 0);
9634 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9636 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9637 ssl
.SetNextProto(GetParam());
9638 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9639 ASSERT_TRUE(ssl
.cert
.get());
9640 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9642 scoped_ptr
<SpdyFrame
> req(
9643 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9644 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9646 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9647 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9648 MockRead spdy_reads
[] = {
9649 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9652 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9653 arraysize(spdy_writes
));
9654 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9656 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9657 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9659 hanging_non_alternate_protocol_socket
.set_connect_data(
9660 never_finishing_connect
);
9661 session_deps_
.socket_factory
->AddSocketDataProvider(
9662 &hanging_non_alternate_protocol_socket
);
9664 TestCompletionCallback callback
;
9666 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9667 scoped_ptr
<HttpTransaction
> trans(
9668 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9670 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9672 EXPECT_EQ(OK
, callback
.WaitForResult());
9674 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9675 ASSERT_TRUE(response
!= NULL
);
9676 ASSERT_TRUE(response
->headers
.get() != NULL
);
9677 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9679 std::string response_data
;
9680 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9681 EXPECT_EQ("hello world", response_data
);
9683 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9685 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9687 EXPECT_EQ(OK
, callback
.WaitForResult());
9689 response
= trans
->GetResponseInfo();
9690 ASSERT_TRUE(response
!= NULL
);
9691 ASSERT_TRUE(response
->headers
.get() != NULL
);
9692 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9693 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9694 EXPECT_TRUE(response
->was_npn_negotiated
);
9696 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9697 EXPECT_EQ("hello!", response_data
);
9700 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9701 session_deps_
.use_alternative_services
= true;
9702 session_deps_
.next_protos
= SpdyNextProtos();
9704 HttpRequestInfo request
;
9705 request
.method
= "GET";
9706 request
.url
= GURL("http://www.example.org/");
9707 request
.load_flags
= 0;
9709 std::string alternate_protocol_http_header
=
9710 GetAlternateProtocolHttpHeader();
9712 MockRead data_reads
[] = {
9713 MockRead("HTTP/1.1 200 OK\r\n"),
9714 MockRead(alternate_protocol_http_header
.c_str()),
9716 MockRead("hello world"),
9717 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9718 MockRead(ASYNC
, OK
),
9721 StaticSocketDataProvider
first_transaction(
9722 data_reads
, arraysize(data_reads
), NULL
, 0);
9723 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9724 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9726 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9727 StaticSocketDataProvider
hanging_socket(
9729 hanging_socket
.set_connect_data(never_finishing_connect
);
9730 // Socket 2 and 3 are the hanging Alternate-Protocol and
9731 // non-Alternate-Protocol jobs from the 2nd transaction.
9732 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9733 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9735 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9736 ssl
.SetNextProto(GetParam());
9737 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9738 ASSERT_TRUE(ssl
.cert
.get());
9739 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9741 scoped_ptr
<SpdyFrame
> req1(
9742 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9743 scoped_ptr
<SpdyFrame
> req2(
9744 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9745 MockWrite spdy_writes
[] = {
9746 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9748 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9749 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9750 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9751 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9752 MockRead spdy_reads
[] = {
9753 CreateMockRead(*resp1
, 2),
9754 CreateMockRead(*data1
, 3),
9755 CreateMockRead(*resp2
, 4),
9756 CreateMockRead(*data2
, 5),
9757 MockRead(ASYNC
, 0, 6),
9760 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9761 arraysize(spdy_writes
));
9762 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9763 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9765 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9766 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9768 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9769 TestCompletionCallback callback1
;
9770 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9772 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9773 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9774 EXPECT_EQ(OK
, callback1
.WaitForResult());
9776 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9777 ASSERT_TRUE(response
!= NULL
);
9778 ASSERT_TRUE(response
->headers
.get() != NULL
);
9779 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9781 std::string response_data
;
9782 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9783 EXPECT_EQ("hello world", response_data
);
9785 TestCompletionCallback callback2
;
9786 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9787 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9790 TestCompletionCallback callback3
;
9791 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9792 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9793 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9795 EXPECT_EQ(OK
, callback2
.WaitForResult());
9796 EXPECT_EQ(OK
, callback3
.WaitForResult());
9798 response
= trans2
.GetResponseInfo();
9799 ASSERT_TRUE(response
!= NULL
);
9800 ASSERT_TRUE(response
->headers
.get() != NULL
);
9801 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9802 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9803 EXPECT_TRUE(response
->was_npn_negotiated
);
9804 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9805 EXPECT_EQ("hello!", response_data
);
9807 response
= trans3
.GetResponseInfo();
9808 ASSERT_TRUE(response
!= NULL
);
9809 ASSERT_TRUE(response
->headers
.get() != NULL
);
9810 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9811 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9812 EXPECT_TRUE(response
->was_npn_negotiated
);
9813 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9814 EXPECT_EQ("hello!", response_data
);
9817 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9818 session_deps_
.use_alternative_services
= true;
9819 session_deps_
.next_protos
= SpdyNextProtos();
9821 HttpRequestInfo request
;
9822 request
.method
= "GET";
9823 request
.url
= GURL("http://www.example.org/");
9824 request
.load_flags
= 0;
9826 std::string alternate_protocol_http_header
=
9827 GetAlternateProtocolHttpHeader();
9829 MockRead data_reads
[] = {
9830 MockRead("HTTP/1.1 200 OK\r\n"),
9831 MockRead(alternate_protocol_http_header
.c_str()),
9833 MockRead("hello world"),
9834 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9835 MockRead(ASYNC
, OK
),
9838 StaticSocketDataProvider
first_transaction(
9839 data_reads
, arraysize(data_reads
), NULL
, 0);
9840 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9842 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9843 ssl
.SetNextProto(GetParam());
9844 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9846 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9847 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9849 hanging_alternate_protocol_socket
.set_connect_data(
9850 never_finishing_connect
);
9851 session_deps_
.socket_factory
->AddSocketDataProvider(
9852 &hanging_alternate_protocol_socket
);
9854 // 2nd request is just a copy of the first one, over HTTP again.
9855 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9857 TestCompletionCallback callback
;
9859 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9860 scoped_ptr
<HttpTransaction
> trans(
9861 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9863 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9864 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9865 EXPECT_EQ(OK
, callback
.WaitForResult());
9867 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9868 ASSERT_TRUE(response
!= NULL
);
9869 ASSERT_TRUE(response
->headers
.get() != NULL
);
9870 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9872 std::string response_data
;
9873 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9874 EXPECT_EQ("hello world", response_data
);
9876 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9878 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9880 EXPECT_EQ(OK
, callback
.WaitForResult());
9882 response
= trans
->GetResponseInfo();
9883 ASSERT_TRUE(response
!= NULL
);
9884 ASSERT_TRUE(response
->headers
.get() != NULL
);
9885 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9886 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9887 EXPECT_FALSE(response
->was_npn_negotiated
);
9889 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9890 EXPECT_EQ("hello world", response_data
);
9893 class CapturingProxyResolver
: public ProxyResolver
{
9895 CapturingProxyResolver() {}
9896 ~CapturingProxyResolver() override
{}
9898 int GetProxyForURL(const GURL
& url
,
9900 const CompletionCallback
& callback
,
9901 RequestHandle
* request
,
9902 const BoundNetLog
& net_log
) override
{
9903 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9904 HostPortPair("myproxy", 80));
9905 results
->UseProxyServer(proxy_server
);
9906 resolved_
.push_back(url
);
9910 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9912 LoadState
GetLoadState(RequestHandle request
) const override
{
9914 return LOAD_STATE_IDLE
;
9917 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9920 std::vector
<GURL
> resolved_
;
9922 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9925 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9927 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9928 : ProxyResolverFactory(false), resolver_(resolver
) {}
9930 int CreateProxyResolver(
9931 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9932 scoped_ptr
<ProxyResolver
>* resolver
,
9933 const net::CompletionCallback
& callback
,
9934 scoped_ptr
<Request
>* request
) override
{
9935 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9940 ProxyResolver
* resolver_
;
9943 TEST_P(HttpNetworkTransactionTest
,
9944 UseAlternateProtocolForTunneledNpnSpdy
) {
9945 session_deps_
.use_alternative_services
= true;
9946 session_deps_
.next_protos
= SpdyNextProtos();
9948 ProxyConfig proxy_config
;
9949 proxy_config
.set_auto_detect(true);
9950 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9952 CapturingProxyResolver capturing_proxy_resolver
;
9953 session_deps_
.proxy_service
.reset(new ProxyService(
9954 new ProxyConfigServiceFixed(proxy_config
),
9956 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9959 session_deps_
.net_log
= &net_log
;
9961 HttpRequestInfo request
;
9962 request
.method
= "GET";
9963 request
.url
= GURL("http://www.example.org/");
9964 request
.load_flags
= 0;
9966 std::string alternate_protocol_http_header
=
9967 GetAlternateProtocolHttpHeader();
9969 MockRead data_reads
[] = {
9970 MockRead("HTTP/1.1 200 OK\r\n"),
9971 MockRead(alternate_protocol_http_header
.c_str()),
9973 MockRead("hello world"),
9974 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9975 MockRead(ASYNC
, OK
),
9978 StaticSocketDataProvider
first_transaction(
9979 data_reads
, arraysize(data_reads
), NULL
, 0);
9980 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9982 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9983 ssl
.SetNextProto(GetParam());
9984 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9985 ASSERT_TRUE(ssl
.cert
.get());
9986 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9988 scoped_ptr
<SpdyFrame
> req(
9989 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9990 MockWrite spdy_writes
[] = {
9992 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9993 "Host: www.example.org\r\n"
9994 "Proxy-Connection: keep-alive\r\n\r\n"),
9995 CreateMockWrite(*req
, 2),
9998 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10000 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10001 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10002 MockRead spdy_reads
[] = {
10003 MockRead(ASYNC
, 1, kCONNECTResponse
),
10004 CreateMockRead(*resp
.get(), 3),
10005 CreateMockRead(*data
.get(), 4),
10006 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
10009 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10010 arraysize(spdy_writes
));
10011 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10013 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10014 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10016 hanging_non_alternate_protocol_socket
.set_connect_data(
10017 never_finishing_connect
);
10018 session_deps_
.socket_factory
->AddSocketDataProvider(
10019 &hanging_non_alternate_protocol_socket
);
10021 TestCompletionCallback callback
;
10023 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10024 scoped_ptr
<HttpTransaction
> trans(
10025 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10027 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10028 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10029 EXPECT_EQ(OK
, callback
.WaitForResult());
10031 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10032 ASSERT_TRUE(response
!= NULL
);
10033 ASSERT_TRUE(response
->headers
.get() != NULL
);
10034 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10035 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10036 EXPECT_FALSE(response
->was_npn_negotiated
);
10038 std::string response_data
;
10039 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10040 EXPECT_EQ("hello world", response_data
);
10042 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10044 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10046 EXPECT_EQ(OK
, callback
.WaitForResult());
10048 response
= trans
->GetResponseInfo();
10049 ASSERT_TRUE(response
!= NULL
);
10050 ASSERT_TRUE(response
->headers
.get() != NULL
);
10051 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10052 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10053 EXPECT_TRUE(response
->was_npn_negotiated
);
10055 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10056 EXPECT_EQ("hello!", response_data
);
10057 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
10058 EXPECT_EQ("http://www.example.org/",
10059 capturing_proxy_resolver
.resolved()[0].spec());
10060 EXPECT_EQ("https://www.example.org/",
10061 capturing_proxy_resolver
.resolved()[1].spec());
10063 LoadTimingInfo load_timing_info
;
10064 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10065 TestLoadTimingNotReusedWithPac(load_timing_info
,
10066 CONNECT_TIMING_HAS_SSL_TIMES
);
10069 TEST_P(HttpNetworkTransactionTest
,
10070 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
10071 session_deps_
.use_alternative_services
= true;
10072 session_deps_
.next_protos
= SpdyNextProtos();
10074 HttpRequestInfo request
;
10075 request
.method
= "GET";
10076 request
.url
= GURL("http://www.example.org/");
10077 request
.load_flags
= 0;
10079 std::string alternate_protocol_http_header
=
10080 GetAlternateProtocolHttpHeader();
10082 MockRead data_reads
[] = {
10083 MockRead("HTTP/1.1 200 OK\r\n"),
10084 MockRead(alternate_protocol_http_header
.c_str()),
10086 MockRead("hello world"),
10087 MockRead(ASYNC
, OK
),
10090 StaticSocketDataProvider
first_transaction(
10091 data_reads
, arraysize(data_reads
), NULL
, 0);
10092 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
10094 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10095 ssl
.SetNextProto(GetParam());
10096 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10097 ASSERT_TRUE(ssl
.cert
.get());
10098 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10100 scoped_ptr
<SpdyFrame
> req(
10101 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10102 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
10104 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10105 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10106 MockRead spdy_reads
[] = {
10107 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
10110 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10111 arraysize(spdy_writes
));
10112 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10114 TestCompletionCallback callback
;
10116 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10118 scoped_ptr
<HttpTransaction
> trans(
10119 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10121 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10122 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10123 EXPECT_EQ(OK
, callback
.WaitForResult());
10125 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10126 ASSERT_TRUE(response
!= NULL
);
10127 ASSERT_TRUE(response
->headers
.get() != NULL
);
10128 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10130 std::string response_data
;
10131 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10132 EXPECT_EQ("hello world", response_data
);
10134 // Set up an initial SpdySession in the pool to reuse.
10135 HostPortPair
host_port_pair("www.example.org", 443);
10136 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10137 PRIVACY_MODE_DISABLED
);
10138 base::WeakPtr
<SpdySession
> spdy_session
=
10139 CreateSecureSpdySession(session
, key
, BoundNetLog());
10141 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10143 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10145 EXPECT_EQ(OK
, callback
.WaitForResult());
10147 response
= trans
->GetResponseInfo();
10148 ASSERT_TRUE(response
!= NULL
);
10149 ASSERT_TRUE(response
->headers
.get() != NULL
);
10150 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10151 EXPECT_TRUE(response
->was_fetched_via_spdy
);
10152 EXPECT_TRUE(response
->was_npn_negotiated
);
10154 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10155 EXPECT_EQ("hello!", response_data
);
10158 // GenerateAuthToken is a mighty big test.
10159 // It tests all permutation of GenerateAuthToken behavior:
10160 // - Synchronous and Asynchronous completion.
10161 // - OK or error on completion.
10162 // - Direct connection, non-authenticating proxy, and authenticating proxy.
10163 // - HTTP or HTTPS backend (to include proxy tunneling).
10164 // - Non-authenticating and authenticating backend.
10166 // In all, there are 44 reasonable permuations (for example, if there are
10167 // problems generating an auth token for an authenticating proxy, we don't
10168 // need to test all permutations of the backend server).
10170 // The test proceeds by going over each of the configuration cases, and
10171 // potentially running up to three rounds in each of the tests. The TestConfig
10172 // specifies both the configuration for the test as well as the expectations
10173 // for the results.
10174 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
10175 static const char kServer
[] = "http://www.example.com";
10176 static const char kSecureServer
[] = "https://www.example.com";
10177 static const char kProxy
[] = "myproxy:70";
10178 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
10186 const MockWrite
kGet(
10187 "GET / HTTP/1.1\r\n"
10188 "Host: www.example.com\r\n"
10189 "Connection: keep-alive\r\n\r\n");
10190 const MockWrite
kGetProxy(
10191 "GET http://www.example.com/ HTTP/1.1\r\n"
10192 "Host: www.example.com\r\n"
10193 "Proxy-Connection: keep-alive\r\n\r\n");
10194 const MockWrite
kGetAuth(
10195 "GET / HTTP/1.1\r\n"
10196 "Host: www.example.com\r\n"
10197 "Connection: keep-alive\r\n"
10198 "Authorization: auth_token\r\n\r\n");
10199 const MockWrite
kGetProxyAuth(
10200 "GET http://www.example.com/ HTTP/1.1\r\n"
10201 "Host: www.example.com\r\n"
10202 "Proxy-Connection: keep-alive\r\n"
10203 "Proxy-Authorization: auth_token\r\n\r\n");
10204 const MockWrite
kGetAuthThroughProxy(
10205 "GET http://www.example.com/ HTTP/1.1\r\n"
10206 "Host: www.example.com\r\n"
10207 "Proxy-Connection: keep-alive\r\n"
10208 "Authorization: auth_token\r\n\r\n");
10209 const MockWrite
kGetAuthWithProxyAuth(
10210 "GET http://www.example.com/ HTTP/1.1\r\n"
10211 "Host: www.example.com\r\n"
10212 "Proxy-Connection: keep-alive\r\n"
10213 "Proxy-Authorization: auth_token\r\n"
10214 "Authorization: auth_token\r\n\r\n");
10215 const MockWrite
kConnect(
10216 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10217 "Host: www.example.com\r\n"
10218 "Proxy-Connection: keep-alive\r\n\r\n");
10219 const MockWrite
kConnectProxyAuth(
10220 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10221 "Host: www.example.com\r\n"
10222 "Proxy-Connection: keep-alive\r\n"
10223 "Proxy-Authorization: auth_token\r\n\r\n");
10225 const MockRead
kSuccess(
10226 "HTTP/1.1 200 OK\r\n"
10227 "Content-Type: text/html; charset=iso-8859-1\r\n"
10228 "Content-Length: 3\r\n\r\n"
10230 const MockRead
kFailure(
10231 "Should not be called.");
10232 const MockRead
kServerChallenge(
10233 "HTTP/1.1 401 Unauthorized\r\n"
10234 "WWW-Authenticate: Mock realm=server\r\n"
10235 "Content-Type: text/html; charset=iso-8859-1\r\n"
10236 "Content-Length: 14\r\n\r\n"
10237 "Unauthorized\r\n");
10238 const MockRead
kProxyChallenge(
10239 "HTTP/1.1 407 Unauthorized\r\n"
10240 "Proxy-Authenticate: Mock realm=proxy\r\n"
10241 "Proxy-Connection: close\r\n"
10242 "Content-Type: text/html; charset=iso-8859-1\r\n"
10243 "Content-Length: 14\r\n\r\n"
10244 "Unauthorized\r\n");
10245 const MockRead
kProxyConnected(
10246 "HTTP/1.1 200 Connection Established\r\n\r\n");
10248 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10249 // no constructors, but the C++ compiler on Windows warns about
10250 // unspecified data in compound literals. So, moved to using constructors,
10251 // and TestRound's created with the default constructor should not be used.
10254 : expected_rv(ERR_UNEXPECTED
),
10258 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10259 int expected_rv_arg
)
10260 : write(write_arg
),
10262 expected_rv(expected_rv_arg
),
10266 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10267 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
10268 const MockRead
* extra_read_arg
)
10269 : write(write_arg
),
10271 expected_rv(expected_rv_arg
),
10272 extra_write(extra_write_arg
),
10273 extra_read(extra_read_arg
) {
10278 const MockWrite
* extra_write
;
10279 const MockRead
* extra_read
;
10282 static const int kNoSSL
= 500;
10284 struct TestConfig
{
10285 const char* const proxy_url
;
10286 AuthTiming proxy_auth_timing
;
10288 const char* const server_url
;
10289 AuthTiming server_auth_timing
;
10290 int server_auth_rv
;
10291 int num_auth_rounds
;
10292 int first_ssl_round
;
10293 TestRound rounds
[3];
10294 } test_configs
[] = {
10295 // Non-authenticating HTTP server with a direct connection.
10296 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10297 { TestRound(kGet
, kSuccess
, OK
)}},
10298 // Authenticating HTTP server with a direct connection.
10299 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10300 { TestRound(kGet
, kServerChallenge
, OK
),
10301 TestRound(kGetAuth
, kSuccess
, OK
)}},
10302 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10303 { TestRound(kGet
, kServerChallenge
, OK
),
10304 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10305 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10306 { TestRound(kGet
, kServerChallenge
, OK
),
10307 TestRound(kGetAuth
, kSuccess
, OK
)}},
10308 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10309 { TestRound(kGet
, kServerChallenge
, OK
),
10310 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10311 // Non-authenticating HTTP server through a non-authenticating proxy.
10312 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10313 { TestRound(kGetProxy
, kSuccess
, OK
)}},
10314 // Authenticating HTTP server through a non-authenticating proxy.
10315 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10316 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10317 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10318 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10319 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10320 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10321 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10322 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10323 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10324 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10325 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10326 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10327 // Non-authenticating HTTP server through an authenticating proxy.
10328 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10329 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10330 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10331 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10332 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10333 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10334 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10335 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10336 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10337 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10338 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10339 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10340 // Authenticating HTTP server through an authenticating proxy.
10341 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10342 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10343 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10344 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10345 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10346 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10347 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10348 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10349 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10350 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10351 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10352 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10353 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10354 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10355 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10356 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10357 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10358 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10359 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10360 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10361 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10362 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10363 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10364 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10365 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10366 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10367 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10368 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10369 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10370 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10371 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10372 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10373 // Non-authenticating HTTPS server with a direct connection.
10374 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10375 { TestRound(kGet
, kSuccess
, OK
)}},
10376 // Authenticating HTTPS server with a direct connection.
10377 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10378 { TestRound(kGet
, kServerChallenge
, OK
),
10379 TestRound(kGetAuth
, kSuccess
, OK
)}},
10380 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10381 { TestRound(kGet
, kServerChallenge
, OK
),
10382 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10383 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10384 { TestRound(kGet
, kServerChallenge
, OK
),
10385 TestRound(kGetAuth
, kSuccess
, OK
)}},
10386 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10387 { TestRound(kGet
, kServerChallenge
, OK
),
10388 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10389 // Non-authenticating HTTPS server with a non-authenticating proxy.
10390 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10391 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10392 // Authenticating HTTPS server through a non-authenticating proxy.
10393 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10394 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10395 TestRound(kGetAuth
, kSuccess
, OK
)}},
10396 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10397 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10398 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10399 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10400 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10401 TestRound(kGetAuth
, kSuccess
, OK
)}},
10402 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10403 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10404 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10405 // Non-Authenticating HTTPS server through an authenticating proxy.
10406 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10407 { TestRound(kConnect
, kProxyChallenge
, OK
),
10408 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10409 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10410 { TestRound(kConnect
, kProxyChallenge
, OK
),
10411 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10412 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10413 { TestRound(kConnect
, kProxyChallenge
, OK
),
10414 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10415 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10416 { TestRound(kConnect
, kProxyChallenge
, OK
),
10417 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10418 // Authenticating HTTPS server through an authenticating proxy.
10419 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10420 { TestRound(kConnect
, kProxyChallenge
, OK
),
10421 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10422 &kGet
, &kServerChallenge
),
10423 TestRound(kGetAuth
, kSuccess
, OK
)}},
10424 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10425 { TestRound(kConnect
, kProxyChallenge
, OK
),
10426 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10427 &kGet
, &kServerChallenge
),
10428 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10429 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10430 { TestRound(kConnect
, kProxyChallenge
, OK
),
10431 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10432 &kGet
, &kServerChallenge
),
10433 TestRound(kGetAuth
, kSuccess
, OK
)}},
10434 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10435 { TestRound(kConnect
, kProxyChallenge
, OK
),
10436 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10437 &kGet
, &kServerChallenge
),
10438 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10439 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10440 { TestRound(kConnect
, kProxyChallenge
, OK
),
10441 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10442 &kGet
, &kServerChallenge
),
10443 TestRound(kGetAuth
, kSuccess
, OK
)}},
10444 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10445 { TestRound(kConnect
, kProxyChallenge
, OK
),
10446 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10447 &kGet
, &kServerChallenge
),
10448 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10449 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10450 { TestRound(kConnect
, kProxyChallenge
, OK
),
10451 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10452 &kGet
, &kServerChallenge
),
10453 TestRound(kGetAuth
, kSuccess
, OK
)}},
10454 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10455 { TestRound(kConnect
, kProxyChallenge
, OK
),
10456 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10457 &kGet
, &kServerChallenge
),
10458 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10461 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10462 HttpAuthHandlerMock::Factory
* auth_factory(
10463 new HttpAuthHandlerMock::Factory());
10464 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10465 const TestConfig
& test_config
= test_configs
[i
];
10467 // Set up authentication handlers as necessary.
10468 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10469 for (int n
= 0; n
< 2; n
++) {
10470 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10471 std::string auth_challenge
= "Mock realm=proxy";
10472 GURL
origin(test_config
.proxy_url
);
10473 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10474 auth_challenge
.end());
10475 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10476 origin
, BoundNetLog());
10477 auth_handler
->SetGenerateExpectation(
10478 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10479 test_config
.proxy_auth_rv
);
10480 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10483 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10484 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10485 std::string auth_challenge
= "Mock realm=server";
10486 GURL
origin(test_config
.server_url
);
10487 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10488 auth_challenge
.end());
10489 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10490 origin
, BoundNetLog());
10491 auth_handler
->SetGenerateExpectation(
10492 test_config
.server_auth_timing
== AUTH_ASYNC
,
10493 test_config
.server_auth_rv
);
10494 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10496 if (test_config
.proxy_url
) {
10497 session_deps_
.proxy_service
.reset(
10498 ProxyService::CreateFixed(test_config
.proxy_url
));
10500 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10503 HttpRequestInfo request
;
10504 request
.method
= "GET";
10505 request
.url
= GURL(test_config
.server_url
);
10506 request
.load_flags
= 0;
10508 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10509 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10511 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10513 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10514 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10515 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10516 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10518 // Set up expected reads and writes.
10519 mock_reads
.back().push_back(read_write_round
.read
);
10520 mock_writes
.back().push_back(read_write_round
.write
);
10522 // kProxyChallenge uses Proxy-Connection: close which means that the
10523 // socket is closed and a new one will be created for the next request.
10524 if (read_write_round
.read
.data
== kProxyChallenge
.data
) {
10525 mock_reads
.push_back(std::vector
<MockRead
>());
10526 mock_writes
.push_back(std::vector
<MockWrite
>());
10529 if (read_write_round
.extra_read
) {
10530 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10532 if (read_write_round
.extra_write
) {
10533 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10536 // Add an SSL sequence if necessary.
10537 if (round
>= test_config
.first_ssl_round
)
10538 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10539 &ssl_socket_data_provider
);
10542 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10543 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10544 data_providers
.push_back(new StaticSocketDataProvider(
10545 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10546 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10547 session_deps_
.socket_factory
->AddSocketDataProvider(
10548 data_providers
.back());
10551 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10552 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10553 // Start or restart the transaction.
10554 TestCompletionCallback callback
;
10557 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10559 rv
= trans
.RestartWithAuth(
10560 AuthCredentials(kFoo
, kBar
), callback
.callback());
10562 if (rv
== ERR_IO_PENDING
)
10563 rv
= callback
.WaitForResult();
10565 // Compare results with expected data.
10566 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10567 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10568 if (read_write_round
.expected_rv
!= OK
) {
10569 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10572 if (round
+ 1 < test_config
.num_auth_rounds
) {
10573 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10575 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10581 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10582 // Do multi-round authentication and make sure it works correctly.
10583 HttpAuthHandlerMock::Factory
* auth_factory(
10584 new HttpAuthHandlerMock::Factory());
10585 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10586 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10587 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10588 session_deps_
.host_resolver
->set_synchronous_mode(true);
10590 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10591 auth_handler
->set_connection_based(true);
10592 std::string auth_challenge
= "Mock realm=server";
10593 GURL
origin("http://www.example.com");
10594 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10595 auth_challenge
.end());
10596 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10597 origin
, BoundNetLog());
10598 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10601 const HttpResponseInfo
* response
= NULL
;
10602 HttpRequestInfo request
;
10603 request
.method
= "GET";
10604 request
.url
= origin
;
10605 request
.load_flags
= 0;
10607 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10609 // Use a TCP Socket Pool with only one connection per group. This is used
10610 // to validate that the TCP socket is not released to the pool between
10611 // each round of multi-round authentication.
10612 HttpNetworkSessionPeer
session_peer(session
);
10613 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10614 50, // Max sockets for pool
10615 1, // Max sockets per group
10616 session_deps_
.host_resolver
.get(),
10617 session_deps_
.socket_factory
.get(),
10618 session_deps_
.net_log
);
10619 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10620 new MockClientSocketPoolManager
);
10621 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10622 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10624 scoped_ptr
<HttpTransaction
> trans(
10625 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10626 TestCompletionCallback callback
;
10628 const MockWrite
kGet(
10629 "GET / HTTP/1.1\r\n"
10630 "Host: www.example.com\r\n"
10631 "Connection: keep-alive\r\n\r\n");
10632 const MockWrite
kGetAuth(
10633 "GET / HTTP/1.1\r\n"
10634 "Host: www.example.com\r\n"
10635 "Connection: keep-alive\r\n"
10636 "Authorization: auth_token\r\n\r\n");
10638 const MockRead
kServerChallenge(
10639 "HTTP/1.1 401 Unauthorized\r\n"
10640 "WWW-Authenticate: Mock realm=server\r\n"
10641 "Content-Type: text/html; charset=iso-8859-1\r\n"
10642 "Content-Length: 14\r\n\r\n"
10643 "Unauthorized\r\n");
10644 const MockRead
kSuccess(
10645 "HTTP/1.1 200 OK\r\n"
10646 "Content-Type: text/html; charset=iso-8859-1\r\n"
10647 "Content-Length: 3\r\n\r\n"
10650 MockWrite writes
[] = {
10659 // Competing request
10662 MockRead reads
[] = {
10671 // Competing response
10674 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10675 writes
, arraysize(writes
));
10676 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10678 const char kSocketGroup
[] = "www.example.com:80";
10680 // First round of authentication.
10681 auth_handler
->SetGenerateExpectation(false, OK
);
10682 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10683 if (rv
== ERR_IO_PENDING
)
10684 rv
= callback
.WaitForResult();
10686 response
= trans
->GetResponseInfo();
10687 ASSERT_TRUE(response
!= NULL
);
10688 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10689 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10691 // In between rounds, another request comes in for the same domain.
10692 // It should not be able to grab the TCP socket that trans has already
10694 scoped_ptr
<HttpTransaction
> trans_compete(
10695 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10696 TestCompletionCallback callback_compete
;
10697 rv
= trans_compete
->Start(
10698 &request
, callback_compete
.callback(), BoundNetLog());
10699 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10700 // callback_compete.WaitForResult at this point would stall forever,
10701 // since the HttpNetworkTransaction does not release the request back to
10702 // the pool until after authentication completes.
10704 // Second round of authentication.
10705 auth_handler
->SetGenerateExpectation(false, OK
);
10706 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10707 if (rv
== ERR_IO_PENDING
)
10708 rv
= callback
.WaitForResult();
10710 response
= trans
->GetResponseInfo();
10711 ASSERT_TRUE(response
!= NULL
);
10712 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10713 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10715 // Third round of authentication.
10716 auth_handler
->SetGenerateExpectation(false, OK
);
10717 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10718 if (rv
== ERR_IO_PENDING
)
10719 rv
= callback
.WaitForResult();
10721 response
= trans
->GetResponseInfo();
10722 ASSERT_TRUE(response
!= NULL
);
10723 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10724 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10726 // Fourth round of authentication, which completes successfully.
10727 auth_handler
->SetGenerateExpectation(false, OK
);
10728 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10729 if (rv
== ERR_IO_PENDING
)
10730 rv
= callback
.WaitForResult();
10732 response
= trans
->GetResponseInfo();
10733 ASSERT_TRUE(response
!= NULL
);
10734 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10735 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10737 // Read the body since the fourth round was successful. This will also
10738 // release the socket back to the pool.
10739 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10740 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10741 if (rv
== ERR_IO_PENDING
)
10742 rv
= callback
.WaitForResult();
10744 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10746 // There are still 0 idle sockets, since the trans_compete transaction
10747 // will be handed it immediately after trans releases it to the group.
10748 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10750 // The competing request can now finish. Wait for the headers and then
10752 rv
= callback_compete
.WaitForResult();
10754 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10755 if (rv
== ERR_IO_PENDING
)
10756 rv
= callback
.WaitForResult();
10758 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10761 // Finally, the socket is released to the group.
10762 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10765 // This tests the case that a request is issued via http instead of spdy after
10766 // npn is negotiated.
10767 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10768 session_deps_
.use_alternative_services
= true;
10769 NextProtoVector next_protos
;
10770 next_protos
.push_back(kProtoHTTP11
);
10771 session_deps_
.next_protos
= next_protos
;
10773 HttpRequestInfo request
;
10774 request
.method
= "GET";
10775 request
.url
= GURL("https://www.example.org/");
10776 request
.load_flags
= 0;
10778 MockWrite data_writes
[] = {
10780 "GET / HTTP/1.1\r\n"
10781 "Host: www.example.org\r\n"
10782 "Connection: keep-alive\r\n\r\n"),
10785 std::string alternate_protocol_http_header
=
10786 GetAlternateProtocolHttpHeader();
10788 MockRead data_reads
[] = {
10789 MockRead("HTTP/1.1 200 OK\r\n"),
10790 MockRead(alternate_protocol_http_header
.c_str()),
10792 MockRead("hello world"),
10793 MockRead(SYNCHRONOUS
, OK
),
10796 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10797 ssl
.SetNextProto(kProtoHTTP11
);
10799 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10801 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10802 data_writes
, arraysize(data_writes
));
10803 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10805 TestCompletionCallback callback
;
10807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10808 scoped_ptr
<HttpTransaction
> trans(
10809 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10811 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10813 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10814 EXPECT_EQ(OK
, callback
.WaitForResult());
10816 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10817 ASSERT_TRUE(response
!= NULL
);
10818 ASSERT_TRUE(response
->headers
.get() != NULL
);
10819 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10821 std::string response_data
;
10822 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10823 EXPECT_EQ("hello world", response_data
);
10825 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10826 EXPECT_TRUE(response
->was_npn_negotiated
);
10829 // Simulate the SSL handshake completing with an NPN negotiation followed by an
10830 // immediate server closing of the socket.
10831 // Regression test for https://crbug.com/46369.
10832 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10833 session_deps_
.use_alternative_services
= true;
10834 session_deps_
.next_protos
= SpdyNextProtos();
10836 HttpRequestInfo request
;
10837 request
.method
= "GET";
10838 request
.url
= GURL("https://www.example.org/");
10839 request
.load_flags
= 0;
10841 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10842 ssl
.SetNextProto(GetParam());
10843 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10845 scoped_ptr
<SpdyFrame
> req(
10846 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10847 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10849 MockRead spdy_reads
[] = {
10850 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10853 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10854 arraysize(spdy_writes
));
10855 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10857 TestCompletionCallback callback
;
10859 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10860 scoped_ptr
<HttpTransaction
> trans(
10861 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10863 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10864 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10865 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10868 // A subclass of HttpAuthHandlerMock that records the request URL when
10869 // it gets it. This is needed since the auth handler may get destroyed
10870 // before we get a chance to query it.
10871 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10873 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10875 ~UrlRecordingHttpAuthHandlerMock() override
{}
10878 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10879 const HttpRequestInfo
* request
,
10880 const CompletionCallback
& callback
,
10881 std::string
* auth_token
) override
{
10882 *url_
= request
->url
;
10883 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10884 credentials
, request
, callback
, auth_token
);
10891 // This test ensures that the URL passed into the proxy is upgraded to https
10892 // when doing an Alternate Protocol upgrade.
10893 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10894 session_deps_
.use_alternative_services
= true;
10895 session_deps_
.next_protos
= SpdyNextProtos();
10897 session_deps_
.proxy_service
.reset(
10898 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10899 TestNetLog net_log
;
10900 session_deps_
.net_log
= &net_log
;
10903 HttpAuthHandlerMock::Factory
* auth_factory
=
10904 new HttpAuthHandlerMock::Factory();
10905 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10906 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10907 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10908 auth_factory
->set_do_init_from_challenge(true);
10909 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10912 HttpRequestInfo request
;
10913 request
.method
= "GET";
10914 request
.url
= GURL("http://www.example.org");
10915 request
.load_flags
= 0;
10917 // First round goes unauthenticated through the proxy.
10918 MockWrite data_writes_1
[] = {
10920 "GET http://www.example.org/ HTTP/1.1\r\n"
10921 "Host: www.example.org\r\n"
10922 "Proxy-Connection: keep-alive\r\n"
10925 MockRead data_reads_1
[] = {
10926 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10927 MockRead("HTTP/1.1 200 OK\r\n"),
10928 MockRead("Alternate-Protocol: 443:"),
10929 MockRead(GetAlternateProtocolFromParam()),
10931 MockRead("Proxy-Connection: close\r\n"),
10934 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10935 data_writes_1
, arraysize(data_writes_1
));
10937 // Second round tries to tunnel to www.example.org due to the
10938 // Alternate-Protocol announcement in the first round. It fails due
10939 // to a proxy authentication challenge.
10940 // After the failure, a tunnel is established to www.example.org using
10941 // Proxy-Authorization headers. There is then a SPDY request round.
10943 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10944 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10945 // does a Disconnect and Connect on the same socket, rather than trying
10946 // to obtain a new one.
10948 // NOTE: Originally, the proxy response to the second CONNECT request
10949 // simply returned another 407 so the unit test could skip the SSL connection
10950 // establishment and SPDY framing issues. Alas, the
10951 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10952 // complicated to set up expectations for than the SPDY session.
10954 scoped_ptr
<SpdyFrame
> req(
10955 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10956 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10957 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10959 MockWrite data_writes_2
[] = {
10960 // First connection attempt without Proxy-Authorization.
10961 MockWrite(ASYNC
, 0,
10962 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10963 "Host: www.example.org\r\n"
10964 "Proxy-Connection: keep-alive\r\n"
10967 // Second connection attempt with Proxy-Authorization.
10968 MockWrite(ASYNC
, 2,
10969 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10970 "Host: www.example.org\r\n"
10971 "Proxy-Connection: keep-alive\r\n"
10972 "Proxy-Authorization: auth_token\r\n"
10976 CreateMockWrite(*req
, 4),
10978 MockRead data_reads_2
[] = {
10979 // First connection attempt fails
10981 "HTTP/1.1 407 Unauthorized\r\n"
10982 "Proxy-Authenticate: Mock\r\n"
10983 "Content-Length: 0\r\n"
10984 "Proxy-Connection: keep-alive\r\n"
10987 // Second connection attempt passes
10988 MockRead(ASYNC
, 3, "HTTP/1.1 200 Connected\r\n\r\n"),
10991 CreateMockRead(*resp
.get(), 5), CreateMockRead(*data
.get(), 6),
10992 MockRead(ASYNC
, 0, 0, 7),
10994 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10995 data_writes_2
, arraysize(data_writes_2
));
10997 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10998 ssl
.SetNextProto(GetParam());
10999 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
11000 ASSERT_TRUE(ssl
.cert
.get());
11002 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
11003 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
11005 hanging_non_alternate_protocol_socket
.set_connect_data(
11006 never_finishing_connect
);
11008 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
11009 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
11010 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11011 session_deps_
.socket_factory
->AddSocketDataProvider(
11012 &hanging_non_alternate_protocol_socket
);
11013 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11015 // First round should work and provide the Alternate-Protocol state.
11016 TestCompletionCallback callback_1
;
11017 scoped_ptr
<HttpTransaction
> trans_1(
11018 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11019 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
11020 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11021 EXPECT_EQ(OK
, callback_1
.WaitForResult());
11023 // Second round should attempt a tunnel connect and get an auth challenge.
11024 TestCompletionCallback callback_2
;
11025 scoped_ptr
<HttpTransaction
> trans_2(
11026 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11027 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
11028 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11029 EXPECT_EQ(OK
, callback_2
.WaitForResult());
11030 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
11031 ASSERT_TRUE(response
!= NULL
);
11032 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
11034 // Restart with auth. Tunnel should work and response received.
11035 TestCompletionCallback callback_3
;
11036 rv
= trans_2
->RestartWithAuth(
11037 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
11038 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11039 EXPECT_EQ(OK
, callback_3
.WaitForResult());
11041 // After all that work, these two lines (or actually, just the scheme) are
11042 // what this test is all about. Make sure it happens correctly.
11043 EXPECT_EQ("https", request_url
.scheme());
11044 EXPECT_EQ("www.example.org", request_url
.host());
11046 LoadTimingInfo load_timing_info
;
11047 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
11048 TestLoadTimingNotReusedWithPac(load_timing_info
,
11049 CONNECT_TIMING_HAS_SSL_TIMES
);
11052 // Test that if we cancel the transaction as the connection is completing, that
11053 // everything tears down correctly.
11054 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
11055 // Setup everything about the connection to complete synchronously, so that
11056 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
11057 // for is the callback from the HttpStreamRequest.
11058 // Then cancel the transaction.
11059 // Verify that we don't crash.
11060 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
11061 MockRead data_reads
[] = {
11062 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
11063 MockRead(SYNCHRONOUS
, "hello world"),
11064 MockRead(SYNCHRONOUS
, OK
),
11067 HttpRequestInfo request
;
11068 request
.method
= "GET";
11069 request
.url
= GURL("http://www.example.org/");
11070 request
.load_flags
= 0;
11072 session_deps_
.host_resolver
->set_synchronous_mode(true);
11073 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11074 scoped_ptr
<HttpTransaction
> trans(
11075 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11077 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
11078 data
.set_connect_data(mock_connect
);
11079 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11081 TestCompletionCallback callback
;
11083 BoundTestNetLog log
;
11084 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
11085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11086 trans
.reset(); // Cancel the transaction here.
11088 base::MessageLoop::current()->RunUntilIdle();
11091 // Test that if a transaction is cancelled after receiving the headers, the
11092 // stream is drained properly and added back to the socket pool. The main
11093 // purpose of this test is to make sure that an HttpStreamParser can be read
11094 // from after the HttpNetworkTransaction and the objects it owns have been
11096 // See http://crbug.com/368418
11097 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
11098 MockRead data_reads
[] = {
11099 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
11100 MockRead(ASYNC
, "Content-Length: 2\r\n"),
11101 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
11102 MockRead(ASYNC
, "1"),
11103 // 2 async reads are necessary to trigger a ReadResponseBody call after the
11104 // HttpNetworkTransaction has been deleted.
11105 MockRead(ASYNC
, "2"),
11106 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
11108 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
11109 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11111 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11114 HttpRequestInfo request
;
11115 request
.method
= "GET";
11116 request
.url
= GURL("http://www.example.org/");
11117 request
.load_flags
= 0;
11119 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
11120 TestCompletionCallback callback
;
11122 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
11123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11124 callback
.WaitForResult();
11126 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
11127 ASSERT_TRUE(response
!= NULL
);
11128 EXPECT_TRUE(response
->headers
.get() != NULL
);
11129 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11131 // The transaction and HttpRequestInfo are deleted.
11134 // Let the HttpResponseBodyDrainer drain the socket.
11135 base::MessageLoop::current()->RunUntilIdle();
11137 // Socket should now be idle, waiting to be reused.
11138 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
11141 // Test a basic GET request through a proxy.
11142 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
11143 session_deps_
.proxy_service
.reset(
11144 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11145 BoundTestNetLog log
;
11146 session_deps_
.net_log
= log
.bound().net_log();
11147 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11149 HttpRequestInfo request
;
11150 request
.method
= "GET";
11151 request
.url
= GURL("http://www.example.org/");
11153 MockWrite data_writes1
[] = {
11155 "GET http://www.example.org/ HTTP/1.1\r\n"
11156 "Host: www.example.org\r\n"
11157 "Proxy-Connection: keep-alive\r\n\r\n"),
11160 MockRead data_reads1
[] = {
11161 MockRead("HTTP/1.1 200 OK\r\n"),
11162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11163 MockRead("Content-Length: 100\r\n\r\n"),
11164 MockRead(SYNCHRONOUS
, OK
),
11167 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11168 data_writes1
, arraysize(data_writes1
));
11169 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11171 TestCompletionCallback callback1
;
11173 scoped_ptr
<HttpTransaction
> trans(
11174 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11175 BeforeProxyHeadersSentHandler proxy_headers_handler
;
11176 trans
->SetBeforeProxyHeadersSentCallback(
11177 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
11178 base::Unretained(&proxy_headers_handler
)));
11180 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11183 rv
= callback1
.WaitForResult();
11186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11187 ASSERT_TRUE(response
!= NULL
);
11189 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11190 EXPECT_EQ(200, response
->headers
->response_code());
11191 EXPECT_EQ(100, response
->headers
->GetContentLength());
11192 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11194 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11195 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
11196 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
11197 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11199 LoadTimingInfo load_timing_info
;
11200 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11201 TestLoadTimingNotReusedWithPac(load_timing_info
,
11202 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
11205 // Test a basic HTTPS GET request through a proxy.
11206 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
11207 session_deps_
.proxy_service
.reset(
11208 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11209 BoundTestNetLog log
;
11210 session_deps_
.net_log
= log
.bound().net_log();
11211 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11213 HttpRequestInfo request
;
11214 request
.method
= "GET";
11215 request
.url
= GURL("https://www.example.org/");
11217 // Since we have proxy, should try to establish tunnel.
11218 MockWrite data_writes1
[] = {
11220 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11221 "Host: www.example.org\r\n"
11222 "Proxy-Connection: keep-alive\r\n\r\n"),
11225 "GET / HTTP/1.1\r\n"
11226 "Host: www.example.org\r\n"
11227 "Connection: keep-alive\r\n\r\n"),
11230 MockRead data_reads1
[] = {
11231 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11233 MockRead("HTTP/1.1 200 OK\r\n"),
11234 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11235 MockRead("Content-Length: 100\r\n\r\n"),
11236 MockRead(SYNCHRONOUS
, OK
),
11239 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11240 data_writes1
, arraysize(data_writes1
));
11241 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11242 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11243 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11245 TestCompletionCallback callback1
;
11247 scoped_ptr
<HttpTransaction
> trans(
11248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11250 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11251 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11253 rv
= callback1
.WaitForResult();
11255 TestNetLogEntry::List entries
;
11256 log
.GetEntries(&entries
);
11257 size_t pos
= ExpectLogContainsSomewhere(
11258 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11259 NetLog::PHASE_NONE
);
11260 ExpectLogContainsSomewhere(
11262 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11263 NetLog::PHASE_NONE
);
11265 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11266 ASSERT_TRUE(response
!= NULL
);
11268 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11269 EXPECT_EQ(200, response
->headers
->response_code());
11270 EXPECT_EQ(100, response
->headers
->GetContentLength());
11271 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11272 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11274 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11276 LoadTimingInfo load_timing_info
;
11277 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11278 TestLoadTimingNotReusedWithPac(load_timing_info
,
11279 CONNECT_TIMING_HAS_SSL_TIMES
);
11282 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11283 // while establishing the tunnel.
11284 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
11285 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
11286 BoundTestNetLog log
;
11287 session_deps_
.net_log
= log
.bound().net_log();
11288 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11290 HttpRequestInfo request
;
11291 request
.method
= "GET";
11292 request
.url
= GURL("https://www.example.org/");
11294 // Since we have proxy, should try to establish tunnel.
11295 MockWrite data_writes1
[] = {
11297 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11298 "Host: www.example.org\r\n"
11299 "Proxy-Connection: keep-alive\r\n\r\n"),
11302 "GET / HTTP/1.1\r\n"
11303 "Host: www.example.org\r\n"
11304 "Connection: keep-alive\r\n\r\n"),
11307 MockRead data_reads1
[] = {
11308 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
11309 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11310 MockRead(ASYNC
, 0, 0), // EOF
11313 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11314 data_writes1
, arraysize(data_writes1
));
11315 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11316 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11317 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11319 TestCompletionCallback callback1
;
11321 scoped_ptr
<HttpTransaction
> trans(
11322 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11324 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11325 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11327 rv
= callback1
.WaitForResult();
11328 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
11329 TestNetLogEntry::List entries
;
11330 log
.GetEntries(&entries
);
11331 size_t pos
= ExpectLogContainsSomewhere(
11332 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11333 NetLog::PHASE_NONE
);
11334 ExpectLogContainsSomewhere(
11336 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11337 NetLog::PHASE_NONE
);
11340 // Test for crbug.com/55424.
11341 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
11342 scoped_ptr
<SpdyFrame
> req(
11343 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11344 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
11346 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11347 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11348 MockRead spdy_reads
[] = {
11349 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
11352 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
11353 arraysize(spdy_writes
));
11354 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11356 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11357 ssl
.SetNextProto(GetParam());
11358 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11360 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11362 // Set up an initial SpdySession in the pool to reuse.
11363 HostPortPair
host_port_pair("www.example.org", 443);
11364 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11365 PRIVACY_MODE_DISABLED
);
11366 base::WeakPtr
<SpdySession
> spdy_session
=
11367 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11369 HttpRequestInfo request
;
11370 request
.method
= "GET";
11371 request
.url
= GURL("https://www.example.org/");
11372 request
.load_flags
= 0;
11374 // This is the important line that marks this as a preconnect.
11375 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11377 scoped_ptr
<HttpTransaction
> trans(
11378 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11380 TestCompletionCallback callback
;
11381 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11382 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11383 EXPECT_EQ(OK
, callback
.WaitForResult());
11386 // Given a net error, cause that error to be returned from the first Write()
11387 // call and verify that the HttpTransaction fails with that error.
11388 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11389 int error
, IoMode mode
) {
11390 HttpRequestInfo request_info
;
11391 request_info
.url
= GURL("https://www.example.com/");
11392 request_info
.method
= "GET";
11393 request_info
.load_flags
= LOAD_NORMAL
;
11395 SSLSocketDataProvider
ssl_data(mode
, OK
);
11396 MockWrite data_writes
[] = {
11397 MockWrite(mode
, error
),
11399 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11400 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11401 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11403 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11404 scoped_ptr
<HttpTransaction
> trans(
11405 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11407 TestCompletionCallback callback
;
11408 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11409 if (rv
== ERR_IO_PENDING
)
11410 rv
= callback
.WaitForResult();
11411 ASSERT_EQ(error
, rv
);
11414 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11415 // Just check a grab bag of cert errors.
11416 static const int kErrors
[] = {
11417 ERR_CERT_COMMON_NAME_INVALID
,
11418 ERR_CERT_AUTHORITY_INVALID
,
11419 ERR_CERT_DATE_INVALID
,
11421 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11422 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11423 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11427 // Ensure that a client certificate is removed from the SSL client auth
11429 // 1) No proxy is involved.
11430 // 2) TLS False Start is disabled.
11431 // 3) The initial TLS handshake requests a client certificate.
11432 // 4) The client supplies an invalid/unacceptable certificate.
11433 TEST_P(HttpNetworkTransactionTest
,
11434 ClientAuthCertCache_Direct_NoFalseStart
) {
11435 HttpRequestInfo request_info
;
11436 request_info
.url
= GURL("https://www.example.com/");
11437 request_info
.method
= "GET";
11438 request_info
.load_flags
= LOAD_NORMAL
;
11440 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11441 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11443 // [ssl_]data1 contains the data for the first SSL handshake. When a
11444 // CertificateRequest is received for the first time, the handshake will
11445 // be aborted to allow the caller to provide a certificate.
11446 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11447 ssl_data1
.cert_request_info
= cert_request
.get();
11448 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11449 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11450 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11452 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11453 // False Start is not being used, the result of the SSL handshake will be
11454 // returned as part of the SSLClientSocket::Connect() call. This test
11455 // matches the result of a server sending a handshake_failure alert,
11456 // rather than a Finished message, because it requires a client
11457 // certificate and none was supplied.
11458 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11459 ssl_data2
.cert_request_info
= cert_request
.get();
11460 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11461 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11462 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11464 // [ssl_]data3 contains the data for the third SSL handshake. When a
11465 // connection to a server fails during an SSL handshake,
11466 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11467 // connection was attempted with TLSv1.2. This is transparent to the caller
11468 // of the HttpNetworkTransaction. Because this test failure is due to
11469 // requiring a client certificate, this fallback handshake should also
11471 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11472 ssl_data3
.cert_request_info
= cert_request
.get();
11473 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11474 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11475 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11477 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11478 // connection to a server fails during an SSL handshake,
11479 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11480 // connection was attempted with TLSv1.1. This is transparent to the caller
11481 // of the HttpNetworkTransaction. Because this test failure is due to
11482 // requiring a client certificate, this fallback handshake should also
11484 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11485 ssl_data4
.cert_request_info
= cert_request
.get();
11486 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11487 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11488 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11490 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11491 scoped_ptr
<HttpTransaction
> trans(
11492 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11494 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11495 TestCompletionCallback callback
;
11496 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11497 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11499 // Complete the SSL handshake, which should abort due to requiring a
11500 // client certificate.
11501 rv
= callback
.WaitForResult();
11502 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11504 // Indicate that no certificate should be supplied. From the perspective
11505 // of SSLClientCertCache, NULL is just as meaningful as a real
11506 // certificate, so this is the same as supply a
11507 // legitimate-but-unacceptable certificate.
11508 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11509 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11511 // Ensure the certificate was added to the client auth cache before
11512 // allowing the connection to continue restarting.
11513 scoped_refptr
<X509Certificate
> client_cert
;
11514 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11515 HostPortPair("www.example.com", 443), &client_cert
));
11516 ASSERT_EQ(NULL
, client_cert
.get());
11518 // Restart the handshake. This will consume ssl_data2, which fails, and
11519 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11520 // The result code is checked against what ssl_data4 should return.
11521 rv
= callback
.WaitForResult();
11522 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11524 // Ensure that the client certificate is removed from the cache on a
11525 // handshake failure.
11526 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11527 HostPortPair("www.example.com", 443), &client_cert
));
11530 // Ensure that a client certificate is removed from the SSL client auth
11532 // 1) No proxy is involved.
11533 // 2) TLS False Start is enabled.
11534 // 3) The initial TLS handshake requests a client certificate.
11535 // 4) The client supplies an invalid/unacceptable certificate.
11536 TEST_P(HttpNetworkTransactionTest
,
11537 ClientAuthCertCache_Direct_FalseStart
) {
11538 HttpRequestInfo request_info
;
11539 request_info
.url
= GURL("https://www.example.com/");
11540 request_info
.method
= "GET";
11541 request_info
.load_flags
= LOAD_NORMAL
;
11543 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11544 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11546 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11547 // return successfully after reading up to the peer's Certificate message.
11548 // This is to allow the caller to call SSLClientSocket::Write(), which can
11549 // enqueue application data to be sent in the same packet as the
11550 // ChangeCipherSpec and Finished messages.
11551 // The actual handshake will be finished when SSLClientSocket::Read() is
11552 // called, which expects to process the peer's ChangeCipherSpec and
11553 // Finished messages. If there was an error negotiating with the peer,
11554 // such as due to the peer requiring a client certificate when none was
11555 // supplied, the alert sent by the peer won't be processed until Read() is
11558 // Like the non-False Start case, when a client certificate is requested by
11559 // the peer, the handshake is aborted during the Connect() call.
11560 // [ssl_]data1 represents the initial SSL handshake with the peer.
11561 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11562 ssl_data1
.cert_request_info
= cert_request
.get();
11563 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11564 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11565 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11567 // When a client certificate is supplied, Connect() will not be aborted
11568 // when the peer requests the certificate. Instead, the handshake will
11569 // artificially succeed, allowing the caller to write the HTTP request to
11570 // the socket. The handshake messages are not processed until Read() is
11571 // called, which then detects that the handshake was aborted, due to the
11572 // peer sending a handshake_failure because it requires a client
11574 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11575 ssl_data2
.cert_request_info
= cert_request
.get();
11576 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11577 MockRead data2_reads
[] = {
11578 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11580 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11581 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11583 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11584 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11585 // TLSv1. It has the same behaviour as [ssl_]data2.
11586 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11587 ssl_data3
.cert_request_info
= cert_request
.get();
11588 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11589 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11590 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11592 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11593 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11594 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11595 ssl_data4
.cert_request_info
= cert_request
.get();
11596 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11597 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11598 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11600 // Need one more if TLSv1.2 is enabled.
11601 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11602 ssl_data5
.cert_request_info
= cert_request
.get();
11603 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11604 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11605 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11607 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11608 scoped_ptr
<HttpTransaction
> trans(
11609 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11611 // Begin the initial SSL handshake.
11612 TestCompletionCallback callback
;
11613 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11614 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11616 // Complete the SSL handshake, which should abort due to requiring a
11617 // client certificate.
11618 rv
= callback
.WaitForResult();
11619 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11621 // Indicate that no certificate should be supplied. From the perspective
11622 // of SSLClientCertCache, NULL is just as meaningful as a real
11623 // certificate, so this is the same as supply a
11624 // legitimate-but-unacceptable certificate.
11625 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11626 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11628 // Ensure the certificate was added to the client auth cache before
11629 // allowing the connection to continue restarting.
11630 scoped_refptr
<X509Certificate
> client_cert
;
11631 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11632 HostPortPair("www.example.com", 443), &client_cert
));
11633 ASSERT_EQ(NULL
, client_cert
.get());
11635 // Restart the handshake. This will consume ssl_data2, which fails, and
11636 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11637 // The result code is checked against what ssl_data4 should return.
11638 rv
= callback
.WaitForResult();
11639 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11641 // Ensure that the client certificate is removed from the cache on a
11642 // handshake failure.
11643 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11644 HostPortPair("www.example.com", 443), &client_cert
));
11647 // Ensure that a client certificate is removed from the SSL client auth
11649 // 1) An HTTPS proxy is involved.
11650 // 3) The HTTPS proxy requests a client certificate.
11651 // 4) The client supplies an invalid/unacceptable certificate for the
11653 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11654 // then for connecting to an HTTP endpoint.
11655 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11656 session_deps_
.proxy_service
.reset(
11657 ProxyService::CreateFixed("https://proxy:70"));
11658 BoundTestNetLog log
;
11659 session_deps_
.net_log
= log
.bound().net_log();
11661 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11662 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11664 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11665 // [ssl_]data[1-3]. Rather than represending the endpoint
11666 // (www.example.com:443), they represent failures with the HTTPS proxy
11668 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11669 ssl_data1
.cert_request_info
= cert_request
.get();
11670 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11671 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11672 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11674 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11675 ssl_data2
.cert_request_info
= cert_request
.get();
11676 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11677 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11678 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11680 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11682 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11683 ssl_data3
.cert_request_info
= cert_request
.get();
11684 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11685 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11686 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11689 HttpRequestInfo requests
[2];
11690 requests
[0].url
= GURL("https://www.example.com/");
11691 requests
[0].method
= "GET";
11692 requests
[0].load_flags
= LOAD_NORMAL
;
11694 requests
[1].url
= GURL("http://www.example.com/");
11695 requests
[1].method
= "GET";
11696 requests
[1].load_flags
= LOAD_NORMAL
;
11698 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11699 session_deps_
.socket_factory
->ResetNextMockIndexes();
11700 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11701 scoped_ptr
<HttpNetworkTransaction
> trans(
11702 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11704 // Begin the SSL handshake with the proxy.
11705 TestCompletionCallback callback
;
11706 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11707 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11709 // Complete the SSL handshake, which should abort due to requiring a
11710 // client certificate.
11711 rv
= callback
.WaitForResult();
11712 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11714 // Indicate that no certificate should be supplied. From the perspective
11715 // of SSLClientCertCache, NULL is just as meaningful as a real
11716 // certificate, so this is the same as supply a
11717 // legitimate-but-unacceptable certificate.
11718 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11719 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11721 // Ensure the certificate was added to the client auth cache before
11722 // allowing the connection to continue restarting.
11723 scoped_refptr
<X509Certificate
> client_cert
;
11724 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11725 HostPortPair("proxy", 70), &client_cert
));
11726 ASSERT_EQ(NULL
, client_cert
.get());
11727 // Ensure the certificate was NOT cached for the endpoint. This only
11728 // applies to HTTPS requests, but is fine to check for HTTP requests.
11729 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11730 HostPortPair("www.example.com", 443), &client_cert
));
11732 // Restart the handshake. This will consume ssl_data2, which fails, and
11733 // then consume ssl_data3, which should also fail. The result code is
11734 // checked against what ssl_data3 should return.
11735 rv
= callback
.WaitForResult();
11736 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11738 // Now that the new handshake has failed, ensure that the client
11739 // certificate was removed from the client auth cache.
11740 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11741 HostPortPair("proxy", 70), &client_cert
));
11742 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11743 HostPortPair("www.example.com", 443), &client_cert
));
11747 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPooling
) {
11748 session_deps_
.use_alternative_services
= true;
11749 session_deps_
.next_protos
= SpdyNextProtos();
11751 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11752 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11753 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11754 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11755 pool_peer
.DisableDomainAuthenticationVerification();
11757 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11758 ssl
.SetNextProto(GetParam());
11759 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11761 scoped_ptr
<SpdyFrame
> host1_req(
11762 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11763 scoped_ptr
<SpdyFrame
> host2_req(
11764 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11765 MockWrite spdy_writes
[] = {
11766 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11768 scoped_ptr
<SpdyFrame
> host1_resp(
11769 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11770 scoped_ptr
<SpdyFrame
> host1_resp_body(
11771 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11772 scoped_ptr
<SpdyFrame
> host2_resp(
11773 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11774 scoped_ptr
<SpdyFrame
> host2_resp_body(
11775 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11776 MockRead spdy_reads
[] = {
11777 CreateMockRead(*host1_resp
, 1),
11778 CreateMockRead(*host1_resp_body
, 2),
11779 CreateMockRead(*host2_resp
, 4),
11780 CreateMockRead(*host2_resp_body
, 5),
11781 MockRead(ASYNC
, 0, 6),
11784 IPAddressNumber ip
;
11785 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11786 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11787 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11788 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11789 spdy_writes
, arraysize(spdy_writes
));
11790 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11792 TestCompletionCallback callback
;
11793 HttpRequestInfo request1
;
11794 request1
.method
= "GET";
11795 request1
.url
= GURL("https://www.example.org/");
11796 request1
.load_flags
= 0;
11797 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11799 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11800 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11801 EXPECT_EQ(OK
, callback
.WaitForResult());
11803 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11804 ASSERT_TRUE(response
!= NULL
);
11805 ASSERT_TRUE(response
->headers
.get() != NULL
);
11806 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11808 std::string response_data
;
11809 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11810 EXPECT_EQ("hello!", response_data
);
11812 // Preload www.gmail.com into HostCache.
11813 HostPortPair
host_port("www.gmail.com", 443);
11814 HostResolver::RequestInfo
resolve_info(host_port
);
11815 AddressList ignored
;
11816 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11819 callback
.callback(),
11822 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11823 rv
= callback
.WaitForResult();
11826 HttpRequestInfo request2
;
11827 request2
.method
= "GET";
11828 request2
.url
= GURL("https://www.gmail.com/");
11829 request2
.load_flags
= 0;
11830 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11832 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11833 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11834 EXPECT_EQ(OK
, callback
.WaitForResult());
11836 response
= trans2
.GetResponseInfo();
11837 ASSERT_TRUE(response
!= NULL
);
11838 ASSERT_TRUE(response
->headers
.get() != NULL
);
11839 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11840 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11841 EXPECT_TRUE(response
->was_npn_negotiated
);
11842 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11843 EXPECT_EQ("hello!", response_data
);
11846 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11847 session_deps_
.use_alternative_services
= true;
11848 session_deps_
.next_protos
= SpdyNextProtos();
11850 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11851 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11852 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11853 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11854 pool_peer
.DisableDomainAuthenticationVerification();
11856 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11857 ssl
.SetNextProto(GetParam());
11858 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11860 scoped_ptr
<SpdyFrame
> host1_req(
11861 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11862 scoped_ptr
<SpdyFrame
> host2_req(
11863 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11864 MockWrite spdy_writes
[] = {
11865 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11867 scoped_ptr
<SpdyFrame
> host1_resp(
11868 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11869 scoped_ptr
<SpdyFrame
> host1_resp_body(
11870 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11871 scoped_ptr
<SpdyFrame
> host2_resp(
11872 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11873 scoped_ptr
<SpdyFrame
> host2_resp_body(
11874 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11875 MockRead spdy_reads
[] = {
11876 CreateMockRead(*host1_resp
, 1),
11877 CreateMockRead(*host1_resp_body
, 2),
11878 CreateMockRead(*host2_resp
, 4),
11879 CreateMockRead(*host2_resp_body
, 5),
11880 MockRead(ASYNC
, 0, 6),
11883 IPAddressNumber ip
;
11884 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11885 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11886 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11887 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11888 spdy_writes
, arraysize(spdy_writes
));
11889 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11891 TestCompletionCallback callback
;
11892 HttpRequestInfo request1
;
11893 request1
.method
= "GET";
11894 request1
.url
= GURL("https://www.example.org/");
11895 request1
.load_flags
= 0;
11896 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11898 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11899 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11900 EXPECT_EQ(OK
, callback
.WaitForResult());
11902 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11903 ASSERT_TRUE(response
!= NULL
);
11904 ASSERT_TRUE(response
->headers
.get() != NULL
);
11905 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11907 std::string response_data
;
11908 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11909 EXPECT_EQ("hello!", response_data
);
11911 HttpRequestInfo request2
;
11912 request2
.method
= "GET";
11913 request2
.url
= GURL("https://www.gmail.com/");
11914 request2
.load_flags
= 0;
11915 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11917 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11918 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11919 EXPECT_EQ(OK
, callback
.WaitForResult());
11921 response
= trans2
.GetResponseInfo();
11922 ASSERT_TRUE(response
!= NULL
);
11923 ASSERT_TRUE(response
->headers
.get() != NULL
);
11924 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11925 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11926 EXPECT_TRUE(response
->was_npn_negotiated
);
11927 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11928 EXPECT_EQ("hello!", response_data
);
11931 class OneTimeCachingHostResolver
: public HostResolver
{
11933 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11934 : host_port_(host_port
) {}
11935 ~OneTimeCachingHostResolver() override
{}
11937 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11939 // HostResolver methods:
11940 int Resolve(const RequestInfo
& info
,
11941 RequestPriority priority
,
11942 AddressList
* addresses
,
11943 const CompletionCallback
& callback
,
11944 RequestHandle
* out_req
,
11945 const BoundNetLog
& net_log
) override
{
11946 return host_resolver_
.Resolve(
11947 info
, priority
, addresses
, callback
, out_req
, net_log
);
11950 int ResolveFromCache(const RequestInfo
& info
,
11951 AddressList
* addresses
,
11952 const BoundNetLog
& net_log
) override
{
11953 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11954 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11955 host_resolver_
.GetHostCache()->clear();
11959 void CancelRequest(RequestHandle req
) override
{
11960 host_resolver_
.CancelRequest(req
);
11963 MockCachingHostResolver
* GetMockHostResolver() {
11964 return &host_resolver_
;
11968 MockCachingHostResolver host_resolver_
;
11969 const HostPortPair host_port_
;
11972 TEST_P(HttpNetworkTransactionTest
,
11973 UseIPConnectionPoolingWithHostCacheExpiration
) {
11974 session_deps_
.use_alternative_services
= true;
11975 session_deps_
.next_protos
= SpdyNextProtos();
11977 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11978 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11979 HttpNetworkSession::Params params
=
11980 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11981 params
.host_resolver
= &host_resolver
;
11982 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11983 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11984 pool_peer
.DisableDomainAuthenticationVerification();
11986 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11987 ssl
.SetNextProto(GetParam());
11988 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11990 scoped_ptr
<SpdyFrame
> host1_req(
11991 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11992 scoped_ptr
<SpdyFrame
> host2_req(
11993 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11994 MockWrite spdy_writes
[] = {
11995 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11997 scoped_ptr
<SpdyFrame
> host1_resp(
11998 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11999 scoped_ptr
<SpdyFrame
> host1_resp_body(
12000 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12001 scoped_ptr
<SpdyFrame
> host2_resp(
12002 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12003 scoped_ptr
<SpdyFrame
> host2_resp_body(
12004 spdy_util_
.ConstructSpdyBodyFrame(3, true));
12005 MockRead spdy_reads
[] = {
12006 CreateMockRead(*host1_resp
, 1),
12007 CreateMockRead(*host1_resp_body
, 2),
12008 CreateMockRead(*host2_resp
, 4),
12009 CreateMockRead(*host2_resp_body
, 5),
12010 MockRead(ASYNC
, 0, 6),
12013 IPAddressNumber ip
;
12014 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
12015 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12016 MockConnect
connect(ASYNC
, OK
, peer_addr
);
12017 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
12018 spdy_writes
, arraysize(spdy_writes
));
12019 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
12021 TestCompletionCallback callback
;
12022 HttpRequestInfo request1
;
12023 request1
.method
= "GET";
12024 request1
.url
= GURL("https://www.example.org/");
12025 request1
.load_flags
= 0;
12026 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12028 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
12029 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12030 EXPECT_EQ(OK
, callback
.WaitForResult());
12032 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
12033 ASSERT_TRUE(response
!= NULL
);
12034 ASSERT_TRUE(response
->headers
.get() != NULL
);
12035 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12037 std::string response_data
;
12038 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
12039 EXPECT_EQ("hello!", response_data
);
12041 // Preload cache entries into HostCache.
12042 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
12043 AddressList ignored
;
12044 rv
= host_resolver
.Resolve(resolve_info
,
12047 callback
.callback(),
12050 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12051 rv
= callback
.WaitForResult();
12054 HttpRequestInfo request2
;
12055 request2
.method
= "GET";
12056 request2
.url
= GURL("https://www.gmail.com/");
12057 request2
.load_flags
= 0;
12058 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12060 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
12061 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12062 EXPECT_EQ(OK
, callback
.WaitForResult());
12064 response
= trans2
.GetResponseInfo();
12065 ASSERT_TRUE(response
!= NULL
);
12066 ASSERT_TRUE(response
->headers
.get() != NULL
);
12067 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12068 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12069 EXPECT_TRUE(response
->was_npn_negotiated
);
12070 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
12071 EXPECT_EQ("hello!", response_data
);
12074 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
12075 const std::string https_url
= "https://www.example.org:8080/";
12076 const std::string http_url
= "http://www.example.org:8080/";
12078 // SPDY GET for HTTPS URL
12079 scoped_ptr
<SpdyFrame
> req1(
12080 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12082 MockWrite writes1
[] = {
12083 CreateMockWrite(*req1
, 0),
12086 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12087 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12088 MockRead reads1
[] = {
12089 CreateMockRead(*resp1
, 1),
12090 CreateMockRead(*body1
, 2),
12091 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
12094 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
12095 arraysize(writes1
));
12096 MockConnect
connect_data1(ASYNC
, OK
);
12097 data1
.set_connect_data(connect_data1
);
12099 // HTTP GET for the HTTP URL
12100 MockWrite writes2
[] = {
12101 MockWrite(ASYNC
, 0,
12102 "GET / HTTP/1.1\r\n"
12103 "Host: www.example.org:8080\r\n"
12104 "Connection: keep-alive\r\n\r\n"),
12107 MockRead reads2
[] = {
12108 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
12109 MockRead(ASYNC
, 2, "hello"),
12110 MockRead(ASYNC
, OK
, 3),
12113 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12114 arraysize(writes2
));
12116 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12117 ssl
.SetNextProto(GetParam());
12118 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12119 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12120 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12122 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12124 // Start the first transaction to set up the SpdySession
12125 HttpRequestInfo request1
;
12126 request1
.method
= "GET";
12127 request1
.url
= GURL(https_url
);
12128 request1
.load_flags
= 0;
12129 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12130 TestCompletionCallback callback1
;
12131 EXPECT_EQ(ERR_IO_PENDING
,
12132 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12133 base::MessageLoop::current()->RunUntilIdle();
12135 EXPECT_EQ(OK
, callback1
.WaitForResult());
12136 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12138 // Now, start the HTTP request
12139 HttpRequestInfo request2
;
12140 request2
.method
= "GET";
12141 request2
.url
= GURL(http_url
);
12142 request2
.load_flags
= 0;
12143 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12144 TestCompletionCallback callback2
;
12145 EXPECT_EQ(ERR_IO_PENDING
,
12146 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12147 base::MessageLoop::current()->RunUntilIdle();
12149 EXPECT_EQ(OK
, callback2
.WaitForResult());
12150 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12153 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
12155 void Run(bool pooling
, bool valid
) {
12156 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
12158 HostPortPair
alternative("www.example.org", 443);
12160 base::FilePath certs_dir
= GetTestCertsDirectory();
12161 scoped_refptr
<X509Certificate
> cert(
12162 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
12163 ASSERT_TRUE(cert
.get());
12164 bool common_name_fallback_used
;
12166 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
12168 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
12169 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12170 ssl
.SetNextProto(GetParam());
12172 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12174 // If pooling, then start a request to alternative first to create a
12176 std::string url0
= "https://www.example.org:443";
12177 // Second request to origin, which has an alternative service, and could
12178 // open a connection to the alternative host or pool to the existing one.
12179 std::string
url1("https://");
12180 url1
.append(origin
.host());
12181 url1
.append(":443");
12183 scoped_ptr
<SpdyFrame
> req0
;
12184 scoped_ptr
<SpdyFrame
> req1
;
12185 scoped_ptr
<SpdyFrame
> resp0
;
12186 scoped_ptr
<SpdyFrame
> body0
;
12187 scoped_ptr
<SpdyFrame
> resp1
;
12188 scoped_ptr
<SpdyFrame
> body1
;
12189 std::vector
<MockWrite
> writes
;
12190 std::vector
<MockRead
> reads
;
12193 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
12194 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
12196 writes
.push_back(CreateMockWrite(*req0
, 0));
12197 writes
.push_back(CreateMockWrite(*req1
, 3));
12199 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12200 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12201 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12202 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12204 reads
.push_back(CreateMockRead(*resp0
, 1));
12205 reads
.push_back(CreateMockRead(*body0
, 2));
12206 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
12207 reads
.push_back(CreateMockRead(*resp1
, 5));
12208 reads
.push_back(CreateMockRead(*body1
, 6));
12209 reads
.push_back(MockRead(ASYNC
, OK
, 7));
12211 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
12213 writes
.push_back(CreateMockWrite(*req1
, 0));
12215 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12216 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12218 reads
.push_back(CreateMockRead(*resp1
, 1));
12219 reads
.push_back(CreateMockRead(*body1
, 2));
12220 reads
.push_back(MockRead(ASYNC
, OK
, 3));
12223 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
12224 vector_as_array(&writes
), writes
.size());
12225 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12227 // Connection to the origin fails.
12228 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12229 StaticSocketDataProvider data_refused
;
12230 data_refused
.set_connect_data(mock_connect
);
12231 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12233 session_deps_
.use_alternative_services
= true;
12234 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12235 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12236 session
->http_server_properties();
12237 AlternativeService
alternative_service(
12238 AlternateProtocolFromNextProto(GetParam()), alternative
);
12239 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12240 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12243 // First request to alternative.
12245 scoped_ptr
<HttpTransaction
> trans0(
12246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12247 HttpRequestInfo request0
;
12248 request0
.method
= "GET";
12249 request0
.url
= GURL(url0
);
12250 request0
.load_flags
= 0;
12251 TestCompletionCallback callback0
;
12253 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
12254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12255 rv
= callback0
.WaitForResult();
12259 // Second request to origin.
12260 scoped_ptr
<HttpTransaction
> trans1(
12261 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12262 HttpRequestInfo request1
;
12263 request1
.method
= "GET";
12264 request1
.url
= GURL(url1
);
12265 request1
.load_flags
= 0;
12266 TestCompletionCallback callback1
;
12268 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12270 base::MessageLoop::current()->RunUntilIdle();
12271 if (data
.IsReadPaused()) {
12272 data
.CompleteRead();
12274 rv
= callback1
.WaitForResult();
12279 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12281 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
12287 INSTANTIATE_TEST_CASE_P(NextProto
,
12288 AltSvcCertificateVerificationTest
,
12289 testing::Values(kProtoSPDY31
,
12292 // The alternative service host must exhibit a certificate that is valid for the
12293 // origin host. Test that this is enforced when pooling to an existing
12295 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
12299 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
12303 // The alternative service host must exhibit a certificate that is valid for the
12304 // origin host. Test that this is enforced when opening a new connection.
12305 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
12309 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
12313 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12314 // with the alternative server. That connection should not be used.
12315 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
12316 HostPortPair
origin("origin.example.org", 443);
12317 HostPortPair
alternative("alternative.example.org", 443);
12319 // Negotiate HTTP/1.1 with alternative.example.org.
12320 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12321 ssl
.SetNextProto(kProtoHTTP11
);
12322 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12324 // No data should be read from the alternative, because HTTP/1.1 is
12326 StaticSocketDataProvider data
;
12327 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12329 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12330 // negotiated. In order to test this, a failed connection to the origin is
12331 // mocked. This way the request relies on the alternate Job.
12332 StaticSocketDataProvider data_refused
;
12333 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12334 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12336 // Set up alternative service for origin.
12337 session_deps_
.use_alternative_services
= true;
12338 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12339 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12340 session
->http_server_properties();
12341 AlternativeService
alternative_service(
12342 AlternateProtocolFromNextProto(GetParam()), alternative
);
12343 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12344 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12347 scoped_ptr
<HttpTransaction
> trans(
12348 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12349 HttpRequestInfo request
;
12350 request
.method
= "GET";
12351 request
.url
= GURL("https://origin.example.org:443");
12352 request
.load_flags
= 0;
12353 TestCompletionCallback callback
;
12355 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12356 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12357 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12358 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
12361 // A request to a server with an alternative service fires two Jobs: one to the
12362 // origin, and an alternate one to the alternative server. If the former
12363 // succeeds, the request should succeed, even if the latter fails because
12364 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12365 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
12366 HostPortPair
origin("origin.example.org", 443);
12367 HostPortPair
alternative("alternative.example.org", 443);
12369 // Negotiate HTTP/1.1 with alternative.
12370 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
12371 alternative_ssl
.SetNextProto(kProtoHTTP11
);
12372 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
12374 // No data should be read from the alternative, because HTTP/1.1 is
12376 StaticSocketDataProvider data
;
12377 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12379 // Negotiate HTTP/1.1 with origin.
12380 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
12381 origin_ssl
.SetNextProto(kProtoHTTP11
);
12382 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
12384 MockWrite http_writes
[] = {
12386 "GET / HTTP/1.1\r\n"
12387 "Host: origin.example.org\r\n"
12388 "Connection: keep-alive\r\n\r\n"),
12390 "GET /second HTTP/1.1\r\n"
12391 "Host: origin.example.org\r\n"
12392 "Connection: keep-alive\r\n\r\n"),
12395 MockRead http_reads
[] = {
12396 MockRead("HTTP/1.1 200 OK\r\n"),
12397 MockRead("Content-Type: text/html\r\n"),
12398 MockRead("Content-Length: 6\r\n\r\n"),
12399 MockRead("foobar"),
12400 MockRead("HTTP/1.1 200 OK\r\n"),
12401 MockRead("Content-Type: text/html\r\n"),
12402 MockRead("Content-Length: 7\r\n\r\n"),
12403 MockRead("another"),
12405 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12406 http_writes
, arraysize(http_writes
));
12407 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12409 // Set up alternative service for origin.
12410 session_deps_
.use_alternative_services
= true;
12411 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12412 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12413 session
->http_server_properties();
12414 AlternativeService
alternative_service(
12415 AlternateProtocolFromNextProto(GetParam()), alternative
);
12416 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12417 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12420 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12421 HttpRequestInfo request1
;
12422 request1
.method
= "GET";
12423 request1
.url
= GURL("https://origin.example.org:443");
12424 request1
.load_flags
= 0;
12425 TestCompletionCallback callback1
;
12427 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12428 rv
= callback1
.GetResult(rv
);
12431 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12432 ASSERT_TRUE(response1
!= nullptr);
12433 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12434 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12436 std::string response_data1
;
12437 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12438 EXPECT_EQ("foobar", response_data1
);
12440 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12441 // for alternative service.
12443 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12445 // Since |alternative_service| is broken, a second transaction to origin
12446 // should not start an alternate Job. It should pool to existing connection
12448 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12449 HttpRequestInfo request2
;
12450 request2
.method
= "GET";
12451 request2
.url
= GURL("https://origin.example.org:443/second");
12452 request2
.load_flags
= 0;
12453 TestCompletionCallback callback2
;
12455 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12456 rv
= callback2
.GetResult(rv
);
12459 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12460 ASSERT_TRUE(response2
!= nullptr);
12461 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12462 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12464 std::string response_data2
;
12465 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12466 EXPECT_EQ("another", response_data2
);
12469 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12470 // HTTP/1.1 socket open to the alternative server. That socket should not be
12472 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12473 HostPortPair
origin("origin.example.org", 443);
12474 HostPortPair
alternative("alternative.example.org", 443);
12475 std::string origin_url
= "https://origin.example.org:443";
12476 std::string alternative_url
= "https://alternative.example.org:443";
12478 // Negotiate HTTP/1.1 with alternative.example.org.
12479 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12480 ssl
.SetNextProto(kProtoHTTP11
);
12481 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12483 // HTTP/1.1 data for |request1| and |request2|.
12484 MockWrite http_writes
[] = {
12486 "GET / HTTP/1.1\r\n"
12487 "Host: alternative.example.org\r\n"
12488 "Connection: keep-alive\r\n\r\n"),
12490 "GET / HTTP/1.1\r\n"
12491 "Host: alternative.example.org\r\n"
12492 "Connection: keep-alive\r\n\r\n"),
12495 MockRead http_reads
[] = {
12497 "HTTP/1.1 200 OK\r\n"
12498 "Content-Type: text/html; charset=iso-8859-1\r\n"
12499 "Content-Length: 40\r\n\r\n"
12500 "first HTTP/1.1 response from alternative"),
12502 "HTTP/1.1 200 OK\r\n"
12503 "Content-Type: text/html; charset=iso-8859-1\r\n"
12504 "Content-Length: 41\r\n\r\n"
12505 "second HTTP/1.1 response from alternative"),
12507 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12508 http_writes
, arraysize(http_writes
));
12509 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12511 // This test documents that an alternate Job should not pool to an already
12512 // existing HTTP/1.1 connection. In order to test this, a failed connection
12513 // to the origin is mocked. This way |request2| relies on the alternate Job.
12514 StaticSocketDataProvider data_refused
;
12515 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12516 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12518 // Set up alternative service for origin.
12519 session_deps_
.use_alternative_services
= true;
12520 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12521 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12522 session
->http_server_properties();
12523 AlternativeService
alternative_service(
12524 AlternateProtocolFromNextProto(GetParam()), alternative
);
12525 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12526 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12529 // First transaction to alternative to open an HTTP/1.1 socket.
12530 scoped_ptr
<HttpTransaction
> trans1(
12531 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12532 HttpRequestInfo request1
;
12533 request1
.method
= "GET";
12534 request1
.url
= GURL(alternative_url
);
12535 request1
.load_flags
= 0;
12536 TestCompletionCallback callback1
;
12538 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12539 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12540 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12541 ASSERT_TRUE(response1
);
12542 ASSERT_TRUE(response1
->headers
.get());
12543 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12544 EXPECT_TRUE(response1
->was_npn_negotiated
);
12545 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12546 std::string response_data1
;
12547 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12548 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12550 // Request for origin.example.org, which has an alternative service. This
12551 // will start two Jobs: the alternative looks for connections to pool to,
12552 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12553 // open other connections to alternative server. The Job to origin fails, so
12554 // this request fails.
12555 scoped_ptr
<HttpTransaction
> trans2(
12556 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12557 HttpRequestInfo request2
;
12558 request2
.method
= "GET";
12559 request2
.url
= GURL(origin_url
);
12560 request2
.load_flags
= 0;
12561 TestCompletionCallback callback2
;
12563 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12564 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12566 // Another transaction to alternative. This is to test that the HTTP/1.1
12567 // socket is still open and in the pool.
12568 scoped_ptr
<HttpTransaction
> trans3(
12569 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12570 HttpRequestInfo request3
;
12571 request3
.method
= "GET";
12572 request3
.url
= GURL(alternative_url
);
12573 request3
.load_flags
= 0;
12574 TestCompletionCallback callback3
;
12576 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12577 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12578 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12579 ASSERT_TRUE(response3
);
12580 ASSERT_TRUE(response3
->headers
.get());
12581 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12582 EXPECT_TRUE(response3
->was_npn_negotiated
);
12583 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12584 std::string response_data3
;
12585 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12586 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12589 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12590 const std::string https_url
= "https://www.example.org:8080/";
12591 const std::string http_url
= "http://www.example.org:8080/";
12593 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12594 const HostPortPair
host_port_pair("www.example.org", 8080);
12595 scoped_ptr
<SpdyFrame
> connect(
12596 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12597 scoped_ptr
<SpdyFrame
> req1(
12598 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12599 scoped_ptr
<SpdyFrame
> wrapped_req1(
12600 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12602 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12603 SpdyHeaderBlock req2_block
;
12604 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12605 req2_block
[spdy_util_
.GetPathKey()] = "/";
12606 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12607 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12608 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12609 scoped_ptr
<SpdyFrame
> req2(
12610 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12612 MockWrite writes1
[] = {
12613 CreateMockWrite(*connect
, 0),
12614 CreateMockWrite(*wrapped_req1
, 2),
12615 CreateMockWrite(*req2
, 5),
12618 scoped_ptr
<SpdyFrame
> conn_resp(
12619 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12620 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12621 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12622 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12623 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12624 scoped_ptr
<SpdyFrame
> wrapped_body1(
12625 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12626 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12627 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12628 MockRead reads1
[] = {
12629 CreateMockRead(*conn_resp
, 1),
12630 CreateMockRead(*wrapped_resp1
, 3),
12631 CreateMockRead(*wrapped_body1
, 4),
12632 CreateMockRead(*resp2
, 6),
12633 CreateMockRead(*body2
, 7),
12634 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12637 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12638 writes1
, arraysize(writes1
));
12639 MockConnect
connect_data1(ASYNC
, OK
);
12640 data1
.set_connect_data(connect_data1
);
12642 session_deps_
.proxy_service
.reset(
12643 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12645 session_deps_
.net_log
= &log
;
12646 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12647 ssl1
.SetNextProto(GetParam());
12648 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12649 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12650 ssl2
.SetNextProto(GetParam());
12651 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12652 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12654 scoped_refptr
<HttpNetworkSession
> session(
12655 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12657 // Start the first transaction to set up the SpdySession
12658 HttpRequestInfo request1
;
12659 request1
.method
= "GET";
12660 request1
.url
= GURL(https_url
);
12661 request1
.load_flags
= 0;
12662 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12663 TestCompletionCallback callback1
;
12664 EXPECT_EQ(ERR_IO_PENDING
,
12665 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12666 base::MessageLoop::current()->RunUntilIdle();
12669 EXPECT_EQ(OK
, callback1
.WaitForResult());
12670 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12672 LoadTimingInfo load_timing_info1
;
12673 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12674 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12675 CONNECT_TIMING_HAS_SSL_TIMES
);
12677 // Now, start the HTTP request
12678 HttpRequestInfo request2
;
12679 request2
.method
= "GET";
12680 request2
.url
= GURL(http_url
);
12681 request2
.load_flags
= 0;
12682 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12683 TestCompletionCallback callback2
;
12684 EXPECT_EQ(ERR_IO_PENDING
,
12685 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12686 base::MessageLoop::current()->RunUntilIdle();
12689 EXPECT_EQ(OK
, callback2
.WaitForResult());
12690 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12692 LoadTimingInfo load_timing_info2
;
12693 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12694 // The established SPDY sessions is considered reused by the HTTP request.
12695 TestLoadTimingReusedWithPac(load_timing_info2
);
12696 // HTTP requests over a SPDY session should have a different connection
12697 // socket_log_id than requests over a tunnel.
12698 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12701 // Test that in the case where we have a SPDY session to a SPDY proxy
12702 // that we do not pool other origins that resolve to the same IP when
12703 // the certificate does not match the new origin.
12704 // http://crbug.com/134690
12705 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12706 const std::string url1
= "http://www.example.org/";
12707 const std::string url2
= "https://news.example.org/";
12708 const std::string ip_addr
= "1.2.3.4";
12710 // SPDY GET for HTTP URL (through SPDY proxy)
12711 scoped_ptr
<SpdyHeaderBlock
> headers(
12712 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12713 scoped_ptr
<SpdyFrame
> req1(
12714 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12716 MockWrite writes1
[] = {
12717 CreateMockWrite(*req1
, 0),
12720 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12721 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12722 MockRead reads1
[] = {
12723 CreateMockRead(*resp1
, 1),
12724 CreateMockRead(*body1
, 2),
12725 MockRead(ASYNC
, OK
, 3) // EOF
12728 scoped_ptr
<DeterministicSocketData
> data1(
12729 new DeterministicSocketData(reads1
, arraysize(reads1
),
12730 writes1
, arraysize(writes1
)));
12731 IPAddressNumber ip
;
12732 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12733 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12734 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12735 data1
->set_connect_data(connect_data1
);
12737 // SPDY GET for HTTPS URL (direct)
12738 scoped_ptr
<SpdyFrame
> req2(
12739 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12741 MockWrite writes2
[] = {
12742 CreateMockWrite(*req2
, 0),
12745 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12746 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12747 MockRead reads2
[] = {
12748 CreateMockRead(*resp2
, 1),
12749 CreateMockRead(*body2
, 2),
12750 MockRead(ASYNC
, OK
, 3) // EOF
12753 scoped_ptr
<DeterministicSocketData
> data2(
12754 new DeterministicSocketData(reads2
, arraysize(reads2
),
12755 writes2
, arraysize(writes2
)));
12756 MockConnect
connect_data2(ASYNC
, OK
);
12757 data2
->set_connect_data(connect_data2
);
12759 // Set up a proxy config that sends HTTP requests to a proxy, and
12760 // all others direct.
12761 ProxyConfig proxy_config
;
12762 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12763 session_deps_
.proxy_service
.reset(new ProxyService(
12764 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12766 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12767 ssl1
.SetNextProto(GetParam());
12768 // Load a valid cert. Note, that this does not need to
12769 // be valid for proxy because the MockSSLClientSocket does
12770 // not actually verify it. But SpdySession will use this
12771 // to see if it is valid for the new origin
12772 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12773 ASSERT_TRUE(ssl1
.cert
.get());
12774 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12775 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12778 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12779 ssl2
.SetNextProto(GetParam());
12780 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12781 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12784 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12785 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12786 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12788 scoped_refptr
<HttpNetworkSession
> session(
12789 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12791 // Start the first transaction to set up the SpdySession
12792 HttpRequestInfo request1
;
12793 request1
.method
= "GET";
12794 request1
.url
= GURL(url1
);
12795 request1
.load_flags
= 0;
12796 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12797 TestCompletionCallback callback1
;
12798 ASSERT_EQ(ERR_IO_PENDING
,
12799 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12802 ASSERT_TRUE(callback1
.have_result());
12803 EXPECT_EQ(OK
, callback1
.WaitForResult());
12804 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12806 // Now, start the HTTP request
12807 HttpRequestInfo request2
;
12808 request2
.method
= "GET";
12809 request2
.url
= GURL(url2
);
12810 request2
.load_flags
= 0;
12811 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12812 TestCompletionCallback callback2
;
12813 EXPECT_EQ(ERR_IO_PENDING
,
12814 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12815 base::MessageLoop::current()->RunUntilIdle();
12818 ASSERT_TRUE(callback2
.have_result());
12819 EXPECT_EQ(OK
, callback2
.WaitForResult());
12820 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12823 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12824 // error) in SPDY session, removes the socket from pool and closes the SPDY
12825 // session. Verify that new url's from the same HttpNetworkSession (and a new
12826 // SpdySession) do work. http://crbug.com/224701
12827 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12828 const std::string https_url
= "https://www.example.org/";
12830 MockRead reads1
[] = {
12831 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12834 SequencedSocketData
data1(reads1
, arraysize(reads1
), NULL
, 0);
12836 scoped_ptr
<SpdyFrame
> req2(
12837 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12838 MockWrite writes2
[] = {
12839 CreateMockWrite(*req2
, 0),
12842 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12843 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12844 MockRead reads2
[] = {
12845 CreateMockRead(*resp2
, 1),
12846 CreateMockRead(*body2
, 2),
12847 MockRead(ASYNC
, OK
, 3) // EOF
12850 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12851 arraysize(writes2
));
12853 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12854 ssl1
.SetNextProto(GetParam());
12855 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12856 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12858 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12859 ssl2
.SetNextProto(GetParam());
12860 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12861 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12863 scoped_refptr
<HttpNetworkSession
> session(
12864 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
12866 // Start the first transaction to set up the SpdySession and verify that
12867 // connection was closed.
12868 HttpRequestInfo request1
;
12869 request1
.method
= "GET";
12870 request1
.url
= GURL(https_url
);
12871 request1
.load_flags
= 0;
12872 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12873 TestCompletionCallback callback1
;
12874 EXPECT_EQ(ERR_IO_PENDING
,
12875 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12876 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12878 // Now, start the second request and make sure it succeeds.
12879 HttpRequestInfo request2
;
12880 request2
.method
= "GET";
12881 request2
.url
= GURL(https_url
);
12882 request2
.load_flags
= 0;
12883 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12884 TestCompletionCallback callback2
;
12885 EXPECT_EQ(ERR_IO_PENDING
,
12886 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12888 ASSERT_EQ(OK
, callback2
.WaitForResult());
12889 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12892 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12893 session_deps_
.next_protos
= SpdyNextProtos();
12894 ClientSocketPoolManager::set_max_sockets_per_group(
12895 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12896 ClientSocketPoolManager::set_max_sockets_per_pool(
12897 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12899 // Use two different hosts with different IPs so they don't get pooled.
12900 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12901 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12902 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12904 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12905 ssl1
.SetNextProto(GetParam());
12906 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12907 ssl2
.SetNextProto(GetParam());
12908 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12909 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12911 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12912 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12913 MockWrite spdy1_writes
[] = {
12914 CreateMockWrite(*host1_req
, 0),
12916 scoped_ptr
<SpdyFrame
> host1_resp(
12917 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12918 scoped_ptr
<SpdyFrame
> host1_resp_body(
12919 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12920 MockRead spdy1_reads
[] = {
12921 CreateMockRead(*host1_resp
, 1),
12922 CreateMockRead(*host1_resp_body
, 2),
12923 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12926 scoped_ptr
<SequencedSocketData
> spdy1_data(
12927 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12928 arraysize(spdy1_writes
)));
12929 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12931 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12932 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12933 MockWrite spdy2_writes
[] = {
12934 CreateMockWrite(*host2_req
, 0),
12936 scoped_ptr
<SpdyFrame
> host2_resp(
12937 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12938 scoped_ptr
<SpdyFrame
> host2_resp_body(
12939 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12940 MockRead spdy2_reads
[] = {
12941 CreateMockRead(*host2_resp
, 1),
12942 CreateMockRead(*host2_resp_body
, 2),
12943 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12946 scoped_ptr
<SequencedSocketData
> spdy2_data(
12947 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12948 arraysize(spdy2_writes
)));
12949 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12951 MockWrite http_write
[] = {
12952 MockWrite("GET / HTTP/1.1\r\n"
12953 "Host: www.a.com\r\n"
12954 "Connection: keep-alive\r\n\r\n"),
12957 MockRead http_read
[] = {
12958 MockRead("HTTP/1.1 200 OK\r\n"),
12959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12960 MockRead("Content-Length: 6\r\n\r\n"),
12961 MockRead("hello!"),
12963 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12964 http_write
, arraysize(http_write
));
12965 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12967 HostPortPair
host_port_pair_a("www.a.com", 443);
12968 SpdySessionKey
spdy_session_key_a(
12969 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12971 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12973 TestCompletionCallback callback
;
12974 HttpRequestInfo request1
;
12975 request1
.method
= "GET";
12976 request1
.url
= GURL("https://www.a.com/");
12977 request1
.load_flags
= 0;
12978 scoped_ptr
<HttpNetworkTransaction
> trans(
12979 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12981 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12982 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12983 EXPECT_EQ(OK
, callback
.WaitForResult());
12985 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12986 ASSERT_TRUE(response
!= NULL
);
12987 ASSERT_TRUE(response
->headers
.get() != NULL
);
12988 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12989 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12990 EXPECT_TRUE(response
->was_npn_negotiated
);
12992 std::string response_data
;
12993 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12994 EXPECT_EQ("hello!", response_data
);
12997 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12999 HostPortPair
host_port_pair_b("www.b.com", 443);
13000 SpdySessionKey
spdy_session_key_b(
13001 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
13003 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13004 HttpRequestInfo request2
;
13005 request2
.method
= "GET";
13006 request2
.url
= GURL("https://www.b.com/");
13007 request2
.load_flags
= 0;
13008 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13010 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
13011 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13012 EXPECT_EQ(OK
, callback
.WaitForResult());
13014 response
= trans
->GetResponseInfo();
13015 ASSERT_TRUE(response
!= NULL
);
13016 ASSERT_TRUE(response
->headers
.get() != NULL
);
13017 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
13018 EXPECT_TRUE(response
->was_fetched_via_spdy
);
13019 EXPECT_TRUE(response
->was_npn_negotiated
);
13020 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
13021 EXPECT_EQ("hello!", response_data
);
13023 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13025 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13027 HostPortPair
host_port_pair_a1("www.a.com", 80);
13028 SpdySessionKey
spdy_session_key_a1(
13029 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
13031 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
13032 HttpRequestInfo request3
;
13033 request3
.method
= "GET";
13034 request3
.url
= GURL("http://www.a.com/");
13035 request3
.load_flags
= 0;
13036 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13038 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
13039 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13040 EXPECT_EQ(OK
, callback
.WaitForResult());
13042 response
= trans
->GetResponseInfo();
13043 ASSERT_TRUE(response
!= NULL
);
13044 ASSERT_TRUE(response
->headers
.get() != NULL
);
13045 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
13046 EXPECT_FALSE(response
->was_fetched_via_spdy
);
13047 EXPECT_FALSE(response
->was_npn_negotiated
);
13048 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
13049 EXPECT_EQ("hello!", response_data
);
13051 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
13053 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
13056 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
13057 HttpRequestInfo request
;
13058 request
.method
= "GET";
13059 request
.url
= GURL("http://www.example.org/");
13060 request
.load_flags
= 0;
13062 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13063 scoped_ptr
<HttpTransaction
> trans(
13064 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13066 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
13067 StaticSocketDataProvider data
;
13068 data
.set_connect_data(mock_connect
);
13069 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13071 TestCompletionCallback callback
;
13073 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13074 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13076 rv
= callback
.WaitForResult();
13077 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
13079 // We don't care whether this succeeds or fails, but it shouldn't crash.
13080 HttpRequestHeaders request_headers
;
13081 trans
->GetFullRequestHeaders(&request_headers
);
13083 ConnectionAttempts attempts
;
13084 trans
->GetConnectionAttempts(&attempts
);
13085 ASSERT_EQ(1u, attempts
.size());
13086 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
13089 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
13090 HttpRequestInfo request
;
13091 request
.method
= "GET";
13092 request
.url
= GURL("http://www.example.org/");
13093 request
.load_flags
= 0;
13095 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13096 scoped_ptr
<HttpTransaction
> trans(
13097 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13099 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
13100 StaticSocketDataProvider data
;
13101 data
.set_connect_data(mock_connect
);
13102 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13104 TestCompletionCallback callback
;
13106 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13107 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13109 rv
= callback
.WaitForResult();
13110 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
13112 // We don't care whether this succeeds or fails, but it shouldn't crash.
13113 HttpRequestHeaders request_headers
;
13114 trans
->GetFullRequestHeaders(&request_headers
);
13116 ConnectionAttempts attempts
;
13117 trans
->GetConnectionAttempts(&attempts
);
13118 ASSERT_EQ(1u, attempts
.size());
13119 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
13122 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
13123 HttpRequestInfo request
;
13124 request
.method
= "GET";
13125 request
.url
= GURL("http://www.example.org/");
13126 request
.load_flags
= 0;
13128 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13129 scoped_ptr
<HttpTransaction
> trans(
13130 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13132 MockWrite data_writes
[] = {
13133 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13135 MockRead data_reads
[] = {
13136 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
13139 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13140 data_writes
, arraysize(data_writes
));
13141 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13143 TestCompletionCallback callback
;
13145 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13148 rv
= callback
.WaitForResult();
13149 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13151 HttpRequestHeaders request_headers
;
13152 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13153 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13156 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
13157 HttpRequestInfo request
;
13158 request
.method
= "GET";
13159 request
.url
= GURL("http://www.example.org/");
13160 request
.load_flags
= 0;
13162 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13163 scoped_ptr
<HttpTransaction
> trans(
13164 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13166 MockWrite data_writes
[] = {
13167 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
13169 MockRead data_reads
[] = {
13170 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
13173 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13174 data_writes
, arraysize(data_writes
));
13175 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13177 TestCompletionCallback callback
;
13179 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13182 rv
= callback
.WaitForResult();
13183 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13185 HttpRequestHeaders request_headers
;
13186 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13187 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13190 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
13191 HttpRequestInfo request
;
13192 request
.method
= "GET";
13193 request
.url
= GURL("http://www.example.org/");
13194 request
.load_flags
= 0;
13196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13197 scoped_ptr
<HttpTransaction
> trans(
13198 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13200 MockWrite data_writes
[] = {
13202 "GET / HTTP/1.1\r\n"
13203 "Host: www.example.org\r\n"
13204 "Connection: keep-alive\r\n\r\n"),
13206 MockRead data_reads
[] = {
13207 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13210 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13211 data_writes
, arraysize(data_writes
));
13212 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13214 TestCompletionCallback callback
;
13216 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13217 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13219 rv
= callback
.WaitForResult();
13220 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13222 HttpRequestHeaders request_headers
;
13223 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13224 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13227 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
13228 HttpRequestInfo request
;
13229 request
.method
= "GET";
13230 request
.url
= GURL("http://www.example.org/");
13231 request
.load_flags
= 0;
13233 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13234 scoped_ptr
<HttpTransaction
> trans(
13235 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13237 MockWrite data_writes
[] = {
13239 "GET / HTTP/1.1\r\n"
13240 "Host: www.example.org\r\n"
13241 "Connection: keep-alive\r\n\r\n"),
13243 MockRead data_reads
[] = {
13244 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
13247 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13248 data_writes
, arraysize(data_writes
));
13249 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13251 TestCompletionCallback callback
;
13253 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13256 rv
= callback
.WaitForResult();
13257 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13259 HttpRequestHeaders request_headers
;
13260 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13261 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13264 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
13265 HttpRequestInfo request
;
13266 request
.method
= "GET";
13267 request
.url
= GURL("http://www.example.org/");
13268 request
.load_flags
= 0;
13269 request
.extra_headers
.SetHeader("X-Foo", "bar");
13271 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13272 scoped_ptr
<HttpTransaction
> trans(
13273 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13275 MockWrite data_writes
[] = {
13277 "GET / HTTP/1.1\r\n"
13278 "Host: www.example.org\r\n"
13279 "Connection: keep-alive\r\n"
13280 "X-Foo: bar\r\n\r\n"),
13282 MockRead data_reads
[] = {
13283 MockRead("HTTP/1.1 200 OK\r\n"
13284 "Content-Length: 5\r\n\r\n"
13286 MockRead(ASYNC
, ERR_UNEXPECTED
),
13289 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13290 data_writes
, arraysize(data_writes
));
13291 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13293 TestCompletionCallback callback
;
13295 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13296 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13298 rv
= callback
.WaitForResult();
13301 HttpRequestHeaders request_headers
;
13302 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13304 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
13305 EXPECT_EQ("bar", foo
);
13310 // Fake HttpStream that simply records calls to SetPriority().
13311 class FakeStream
: public HttpStream
,
13312 public base::SupportsWeakPtr
<FakeStream
> {
13314 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
13315 ~FakeStream() override
{}
13317 RequestPriority
priority() const { return priority_
; }
13319 int InitializeStream(const HttpRequestInfo
* request_info
,
13320 RequestPriority priority
,
13321 const BoundNetLog
& net_log
,
13322 const CompletionCallback
& callback
) override
{
13323 return ERR_IO_PENDING
;
13326 int SendRequest(const HttpRequestHeaders
& request_headers
,
13327 HttpResponseInfo
* response
,
13328 const CompletionCallback
& callback
) override
{
13330 return ERR_UNEXPECTED
;
13333 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13335 return ERR_UNEXPECTED
;
13338 int ReadResponseBody(IOBuffer
* buf
,
13340 const CompletionCallback
& callback
) override
{
13342 return ERR_UNEXPECTED
;
13345 void Close(bool not_reusable
) override
{}
13347 bool IsResponseBodyComplete() const override
{
13352 bool CanFindEndOfResponse() const override
{ return false; }
13354 bool IsConnectionReused() const override
{
13359 void SetConnectionReused() override
{ ADD_FAILURE(); }
13361 bool IsConnectionReusable() const override
{
13366 int64
GetTotalReceivedBytes() const override
{
13371 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13376 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
13378 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13382 bool IsSpdyHttpStream() const override
{
13387 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
13389 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13391 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
13393 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
13396 RequestPriority priority_
;
13398 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
13401 // Fake HttpStreamRequest that simply records calls to SetPriority()
13402 // and vends FakeStreams with its current priority.
13403 class FakeStreamRequest
: public HttpStreamRequest
,
13404 public base::SupportsWeakPtr
<FakeStreamRequest
> {
13406 FakeStreamRequest(RequestPriority priority
,
13407 HttpStreamRequest::Delegate
* delegate
)
13408 : priority_(priority
),
13409 delegate_(delegate
),
13410 websocket_stream_create_helper_(NULL
) {}
13412 FakeStreamRequest(RequestPriority priority
,
13413 HttpStreamRequest::Delegate
* delegate
,
13414 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13415 : priority_(priority
),
13416 delegate_(delegate
),
13417 websocket_stream_create_helper_(create_helper
) {}
13419 ~FakeStreamRequest() override
{}
13421 RequestPriority
priority() const { return priority_
; }
13423 const WebSocketHandshakeStreamBase::CreateHelper
*
13424 websocket_stream_create_helper() const {
13425 return websocket_stream_create_helper_
;
13428 // Create a new FakeStream and pass it to the request's
13429 // delegate. Returns a weak pointer to the FakeStream.
13430 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13431 FakeStream
* fake_stream
= new FakeStream(priority_
);
13432 // Do this before calling OnStreamReady() as OnStreamReady() may
13433 // immediately delete |fake_stream|.
13434 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13435 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13436 return weak_stream
;
13439 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13441 return ERR_UNEXPECTED
;
13444 LoadState
GetLoadState() const override
{
13446 return LoadState();
13449 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13451 bool was_npn_negotiated() const override
{ return false; }
13453 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13455 bool using_spdy() const override
{ return false; }
13457 const ConnectionAttempts
& connection_attempts() const override
{
13458 static ConnectionAttempts no_attempts
;
13459 return no_attempts
;
13463 RequestPriority priority_
;
13464 HttpStreamRequest::Delegate
* const delegate_
;
13465 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13467 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13470 // Fake HttpStreamFactory that vends FakeStreamRequests.
13471 class FakeStreamFactory
: public HttpStreamFactory
{
13473 FakeStreamFactory() {}
13474 ~FakeStreamFactory() override
{}
13476 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13477 // RequestStream() (which may be NULL if it was destroyed already).
13478 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13479 return last_stream_request_
;
13482 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13483 RequestPriority priority
,
13484 const SSLConfig
& server_ssl_config
,
13485 const SSLConfig
& proxy_ssl_config
,
13486 HttpStreamRequest::Delegate
* delegate
,
13487 const BoundNetLog
& net_log
) override
{
13488 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13489 last_stream_request_
= fake_request
->AsWeakPtr();
13490 return fake_request
;
13493 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13494 const HttpRequestInfo
& info
,
13495 RequestPriority priority
,
13496 const SSLConfig
& server_ssl_config
,
13497 const SSLConfig
& proxy_ssl_config
,
13498 HttpStreamRequest::Delegate
* delegate
,
13499 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13500 const BoundNetLog
& net_log
) override
{
13501 FakeStreamRequest
* fake_request
=
13502 new FakeStreamRequest(priority
, delegate
, create_helper
);
13503 last_stream_request_
= fake_request
->AsWeakPtr();
13504 return fake_request
;
13507 void PreconnectStreams(int num_streams
,
13508 const HttpRequestInfo
& info
,
13509 const SSLConfig
& server_ssl_config
,
13510 const SSLConfig
& proxy_ssl_config
) override
{
13514 const HostMappingRules
* GetHostMappingRules() const override
{
13520 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13522 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13525 // TODO(ricea): Maybe unify this with the one in
13526 // url_request_http_job_unittest.cc ?
13527 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13529 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13531 : state_(connection
.release(), using_proxy
) {}
13533 // Fake implementation of HttpStreamBase methods.
13534 // This ends up being quite "real" because this object has to really send data
13535 // on the mock socket. It might be easier to use the real implementation, but
13536 // the fact that the WebSocket code is not compiled on iOS makes that
13538 int InitializeStream(const HttpRequestInfo
* request_info
,
13539 RequestPriority priority
,
13540 const BoundNetLog
& net_log
,
13541 const CompletionCallback
& callback
) override
{
13542 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13546 int SendRequest(const HttpRequestHeaders
& request_headers
,
13547 HttpResponseInfo
* response
,
13548 const CompletionCallback
& callback
) override
{
13549 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13550 response
, callback
);
13553 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13554 return parser()->ReadResponseHeaders(callback
);
13557 int ReadResponseBody(IOBuffer
* buf
,
13559 const CompletionCallback
& callback
) override
{
13561 return ERR_IO_PENDING
;
13564 void Close(bool not_reusable
) override
{
13566 parser()->Close(true);
13569 bool IsResponseBodyComplete() const override
{
13574 bool CanFindEndOfResponse() const override
{
13575 return parser()->CanFindEndOfResponse();
13578 bool IsConnectionReused() const override
{
13582 void SetConnectionReused() override
{ NOTREACHED(); }
13584 bool IsConnectionReusable() const override
{
13589 int64
GetTotalReceivedBytes() const override
{
13594 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13599 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13601 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13605 bool IsSpdyHttpStream() const override
{
13610 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13612 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13614 UploadProgress
GetUploadProgress() const override
{
13616 return UploadProgress();
13619 HttpStream
* RenewStreamForAuth() override
{
13624 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13625 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13627 return scoped_ptr
<WebSocketStream
>();
13631 HttpStreamParser
* parser() const { return state_
.parser(); }
13632 HttpBasicState state_
;
13634 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13637 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13639 class FakeWebSocketStreamCreateHelper
:
13640 public WebSocketHandshakeStreamBase::CreateHelper
{
13642 WebSocketHandshakeStreamBase
* CreateBasicStream(
13643 scoped_ptr
<ClientSocketHandle
> connection
,
13644 bool using_proxy
) override
{
13645 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13649 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13650 const base::WeakPtr
<SpdySession
>& session
,
13651 bool use_relative_url
) override
{
13656 ~FakeWebSocketStreamCreateHelper() override
{}
13658 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13660 return scoped_ptr
<WebSocketStream
>();
13666 // Make sure that HttpNetworkTransaction passes on its priority to its
13667 // stream request on start.
13668 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13669 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13670 HttpNetworkSessionPeer
peer(session
);
13671 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13672 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13674 HttpNetworkTransaction
trans(LOW
, session
.get());
13676 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13678 HttpRequestInfo request
;
13679 TestCompletionCallback callback
;
13680 EXPECT_EQ(ERR_IO_PENDING
,
13681 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13683 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13684 fake_factory
->last_stream_request();
13685 ASSERT_TRUE(fake_request
!= NULL
);
13686 EXPECT_EQ(LOW
, fake_request
->priority());
13689 // Make sure that HttpNetworkTransaction passes on its priority
13690 // updates to its stream request.
13691 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13692 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13693 HttpNetworkSessionPeer
peer(session
);
13694 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13695 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13697 HttpNetworkTransaction
trans(LOW
, session
.get());
13699 HttpRequestInfo request
;
13700 TestCompletionCallback callback
;
13701 EXPECT_EQ(ERR_IO_PENDING
,
13702 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13704 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13705 fake_factory
->last_stream_request();
13706 ASSERT_TRUE(fake_request
!= NULL
);
13707 EXPECT_EQ(LOW
, fake_request
->priority());
13709 trans
.SetPriority(LOWEST
);
13710 ASSERT_TRUE(fake_request
!= NULL
);
13711 EXPECT_EQ(LOWEST
, fake_request
->priority());
13714 // Make sure that HttpNetworkTransaction passes on its priority
13715 // updates to its stream.
13716 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13717 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13718 HttpNetworkSessionPeer
peer(session
);
13719 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13720 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13722 HttpNetworkTransaction
trans(LOW
, session
.get());
13724 HttpRequestInfo request
;
13725 TestCompletionCallback callback
;
13726 EXPECT_EQ(ERR_IO_PENDING
,
13727 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13729 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13730 fake_factory
->last_stream_request();
13731 ASSERT_TRUE(fake_request
!= NULL
);
13732 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13733 ASSERT_TRUE(fake_stream
!= NULL
);
13734 EXPECT_EQ(LOW
, fake_stream
->priority());
13736 trans
.SetPriority(LOWEST
);
13737 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13740 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13741 // The same logic needs to be tested for both ws: and wss: schemes, but this
13742 // test is already parameterised on NextProto, so it uses a loop to verify
13743 // that the different schemes work.
13744 std::string test_cases
[] = {"ws://www.example.org/",
13745 "wss://www.example.org/"};
13746 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13747 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13748 HttpNetworkSessionPeer
peer(session
);
13749 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13750 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13751 peer
.SetHttpStreamFactoryForWebSocket(
13752 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13754 HttpNetworkTransaction
trans(LOW
, session
.get());
13755 trans
.SetWebSocketHandshakeStreamCreateHelper(
13756 &websocket_stream_create_helper
);
13758 HttpRequestInfo request
;
13759 TestCompletionCallback callback
;
13760 request
.method
= "GET";
13761 request
.url
= GURL(test_cases
[i
]);
13763 EXPECT_EQ(ERR_IO_PENDING
,
13764 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13766 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13767 fake_factory
->last_stream_request();
13768 ASSERT_TRUE(fake_request
!= NULL
);
13769 EXPECT_EQ(&websocket_stream_create_helper
,
13770 fake_request
->websocket_stream_create_helper());
13774 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13775 // if the transport socket pool is stalled on the global socket limit.
13776 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13777 ClientSocketPoolManager::set_max_sockets_per_group(
13778 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13779 ClientSocketPoolManager::set_max_sockets_per_pool(
13780 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13782 // Set up SSL request.
13784 HttpRequestInfo ssl_request
;
13785 ssl_request
.method
= "GET";
13786 ssl_request
.url
= GURL("https://www.example.org/");
13788 MockWrite ssl_writes
[] = {
13790 "GET / HTTP/1.1\r\n"
13791 "Host: www.example.org\r\n"
13792 "Connection: keep-alive\r\n\r\n"),
13794 MockRead ssl_reads
[] = {
13795 MockRead("HTTP/1.1 200 OK\r\n"),
13796 MockRead("Content-Length: 11\r\n\r\n"),
13797 MockRead("hello world"),
13798 MockRead(SYNCHRONOUS
, OK
),
13800 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13801 ssl_writes
, arraysize(ssl_writes
));
13802 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13804 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13805 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13807 // Set up HTTP request.
13809 HttpRequestInfo http_request
;
13810 http_request
.method
= "GET";
13811 http_request
.url
= GURL("http://www.example.org/");
13813 MockWrite http_writes
[] = {
13815 "GET / HTTP/1.1\r\n"
13816 "Host: www.example.org\r\n"
13817 "Connection: keep-alive\r\n\r\n"),
13819 MockRead http_reads
[] = {
13820 MockRead("HTTP/1.1 200 OK\r\n"),
13821 MockRead("Content-Length: 7\r\n\r\n"),
13822 MockRead("falafel"),
13823 MockRead(SYNCHRONOUS
, OK
),
13825 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13826 http_writes
, arraysize(http_writes
));
13827 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13829 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13831 // Start the SSL request.
13832 TestCompletionCallback ssl_callback
;
13833 scoped_ptr
<HttpTransaction
> ssl_trans(
13834 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13835 ASSERT_EQ(ERR_IO_PENDING
,
13836 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13839 // Start the HTTP request. Pool should stall.
13840 TestCompletionCallback http_callback
;
13841 scoped_ptr
<HttpTransaction
> http_trans(
13842 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13843 ASSERT_EQ(ERR_IO_PENDING
,
13844 http_trans
->Start(&http_request
, http_callback
.callback(),
13846 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13848 // Wait for response from SSL request.
13849 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13850 std::string response_data
;
13851 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13852 EXPECT_EQ("hello world", response_data
);
13854 // The SSL socket should automatically be closed, so the HTTP request can
13856 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13857 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13859 // The HTTP request can now complete.
13860 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13861 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13862 EXPECT_EQ("falafel", response_data
);
13864 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13867 // Tests that when a SSL connection is established but there's no corresponding
13868 // request that needs it, the new socket is closed if the transport socket pool
13869 // is stalled on the global socket limit.
13870 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13871 ClientSocketPoolManager::set_max_sockets_per_group(
13872 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13873 ClientSocketPoolManager::set_max_sockets_per_pool(
13874 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13876 // Set up an ssl request.
13878 HttpRequestInfo ssl_request
;
13879 ssl_request
.method
= "GET";
13880 ssl_request
.url
= GURL("https://www.foopy.com/");
13882 // No data will be sent on the SSL socket.
13883 StaticSocketDataProvider ssl_data
;
13884 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13886 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13887 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13889 // Set up HTTP request.
13891 HttpRequestInfo http_request
;
13892 http_request
.method
= "GET";
13893 http_request
.url
= GURL("http://www.example.org/");
13895 MockWrite http_writes
[] = {
13897 "GET / HTTP/1.1\r\n"
13898 "Host: www.example.org\r\n"
13899 "Connection: keep-alive\r\n\r\n"),
13901 MockRead http_reads
[] = {
13902 MockRead("HTTP/1.1 200 OK\r\n"),
13903 MockRead("Content-Length: 7\r\n\r\n"),
13904 MockRead("falafel"),
13905 MockRead(SYNCHRONOUS
, OK
),
13907 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13908 http_writes
, arraysize(http_writes
));
13909 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13911 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13913 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13914 // cancelled when a normal transaction is cancelled.
13915 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13916 SSLConfig ssl_config
;
13917 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13918 http_stream_factory
->PreconnectStreams(1, ssl_request
, ssl_config
,
13920 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13922 // Start the HTTP request. Pool should stall.
13923 TestCompletionCallback http_callback
;
13924 scoped_ptr
<HttpTransaction
> http_trans(
13925 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13926 ASSERT_EQ(ERR_IO_PENDING
,
13927 http_trans
->Start(&http_request
, http_callback
.callback(),
13929 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13931 // The SSL connection will automatically be closed once the connection is
13932 // established, to let the HTTP request start.
13933 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13934 std::string response_data
;
13935 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13936 EXPECT_EQ("falafel", response_data
);
13938 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13941 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13942 ScopedVector
<UploadElementReader
> element_readers
;
13943 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13944 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13946 HttpRequestInfo request
;
13947 request
.method
= "POST";
13948 request
.url
= GURL("http://www.foo.com/");
13949 request
.upload_data_stream
= &upload_data_stream
;
13950 request
.load_flags
= 0;
13952 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13953 scoped_ptr
<HttpTransaction
> trans(
13954 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13955 // Send headers successfully, but get an error while sending the body.
13956 MockWrite data_writes
[] = {
13957 MockWrite("POST / HTTP/1.1\r\n"
13958 "Host: www.foo.com\r\n"
13959 "Connection: keep-alive\r\n"
13960 "Content-Length: 3\r\n\r\n"),
13961 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13964 MockRead data_reads
[] = {
13965 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13966 MockRead("hello world"),
13967 MockRead(SYNCHRONOUS
, OK
),
13969 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13970 arraysize(data_writes
));
13971 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13973 TestCompletionCallback callback
;
13975 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13978 rv
= callback
.WaitForResult();
13981 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13982 ASSERT_TRUE(response
!= NULL
);
13984 EXPECT_TRUE(response
->headers
.get() != NULL
);
13985 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13987 std::string response_data
;
13988 rv
= ReadTransaction(trans
.get(), &response_data
);
13990 EXPECT_EQ("hello world", response_data
);
13993 // This test makes sure the retry logic doesn't trigger when reading an error
13994 // response from a server that rejected a POST with a CONNECTION_RESET.
13995 TEST_P(HttpNetworkTransactionTest
,
13996 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13997 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13998 MockWrite data_writes
[] = {
13999 MockWrite("GET / HTTP/1.1\r\n"
14000 "Host: www.foo.com\r\n"
14001 "Connection: keep-alive\r\n\r\n"),
14002 MockWrite("POST / HTTP/1.1\r\n"
14003 "Host: www.foo.com\r\n"
14004 "Connection: keep-alive\r\n"
14005 "Content-Length: 3\r\n\r\n"),
14006 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14009 MockRead data_reads
[] = {
14010 MockRead("HTTP/1.1 200 Peachy\r\n"
14011 "Content-Length: 14\r\n\r\n"),
14012 MockRead("first response"),
14013 MockRead("HTTP/1.1 400 Not OK\r\n"
14014 "Content-Length: 15\r\n\r\n"),
14015 MockRead("second response"),
14016 MockRead(SYNCHRONOUS
, OK
),
14018 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14019 arraysize(data_writes
));
14020 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14022 TestCompletionCallback callback
;
14023 HttpRequestInfo request1
;
14024 request1
.method
= "GET";
14025 request1
.url
= GURL("http://www.foo.com/");
14026 request1
.load_flags
= 0;
14028 scoped_ptr
<HttpTransaction
> trans1(
14029 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14030 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
14031 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14033 rv
= callback
.WaitForResult();
14036 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
14037 ASSERT_TRUE(response1
!= NULL
);
14039 EXPECT_TRUE(response1
->headers
.get() != NULL
);
14040 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
14042 std::string response_data1
;
14043 rv
= ReadTransaction(trans1
.get(), &response_data1
);
14045 EXPECT_EQ("first response", response_data1
);
14046 // Delete the transaction to release the socket back into the socket pool.
14049 ScopedVector
<UploadElementReader
> element_readers
;
14050 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14051 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14053 HttpRequestInfo request2
;
14054 request2
.method
= "POST";
14055 request2
.url
= GURL("http://www.foo.com/");
14056 request2
.upload_data_stream
= &upload_data_stream
;
14057 request2
.load_flags
= 0;
14059 scoped_ptr
<HttpTransaction
> trans2(
14060 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14061 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
14062 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14064 rv
= callback
.WaitForResult();
14067 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
14068 ASSERT_TRUE(response2
!= NULL
);
14070 EXPECT_TRUE(response2
->headers
.get() != NULL
);
14071 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
14073 std::string response_data2
;
14074 rv
= ReadTransaction(trans2
.get(), &response_data2
);
14076 EXPECT_EQ("second response", response_data2
);
14079 TEST_P(HttpNetworkTransactionTest
,
14080 PostReadsErrorResponseAfterResetPartialBodySent
) {
14081 ScopedVector
<UploadElementReader
> element_readers
;
14082 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14083 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14085 HttpRequestInfo request
;
14086 request
.method
= "POST";
14087 request
.url
= GURL("http://www.foo.com/");
14088 request
.upload_data_stream
= &upload_data_stream
;
14089 request
.load_flags
= 0;
14091 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14092 scoped_ptr
<HttpTransaction
> trans(
14093 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14094 // Send headers successfully, but get an error while sending the body.
14095 MockWrite data_writes
[] = {
14096 MockWrite("POST / HTTP/1.1\r\n"
14097 "Host: www.foo.com\r\n"
14098 "Connection: keep-alive\r\n"
14099 "Content-Length: 3\r\n\r\n"
14101 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14104 MockRead data_reads
[] = {
14105 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14106 MockRead("hello world"),
14107 MockRead(SYNCHRONOUS
, OK
),
14109 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14110 arraysize(data_writes
));
14111 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14113 TestCompletionCallback callback
;
14115 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14118 rv
= callback
.WaitForResult();
14121 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14122 ASSERT_TRUE(response
!= NULL
);
14124 EXPECT_TRUE(response
->headers
.get() != NULL
);
14125 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14127 std::string response_data
;
14128 rv
= ReadTransaction(trans
.get(), &response_data
);
14130 EXPECT_EQ("hello world", response_data
);
14133 // This tests the more common case than the previous test, where headers and
14134 // body are not merged into a single request.
14135 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
14136 ScopedVector
<UploadElementReader
> element_readers
;
14137 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14138 ChunkedUploadDataStream
upload_data_stream(0);
14140 HttpRequestInfo request
;
14141 request
.method
= "POST";
14142 request
.url
= GURL("http://www.foo.com/");
14143 request
.upload_data_stream
= &upload_data_stream
;
14144 request
.load_flags
= 0;
14146 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14147 scoped_ptr
<HttpTransaction
> trans(
14148 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14149 // Send headers successfully, but get an error while sending the body.
14150 MockWrite data_writes
[] = {
14151 MockWrite("POST / HTTP/1.1\r\n"
14152 "Host: www.foo.com\r\n"
14153 "Connection: keep-alive\r\n"
14154 "Transfer-Encoding: chunked\r\n\r\n"),
14155 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14158 MockRead data_reads
[] = {
14159 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14160 MockRead("hello world"),
14161 MockRead(SYNCHRONOUS
, OK
),
14163 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14164 arraysize(data_writes
));
14165 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14167 TestCompletionCallback callback
;
14169 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14171 // Make sure the headers are sent before adding a chunk. This ensures that
14172 // they can't be merged with the body in a single send. Not currently
14173 // necessary since a chunked body is never merged with headers, but this makes
14174 // the test more future proof.
14175 base::RunLoop().RunUntilIdle();
14177 upload_data_stream
.AppendData("last chunk", 10, true);
14179 rv
= callback
.WaitForResult();
14182 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14183 ASSERT_TRUE(response
!= NULL
);
14185 EXPECT_TRUE(response
->headers
.get() != NULL
);
14186 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14188 std::string response_data
;
14189 rv
= ReadTransaction(trans
.get(), &response_data
);
14191 EXPECT_EQ("hello world", response_data
);
14194 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
14195 ScopedVector
<UploadElementReader
> element_readers
;
14196 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14197 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14199 HttpRequestInfo request
;
14200 request
.method
= "POST";
14201 request
.url
= GURL("http://www.foo.com/");
14202 request
.upload_data_stream
= &upload_data_stream
;
14203 request
.load_flags
= 0;
14205 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14206 scoped_ptr
<HttpTransaction
> trans(
14207 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14209 MockWrite data_writes
[] = {
14210 MockWrite("POST / HTTP/1.1\r\n"
14211 "Host: www.foo.com\r\n"
14212 "Connection: keep-alive\r\n"
14213 "Content-Length: 3\r\n\r\n"),
14214 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14217 MockRead data_reads
[] = {
14218 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14219 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14220 MockRead("hello world"),
14221 MockRead(SYNCHRONOUS
, OK
),
14223 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14224 arraysize(data_writes
));
14225 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14227 TestCompletionCallback callback
;
14229 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14230 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14232 rv
= callback
.WaitForResult();
14235 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14236 ASSERT_TRUE(response
!= NULL
);
14238 EXPECT_TRUE(response
->headers
.get() != NULL
);
14239 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14241 std::string response_data
;
14242 rv
= ReadTransaction(trans
.get(), &response_data
);
14244 EXPECT_EQ("hello world", response_data
);
14247 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
14248 ScopedVector
<UploadElementReader
> element_readers
;
14249 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14250 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14252 HttpRequestInfo request
;
14253 request
.method
= "POST";
14254 request
.url
= GURL("http://www.foo.com/");
14255 request
.upload_data_stream
= &upload_data_stream
;
14256 request
.load_flags
= 0;
14258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14259 scoped_ptr
<HttpTransaction
> trans(
14260 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14261 // Send headers successfully, but get an error while sending the body.
14262 MockWrite data_writes
[] = {
14263 MockWrite("POST / HTTP/1.1\r\n"
14264 "Host: www.foo.com\r\n"
14265 "Connection: keep-alive\r\n"
14266 "Content-Length: 3\r\n\r\n"),
14267 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14270 MockRead data_reads
[] = {
14271 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14272 MockRead("hello world"),
14273 MockRead(SYNCHRONOUS
, OK
),
14275 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14276 arraysize(data_writes
));
14277 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14279 TestCompletionCallback callback
;
14281 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14284 rv
= callback
.WaitForResult();
14285 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14288 TEST_P(HttpNetworkTransactionTest
,
14289 PostIgnoresNonErrorResponseAfterResetAnd100
) {
14290 ScopedVector
<UploadElementReader
> element_readers
;
14291 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14292 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14294 HttpRequestInfo request
;
14295 request
.method
= "POST";
14296 request
.url
= GURL("http://www.foo.com/");
14297 request
.upload_data_stream
= &upload_data_stream
;
14298 request
.load_flags
= 0;
14300 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14301 scoped_ptr
<HttpTransaction
> trans(
14302 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14303 // Send headers successfully, but get an error while sending the body.
14304 MockWrite data_writes
[] = {
14305 MockWrite("POST / HTTP/1.1\r\n"
14306 "Host: www.foo.com\r\n"
14307 "Connection: keep-alive\r\n"
14308 "Content-Length: 3\r\n\r\n"),
14309 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14312 MockRead data_reads
[] = {
14313 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14314 MockRead("HTTP/1.0 302 Redirect\r\n"),
14315 MockRead("Location: http://somewhere-else.com/\r\n"),
14316 MockRead("Content-Length: 0\r\n\r\n"),
14317 MockRead(SYNCHRONOUS
, OK
),
14319 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14320 arraysize(data_writes
));
14321 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14323 TestCompletionCallback callback
;
14325 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14326 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14328 rv
= callback
.WaitForResult();
14329 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14332 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
14333 ScopedVector
<UploadElementReader
> element_readers
;
14334 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14335 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14337 HttpRequestInfo request
;
14338 request
.method
= "POST";
14339 request
.url
= GURL("http://www.foo.com/");
14340 request
.upload_data_stream
= &upload_data_stream
;
14341 request
.load_flags
= 0;
14343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14344 scoped_ptr
<HttpTransaction
> trans(
14345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14346 // Send headers successfully, but get an error while sending the body.
14347 MockWrite data_writes
[] = {
14348 MockWrite("POST / HTTP/1.1\r\n"
14349 "Host: www.foo.com\r\n"
14350 "Connection: keep-alive\r\n"
14351 "Content-Length: 3\r\n\r\n"),
14352 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14355 MockRead data_reads
[] = {
14356 MockRead("HTTP 0.9 rocks!"),
14357 MockRead(SYNCHRONOUS
, OK
),
14359 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14360 arraysize(data_writes
));
14361 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14363 TestCompletionCallback callback
;
14365 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14366 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14368 rv
= callback
.WaitForResult();
14369 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14372 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
14373 ScopedVector
<UploadElementReader
> element_readers
;
14374 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14375 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14377 HttpRequestInfo request
;
14378 request
.method
= "POST";
14379 request
.url
= GURL("http://www.foo.com/");
14380 request
.upload_data_stream
= &upload_data_stream
;
14381 request
.load_flags
= 0;
14383 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14384 scoped_ptr
<HttpTransaction
> trans(
14385 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14386 // Send headers successfully, but get an error while sending the body.
14387 MockWrite data_writes
[] = {
14388 MockWrite("POST / HTTP/1.1\r\n"
14389 "Host: www.foo.com\r\n"
14390 "Connection: keep-alive\r\n"
14391 "Content-Length: 3\r\n\r\n"),
14392 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14395 MockRead data_reads
[] = {
14396 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14397 MockRead(SYNCHRONOUS
, OK
),
14399 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14400 arraysize(data_writes
));
14401 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14403 TestCompletionCallback callback
;
14405 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14406 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14408 rv
= callback
.WaitForResult();
14409 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14412 // Verify that proxy headers are not sent to the destination server when
14413 // establishing a tunnel for a secure WebSocket connection.
14414 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14415 HttpRequestInfo request
;
14416 request
.method
= "GET";
14417 request
.url
= GURL("wss://www.example.org/");
14418 AddWebSocketHeaders(&request
.extra_headers
);
14420 // Configure against proxy server "myproxy:70".
14421 session_deps_
.proxy_service
.reset(
14422 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14424 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14426 // Since a proxy is configured, try to establish a tunnel.
14427 MockWrite data_writes
[] = {
14429 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14430 "Host: www.example.org\r\n"
14431 "Proxy-Connection: keep-alive\r\n\r\n"),
14433 // After calling trans->RestartWithAuth(), this is the request we should
14434 // be issuing -- the final header line contains the credentials.
14436 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14437 "Host: www.example.org\r\n"
14438 "Proxy-Connection: keep-alive\r\n"
14439 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14442 "GET / HTTP/1.1\r\n"
14443 "Host: www.example.org\r\n"
14444 "Connection: Upgrade\r\n"
14445 "Upgrade: websocket\r\n"
14446 "Origin: http://www.example.org\r\n"
14447 "Sec-WebSocket-Version: 13\r\n"
14448 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14451 // The proxy responds to the connect with a 407, using a persistent
14453 MockRead data_reads
[] = {
14455 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14456 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14457 MockRead("Content-Length: 0\r\n"),
14458 MockRead("Proxy-Connection: keep-alive\r\n\r\n"),
14460 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14462 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14463 MockRead("Upgrade: websocket\r\n"),
14464 MockRead("Connection: Upgrade\r\n"),
14465 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14468 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14469 arraysize(data_writes
));
14470 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14471 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14472 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14474 scoped_ptr
<HttpTransaction
> trans(
14475 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14476 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14477 trans
->SetWebSocketHandshakeStreamCreateHelper(
14478 &websocket_stream_create_helper
);
14481 TestCompletionCallback callback
;
14483 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14484 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14486 rv
= callback
.WaitForResult();
14490 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14491 ASSERT_TRUE(response
);
14492 ASSERT_TRUE(response
->headers
.get());
14493 EXPECT_EQ(407, response
->headers
->response_code());
14496 TestCompletionCallback callback
;
14498 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14499 callback
.callback());
14500 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14502 rv
= callback
.WaitForResult();
14506 response
= trans
->GetResponseInfo();
14507 ASSERT_TRUE(response
);
14508 ASSERT_TRUE(response
->headers
.get());
14510 EXPECT_EQ(101, response
->headers
->response_code());
14513 session
->CloseAllConnections();
14516 // Verify that proxy headers are not sent to the destination server when
14517 // establishing a tunnel for an insecure WebSocket connection.
14518 // This requires the authentication info to be injected into the auth cache
14519 // due to crbug.com/395064
14520 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14521 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14522 HttpRequestInfo request
;
14523 request
.method
= "GET";
14524 request
.url
= GURL("ws://www.example.org/");
14525 AddWebSocketHeaders(&request
.extra_headers
);
14527 // Configure against proxy server "myproxy:70".
14528 session_deps_
.proxy_service
.reset(
14529 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14531 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14533 MockWrite data_writes
[] = {
14534 // Try to establish a tunnel for the WebSocket connection, with
14535 // credentials. Because WebSockets have a separate set of socket pools,
14536 // they cannot and will not use the same TCP/IP connection as the
14537 // preflight HTTP request.
14539 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14540 "Host: www.example.org:80\r\n"
14541 "Proxy-Connection: keep-alive\r\n"
14542 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14545 "GET / HTTP/1.1\r\n"
14546 "Host: www.example.org\r\n"
14547 "Connection: Upgrade\r\n"
14548 "Upgrade: websocket\r\n"
14549 "Origin: http://www.example.org\r\n"
14550 "Sec-WebSocket-Version: 13\r\n"
14551 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14554 MockRead data_reads
[] = {
14555 // HTTP CONNECT with credentials.
14556 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14558 // WebSocket connection established inside tunnel.
14559 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14560 MockRead("Upgrade: websocket\r\n"),
14561 MockRead("Connection: Upgrade\r\n"),
14562 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14565 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14566 arraysize(data_writes
));
14567 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14569 session
->http_auth_cache()->Add(
14570 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14571 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14573 scoped_ptr
<HttpTransaction
> trans(
14574 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14575 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14576 trans
->SetWebSocketHandshakeStreamCreateHelper(
14577 &websocket_stream_create_helper
);
14579 TestCompletionCallback callback
;
14581 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14584 rv
= callback
.WaitForResult();
14587 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14588 ASSERT_TRUE(response
);
14589 ASSERT_TRUE(response
->headers
.get());
14591 EXPECT_EQ(101, response
->headers
->response_code());
14594 session
->CloseAllConnections();