1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/test/test_file_util.h"
24 #include "net/base/auth.h"
25 #include "net/base/chunked_upload_data_stream.h"
26 #include "net/base/completion_callback.h"
27 #include "net/base/elements_upload_data_stream.h"
28 #include "net/base/load_timing_info.h"
29 #include "net/base/load_timing_info_test_util.h"
30 #include "net/base/net_errors.h"
31 #include "net/base/request_priority.h"
32 #include "net/base/test_completion_callback.h"
33 #include "net/base/test_data_directory.h"
34 #include "net/base/upload_bytes_element_reader.h"
35 #include "net/base/upload_file_element_reader.h"
36 #include "net/cert/mock_cert_verifier.h"
37 #include "net/dns/host_cache.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/http/http_auth_challenge_tokenizer.h"
40 #include "net/http/http_auth_handler_digest.h"
41 #include "net/http/http_auth_handler_mock.h"
42 #include "net/http/http_auth_handler_ntlm.h"
43 #include "net/http/http_basic_state.h"
44 #include "net/http/http_basic_stream.h"
45 #include "net/http/http_network_session.h"
46 #include "net/http/http_network_session_peer.h"
47 #include "net/http/http_request_headers.h"
48 #include "net/http/http_server_properties_impl.h"
49 #include "net/http/http_stream.h"
50 #include "net/http/http_stream_factory.h"
51 #include "net/http/http_stream_parser.h"
52 #include "net/http/http_transaction_test_util.h"
53 #include "net/log/net_log.h"
54 #include "net/log/net_log_unittest.h"
55 #include "net/log/test_net_log.h"
56 #include "net/proxy/mock_proxy_resolver.h"
57 #include "net/proxy/proxy_config_service_fixed.h"
58 #include "net/proxy/proxy_info.h"
59 #include "net/proxy/proxy_resolver.h"
60 #include "net/proxy/proxy_service.h"
61 #include "net/socket/client_socket_factory.h"
62 #include "net/socket/client_socket_pool_manager.h"
63 #include "net/socket/mock_client_socket_pool_manager.h"
64 #include "net/socket/next_proto.h"
65 #include "net/socket/socket_test_util.h"
66 #include "net/socket/ssl_client_socket.h"
67 #include "net/spdy/spdy_framer.h"
68 #include "net/spdy/spdy_session.h"
69 #include "net/spdy/spdy_session_pool.h"
70 #include "net/spdy/spdy_test_util_common.h"
71 #include "net/ssl/ssl_cert_request_info.h"
72 #include "net/ssl/ssl_config_service.h"
73 #include "net/ssl/ssl_config_service_defaults.h"
74 #include "net/ssl/ssl_info.h"
75 #include "net/test/cert_test_util.h"
76 #include "net/websockets/websocket_handshake_stream_base.h"
77 #include "testing/gtest/include/gtest/gtest.h"
78 #include "testing/platform_test.h"
81 using base::ASCIIToUTF16
;
83 //-----------------------------------------------------------------------------
89 const base::string16
kBar(ASCIIToUTF16("bar"));
90 const base::string16
kBar2(ASCIIToUTF16("bar2"));
91 const base::string16
kBar3(ASCIIToUTF16("bar3"));
92 const base::string16
kBaz(ASCIIToUTF16("baz"));
93 const base::string16
kFirst(ASCIIToUTF16("first"));
94 const base::string16
kFoo(ASCIIToUTF16("foo"));
95 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
96 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
97 const base::string16
kFou(ASCIIToUTF16("fou"));
98 const base::string16
kSecond(ASCIIToUTF16("second"));
99 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
100 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
102 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession
* session
) {
103 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
107 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession
* session
) {
108 return session
->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
112 bool IsTransportSocketPoolStalled(HttpNetworkSession
* session
) {
113 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
117 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
118 // a JSONified list of headers as a single string. Uses single quotes instead
119 // of double quotes for easier comparison. Returns false on failure.
120 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
123 base::ListValue
* header_list
;
124 if (!params
->GetList("headers", &header_list
))
126 std::string double_quote_headers
;
127 base::JSONWriter::Write(header_list
, &double_quote_headers
);
128 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
132 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
134 void TestLoadTimingReused(const LoadTimingInfo
& load_timing_info
) {
135 EXPECT_TRUE(load_timing_info
.socket_reused
);
136 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
138 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
139 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
141 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
142 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
144 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
146 // Set at a higher level.
147 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
148 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
149 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
152 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
154 void TestLoadTimingNotReused(const LoadTimingInfo
& load_timing_info
,
155 int connect_timing_flags
) {
156 EXPECT_FALSE(load_timing_info
.socket_reused
);
157 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
159 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
160 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
162 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
163 connect_timing_flags
);
164 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
165 load_timing_info
.send_start
);
167 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
169 // Set at a higher level.
170 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
171 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
172 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
175 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
177 void TestLoadTimingReusedWithPac(const LoadTimingInfo
& load_timing_info
) {
178 EXPECT_TRUE(load_timing_info
.socket_reused
);
179 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
181 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
183 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
184 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
185 load_timing_info
.proxy_resolve_end
);
186 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
187 load_timing_info
.send_start
);
188 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
190 // Set at a higher level.
191 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
192 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
193 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
196 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
198 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo
& load_timing_info
,
199 int connect_timing_flags
) {
200 EXPECT_FALSE(load_timing_info
.socket_reused
);
201 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
203 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
204 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
205 load_timing_info
.proxy_resolve_end
);
206 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
207 load_timing_info
.connect_timing
.connect_start
);
208 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
209 connect_timing_flags
);
210 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
211 load_timing_info
.send_start
);
213 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
215 // Set at a higher level.
216 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
217 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
218 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
221 void AddWebSocketHeaders(HttpRequestHeaders
* headers
) {
222 headers
->SetHeader("Connection", "Upgrade");
223 headers
->SetHeader("Upgrade", "websocket");
224 headers
->SetHeader("Origin", "http://www.example.org");
225 headers
->SetHeader("Sec-WebSocket-Version", "13");
226 headers
->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
229 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
230 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
235 class HttpNetworkTransactionTest
236 : public PlatformTest
,
237 public ::testing::WithParamInterface
<NextProto
> {
239 virtual ~HttpNetworkTransactionTest() {
240 // Important to restore the per-pool limit first, since the pool limit must
241 // always be greater than group limit, and the tests reduce both limits.
242 ClientSocketPoolManager::set_max_sockets_per_pool(
243 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
244 ClientSocketPoolManager::set_max_sockets_per_group(
245 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
249 HttpNetworkTransactionTest()
250 : spdy_util_(GetParam()),
251 session_deps_(GetParam()),
252 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
253 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
254 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
255 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
258 struct SimpleGetHelperResult
{
260 std::string status_line
;
261 std::string response_data
;
262 int64 totalReceivedBytes
;
263 LoadTimingInfo load_timing_info
;
266 void SetUp() override
{
267 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
268 base::MessageLoop::current()->RunUntilIdle();
271 void TearDown() override
{
272 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
273 base::MessageLoop::current()->RunUntilIdle();
274 // Empty the current queue.
275 base::MessageLoop::current()->RunUntilIdle();
276 PlatformTest::TearDown();
277 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
278 base::MessageLoop::current()->RunUntilIdle();
281 const char* GetAlternateProtocolFromParam() {
283 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
286 // This is the expected return from a current server advertising SPDY.
287 std::string
GetAlternateProtocolHttpHeader() {
288 return std::string("Alternate-Protocol: 443:") +
289 GetAlternateProtocolFromParam() + "\r\n\r\n";
292 // Either |write_failure| specifies a write failure or |read_failure|
293 // specifies a read failure when using a reused socket. In either case, the
294 // failure should cause the network transaction to resend the request, and the
295 // other argument should be NULL.
296 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
297 const MockRead
* read_failure
);
299 // Either |write_failure| specifies a write failure or |read_failure|
300 // specifies a read failure when using a reused socket. In either case, the
301 // failure should cause the network transaction to resend the request, and the
302 // other argument should be NULL.
303 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
304 const MockRead
* read_failure
,
307 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
309 SimpleGetHelperResult out
;
311 HttpRequestInfo request
;
312 request
.method
= "GET";
313 request
.url
= GURL("http://www.example.org/");
314 request
.load_flags
= 0;
317 session_deps_
.net_log
= log
.bound().net_log();
318 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
319 scoped_ptr
<HttpTransaction
> trans(
320 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
322 for (size_t i
= 0; i
< data_count
; ++i
) {
323 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
326 TestCompletionCallback callback
;
328 EXPECT_TRUE(log
.bound().GetCaptureMode().enabled());
329 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
330 EXPECT_EQ(ERR_IO_PENDING
, rv
);
332 out
.rv
= callback
.WaitForResult();
334 // Even in the failure cases that use this function, connections are always
335 // successfully established before the error.
336 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
337 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
342 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
343 // Can't use ASSERT_* inside helper functions like this, so
345 if (response
== NULL
|| response
->headers
.get() == NULL
) {
346 out
.rv
= ERR_UNEXPECTED
;
349 out
.status_line
= response
->headers
->GetStatusLine();
351 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
352 EXPECT_EQ(80, response
->socket_address
.port());
354 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
357 TestNetLog::CapturedEntryList entries
;
358 log
.GetEntries(&entries
);
359 size_t pos
= ExpectLogContainsSomewhere(
360 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
362 ExpectLogContainsSomewhere(
364 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
368 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
369 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
371 HttpRequestHeaders request_headers
;
372 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
374 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
375 EXPECT_EQ("www.example.org", value
);
376 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
377 EXPECT_EQ("keep-alive", value
);
379 std::string response_headers
;
380 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
381 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
384 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
388 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
389 size_t reads_count
) {
390 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
391 StaticSocketDataProvider
* data
[] = { &reads
};
392 return SimpleGetHelperForData(data
, 1);
395 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
397 for (size_t i
= 0; i
< reads_count
; ++i
)
398 size
+= data_reads
[i
].data_len
;
402 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
403 int expected_status
);
405 void ConnectStatusHelper(const MockRead
& status
);
407 void BypassHostCacheOnRefreshHelper(int load_flags
);
409 void CheckErrorIsPassedBack(int error
, IoMode mode
);
411 SpdyTestUtil spdy_util_
;
412 SpdySessionDependencies session_deps_
;
414 // Original socket limits. Some tests set these. Safest to always restore
415 // them once each test has been run.
416 int old_max_group_sockets_
;
417 int old_max_pool_sockets_
;
420 INSTANTIATE_TEST_CASE_P(NextProto
,
421 HttpNetworkTransactionTest
,
422 testing::Values(kProtoSPDY31
,
428 class BeforeNetworkStartHandler
{
430 explicit BeforeNetworkStartHandler(bool defer
)
431 : defer_on_before_network_start_(defer
),
432 observed_before_network_start_(false) {}
434 void OnBeforeNetworkStart(bool* defer
) {
435 *defer
= defer_on_before_network_start_
;
436 observed_before_network_start_
= true;
439 bool observed_before_network_start() const {
440 return observed_before_network_start_
;
444 const bool defer_on_before_network_start_
;
445 bool observed_before_network_start_
;
447 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
450 class BeforeProxyHeadersSentHandler
{
452 BeforeProxyHeadersSentHandler()
453 : observed_before_proxy_headers_sent_(false) {}
455 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
456 HttpRequestHeaders
* request_headers
) {
457 observed_before_proxy_headers_sent_
= true;
458 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
461 bool observed_before_proxy_headers_sent() const {
462 return observed_before_proxy_headers_sent_
;
465 std::string
observed_proxy_server_uri() const {
466 return observed_proxy_server_uri_
;
470 bool observed_before_proxy_headers_sent_
;
471 std::string observed_proxy_server_uri_
;
473 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
476 // Fill |str| with a long header list that consumes >= |size| bytes.
477 void FillLargeHeadersString(std::string
* str
, int size
) {
479 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
480 const int sizeof_row
= strlen(row
);
481 const int num_rows
= static_cast<int>(
482 ceil(static_cast<float>(size
) / sizeof_row
));
483 const int sizeof_data
= num_rows
* sizeof_row
;
484 DCHECK(sizeof_data
>= size
);
485 str
->reserve(sizeof_data
);
487 for (int i
= 0; i
< num_rows
; ++i
)
488 str
->append(row
, sizeof_row
);
491 // Alternative functions that eliminate randomness and dependency on the local
492 // host name so that the generated NTLM messages are reproducible.
493 void MockGenerateRandom1(uint8
* output
, size_t n
) {
494 static const uint8 bytes
[] = {
495 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
497 static size_t current_byte
= 0;
498 for (size_t i
= 0; i
< n
; ++i
) {
499 output
[i
] = bytes
[current_byte
++];
500 current_byte
%= arraysize(bytes
);
504 void MockGenerateRandom2(uint8
* output
, size_t n
) {
505 static const uint8 bytes
[] = {
506 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
507 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
509 static size_t current_byte
= 0;
510 for (size_t i
= 0; i
< n
; ++i
) {
511 output
[i
] = bytes
[current_byte
++];
512 current_byte
%= arraysize(bytes
);
516 std::string
MockGetHostName() {
520 template<typename ParentPool
>
521 class CaptureGroupNameSocketPool
: public ParentPool
{
523 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
524 CertVerifier
* cert_verifier
);
526 const std::string
last_group_name_received() const {
527 return last_group_name_
;
530 int RequestSocket(const std::string
& group_name
,
531 const void* socket_params
,
532 RequestPriority priority
,
533 ClientSocketHandle
* handle
,
534 const CompletionCallback
& callback
,
535 const BoundNetLog
& net_log
) override
{
536 last_group_name_
= group_name
;
537 return ERR_IO_PENDING
;
539 void CancelRequest(const std::string
& group_name
,
540 ClientSocketHandle
* handle
) override
{}
541 void ReleaseSocket(const std::string
& group_name
,
542 scoped_ptr
<StreamSocket
> socket
,
544 void CloseIdleSockets() override
{}
545 int IdleSocketCount() const override
{ return 0; }
546 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
549 LoadState
GetLoadState(const std::string
& group_name
,
550 const ClientSocketHandle
* handle
) const override
{
551 return LOAD_STATE_IDLE
;
553 base::TimeDelta
ConnectionTimeout() const override
{
554 return base::TimeDelta();
558 std::string last_group_name_
;
561 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
562 CaptureGroupNameTransportSocketPool
;
563 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
564 CaptureGroupNameHttpProxySocketPool
;
565 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
566 CaptureGroupNameSOCKSSocketPool
;
567 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
568 CaptureGroupNameSSLSocketPool
;
570 template <typename ParentPool
>
571 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
572 HostResolver
* host_resolver
,
573 CertVerifier
* /* cert_verifier */)
574 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
578 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
579 HostResolver
* /* host_resolver */,
580 CertVerifier
* /* cert_verifier */)
581 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
585 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
586 HostResolver
* /* host_resolver */,
587 CertVerifier
* cert_verifier
)
588 : SSLClientSocketPool(0,
604 //-----------------------------------------------------------------------------
606 // Helper functions for validating that AuthChallengeInfo's are correctly
607 // configured for common cases.
608 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
611 EXPECT_FALSE(auth_challenge
->is_proxy
);
612 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
613 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
614 EXPECT_EQ("basic", auth_challenge
->scheme
);
618 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
621 EXPECT_TRUE(auth_challenge
->is_proxy
);
622 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
623 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
624 EXPECT_EQ("basic", auth_challenge
->scheme
);
628 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
631 EXPECT_FALSE(auth_challenge
->is_proxy
);
632 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
633 EXPECT_EQ("digestive", auth_challenge
->realm
);
634 EXPECT_EQ("digest", auth_challenge
->scheme
);
638 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
641 EXPECT_FALSE(auth_challenge
->is_proxy
);
642 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
643 EXPECT_EQ(std::string(), auth_challenge
->realm
);
644 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
650 TEST_P(HttpNetworkTransactionTest
, Basic
) {
651 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
652 scoped_ptr
<HttpTransaction
> trans(
653 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
656 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
657 MockRead data_reads
[] = {
658 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
659 MockRead("hello world"),
660 MockRead(SYNCHRONOUS
, OK
),
662 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
663 arraysize(data_reads
));
664 EXPECT_EQ(OK
, out
.rv
);
665 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
666 EXPECT_EQ("hello world", out
.response_data
);
667 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
668 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
671 // Response with no status line.
672 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
673 MockRead data_reads
[] = {
674 MockRead("hello world"),
675 MockRead(SYNCHRONOUS
, OK
),
677 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
678 arraysize(data_reads
));
679 EXPECT_EQ(OK
, out
.rv
);
680 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
681 EXPECT_EQ("hello world", out
.response_data
);
682 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
683 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
686 // Allow up to 4 bytes of junk to precede status line.
687 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
688 MockRead data_reads
[] = {
689 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
690 MockRead(SYNCHRONOUS
, OK
),
692 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
693 arraysize(data_reads
));
694 EXPECT_EQ(OK
, out
.rv
);
695 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
696 EXPECT_EQ("DATA", out
.response_data
);
697 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
698 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
701 // Allow up to 4 bytes of junk to precede status line.
702 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
703 MockRead data_reads
[] = {
704 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
705 MockRead(SYNCHRONOUS
, OK
),
707 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
708 arraysize(data_reads
));
709 EXPECT_EQ(OK
, out
.rv
);
710 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
711 EXPECT_EQ("DATA", out
.response_data
);
712 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
713 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
716 // Beyond 4 bytes of slop and it should fail to find a status line.
717 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
718 MockRead data_reads
[] = {
719 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
720 MockRead(SYNCHRONOUS
, OK
),
722 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
723 arraysize(data_reads
));
724 EXPECT_EQ(OK
, out
.rv
);
725 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
726 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
727 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
728 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
731 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
732 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
733 MockRead data_reads
[] = {
738 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
739 MockRead(SYNCHRONOUS
, OK
),
741 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
742 arraysize(data_reads
));
743 EXPECT_EQ(OK
, out
.rv
);
744 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
745 EXPECT_EQ("DATA", out
.response_data
);
746 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
747 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
750 // Close the connection before enough bytes to have a status line.
751 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
752 MockRead data_reads
[] = {
754 MockRead(SYNCHRONOUS
, OK
),
756 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
757 arraysize(data_reads
));
758 EXPECT_EQ(OK
, out
.rv
);
759 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
760 EXPECT_EQ("HTT", out
.response_data
);
761 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
762 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
765 // Simulate a 204 response, lacking a Content-Length header, sent over a
766 // persistent connection. The response should still terminate since a 204
767 // cannot have a response body.
768 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
769 char junk
[] = "junk";
770 MockRead data_reads
[] = {
771 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
772 MockRead(junk
), // Should not be read!!
773 MockRead(SYNCHRONOUS
, OK
),
775 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
776 arraysize(data_reads
));
777 EXPECT_EQ(OK
, out
.rv
);
778 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
779 EXPECT_EQ("", out
.response_data
);
780 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
781 int64 response_size
= reads_size
- strlen(junk
);
782 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
785 // A simple request using chunked encoding with some extra data after.
786 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
787 std::string final_chunk
= "0\r\n\r\n";
788 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
789 std::string last_read
= final_chunk
+ extra_data
;
790 MockRead data_reads
[] = {
791 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
792 MockRead("5\r\nHello\r\n"),
795 MockRead("5\r\nworld\r\n"),
796 MockRead(last_read
.data()),
797 MockRead(SYNCHRONOUS
, OK
),
799 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
800 arraysize(data_reads
));
801 EXPECT_EQ(OK
, out
.rv
);
802 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
803 EXPECT_EQ("Hello world", out
.response_data
);
804 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
805 int64 response_size
= reads_size
- extra_data
.size();
806 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
809 // Next tests deal with http://crbug.com/56344.
811 TEST_P(HttpNetworkTransactionTest
,
812 MultipleContentLengthHeadersNoTransferEncoding
) {
813 MockRead data_reads
[] = {
814 MockRead("HTTP/1.1 200 OK\r\n"),
815 MockRead("Content-Length: 10\r\n"),
816 MockRead("Content-Length: 5\r\n\r\n"),
818 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
819 arraysize(data_reads
));
820 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
823 TEST_P(HttpNetworkTransactionTest
,
824 DuplicateContentLengthHeadersNoTransferEncoding
) {
825 MockRead data_reads
[] = {
826 MockRead("HTTP/1.1 200 OK\r\n"),
827 MockRead("Content-Length: 5\r\n"),
828 MockRead("Content-Length: 5\r\n\r\n"),
831 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
832 arraysize(data_reads
));
833 EXPECT_EQ(OK
, out
.rv
);
834 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
835 EXPECT_EQ("Hello", out
.response_data
);
838 TEST_P(HttpNetworkTransactionTest
,
839 ComplexContentLengthHeadersNoTransferEncoding
) {
840 // More than 2 dupes.
842 MockRead data_reads
[] = {
843 MockRead("HTTP/1.1 200 OK\r\n"),
844 MockRead("Content-Length: 5\r\n"),
845 MockRead("Content-Length: 5\r\n"),
846 MockRead("Content-Length: 5\r\n\r\n"),
849 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
850 arraysize(data_reads
));
851 EXPECT_EQ(OK
, out
.rv
);
852 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
853 EXPECT_EQ("Hello", out
.response_data
);
857 MockRead data_reads
[] = {
858 MockRead("HTTP/1.0 200 OK\r\n"),
859 MockRead("Content-Length: 5\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n\r\n"),
864 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
865 arraysize(data_reads
));
866 EXPECT_EQ(OK
, out
.rv
);
867 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
868 EXPECT_EQ("Hello", out
.response_data
);
870 // 2 dupes and one mismatched.
872 MockRead data_reads
[] = {
873 MockRead("HTTP/1.1 200 OK\r\n"),
874 MockRead("Content-Length: 10\r\n"),
875 MockRead("Content-Length: 10\r\n"),
876 MockRead("Content-Length: 5\r\n\r\n"),
878 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
879 arraysize(data_reads
));
880 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
884 TEST_P(HttpNetworkTransactionTest
,
885 MultipleContentLengthHeadersTransferEncoding
) {
886 MockRead data_reads
[] = {
887 MockRead("HTTP/1.1 200 OK\r\n"),
888 MockRead("Content-Length: 666\r\n"),
889 MockRead("Content-Length: 1337\r\n"),
890 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
891 MockRead("5\r\nHello\r\n"),
894 MockRead("5\r\nworld\r\n"),
895 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
896 MockRead(SYNCHRONOUS
, OK
),
898 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
899 arraysize(data_reads
));
900 EXPECT_EQ(OK
, out
.rv
);
901 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
902 EXPECT_EQ("Hello world", out
.response_data
);
905 // Next tests deal with http://crbug.com/98895.
907 // Checks that a single Content-Disposition header results in no error.
908 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
909 MockRead data_reads
[] = {
910 MockRead("HTTP/1.1 200 OK\r\n"),
911 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
912 MockRead("Content-Length: 5\r\n\r\n"),
915 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
916 arraysize(data_reads
));
917 EXPECT_EQ(OK
, out
.rv
);
918 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
919 EXPECT_EQ("Hello", out
.response_data
);
922 // Checks that two identical Content-Disposition headers result in no error.
923 TEST_P(HttpNetworkTransactionTest
,
924 TwoIdenticalContentDispositionHeaders
) {
925 MockRead data_reads
[] = {
926 MockRead("HTTP/1.1 200 OK\r\n"),
927 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
928 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
929 MockRead("Content-Length: 5\r\n\r\n"),
932 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
933 arraysize(data_reads
));
934 EXPECT_EQ(OK
, out
.rv
);
935 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
936 EXPECT_EQ("Hello", out
.response_data
);
939 // Checks that two distinct Content-Disposition headers result in an error.
940 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
941 MockRead data_reads
[] = {
942 MockRead("HTTP/1.1 200 OK\r\n"),
943 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
944 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
945 MockRead("Content-Length: 5\r\n\r\n"),
948 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
949 arraysize(data_reads
));
950 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
953 // Checks that two identical Location headers result in no error.
954 // Also tests Location header behavior.
955 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
956 MockRead data_reads
[] = {
957 MockRead("HTTP/1.1 302 Redirect\r\n"),
958 MockRead("Location: http://good.com/\r\n"),
959 MockRead("Location: http://good.com/\r\n"),
960 MockRead("Content-Length: 0\r\n\r\n"),
961 MockRead(SYNCHRONOUS
, OK
),
964 HttpRequestInfo request
;
965 request
.method
= "GET";
966 request
.url
= GURL("http://redirect.com/");
967 request
.load_flags
= 0;
969 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
970 scoped_ptr
<HttpTransaction
> trans(
971 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
973 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
974 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
976 TestCompletionCallback callback
;
978 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
981 EXPECT_EQ(OK
, callback
.WaitForResult());
983 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
984 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
985 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
987 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
988 EXPECT_EQ("http://good.com/", url
);
989 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
992 // Checks that two distinct Location headers result in an error.
993 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
994 MockRead data_reads
[] = {
995 MockRead("HTTP/1.1 302 Redirect\r\n"),
996 MockRead("Location: http://good.com/\r\n"),
997 MockRead("Location: http://evil.com/\r\n"),
998 MockRead("Content-Length: 0\r\n\r\n"),
999 MockRead(SYNCHRONOUS
, OK
),
1001 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1002 arraysize(data_reads
));
1003 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1006 // Do a request using the HEAD method. Verify that we don't try to read the
1007 // message body (since HEAD has none).
1008 TEST_P(HttpNetworkTransactionTest
, Head
) {
1009 HttpRequestInfo request
;
1010 request
.method
= "HEAD";
1011 request
.url
= GURL("http://www.example.org/");
1012 request
.load_flags
= 0;
1014 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1015 scoped_ptr
<HttpTransaction
> trans(
1016 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1017 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1018 trans
->SetBeforeProxyHeadersSentCallback(
1019 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1020 base::Unretained(&proxy_headers_handler
)));
1022 MockWrite data_writes1
[] = {
1024 "HEAD / HTTP/1.1\r\n"
1025 "Host: www.example.org\r\n"
1026 "Connection: keep-alive\r\n"
1027 "Content-Length: 0\r\n\r\n"),
1029 MockRead data_reads1
[] = {
1030 MockRead("HTTP/1.1 404 Not Found\r\n"),
1031 MockRead("Server: Blah\r\n"),
1032 MockRead("Content-Length: 1234\r\n\r\n"),
1034 // No response body because the test stops reading here.
1035 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1038 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1039 data_writes1
, arraysize(data_writes1
));
1040 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1042 TestCompletionCallback callback1
;
1044 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1047 rv
= callback1
.WaitForResult();
1050 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1051 ASSERT_TRUE(response
!= NULL
);
1053 // Check that the headers got parsed.
1054 EXPECT_TRUE(response
->headers
.get() != NULL
);
1055 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1056 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1057 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1058 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1060 std::string server_header
;
1062 bool has_server_header
= response
->headers
->EnumerateHeader(
1063 &iter
, "Server", &server_header
);
1064 EXPECT_TRUE(has_server_header
);
1065 EXPECT_EQ("Blah", server_header
);
1067 // Reading should give EOF right away, since there is no message body
1068 // (despite non-zero content-length).
1069 std::string response_data
;
1070 rv
= ReadTransaction(trans
.get(), &response_data
);
1072 EXPECT_EQ("", response_data
);
1075 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1078 MockRead data_reads
[] = {
1079 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1081 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1083 MockRead(SYNCHRONOUS
, OK
),
1085 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1086 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1088 const char* const kExpectedResponseData
[] = {
1092 for (int i
= 0; i
< 2; ++i
) {
1093 HttpRequestInfo request
;
1094 request
.method
= "GET";
1095 request
.url
= GURL("http://www.example.org/");
1096 request
.load_flags
= 0;
1098 scoped_ptr
<HttpTransaction
> trans(
1099 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1101 TestCompletionCallback callback
;
1103 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1104 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1106 rv
= callback
.WaitForResult();
1109 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1110 ASSERT_TRUE(response
!= NULL
);
1112 EXPECT_TRUE(response
->headers
.get() != NULL
);
1113 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1114 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1116 std::string response_data
;
1117 rv
= ReadTransaction(trans
.get(), &response_data
);
1119 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1123 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1124 ScopedVector
<UploadElementReader
> element_readers
;
1125 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1126 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1128 HttpRequestInfo request
;
1129 request
.method
= "POST";
1130 request
.url
= GURL("http://www.foo.com/");
1131 request
.upload_data_stream
= &upload_data_stream
;
1132 request
.load_flags
= 0;
1134 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1135 scoped_ptr
<HttpTransaction
> trans(
1136 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1138 MockRead data_reads
[] = {
1139 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1140 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1141 MockRead("hello world"),
1142 MockRead(SYNCHRONOUS
, OK
),
1144 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1145 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1147 TestCompletionCallback callback
;
1149 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1150 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1152 rv
= callback
.WaitForResult();
1155 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1156 ASSERT_TRUE(response
!= NULL
);
1158 EXPECT_TRUE(response
->headers
.get() != NULL
);
1159 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1161 std::string response_data
;
1162 rv
= ReadTransaction(trans
.get(), &response_data
);
1164 EXPECT_EQ("hello world", response_data
);
1167 // This test is almost the same as Ignores100 above, but the response contains
1168 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1169 // HTTP/1.1 and the two status headers are read in one read.
1170 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1171 HttpRequestInfo request
;
1172 request
.method
= "GET";
1173 request
.url
= GURL("http://www.foo.com/");
1174 request
.load_flags
= 0;
1176 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1177 scoped_ptr
<HttpTransaction
> trans(
1178 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1180 MockRead data_reads
[] = {
1181 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1182 "HTTP/1.1 200 OK\r\n\r\n"),
1183 MockRead("hello world"),
1184 MockRead(SYNCHRONOUS
, OK
),
1186 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1187 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1189 TestCompletionCallback callback
;
1191 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1192 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1194 rv
= callback
.WaitForResult();
1197 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1198 ASSERT_TRUE(response
!= NULL
);
1200 EXPECT_TRUE(response
->headers
.get() != NULL
);
1201 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1203 std::string response_data
;
1204 rv
= ReadTransaction(trans
.get(), &response_data
);
1206 EXPECT_EQ("hello world", response_data
);
1209 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1210 HttpRequestInfo request
;
1211 request
.method
= "POST";
1212 request
.url
= GURL("http://www.foo.com/");
1213 request
.load_flags
= 0;
1215 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1216 scoped_ptr
<HttpTransaction
> trans(
1217 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1219 MockRead data_reads
[] = {
1220 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1223 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1224 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1226 TestCompletionCallback callback
;
1228 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1229 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1231 rv
= callback
.WaitForResult();
1234 std::string response_data
;
1235 rv
= ReadTransaction(trans
.get(), &response_data
);
1237 EXPECT_EQ("", response_data
);
1240 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1241 HttpRequestInfo request
;
1242 request
.method
= "POST";
1243 request
.url
= GURL("http://www.foo.com/");
1244 request
.load_flags
= 0;
1246 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1247 scoped_ptr
<HttpTransaction
> trans(
1248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1250 MockRead data_reads
[] = {
1253 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1254 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1256 TestCompletionCallback callback
;
1258 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1259 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1261 rv
= callback
.WaitForResult();
1262 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1265 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1266 const MockWrite
* write_failure
,
1267 const MockRead
* read_failure
) {
1268 HttpRequestInfo request
;
1269 request
.method
= "GET";
1270 request
.url
= GURL("http://www.foo.com/");
1271 request
.load_flags
= 0;
1274 session_deps_
.net_log
= &net_log
;
1275 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1277 // Written data for successfully sending both requests.
1278 MockWrite data1_writes
[] = {
1279 MockWrite("GET / HTTP/1.1\r\n"
1280 "Host: www.foo.com\r\n"
1281 "Connection: keep-alive\r\n\r\n"),
1282 MockWrite("GET / HTTP/1.1\r\n"
1283 "Host: www.foo.com\r\n"
1284 "Connection: keep-alive\r\n\r\n")
1287 // Read results for the first request.
1288 MockRead data1_reads
[] = {
1289 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1291 MockRead(ASYNC
, OK
),
1294 if (write_failure
) {
1295 ASSERT_FALSE(read_failure
);
1296 data1_writes
[1] = *write_failure
;
1298 ASSERT_TRUE(read_failure
);
1299 data1_reads
[2] = *read_failure
;
1302 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1303 data1_writes
, arraysize(data1_writes
));
1304 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1306 MockRead data2_reads
[] = {
1307 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1309 MockRead(ASYNC
, OK
),
1311 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1312 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1314 const char* const kExpectedResponseData
[] = {
1318 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1319 for (int i
= 0; i
< 2; ++i
) {
1320 TestCompletionCallback callback
;
1322 scoped_ptr
<HttpTransaction
> trans(
1323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1325 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1326 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1328 rv
= callback
.WaitForResult();
1331 LoadTimingInfo load_timing_info
;
1332 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1333 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1335 first_socket_log_id
= load_timing_info
.socket_log_id
;
1337 // The second request should be using a new socket.
1338 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1341 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1342 ASSERT_TRUE(response
!= NULL
);
1344 EXPECT_TRUE(response
->headers
.get() != NULL
);
1345 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1347 std::string response_data
;
1348 rv
= ReadTransaction(trans
.get(), &response_data
);
1350 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1354 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1355 const MockWrite
* write_failure
,
1356 const MockRead
* read_failure
,
1358 HttpRequestInfo request
;
1359 request
.method
= "GET";
1360 request
.url
= GURL("https://www.foo.com/");
1361 request
.load_flags
= 0;
1364 session_deps_
.net_log
= &net_log
;
1365 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1367 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1368 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1370 ssl1
.SetNextProto(GetParam());
1371 ssl2
.SetNextProto(GetParam());
1373 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1374 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1376 // SPDY versions of the request and response.
1377 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1378 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1379 scoped_ptr
<SpdyFrame
> spdy_response(
1380 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1381 scoped_ptr
<SpdyFrame
> spdy_data(
1382 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1384 // HTTP/1.1 versions of the request and response.
1385 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1386 "Host: www.foo.com\r\n"
1387 "Connection: keep-alive\r\n\r\n";
1388 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1389 const char kHttpData
[] = "hello";
1391 std::vector
<MockRead
> data1_reads
;
1392 std::vector
<MockWrite
> data1_writes
;
1393 if (write_failure
) {
1394 ASSERT_FALSE(read_failure
);
1395 data1_writes
.push_back(*write_failure
);
1396 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1398 ASSERT_TRUE(read_failure
);
1400 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1402 data1_writes
.push_back(MockWrite(kHttpRequest
));
1404 data1_reads
.push_back(*read_failure
);
1407 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1408 &data1_writes
[0], data1_writes
.size());
1409 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1411 std::vector
<MockRead
> data2_reads
;
1412 std::vector
<MockWrite
> data2_writes
;
1415 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1417 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1418 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1419 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1421 data2_writes
.push_back(
1422 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1424 data2_reads
.push_back(
1425 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1426 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1427 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1429 OrderedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1430 &data2_writes
[0], data2_writes
.size());
1431 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1433 // Preconnect a socket.
1434 SSLConfig ssl_config
;
1435 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1436 session
->GetNextProtos(&ssl_config
.next_protos
);
1437 session
->http_stream_factory()->PreconnectStreams(
1438 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1439 // Wait for the preconnect to complete.
1440 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1441 base::RunLoop().RunUntilIdle();
1442 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1444 // Make the request.
1445 TestCompletionCallback callback
;
1447 scoped_ptr
<HttpTransaction
> trans(
1448 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1450 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1451 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1453 rv
= callback
.WaitForResult();
1456 LoadTimingInfo load_timing_info
;
1457 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1458 TestLoadTimingNotReused(
1460 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1462 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1463 ASSERT_TRUE(response
!= NULL
);
1465 EXPECT_TRUE(response
->headers
.get() != NULL
);
1466 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1468 std::string response_data
;
1469 rv
= ReadTransaction(trans
.get(), &response_data
);
1471 EXPECT_EQ(kHttpData
, response_data
);
1474 TEST_P(HttpNetworkTransactionTest
,
1475 KeepAliveConnectionNotConnectedOnWrite
) {
1476 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1477 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1480 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1481 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1482 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1485 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1486 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1487 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1490 // Make sure that on a 408 response (Request Timeout), the request is retried,
1491 // if the socket was a reused keep alive socket.
1492 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1493 MockRead
read_failure(SYNCHRONOUS
,
1494 "HTTP/1.1 408 Request Timeout\r\n"
1495 "Connection: Keep-Alive\r\n"
1496 "Content-Length: 6\r\n\r\n"
1498 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1501 TEST_P(HttpNetworkTransactionTest
,
1502 PreconnectErrorNotConnectedOnWrite
) {
1503 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1504 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1507 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1508 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1509 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1512 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1513 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1514 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1517 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1518 MockRead
read_failure(ASYNC
, OK
); // EOF
1519 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1522 // Make sure that on a 408 response (Request Timeout), the request is retried,
1523 // if the socket was a preconnected (UNUSED_IDLE) socket.
1524 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1525 MockRead
read_failure(SYNCHRONOUS
,
1526 "HTTP/1.1 408 Request Timeout\r\n"
1527 "Connection: Keep-Alive\r\n"
1528 "Content-Length: 6\r\n\r\n"
1530 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1531 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1534 TEST_P(HttpNetworkTransactionTest
,
1535 SpdyPreconnectErrorNotConnectedOnWrite
) {
1536 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1537 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1540 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1541 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1542 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1545 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1546 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1547 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1550 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1551 MockRead
read_failure(ASYNC
, OK
); // EOF
1552 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1555 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1556 HttpRequestInfo request
;
1557 request
.method
= "GET";
1558 request
.url
= GURL("http://www.example.org/");
1559 request
.load_flags
= 0;
1561 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1562 scoped_ptr
<HttpTransaction
> trans(
1563 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1565 MockRead data_reads
[] = {
1566 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1567 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1568 MockRead("hello world"),
1569 MockRead(SYNCHRONOUS
, OK
),
1571 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1572 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1574 TestCompletionCallback callback
;
1576 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1577 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1579 rv
= callback
.WaitForResult();
1580 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1582 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1583 EXPECT_TRUE(response
== NULL
);
1586 // What do various browsers do when the server closes a non-keepalive
1587 // connection without sending any response header or body?
1590 // Safari 3.1.2 (Windows): error page
1591 // Firefox 3.0.1: blank page
1592 // Opera 9.52: after five attempts, blank page
1593 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1594 // Us: error page (EMPTY_RESPONSE)
1595 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1596 MockRead data_reads
[] = {
1597 MockRead(SYNCHRONOUS
, OK
), // EOF
1598 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1599 MockRead("hello world"),
1600 MockRead(SYNCHRONOUS
, OK
),
1602 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1603 arraysize(data_reads
));
1604 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1607 // Test that network access can be deferred and resumed.
1608 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1609 HttpRequestInfo request
;
1610 request
.method
= "GET";
1611 request
.url
= GURL("http://www.example.org/");
1612 request
.load_flags
= 0;
1614 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1615 scoped_ptr
<HttpTransaction
> trans(
1616 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1618 // Defer on OnBeforeNetworkStart.
1619 BeforeNetworkStartHandler
net_start_handler(true); // defer
1620 trans
->SetBeforeNetworkStartCallback(
1621 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1622 base::Unretained(&net_start_handler
)));
1624 MockRead data_reads
[] = {
1625 MockRead("HTTP/1.0 200 OK\r\n"),
1626 MockRead("Content-Length: 5\r\n\r\n"),
1628 MockRead(SYNCHRONOUS
, 0),
1630 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1631 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1633 TestCompletionCallback callback
;
1635 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1636 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1637 base::MessageLoop::current()->RunUntilIdle();
1639 // Should have deferred for network start.
1640 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1641 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1642 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1644 trans
->ResumeNetworkStart();
1645 rv
= callback
.WaitForResult();
1647 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1649 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1650 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1651 if (rv
== ERR_IO_PENDING
)
1652 rv
= callback
.WaitForResult();
1657 // Test that network use can be deferred and canceled.
1658 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1659 HttpRequestInfo request
;
1660 request
.method
= "GET";
1661 request
.url
= GURL("http://www.example.org/");
1662 request
.load_flags
= 0;
1664 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1665 scoped_ptr
<HttpTransaction
> trans(
1666 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1668 // Defer on OnBeforeNetworkStart.
1669 BeforeNetworkStartHandler
net_start_handler(true); // defer
1670 trans
->SetBeforeNetworkStartCallback(
1671 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1672 base::Unretained(&net_start_handler
)));
1674 TestCompletionCallback callback
;
1676 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1677 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1678 base::MessageLoop::current()->RunUntilIdle();
1680 // Should have deferred for network start.
1681 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1682 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1683 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1686 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1687 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1688 // destructor in such situations.
1689 // See http://crbug.com/154712 and http://crbug.com/156609.
1690 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1691 HttpRequestInfo request
;
1692 request
.method
= "GET";
1693 request
.url
= GURL("http://www.example.org/");
1694 request
.load_flags
= 0;
1696 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1697 scoped_ptr
<HttpTransaction
> trans(
1698 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1700 MockRead data_reads
[] = {
1701 MockRead("HTTP/1.0 200 OK\r\n"),
1702 MockRead("Connection: keep-alive\r\n"),
1703 MockRead("Content-Length: 100\r\n\r\n"),
1705 MockRead(SYNCHRONOUS
, 0),
1707 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1708 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1710 TestCompletionCallback callback
;
1712 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1713 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1715 rv
= callback
.WaitForResult();
1718 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1719 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1720 if (rv
== ERR_IO_PENDING
)
1721 rv
= callback
.WaitForResult();
1723 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1724 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1727 base::MessageLoop::current()->RunUntilIdle();
1728 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1731 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1732 HttpRequestInfo request
;
1733 request
.method
= "GET";
1734 request
.url
= GURL("http://www.example.org/");
1735 request
.load_flags
= 0;
1737 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1738 scoped_ptr
<HttpTransaction
> trans(
1739 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1741 MockRead data_reads
[] = {
1742 MockRead("HTTP/1.0 200 OK\r\n"),
1743 MockRead("Connection: keep-alive\r\n"),
1744 MockRead("Content-Length: 100\r\n\r\n"),
1745 MockRead(SYNCHRONOUS
, 0),
1747 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1748 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1750 TestCompletionCallback callback
;
1752 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1753 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1755 rv
= callback
.WaitForResult();
1758 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1759 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1760 if (rv
== ERR_IO_PENDING
)
1761 rv
= callback
.WaitForResult();
1762 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1765 base::MessageLoop::current()->RunUntilIdle();
1766 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1769 // Test that we correctly reuse a keep-alive connection after not explicitly
1770 // reading the body.
1771 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1772 HttpRequestInfo request
;
1773 request
.method
= "GET";
1774 request
.url
= GURL("http://www.foo.com/");
1775 request
.load_flags
= 0;
1778 session_deps_
.net_log
= &net_log
;
1779 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1781 // Note that because all these reads happen in the same
1782 // StaticSocketDataProvider, it shows that the same socket is being reused for
1783 // all transactions.
1784 MockRead data1_reads
[] = {
1785 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1786 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1787 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1788 MockRead("HTTP/1.1 302 Found\r\n"
1789 "Content-Length: 0\r\n\r\n"),
1790 MockRead("HTTP/1.1 302 Found\r\n"
1791 "Content-Length: 5\r\n\r\n"
1793 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1794 "Content-Length: 0\r\n\r\n"),
1795 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1796 "Content-Length: 5\r\n\r\n"
1798 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1801 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1802 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1804 MockRead data2_reads
[] = {
1805 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1807 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1808 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1810 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1811 std::string response_lines
[kNumUnreadBodies
];
1813 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1814 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1815 TestCompletionCallback callback
;
1817 scoped_ptr
<HttpTransaction
> trans(
1818 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1820 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1823 rv
= callback
.WaitForResult();
1826 LoadTimingInfo load_timing_info
;
1827 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1829 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1830 first_socket_log_id
= load_timing_info
.socket_log_id
;
1832 TestLoadTimingReused(load_timing_info
);
1833 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1836 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1837 ASSERT_TRUE(response
!= NULL
);
1839 ASSERT_TRUE(response
->headers
.get() != NULL
);
1840 response_lines
[i
] = response
->headers
->GetStatusLine();
1842 // We intentionally don't read the response bodies.
1845 const char* const kStatusLines
[] = {
1846 "HTTP/1.1 204 No Content",
1847 "HTTP/1.1 205 Reset Content",
1848 "HTTP/1.1 304 Not Modified",
1849 "HTTP/1.1 302 Found",
1850 "HTTP/1.1 302 Found",
1851 "HTTP/1.1 301 Moved Permanently",
1852 "HTTP/1.1 301 Moved Permanently",
1855 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1856 "forgot to update kStatusLines");
1858 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1859 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1861 TestCompletionCallback callback
;
1862 scoped_ptr
<HttpTransaction
> trans(
1863 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1864 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1865 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1866 rv
= callback
.WaitForResult();
1868 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1869 ASSERT_TRUE(response
!= NULL
);
1870 ASSERT_TRUE(response
->headers
.get() != NULL
);
1871 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1872 std::string response_data
;
1873 rv
= ReadTransaction(trans
.get(), &response_data
);
1875 EXPECT_EQ("hello", response_data
);
1878 // Test the request-challenge-retry sequence for basic auth.
1879 // (basic auth is the easiest to mock, because it has no randomness).
1880 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1881 HttpRequestInfo request
;
1882 request
.method
= "GET";
1883 request
.url
= GURL("http://www.example.org/");
1884 request
.load_flags
= 0;
1887 session_deps_
.net_log
= &log
;
1888 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1889 scoped_ptr
<HttpTransaction
> trans(
1890 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1892 MockWrite data_writes1
[] = {
1894 "GET / HTTP/1.1\r\n"
1895 "Host: www.example.org\r\n"
1896 "Connection: keep-alive\r\n\r\n"),
1899 MockRead data_reads1
[] = {
1900 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1901 // Give a couple authenticate options (only the middle one is actually
1903 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1904 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1905 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1906 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1907 // Large content-length -- won't matter, as connection will be reset.
1908 MockRead("Content-Length: 10000\r\n\r\n"),
1909 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1912 // After calling trans->RestartWithAuth(), this is the request we should
1913 // be issuing -- the final header line contains the credentials.
1914 MockWrite data_writes2
[] = {
1916 "GET / HTTP/1.1\r\n"
1917 "Host: www.example.org\r\n"
1918 "Connection: keep-alive\r\n"
1919 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1922 // Lastly, the server responds with the actual content.
1923 MockRead data_reads2
[] = {
1924 MockRead("HTTP/1.0 200 OK\r\n"),
1925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1926 MockRead("Content-Length: 100\r\n\r\n"),
1927 MockRead(SYNCHRONOUS
, OK
),
1930 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1931 data_writes1
, arraysize(data_writes1
));
1932 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1933 data_writes2
, arraysize(data_writes2
));
1934 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1935 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1937 TestCompletionCallback callback1
;
1939 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1940 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1942 rv
= callback1
.WaitForResult();
1945 LoadTimingInfo load_timing_info1
;
1946 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1947 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1949 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1950 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1952 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1953 ASSERT_TRUE(response
!= NULL
);
1954 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1956 TestCompletionCallback callback2
;
1958 rv
= trans
->RestartWithAuth(
1959 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1960 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1962 rv
= callback2
.WaitForResult();
1965 LoadTimingInfo load_timing_info2
;
1966 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1967 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1968 // The load timing after restart should have a new socket ID, and times after
1969 // those of the first load timing.
1970 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1971 load_timing_info2
.connect_timing
.connect_start
);
1972 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1974 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1975 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1977 response
= trans
->GetResponseInfo();
1978 ASSERT_TRUE(response
!= NULL
);
1979 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1980 EXPECT_EQ(100, response
->headers
->GetContentLength());
1983 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1984 HttpRequestInfo request
;
1985 request
.method
= "GET";
1986 request
.url
= GURL("http://www.example.org/");
1987 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1989 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1990 scoped_ptr
<HttpTransaction
> trans(
1991 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1993 MockWrite data_writes
[] = {
1995 "GET / HTTP/1.1\r\n"
1996 "Host: www.example.org\r\n"
1997 "Connection: keep-alive\r\n\r\n"),
2000 MockRead data_reads
[] = {
2001 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2002 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2004 // Large content-length -- won't matter, as connection will be reset.
2005 MockRead("Content-Length: 10000\r\n\r\n"),
2006 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2009 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2010 data_writes
, arraysize(data_writes
));
2011 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2012 TestCompletionCallback callback
;
2014 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2015 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2017 rv
= callback
.WaitForResult();
2020 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2021 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2023 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2024 ASSERT_TRUE(response
!= NULL
);
2025 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2028 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2030 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2031 HttpRequestInfo request
;
2032 request
.method
= "GET";
2033 request
.url
= GURL("http://www.example.org/");
2034 request
.load_flags
= 0;
2037 session_deps_
.net_log
= &log
;
2038 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2040 MockWrite data_writes1
[] = {
2042 "GET / HTTP/1.1\r\n"
2043 "Host: www.example.org\r\n"
2044 "Connection: keep-alive\r\n\r\n"),
2046 // After calling trans->RestartWithAuth(), this is the request we should
2047 // be issuing -- the final header line contains the credentials.
2049 "GET / HTTP/1.1\r\n"
2050 "Host: www.example.org\r\n"
2051 "Connection: keep-alive\r\n"
2052 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2055 MockRead data_reads1
[] = {
2056 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2057 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2059 MockRead("Content-Length: 14\r\n\r\n"),
2060 MockRead("Unauthorized\r\n"),
2062 // Lastly, the server responds with the actual content.
2063 MockRead("HTTP/1.1 200 OK\r\n"),
2064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2065 MockRead("Content-Length: 5\r\n\r\n"),
2069 // If there is a regression where we disconnect a Keep-Alive
2070 // connection during an auth roundtrip, we'll end up reading this.
2071 MockRead data_reads2
[] = {
2072 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2075 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2076 data_writes1
, arraysize(data_writes1
));
2077 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2079 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2080 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2082 TestCompletionCallback callback1
;
2084 scoped_ptr
<HttpTransaction
> trans(
2085 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2086 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2087 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2089 rv
= callback1
.WaitForResult();
2092 LoadTimingInfo load_timing_info1
;
2093 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2094 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2096 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2097 ASSERT_TRUE(response
!= NULL
);
2098 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2100 TestCompletionCallback callback2
;
2102 rv
= trans
->RestartWithAuth(
2103 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2104 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2106 rv
= callback2
.WaitForResult();
2109 LoadTimingInfo load_timing_info2
;
2110 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2111 TestLoadTimingReused(load_timing_info2
);
2112 // The load timing after restart should have the same socket ID, and times
2113 // those of the first load timing.
2114 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2115 load_timing_info2
.send_start
);
2116 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2118 response
= trans
->GetResponseInfo();
2119 ASSERT_TRUE(response
!= NULL
);
2120 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2121 EXPECT_EQ(5, response
->headers
->GetContentLength());
2123 std::string response_data
;
2124 rv
= ReadTransaction(trans
.get(), &response_data
);
2126 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2127 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2130 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2131 // connection and with no response body to drain.
2132 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2133 HttpRequestInfo request
;
2134 request
.method
= "GET";
2135 request
.url
= GURL("http://www.example.org/");
2136 request
.load_flags
= 0;
2138 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2140 MockWrite data_writes1
[] = {
2142 "GET / HTTP/1.1\r\n"
2143 "Host: www.example.org\r\n"
2144 "Connection: keep-alive\r\n\r\n"),
2146 // After calling trans->RestartWithAuth(), this is the request we should
2147 // be issuing -- the final header line contains the credentials.
2149 "GET / HTTP/1.1\r\n"
2150 "Host: www.example.org\r\n"
2151 "Connection: keep-alive\r\n"
2152 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2155 MockRead data_reads1
[] = {
2156 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2157 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2158 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2160 // Lastly, the server responds with the actual content.
2161 MockRead("HTTP/1.1 200 OK\r\n"),
2162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2163 MockRead("Content-Length: 5\r\n\r\n"),
2167 // An incorrect reconnect would cause this to be read.
2168 MockRead data_reads2
[] = {
2169 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2172 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2173 data_writes1
, arraysize(data_writes1
));
2174 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2176 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2177 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2179 TestCompletionCallback callback1
;
2181 scoped_ptr
<HttpTransaction
> trans(
2182 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2183 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2184 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2186 rv
= callback1
.WaitForResult();
2189 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2190 ASSERT_TRUE(response
!= NULL
);
2191 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2193 TestCompletionCallback callback2
;
2195 rv
= trans
->RestartWithAuth(
2196 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2197 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2199 rv
= callback2
.WaitForResult();
2202 response
= trans
->GetResponseInfo();
2203 ASSERT_TRUE(response
!= NULL
);
2204 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2205 EXPECT_EQ(5, response
->headers
->GetContentLength());
2208 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2209 // connection and with a large response body to drain.
2210 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2211 HttpRequestInfo request
;
2212 request
.method
= "GET";
2213 request
.url
= GURL("http://www.example.org/");
2214 request
.load_flags
= 0;
2216 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2218 MockWrite data_writes1
[] = {
2220 "GET / HTTP/1.1\r\n"
2221 "Host: www.example.org\r\n"
2222 "Connection: keep-alive\r\n\r\n"),
2224 // After calling trans->RestartWithAuth(), this is the request we should
2225 // be issuing -- the final header line contains the credentials.
2227 "GET / HTTP/1.1\r\n"
2228 "Host: www.example.org\r\n"
2229 "Connection: keep-alive\r\n"
2230 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2233 // Respond with 5 kb of response body.
2234 std::string
large_body_string("Unauthorized");
2235 large_body_string
.append(5 * 1024, ' ');
2236 large_body_string
.append("\r\n");
2238 MockRead data_reads1
[] = {
2239 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2240 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2242 // 5134 = 12 + 5 * 1024 + 2
2243 MockRead("Content-Length: 5134\r\n\r\n"),
2244 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2246 // Lastly, the server responds with the actual content.
2247 MockRead("HTTP/1.1 200 OK\r\n"),
2248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2249 MockRead("Content-Length: 5\r\n\r\n"),
2253 // An incorrect reconnect would cause this to be read.
2254 MockRead data_reads2
[] = {
2255 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2258 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2259 data_writes1
, arraysize(data_writes1
));
2260 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2262 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2263 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2265 TestCompletionCallback callback1
;
2267 scoped_ptr
<HttpTransaction
> trans(
2268 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2269 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2270 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2272 rv
= callback1
.WaitForResult();
2275 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2276 ASSERT_TRUE(response
!= NULL
);
2277 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2279 TestCompletionCallback callback2
;
2281 rv
= trans
->RestartWithAuth(
2282 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2283 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2285 rv
= callback2
.WaitForResult();
2288 response
= trans
->GetResponseInfo();
2289 ASSERT_TRUE(response
!= NULL
);
2290 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2291 EXPECT_EQ(5, response
->headers
->GetContentLength());
2294 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2295 // connection, but the server gets impatient and closes the connection.
2296 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2297 HttpRequestInfo request
;
2298 request
.method
= "GET";
2299 request
.url
= GURL("http://www.example.org/");
2300 request
.load_flags
= 0;
2302 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2304 MockWrite data_writes1
[] = {
2306 "GET / HTTP/1.1\r\n"
2307 "Host: www.example.org\r\n"
2308 "Connection: keep-alive\r\n\r\n"),
2309 // This simulates the seemingly successful write to a closed connection
2310 // if the bug is not fixed.
2312 "GET / HTTP/1.1\r\n"
2313 "Host: www.example.org\r\n"
2314 "Connection: keep-alive\r\n"
2315 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2318 MockRead data_reads1
[] = {
2319 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2320 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2321 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2322 MockRead("Content-Length: 14\r\n\r\n"),
2323 // Tell MockTCPClientSocket to simulate the server closing the connection.
2324 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2325 MockRead("Unauthorized\r\n"),
2326 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2329 // After calling trans->RestartWithAuth(), this is the request we should
2330 // be issuing -- the final header line contains the credentials.
2331 MockWrite data_writes2
[] = {
2333 "GET / HTTP/1.1\r\n"
2334 "Host: www.example.org\r\n"
2335 "Connection: keep-alive\r\n"
2336 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2339 // Lastly, the server responds with the actual content.
2340 MockRead data_reads2
[] = {
2341 MockRead("HTTP/1.1 200 OK\r\n"),
2342 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2343 MockRead("Content-Length: 5\r\n\r\n"),
2347 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2348 data_writes1
, arraysize(data_writes1
));
2349 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2350 data_writes2
, arraysize(data_writes2
));
2351 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2352 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2354 TestCompletionCallback callback1
;
2356 scoped_ptr
<HttpTransaction
> trans(
2357 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2358 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2359 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2361 rv
= callback1
.WaitForResult();
2364 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2365 ASSERT_TRUE(response
!= NULL
);
2366 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2368 TestCompletionCallback callback2
;
2370 rv
= trans
->RestartWithAuth(
2371 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2372 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2374 rv
= callback2
.WaitForResult();
2377 response
= trans
->GetResponseInfo();
2378 ASSERT_TRUE(response
!= NULL
);
2379 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2380 EXPECT_EQ(5, response
->headers
->GetContentLength());
2383 // Test the request-challenge-retry sequence for basic auth, over a connection
2384 // that requires a restart when setting up an SSL tunnel.
2385 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2386 HttpRequestInfo request
;
2387 request
.method
= "GET";
2388 request
.url
= GURL("https://www.example.org/");
2389 // when the no authentication data flag is set.
2390 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2392 // Configure against proxy server "myproxy:70".
2393 session_deps_
.proxy_service
.reset(
2394 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2395 BoundTestNetLog log
;
2396 session_deps_
.net_log
= log
.bound().net_log();
2397 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2399 // Since we have proxy, should try to establish tunnel.
2400 MockWrite data_writes1
[] = {
2402 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2403 "Host: www.example.org\r\n"
2404 "Proxy-Connection: keep-alive\r\n\r\n"),
2406 // After calling trans->RestartWithAuth(), this is the request we should
2407 // be issuing -- the final header line contains the credentials.
2409 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2410 "Host: www.example.org\r\n"
2411 "Proxy-Connection: keep-alive\r\n"
2412 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2415 "GET / HTTP/1.1\r\n"
2416 "Host: www.example.org\r\n"
2417 "Connection: keep-alive\r\n\r\n"),
2420 // The proxy responds to the connect with a 407, using a persistent
2422 MockRead data_reads1
[] = {
2424 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2425 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2427 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2429 MockRead("HTTP/1.1 200 OK\r\n"),
2430 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2431 MockRead("Content-Length: 5\r\n\r\n"),
2432 MockRead(SYNCHRONOUS
, "hello"),
2435 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2436 data_writes1
, arraysize(data_writes1
));
2437 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2438 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2439 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2441 TestCompletionCallback callback1
;
2443 scoped_ptr
<HttpTransaction
> trans(
2444 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2446 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2447 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2449 rv
= callback1
.WaitForResult();
2451 TestNetLog::CapturedEntryList entries
;
2452 log
.GetEntries(&entries
);
2453 size_t pos
= ExpectLogContainsSomewhere(
2454 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2455 NetLog::PHASE_NONE
);
2456 ExpectLogContainsSomewhere(
2457 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2458 NetLog::PHASE_NONE
);
2460 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2461 ASSERT_TRUE(response
!= NULL
);
2462 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2463 ASSERT_FALSE(response
->headers
.get() == NULL
);
2464 EXPECT_EQ(407, response
->headers
->response_code());
2465 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2466 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2468 LoadTimingInfo load_timing_info
;
2469 // CONNECT requests and responses are handled at the connect job level, so
2470 // the transaction does not yet have a connection.
2471 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2473 TestCompletionCallback callback2
;
2476 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2477 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2479 rv
= callback2
.WaitForResult();
2482 response
= trans
->GetResponseInfo();
2483 ASSERT_TRUE(response
!= NULL
);
2485 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2486 EXPECT_EQ(200, response
->headers
->response_code());
2487 EXPECT_EQ(5, response
->headers
->GetContentLength());
2488 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2490 // The password prompt info should not be set.
2491 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2493 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2494 TestLoadTimingNotReusedWithPac(load_timing_info
,
2495 CONNECT_TIMING_HAS_SSL_TIMES
);
2498 session
->CloseAllConnections();
2501 // Test the request-challenge-retry sequence for basic auth, over a connection
2502 // that requires a restart when setting up an SSL tunnel.
2503 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2504 HttpRequestInfo request
;
2505 request
.method
= "GET";
2506 request
.url
= GURL("https://www.example.org/");
2507 // when the no authentication data flag is set.
2508 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2510 // Configure against proxy server "myproxy:70".
2511 session_deps_
.proxy_service
.reset(
2512 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2513 BoundTestNetLog log
;
2514 session_deps_
.net_log
= log
.bound().net_log();
2515 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2517 // Since we have proxy, should try to establish tunnel.
2518 MockWrite data_writes1
[] = {
2520 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2521 "Host: www.example.org\r\n"
2522 "Proxy-Connection: keep-alive\r\n\r\n"),
2524 // After calling trans->RestartWithAuth(), this is the request we should
2525 // be issuing -- the final header line contains the credentials.
2527 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2528 "Host: www.example.org\r\n"
2529 "Proxy-Connection: keep-alive\r\n"
2530 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2533 "GET / HTTP/1.1\r\n"
2534 "Host: www.example.org\r\n"
2535 "Connection: keep-alive\r\n\r\n"),
2538 // The proxy responds to the connect with a 407, using a persistent
2540 MockRead data_reads1
[] = {
2542 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2543 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2544 MockRead("Proxy-Connection: close\r\n\r\n"),
2546 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2548 MockRead("HTTP/1.1 200 OK\r\n"),
2549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2550 MockRead("Content-Length: 5\r\n\r\n"),
2551 MockRead(SYNCHRONOUS
, "hello"),
2554 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2555 data_writes1
, arraysize(data_writes1
));
2556 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2557 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2558 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2560 TestCompletionCallback callback1
;
2562 scoped_ptr
<HttpTransaction
> trans(
2563 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2565 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2566 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2568 rv
= callback1
.WaitForResult();
2570 TestNetLog::CapturedEntryList entries
;
2571 log
.GetEntries(&entries
);
2572 size_t pos
= ExpectLogContainsSomewhere(
2573 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2574 NetLog::PHASE_NONE
);
2575 ExpectLogContainsSomewhere(
2577 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2578 NetLog::PHASE_NONE
);
2580 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2581 ASSERT_TRUE(response
!= NULL
);
2582 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2583 ASSERT_FALSE(response
->headers
.get() == NULL
);
2584 EXPECT_EQ(407, response
->headers
->response_code());
2585 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2586 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2588 LoadTimingInfo load_timing_info
;
2589 // CONNECT requests and responses are handled at the connect job level, so
2590 // the transaction does not yet have a connection.
2591 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2593 TestCompletionCallback callback2
;
2595 rv
= trans
->RestartWithAuth(
2596 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2597 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2599 rv
= callback2
.WaitForResult();
2602 response
= trans
->GetResponseInfo();
2603 ASSERT_TRUE(response
!= NULL
);
2605 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2606 EXPECT_EQ(200, response
->headers
->response_code());
2607 EXPECT_EQ(5, response
->headers
->GetContentLength());
2608 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2610 // The password prompt info should not be set.
2611 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2613 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2614 TestLoadTimingNotReusedWithPac(load_timing_info
,
2615 CONNECT_TIMING_HAS_SSL_TIMES
);
2618 session
->CloseAllConnections();
2621 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2622 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2623 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2624 HttpRequestInfo request
;
2625 request
.method
= "GET";
2626 request
.url
= GURL("https://www.example.org/");
2627 // Ensure that proxy authentication is attempted even
2628 // when the no authentication data flag is set.
2629 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2631 // Configure against proxy server "myproxy:70".
2632 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2633 BoundTestNetLog log
;
2634 session_deps_
.net_log
= log
.bound().net_log();
2635 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2637 scoped_ptr
<HttpTransaction
> trans(
2638 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2640 // Since we have proxy, should try to establish tunnel.
2641 MockWrite data_writes1
[] = {
2643 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2644 "Host: www.example.org\r\n"
2645 "Proxy-Connection: keep-alive\r\n\r\n"),
2647 // After calling trans->RestartWithAuth(), this is the request we should
2648 // be issuing -- the final header line contains the credentials.
2650 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2651 "Host: www.example.org\r\n"
2652 "Proxy-Connection: keep-alive\r\n"
2653 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2656 // The proxy responds to the connect with a 407, using a persistent
2657 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2658 MockRead data_reads1
[] = {
2660 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2661 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2662 MockRead("Proxy-Connection: keep-alive\r\n"),
2663 MockRead("Content-Length: 10\r\n\r\n"),
2664 MockRead("0123456789"),
2666 // Wrong credentials (wrong password).
2667 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2668 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2669 MockRead("Proxy-Connection: keep-alive\r\n"),
2670 MockRead("Content-Length: 10\r\n\r\n"),
2671 // No response body because the test stops reading here.
2672 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2675 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2676 data_writes1
, arraysize(data_writes1
));
2677 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2679 TestCompletionCallback callback1
;
2681 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2682 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2684 rv
= callback1
.WaitForResult();
2686 TestNetLog::CapturedEntryList entries
;
2687 log
.GetEntries(&entries
);
2688 size_t pos
= ExpectLogContainsSomewhere(
2689 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2690 NetLog::PHASE_NONE
);
2691 ExpectLogContainsSomewhere(
2692 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2693 NetLog::PHASE_NONE
);
2695 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2696 ASSERT_TRUE(response
);
2697 ASSERT_TRUE(response
->headers
);
2698 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2699 EXPECT_EQ(407, response
->headers
->response_code());
2700 EXPECT_EQ(10, response
->headers
->GetContentLength());
2701 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2702 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2704 TestCompletionCallback callback2
;
2706 // Wrong password (should be "bar").
2708 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2709 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2711 rv
= callback2
.WaitForResult();
2714 response
= trans
->GetResponseInfo();
2715 ASSERT_TRUE(response
);
2716 ASSERT_TRUE(response
->headers
);
2717 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2718 EXPECT_EQ(407, response
->headers
->response_code());
2719 EXPECT_EQ(10, response
->headers
->GetContentLength());
2720 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2721 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2723 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2725 session
->CloseAllConnections();
2728 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2729 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2730 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2731 HttpRequestInfo request
;
2732 request
.method
= "GET";
2733 request
.url
= GURL("https://www.example.org/");
2734 // Ensure that proxy authentication is attempted even
2735 // when the no authentication data flag is set.
2736 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2738 // Configure against proxy server "myproxy:70".
2739 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2740 BoundTestNetLog log
;
2741 session_deps_
.net_log
= log
.bound().net_log();
2742 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2744 scoped_ptr
<HttpTransaction
> trans(
2745 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2747 // Since we have proxy, should try to establish tunnel.
2748 MockWrite data_writes1
[] = {
2750 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2751 "Host: www.example.org\r\n"
2752 "Proxy-Connection: keep-alive\r\n\r\n"),
2754 // After calling trans->RestartWithAuth(), this is the request we should
2755 // be issuing -- the final header line contains the credentials.
2757 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2758 "Host: www.example.org\r\n"
2759 "Proxy-Connection: keep-alive\r\n"
2760 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2763 // The proxy responds to the connect with a 407, using a persistent
2765 MockRead data_reads1
[] = {
2767 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2768 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2769 MockRead("Content-Length: 10\r\n\r\n"),
2770 MockRead("0123456789"),
2772 // Wrong credentials (wrong password).
2773 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2774 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2775 MockRead("Content-Length: 10\r\n\r\n"),
2776 // No response body because the test stops reading here.
2777 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2780 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2781 data_writes1
, arraysize(data_writes1
));
2782 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2784 TestCompletionCallback callback1
;
2786 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2789 rv
= callback1
.WaitForResult();
2791 TestNetLog::CapturedEntryList entries
;
2792 log
.GetEntries(&entries
);
2793 size_t pos
= ExpectLogContainsSomewhere(
2794 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2795 NetLog::PHASE_NONE
);
2796 ExpectLogContainsSomewhere(
2798 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2799 NetLog::PHASE_NONE
);
2801 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2802 ASSERT_TRUE(response
);
2803 ASSERT_TRUE(response
->headers
);
2804 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2805 EXPECT_EQ(407, response
->headers
->response_code());
2806 EXPECT_EQ(10, response
->headers
->GetContentLength());
2807 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2808 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2810 TestCompletionCallback callback2
;
2812 // Wrong password (should be "bar").
2813 rv
= trans
->RestartWithAuth(
2814 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2815 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2817 rv
= callback2
.WaitForResult();
2820 response
= trans
->GetResponseInfo();
2821 ASSERT_TRUE(response
);
2822 ASSERT_TRUE(response
->headers
);
2823 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2824 EXPECT_EQ(407, response
->headers
->response_code());
2825 EXPECT_EQ(10, response
->headers
->GetContentLength());
2826 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2827 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2829 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2831 session
->CloseAllConnections();
2834 // Test that we don't read the response body when we fail to establish a tunnel,
2835 // even if the user cancels the proxy's auth attempt.
2836 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2837 HttpRequestInfo request
;
2838 request
.method
= "GET";
2839 request
.url
= GURL("https://www.example.org/");
2840 request
.load_flags
= 0;
2842 // Configure against proxy server "myproxy:70".
2843 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2845 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2847 scoped_ptr
<HttpTransaction
> trans(
2848 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2850 // Since we have proxy, should try to establish tunnel.
2851 MockWrite data_writes
[] = {
2853 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2854 "Host: www.example.org\r\n"
2855 "Proxy-Connection: keep-alive\r\n\r\n"),
2858 // The proxy responds to the connect with a 407.
2859 MockRead data_reads
[] = {
2860 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2861 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2862 MockRead("Content-Length: 10\r\n\r\n"),
2863 MockRead("0123456789"), // Should not be reached.
2864 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2867 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2868 data_writes
, arraysize(data_writes
));
2869 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2871 TestCompletionCallback callback
;
2873 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2874 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2876 rv
= callback
.WaitForResult();
2879 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2880 ASSERT_TRUE(response
);
2881 ASSERT_TRUE(response
->headers
);
2882 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2883 EXPECT_EQ(407, response
->headers
->response_code());
2884 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2886 std::string response_data
;
2887 rv
= ReadTransaction(trans
.get(), &response_data
);
2888 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2890 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2891 session
->CloseAllConnections();
2894 // Test that we don't pass extraneous headers from the proxy's response to the
2895 // caller when the proxy responds to CONNECT with 407.
2896 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2897 HttpRequestInfo request
;
2898 request
.method
= "GET";
2899 request
.url
= GURL("https://www.example.org/");
2900 request
.load_flags
= 0;
2902 // Configure against proxy server "myproxy:70".
2903 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2905 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2907 scoped_ptr
<HttpTransaction
> trans(
2908 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2910 // Since we have proxy, should try to establish tunnel.
2911 MockWrite data_writes
[] = {
2913 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2914 "Host: www.example.org\r\n"
2915 "Proxy-Connection: keep-alive\r\n\r\n"),
2918 // The proxy responds to the connect with a 407.
2919 MockRead data_reads
[] = {
2920 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2921 MockRead("X-Foo: bar\r\n"),
2922 MockRead("Set-Cookie: foo=bar\r\n"),
2923 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2924 MockRead("Content-Length: 10\r\n\r\n"),
2925 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2928 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2929 arraysize(data_writes
));
2930 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2932 TestCompletionCallback callback
;
2934 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2935 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2937 rv
= callback
.WaitForResult();
2940 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2941 ASSERT_TRUE(response
);
2942 ASSERT_TRUE(response
->headers
);
2943 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2944 EXPECT_EQ(407, response
->headers
->response_code());
2945 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2946 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2947 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2949 std::string response_data
;
2950 rv
= ReadTransaction(trans
.get(), &response_data
);
2951 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2953 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2954 session
->CloseAllConnections();
2957 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2958 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2959 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2960 HttpRequestInfo request
;
2961 request
.method
= "GET";
2962 request
.url
= GURL("http://www.example.org/");
2963 request
.load_flags
= 0;
2965 // We are using a DIRECT connection (i.e. no proxy) for this session.
2966 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2967 scoped_ptr
<HttpTransaction
> trans(
2968 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2970 MockWrite data_writes1
[] = {
2972 "GET / HTTP/1.1\r\n"
2973 "Host: www.example.org\r\n"
2974 "Connection: keep-alive\r\n\r\n"),
2977 MockRead data_reads1
[] = {
2978 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2979 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2980 // Large content-length -- won't matter, as connection will be reset.
2981 MockRead("Content-Length: 10000\r\n\r\n"),
2982 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2985 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2986 data_writes1
, arraysize(data_writes1
));
2987 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2989 TestCompletionCallback callback
;
2991 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2992 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2994 rv
= callback
.WaitForResult();
2995 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2998 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2999 // through a non-authenticating proxy. The request should fail with
3000 // ERR_UNEXPECTED_PROXY_AUTH.
3001 // Note that it is impossible to detect if an HTTP server returns a 407 through
3002 // a non-authenticating proxy - there is nothing to indicate whether the
3003 // response came from the proxy or the server, so it is treated as if the proxy
3004 // issued the challenge.
3005 TEST_P(HttpNetworkTransactionTest
,
3006 HttpsServerRequestsProxyAuthThroughProxy
) {
3007 HttpRequestInfo request
;
3008 request
.method
= "GET";
3009 request
.url
= GURL("https://www.example.org/");
3011 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3012 BoundTestNetLog log
;
3013 session_deps_
.net_log
= log
.bound().net_log();
3014 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3016 // Since we have proxy, should try to establish tunnel.
3017 MockWrite data_writes1
[] = {
3019 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3020 "Host: www.example.org\r\n"
3021 "Proxy-Connection: keep-alive\r\n\r\n"),
3024 "GET / HTTP/1.1\r\n"
3025 "Host: www.example.org\r\n"
3026 "Connection: keep-alive\r\n\r\n"),
3029 MockRead data_reads1
[] = {
3030 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3032 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3033 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3035 MockRead(SYNCHRONOUS
, OK
),
3038 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3039 data_writes1
, arraysize(data_writes1
));
3040 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3041 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3042 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3044 TestCompletionCallback callback1
;
3046 scoped_ptr
<HttpTransaction
> trans(
3047 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3049 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3050 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3052 rv
= callback1
.WaitForResult();
3053 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3054 TestNetLog::CapturedEntryList entries
;
3055 log
.GetEntries(&entries
);
3056 size_t pos
= ExpectLogContainsSomewhere(
3057 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3058 NetLog::PHASE_NONE
);
3059 ExpectLogContainsSomewhere(
3061 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3062 NetLog::PHASE_NONE
);
3065 // Test the load timing for HTTPS requests with an HTTP proxy.
3066 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3067 HttpRequestInfo request1
;
3068 request1
.method
= "GET";
3069 request1
.url
= GURL("https://www.example.org/1");
3071 HttpRequestInfo request2
;
3072 request2
.method
= "GET";
3073 request2
.url
= GURL("https://www.example.org/2");
3075 // Configure against proxy server "myproxy:70".
3076 session_deps_
.proxy_service
.reset(
3077 ProxyService::CreateFixed("PROXY myproxy:70"));
3078 BoundTestNetLog log
;
3079 session_deps_
.net_log
= log
.bound().net_log();
3080 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3082 // Since we have proxy, should try to establish tunnel.
3083 MockWrite data_writes1
[] = {
3085 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3086 "Host: www.example.org\r\n"
3087 "Proxy-Connection: keep-alive\r\n\r\n"),
3090 "GET /1 HTTP/1.1\r\n"
3091 "Host: www.example.org\r\n"
3092 "Connection: keep-alive\r\n\r\n"),
3095 "GET /2 HTTP/1.1\r\n"
3096 "Host: www.example.org\r\n"
3097 "Connection: keep-alive\r\n\r\n"),
3100 // The proxy responds to the connect with a 407, using a persistent
3102 MockRead data_reads1
[] = {
3103 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3105 MockRead("HTTP/1.1 200 OK\r\n"),
3106 MockRead("Content-Length: 1\r\n\r\n"),
3107 MockRead(SYNCHRONOUS
, "1"),
3109 MockRead("HTTP/1.1 200 OK\r\n"),
3110 MockRead("Content-Length: 2\r\n\r\n"),
3111 MockRead(SYNCHRONOUS
, "22"),
3114 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3115 data_writes1
, arraysize(data_writes1
));
3116 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3117 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3118 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3120 TestCompletionCallback callback1
;
3121 scoped_ptr
<HttpTransaction
> trans1(
3122 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3124 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3125 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3127 rv
= callback1
.WaitForResult();
3130 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3131 ASSERT_TRUE(response1
!= NULL
);
3132 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3133 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3135 LoadTimingInfo load_timing_info1
;
3136 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3137 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3141 TestCompletionCallback callback2
;
3142 scoped_ptr
<HttpTransaction
> trans2(
3143 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3145 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3146 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3148 rv
= callback2
.WaitForResult();
3151 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3152 ASSERT_TRUE(response2
!= NULL
);
3153 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3154 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3156 LoadTimingInfo load_timing_info2
;
3157 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3158 TestLoadTimingReused(load_timing_info2
);
3160 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3163 session
->CloseAllConnections();
3166 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3167 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3168 HttpRequestInfo request1
;
3169 request1
.method
= "GET";
3170 request1
.url
= GURL("https://www.example.org/1");
3172 HttpRequestInfo request2
;
3173 request2
.method
= "GET";
3174 request2
.url
= GURL("https://www.example.org/2");
3176 // Configure against proxy server "myproxy:70".
3177 session_deps_
.proxy_service
.reset(
3178 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3179 BoundTestNetLog log
;
3180 session_deps_
.net_log
= log
.bound().net_log();
3181 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3183 // Since we have proxy, should try to establish tunnel.
3184 MockWrite data_writes1
[] = {
3186 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3187 "Host: www.example.org\r\n"
3188 "Proxy-Connection: keep-alive\r\n\r\n"),
3191 "GET /1 HTTP/1.1\r\n"
3192 "Host: www.example.org\r\n"
3193 "Connection: keep-alive\r\n\r\n"),
3196 "GET /2 HTTP/1.1\r\n"
3197 "Host: www.example.org\r\n"
3198 "Connection: keep-alive\r\n\r\n"),
3201 // The proxy responds to the connect with a 407, using a persistent
3203 MockRead data_reads1
[] = {
3204 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3206 MockRead("HTTP/1.1 200 OK\r\n"),
3207 MockRead("Content-Length: 1\r\n\r\n"),
3208 MockRead(SYNCHRONOUS
, "1"),
3210 MockRead("HTTP/1.1 200 OK\r\n"),
3211 MockRead("Content-Length: 2\r\n\r\n"),
3212 MockRead(SYNCHRONOUS
, "22"),
3215 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3216 data_writes1
, arraysize(data_writes1
));
3217 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3218 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3219 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3221 TestCompletionCallback callback1
;
3222 scoped_ptr
<HttpTransaction
> trans1(
3223 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3225 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3226 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3228 rv
= callback1
.WaitForResult();
3231 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3232 ASSERT_TRUE(response1
!= NULL
);
3233 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3234 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3236 LoadTimingInfo load_timing_info1
;
3237 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3238 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3239 CONNECT_TIMING_HAS_SSL_TIMES
);
3243 TestCompletionCallback callback2
;
3244 scoped_ptr
<HttpTransaction
> trans2(
3245 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3247 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3248 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3250 rv
= callback2
.WaitForResult();
3253 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3254 ASSERT_TRUE(response2
!= NULL
);
3255 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3256 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3258 LoadTimingInfo load_timing_info2
;
3259 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3260 TestLoadTimingReusedWithPac(load_timing_info2
);
3262 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3265 session
->CloseAllConnections();
3268 // Test a simple get through an HTTPS Proxy.
3269 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3270 HttpRequestInfo request
;
3271 request
.method
= "GET";
3272 request
.url
= GURL("http://www.example.org/");
3274 // Configure against https proxy server "proxy:70".
3275 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3276 "https://proxy:70"));
3277 BoundTestNetLog log
;
3278 session_deps_
.net_log
= log
.bound().net_log();
3279 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3281 // Since we have proxy, should use full url
3282 MockWrite data_writes1
[] = {
3284 "GET http://www.example.org/ HTTP/1.1\r\n"
3285 "Host: www.example.org\r\n"
3286 "Proxy-Connection: keep-alive\r\n\r\n"),
3289 MockRead data_reads1
[] = {
3290 MockRead("HTTP/1.1 200 OK\r\n"),
3291 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3292 MockRead("Content-Length: 100\r\n\r\n"),
3293 MockRead(SYNCHRONOUS
, OK
),
3296 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3297 data_writes1
, arraysize(data_writes1
));
3298 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3299 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3300 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3302 TestCompletionCallback callback1
;
3304 scoped_ptr
<HttpTransaction
> trans(
3305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3307 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3308 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3310 rv
= callback1
.WaitForResult();
3313 LoadTimingInfo load_timing_info
;
3314 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3315 TestLoadTimingNotReused(load_timing_info
,
3316 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3318 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3319 ASSERT_TRUE(response
!= NULL
);
3321 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3322 EXPECT_EQ(200, response
->headers
->response_code());
3323 EXPECT_EQ(100, response
->headers
->GetContentLength());
3324 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3326 // The password prompt info should not be set.
3327 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3330 // Test a SPDY get through an HTTPS Proxy.
3331 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3332 HttpRequestInfo request
;
3333 request
.method
= "GET";
3334 request
.url
= GURL("http://www.example.org/");
3335 request
.load_flags
= 0;
3337 // Configure against https proxy server "proxy:70".
3338 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3339 "https://proxy:70"));
3340 BoundTestNetLog log
;
3341 session_deps_
.net_log
= log
.bound().net_log();
3342 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3344 // fetch http://www.example.org/ via SPDY
3345 scoped_ptr
<SpdyFrame
> req(
3346 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3347 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
3349 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3350 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3351 MockRead spdy_reads
[] = {
3352 CreateMockRead(*resp
),
3353 CreateMockRead(*data
),
3354 MockRead(ASYNC
, 0, 0),
3357 DelayedSocketData
spdy_data(
3358 1, // wait for one write to finish before reading.
3359 spdy_reads
, arraysize(spdy_reads
),
3360 spdy_writes
, arraysize(spdy_writes
));
3361 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3363 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3364 ssl
.SetNextProto(GetParam());
3365 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3367 TestCompletionCallback callback1
;
3369 scoped_ptr
<HttpTransaction
> trans(
3370 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3372 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3373 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3375 rv
= callback1
.WaitForResult();
3378 LoadTimingInfo load_timing_info
;
3379 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3380 TestLoadTimingNotReused(load_timing_info
,
3381 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3383 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3384 ASSERT_TRUE(response
!= NULL
);
3385 ASSERT_TRUE(response
->headers
.get() != NULL
);
3386 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3388 std::string response_data
;
3389 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3390 EXPECT_EQ(kUploadData
, response_data
);
3393 // Verifies that a session which races and wins against the owning transaction
3394 // (completing prior to host resolution), doesn't fail the transaction.
3395 // Regression test for crbug.com/334413.
3396 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3397 HttpRequestInfo request
;
3398 request
.method
= "GET";
3399 request
.url
= GURL("http://www.example.org/");
3400 request
.load_flags
= 0;
3402 // Configure SPDY proxy server "proxy:70".
3403 session_deps_
.proxy_service
.reset(
3404 ProxyService::CreateFixed("https://proxy:70"));
3405 BoundTestNetLog log
;
3406 session_deps_
.net_log
= log
.bound().net_log();
3407 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3409 // Fetch http://www.example.org/ through the SPDY proxy.
3410 scoped_ptr
<SpdyFrame
> req(
3411 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3412 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3414 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3415 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3416 MockRead spdy_reads
[] = {
3417 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3420 DelayedSocketData
spdy_data(
3421 1, // wait for one write to finish before reading.
3423 arraysize(spdy_reads
),
3425 arraysize(spdy_writes
));
3426 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3428 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3429 ssl
.SetNextProto(GetParam());
3430 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3432 TestCompletionCallback callback1
;
3434 scoped_ptr
<HttpTransaction
> trans(
3435 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3437 // Stall the hostname resolution begun by the transaction.
3438 session_deps_
.host_resolver
->set_synchronous_mode(false);
3439 session_deps_
.host_resolver
->set_ondemand_mode(true);
3441 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3442 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3444 // Race a session to the proxy, which completes first.
3445 session_deps_
.host_resolver
->set_ondemand_mode(false);
3447 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3448 base::WeakPtr
<SpdySession
> spdy_session
=
3449 CreateSecureSpdySession(session
, key
, log
.bound());
3451 // Unstall the resolution begun by the transaction.
3452 session_deps_
.host_resolver
->set_ondemand_mode(true);
3453 session_deps_
.host_resolver
->ResolveAllPending();
3455 EXPECT_FALSE(callback1
.have_result());
3456 rv
= callback1
.WaitForResult();
3459 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3460 ASSERT_TRUE(response
!= NULL
);
3461 ASSERT_TRUE(response
->headers
.get() != NULL
);
3462 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3464 std::string response_data
;
3465 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3466 EXPECT_EQ(kUploadData
, response_data
);
3469 // Test a SPDY get through an HTTPS Proxy.
3470 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3471 HttpRequestInfo request
;
3472 request
.method
= "GET";
3473 request
.url
= GURL("http://www.example.org/");
3474 request
.load_flags
= 0;
3476 // Configure against https proxy server "myproxy:70".
3477 session_deps_
.proxy_service
.reset(
3478 ProxyService::CreateFixed("https://myproxy:70"));
3479 BoundTestNetLog log
;
3480 session_deps_
.net_log
= log
.bound().net_log();
3481 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3483 // The first request will be a bare GET, the second request will be a
3484 // GET with a Proxy-Authorization header.
3485 scoped_ptr
<SpdyFrame
> req_get(
3486 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3487 const char* const kExtraAuthorizationHeaders
[] = {
3488 "proxy-authorization", "Basic Zm9vOmJhcg=="
3490 scoped_ptr
<SpdyFrame
> req_get_authorization(
3491 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3492 arraysize(kExtraAuthorizationHeaders
) / 2,
3497 MockWrite spdy_writes
[] = {
3498 CreateMockWrite(*req_get
, 1),
3499 CreateMockWrite(*req_get_authorization
, 4),
3502 // The first response is a 407 proxy authentication challenge, and the second
3503 // response will be a 200 response since the second request includes a valid
3504 // Authorization header.
3505 const char* const kExtraAuthenticationHeaders
[] = {
3506 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3508 scoped_ptr
<SpdyFrame
> resp_authentication(
3509 spdy_util_
.ConstructSpdySynReplyError(
3510 "407 Proxy Authentication Required",
3511 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3513 scoped_ptr
<SpdyFrame
> body_authentication(
3514 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3515 scoped_ptr
<SpdyFrame
> resp_data(
3516 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3517 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3518 MockRead spdy_reads
[] = {
3519 CreateMockRead(*resp_authentication
, 2),
3520 CreateMockRead(*body_authentication
, 3),
3521 CreateMockRead(*resp_data
, 5),
3522 CreateMockRead(*body_data
, 6),
3523 MockRead(ASYNC
, 0, 7),
3526 OrderedSocketData
data(
3527 spdy_reads
, arraysize(spdy_reads
),
3528 spdy_writes
, arraysize(spdy_writes
));
3529 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3531 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3532 ssl
.SetNextProto(GetParam());
3533 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3535 TestCompletionCallback callback1
;
3537 scoped_ptr
<HttpTransaction
> trans(
3538 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3540 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3541 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3543 rv
= callback1
.WaitForResult();
3546 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3548 ASSERT_TRUE(response
!= NULL
);
3549 ASSERT_TRUE(response
->headers
.get() != NULL
);
3550 EXPECT_EQ(407, response
->headers
->response_code());
3551 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3552 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3554 TestCompletionCallback callback2
;
3556 rv
= trans
->RestartWithAuth(
3557 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3560 rv
= callback2
.WaitForResult();
3563 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3565 ASSERT_TRUE(response_restart
!= NULL
);
3566 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3567 EXPECT_EQ(200, response_restart
->headers
->response_code());
3568 // The password prompt info should not be set.
3569 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3572 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3573 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3574 HttpRequestInfo request
;
3575 request
.method
= "GET";
3576 request
.url
= GURL("https://www.example.org/");
3577 request
.load_flags
= 0;
3579 // Configure against https proxy server "proxy:70".
3580 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3581 "https://proxy:70"));
3582 BoundTestNetLog log
;
3583 session_deps_
.net_log
= log
.bound().net_log();
3584 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3586 scoped_ptr
<HttpTransaction
> trans(
3587 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3589 // CONNECT to www.example.org:443 via SPDY
3590 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3591 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3592 // fetch https://www.example.org/ via HTTP
3595 "GET / HTTP/1.1\r\n"
3596 "Host: www.example.org\r\n"
3597 "Connection: keep-alive\r\n\r\n";
3598 scoped_ptr
<SpdyFrame
> wrapped_get(
3599 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3600 scoped_ptr
<SpdyFrame
> conn_resp(
3601 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3602 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3603 "Content-Length: 10\r\n\r\n";
3604 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3605 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3606 scoped_ptr
<SpdyFrame
> wrapped_body(
3607 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3608 scoped_ptr
<SpdyFrame
> window_update(
3609 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3611 MockWrite spdy_writes
[] = {
3612 CreateMockWrite(*connect
, 1),
3613 CreateMockWrite(*wrapped_get
, 3),
3614 CreateMockWrite(*window_update
, 5),
3617 MockRead spdy_reads
[] = {
3618 CreateMockRead(*conn_resp
, 2, ASYNC
),
3619 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3620 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3621 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3622 MockRead(ASYNC
, 0, 8),
3625 OrderedSocketData
spdy_data(
3626 spdy_reads
, arraysize(spdy_reads
),
3627 spdy_writes
, arraysize(spdy_writes
));
3628 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3630 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3631 ssl
.SetNextProto(GetParam());
3632 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3633 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3634 ssl2
.was_npn_negotiated
= false;
3635 ssl2
.protocol_negotiated
= kProtoUnknown
;
3636 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3638 TestCompletionCallback callback1
;
3640 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3643 rv
= callback1
.WaitForResult();
3646 LoadTimingInfo load_timing_info
;
3647 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3648 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3650 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3651 ASSERT_TRUE(response
!= NULL
);
3652 ASSERT_TRUE(response
->headers
.get() != NULL
);
3653 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3655 std::string response_data
;
3656 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3657 EXPECT_EQ("1234567890", response_data
);
3660 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3661 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3662 HttpRequestInfo request
;
3663 request
.method
= "GET";
3664 request
.url
= GURL("https://www.example.org/");
3665 request
.load_flags
= 0;
3667 // Configure against https proxy server "proxy:70".
3668 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3669 "https://proxy:70"));
3670 BoundTestNetLog log
;
3671 session_deps_
.net_log
= log
.bound().net_log();
3672 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3674 scoped_ptr
<HttpTransaction
> trans(
3675 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3677 // CONNECT to www.example.org:443 via SPDY
3678 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3679 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3680 // fetch https://www.example.org/ via SPDY
3681 const char kMyUrl
[] = "https://www.example.org/";
3682 scoped_ptr
<SpdyFrame
> get(
3683 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3684 scoped_ptr
<SpdyFrame
> wrapped_get(
3685 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3686 scoped_ptr
<SpdyFrame
> conn_resp(
3687 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3688 scoped_ptr
<SpdyFrame
> get_resp(
3689 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3690 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3691 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3692 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3693 scoped_ptr
<SpdyFrame
> wrapped_body(
3694 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3695 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3696 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3697 scoped_ptr
<SpdyFrame
> window_update_body(
3698 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3700 MockWrite spdy_writes
[] = {
3701 CreateMockWrite(*connect
, 1),
3702 CreateMockWrite(*wrapped_get
, 3),
3703 CreateMockWrite(*window_update_get_resp
, 5),
3704 CreateMockWrite(*window_update_body
, 7),
3707 MockRead spdy_reads
[] = {
3708 CreateMockRead(*conn_resp
, 2, ASYNC
),
3709 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3710 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3711 MockRead(ASYNC
, 0, 8),
3714 OrderedSocketData
spdy_data(
3715 spdy_reads
, arraysize(spdy_reads
),
3716 spdy_writes
, arraysize(spdy_writes
));
3717 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3719 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3720 ssl
.SetNextProto(GetParam());
3721 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3722 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3723 ssl2
.SetNextProto(GetParam());
3724 ssl2
.protocol_negotiated
= GetParam();
3725 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3727 TestCompletionCallback callback1
;
3729 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3730 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3732 rv
= callback1
.WaitForResult();
3735 LoadTimingInfo load_timing_info
;
3736 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3737 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3739 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3740 ASSERT_TRUE(response
!= NULL
);
3741 ASSERT_TRUE(response
->headers
.get() != NULL
);
3742 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3744 std::string response_data
;
3745 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3746 EXPECT_EQ(kUploadData
, response_data
);
3749 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3750 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3751 HttpRequestInfo request
;
3752 request
.method
= "GET";
3753 request
.url
= GURL("https://www.example.org/");
3754 request
.load_flags
= 0;
3756 // Configure against https proxy server "proxy:70".
3757 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3758 "https://proxy:70"));
3759 BoundTestNetLog log
;
3760 session_deps_
.net_log
= log
.bound().net_log();
3761 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3763 scoped_ptr
<HttpTransaction
> trans(
3764 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3766 // CONNECT to www.example.org:443 via SPDY
3767 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3768 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3769 scoped_ptr
<SpdyFrame
> get(
3770 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3772 MockWrite spdy_writes
[] = {
3773 CreateMockWrite(*connect
, 1),
3774 CreateMockWrite(*get
, 3),
3777 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3778 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3779 MockRead spdy_reads
[] = {
3780 CreateMockRead(*resp
, 2, ASYNC
),
3781 MockRead(ASYNC
, 0, 4),
3784 OrderedSocketData
spdy_data(
3785 spdy_reads
, arraysize(spdy_reads
),
3786 spdy_writes
, arraysize(spdy_writes
));
3787 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3789 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3790 ssl
.SetNextProto(GetParam());
3791 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3792 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3793 ssl2
.SetNextProto(GetParam());
3794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3796 TestCompletionCallback callback1
;
3798 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3799 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3801 rv
= callback1
.WaitForResult();
3802 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3804 // TODO(ttuttle): Anything else to check here?
3807 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3808 // HTTPS Proxy to different servers.
3809 TEST_P(HttpNetworkTransactionTest
,
3810 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3811 // Configure against https proxy server "proxy:70".
3812 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3813 "https://proxy:70"));
3814 BoundTestNetLog log
;
3815 session_deps_
.net_log
= log
.bound().net_log();
3816 scoped_refptr
<HttpNetworkSession
> session(
3817 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3819 HttpRequestInfo request1
;
3820 request1
.method
= "GET";
3821 request1
.url
= GURL("https://www.example.org/");
3822 request1
.load_flags
= 0;
3824 HttpRequestInfo request2
;
3825 request2
.method
= "GET";
3826 request2
.url
= GURL("https://mail.example.org/");
3827 request2
.load_flags
= 0;
3829 // CONNECT to www.example.org:443 via SPDY.
3830 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3831 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3832 scoped_ptr
<SpdyFrame
> conn_resp1(
3833 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3835 // Fetch https://www.example.org/ via HTTP.
3837 "GET / HTTP/1.1\r\n"
3838 "Host: www.example.org\r\n"
3839 "Connection: keep-alive\r\n\r\n";
3840 scoped_ptr
<SpdyFrame
> wrapped_get1(
3841 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3842 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3843 "Content-Length: 1\r\n\r\n";
3844 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3845 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3846 scoped_ptr
<SpdyFrame
> wrapped_body1(
3847 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3848 scoped_ptr
<SpdyFrame
> window_update(
3849 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3851 // CONNECT to mail.example.org:443 via SPDY.
3852 SpdyHeaderBlock connect2_block
;
3853 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3854 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3855 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3856 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3857 scoped_ptr
<SpdyFrame
> connect2(
3858 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3860 scoped_ptr
<SpdyFrame
> conn_resp2(
3861 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3863 // Fetch https://mail.example.org/ via HTTP.
3865 "GET / HTTP/1.1\r\n"
3866 "Host: mail.example.org\r\n"
3867 "Connection: keep-alive\r\n\r\n";
3868 scoped_ptr
<SpdyFrame
> wrapped_get2(
3869 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3870 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3871 "Content-Length: 2\r\n\r\n";
3872 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3873 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3874 scoped_ptr
<SpdyFrame
> wrapped_body2(
3875 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3877 MockWrite spdy_writes
[] = {
3878 CreateMockWrite(*connect1
, 0),
3879 CreateMockWrite(*wrapped_get1
, 2),
3880 CreateMockWrite(*connect2
, 5),
3881 CreateMockWrite(*wrapped_get2
, 7),
3884 MockRead spdy_reads
[] = {
3885 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3886 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3887 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3888 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3889 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3890 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3891 MockRead(ASYNC
, 0, 10),
3894 DeterministicSocketData
spdy_data(
3895 spdy_reads
, arraysize(spdy_reads
),
3896 spdy_writes
, arraysize(spdy_writes
));
3897 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3899 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3900 ssl
.SetNextProto(GetParam());
3901 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3902 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3903 ssl2
.was_npn_negotiated
= false;
3904 ssl2
.protocol_negotiated
= kProtoUnknown
;
3905 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3906 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3907 ssl3
.was_npn_negotiated
= false;
3908 ssl3
.protocol_negotiated
= kProtoUnknown
;
3909 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3911 TestCompletionCallback callback
;
3913 scoped_ptr
<HttpTransaction
> trans(
3914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3915 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3916 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3917 // The first connect and request, each of their responses, and the body.
3918 spdy_data
.RunFor(5);
3920 rv
= callback
.WaitForResult();
3923 LoadTimingInfo load_timing_info
;
3924 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3925 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3927 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3928 ASSERT_TRUE(response
!= NULL
);
3929 ASSERT_TRUE(response
->headers
.get() != NULL
);
3930 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3932 std::string response_data
;
3933 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3934 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3936 scoped_ptr
<HttpTransaction
> trans2(
3937 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3938 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3939 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3941 // The second connect and request, each of their responses, and the body.
3942 spdy_data
.RunFor(5);
3943 rv
= callback
.WaitForResult();
3946 LoadTimingInfo load_timing_info2
;
3947 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3948 // Even though the SPDY connection is reused, a new tunnelled connection has
3949 // to be created, so the socket's load timing looks like a fresh connection.
3950 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3952 // The requests should have different IDs, since they each are using their own
3954 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3956 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3959 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3960 // HTTPS Proxy to the same server.
3961 TEST_P(HttpNetworkTransactionTest
,
3962 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3963 // Configure against https proxy server "proxy:70".
3964 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3965 "https://proxy:70"));
3966 BoundTestNetLog log
;
3967 session_deps_
.net_log
= log
.bound().net_log();
3968 scoped_refptr
<HttpNetworkSession
> session(
3969 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3971 HttpRequestInfo request1
;
3972 request1
.method
= "GET";
3973 request1
.url
= GURL("https://www.example.org/");
3974 request1
.load_flags
= 0;
3976 HttpRequestInfo request2
;
3977 request2
.method
= "GET";
3978 request2
.url
= GURL("https://www.example.org/2");
3979 request2
.load_flags
= 0;
3981 // CONNECT to www.example.org:443 via SPDY.
3982 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3983 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3984 scoped_ptr
<SpdyFrame
> conn_resp1(
3985 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3987 // Fetch https://www.example.org/ via HTTP.
3989 "GET / HTTP/1.1\r\n"
3990 "Host: www.example.org\r\n"
3991 "Connection: keep-alive\r\n\r\n";
3992 scoped_ptr
<SpdyFrame
> wrapped_get1(
3993 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3994 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3995 "Content-Length: 1\r\n\r\n";
3996 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3997 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3998 scoped_ptr
<SpdyFrame
> wrapped_body1(
3999 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
4000 scoped_ptr
<SpdyFrame
> window_update(
4001 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
4003 // Fetch https://www.example.org/2 via HTTP.
4005 "GET /2 HTTP/1.1\r\n"
4006 "Host: www.example.org\r\n"
4007 "Connection: keep-alive\r\n\r\n";
4008 scoped_ptr
<SpdyFrame
> wrapped_get2(
4009 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
4010 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
4011 "Content-Length: 2\r\n\r\n";
4012 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
4013 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4014 scoped_ptr
<SpdyFrame
> wrapped_body2(
4015 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4017 MockWrite spdy_writes
[] = {
4018 CreateMockWrite(*connect1
, 0),
4019 CreateMockWrite(*wrapped_get1
, 2),
4020 CreateMockWrite(*wrapped_get2
, 5),
4023 MockRead spdy_reads
[] = {
4024 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4025 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4026 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4027 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4028 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4029 MockRead(ASYNC
, 0, 8),
4032 DeterministicSocketData
spdy_data(
4033 spdy_reads
, arraysize(spdy_reads
),
4034 spdy_writes
, arraysize(spdy_writes
));
4035 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4037 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4038 ssl
.SetNextProto(GetParam());
4039 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4040 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4041 ssl2
.was_npn_negotiated
= false;
4042 ssl2
.protocol_negotiated
= kProtoUnknown
;
4043 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4045 TestCompletionCallback callback
;
4047 scoped_ptr
<HttpTransaction
> trans(
4048 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4049 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4050 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4051 // The first connect and request, each of their responses, and the body.
4052 spdy_data
.RunFor(5);
4054 rv
= callback
.WaitForResult();
4057 LoadTimingInfo load_timing_info
;
4058 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4059 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4061 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4062 ASSERT_TRUE(response
!= NULL
);
4063 ASSERT_TRUE(response
->headers
.get() != NULL
);
4064 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4066 std::string response_data
;
4067 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4068 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4071 scoped_ptr
<HttpTransaction
> trans2(
4072 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4073 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4074 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4076 // The second request, response, and body. There should not be a second
4078 spdy_data
.RunFor(3);
4079 rv
= callback
.WaitForResult();
4082 LoadTimingInfo load_timing_info2
;
4083 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4084 TestLoadTimingReused(load_timing_info2
);
4086 // The requests should have the same ID.
4087 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4089 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4092 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4093 // Proxy to different servers.
4094 TEST_P(HttpNetworkTransactionTest
,
4095 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4096 // Configure against https proxy server "proxy:70".
4097 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4098 "https://proxy:70"));
4099 BoundTestNetLog log
;
4100 session_deps_
.net_log
= log
.bound().net_log();
4101 scoped_refptr
<HttpNetworkSession
> session(
4102 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
4104 HttpRequestInfo request1
;
4105 request1
.method
= "GET";
4106 request1
.url
= GURL("http://www.example.org/");
4107 request1
.load_flags
= 0;
4109 HttpRequestInfo request2
;
4110 request2
.method
= "GET";
4111 request2
.url
= GURL("http://mail.example.org/");
4112 request2
.load_flags
= 0;
4114 // http://www.example.org/
4115 scoped_ptr
<SpdyHeaderBlock
> headers(
4116 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4117 scoped_ptr
<SpdyFrame
> get1(
4118 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4119 scoped_ptr
<SpdyFrame
> get_resp1(
4120 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4121 scoped_ptr
<SpdyFrame
> body1(
4122 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4124 // http://mail.example.org/
4125 scoped_ptr
<SpdyHeaderBlock
> headers2(
4126 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4127 scoped_ptr
<SpdyFrame
> get2(
4128 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4129 scoped_ptr
<SpdyFrame
> get_resp2(
4130 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4131 scoped_ptr
<SpdyFrame
> body2(
4132 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4134 MockWrite spdy_writes
[] = {
4135 CreateMockWrite(*get1
, 0),
4136 CreateMockWrite(*get2
, 3),
4139 MockRead spdy_reads
[] = {
4140 CreateMockRead(*get_resp1
, 1, ASYNC
),
4141 CreateMockRead(*body1
, 2, ASYNC
),
4142 CreateMockRead(*get_resp2
, 4, ASYNC
),
4143 CreateMockRead(*body2
, 5, ASYNC
),
4144 MockRead(ASYNC
, 0, 6),
4147 DeterministicSocketData
spdy_data(
4148 spdy_reads
, arraysize(spdy_reads
),
4149 spdy_writes
, arraysize(spdy_writes
));
4150 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4152 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4153 ssl
.SetNextProto(GetParam());
4154 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4156 TestCompletionCallback callback
;
4158 scoped_ptr
<HttpTransaction
> trans(
4159 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4160 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4161 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4162 spdy_data
.RunFor(2);
4164 rv
= callback
.WaitForResult();
4167 LoadTimingInfo load_timing_info
;
4168 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4169 TestLoadTimingNotReused(load_timing_info
,
4170 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4172 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4173 ASSERT_TRUE(response
!= NULL
);
4174 ASSERT_TRUE(response
->headers
.get() != NULL
);
4175 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4177 std::string response_data
;
4178 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4179 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
4180 spdy_data
.RunFor(1);
4181 EXPECT_EQ(1, callback
.WaitForResult());
4182 // Delete the first request, so the second one can reuse the socket.
4185 scoped_ptr
<HttpTransaction
> trans2(
4186 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4187 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4188 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4190 spdy_data
.RunFor(2);
4191 rv
= callback
.WaitForResult();
4194 LoadTimingInfo load_timing_info2
;
4195 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4196 TestLoadTimingReused(load_timing_info2
);
4198 // The requests should have the same ID.
4199 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4201 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
4202 spdy_data
.RunFor(1);
4203 EXPECT_EQ(2, callback
.WaitForResult());
4206 // Test the challenge-response-retry sequence through an HTTPS Proxy
4207 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4208 HttpRequestInfo request
;
4209 request
.method
= "GET";
4210 request
.url
= GURL("http://www.example.org/");
4211 // when the no authentication data flag is set.
4212 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4214 // Configure against https proxy server "myproxy:70".
4215 session_deps_
.proxy_service
.reset(
4216 ProxyService::CreateFixed("https://myproxy:70"));
4217 BoundTestNetLog log
;
4218 session_deps_
.net_log
= log
.bound().net_log();
4219 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4221 // Since we have proxy, should use full url
4222 MockWrite data_writes1
[] = {
4224 "GET http://www.example.org/ HTTP/1.1\r\n"
4225 "Host: www.example.org\r\n"
4226 "Proxy-Connection: keep-alive\r\n\r\n"),
4228 // After calling trans->RestartWithAuth(), this is the request we should
4229 // be issuing -- the final header line contains the credentials.
4231 "GET http://www.example.org/ HTTP/1.1\r\n"
4232 "Host: www.example.org\r\n"
4233 "Proxy-Connection: keep-alive\r\n"
4234 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4237 // The proxy responds to the GET with a 407, using a persistent
4239 MockRead data_reads1
[] = {
4241 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4242 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4243 MockRead("Proxy-Connection: keep-alive\r\n"),
4244 MockRead("Content-Length: 0\r\n\r\n"),
4246 MockRead("HTTP/1.1 200 OK\r\n"),
4247 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4248 MockRead("Content-Length: 100\r\n\r\n"),
4249 MockRead(SYNCHRONOUS
, OK
),
4252 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4253 data_writes1
, arraysize(data_writes1
));
4254 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4255 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4256 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4258 TestCompletionCallback callback1
;
4260 scoped_ptr
<HttpTransaction
> trans(
4261 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4263 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4264 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4266 rv
= callback1
.WaitForResult();
4269 LoadTimingInfo load_timing_info
;
4270 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4271 TestLoadTimingNotReused(load_timing_info
,
4272 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4274 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4275 ASSERT_TRUE(response
!= NULL
);
4276 ASSERT_FALSE(response
->headers
.get() == NULL
);
4277 EXPECT_EQ(407, response
->headers
->response_code());
4278 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4279 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4281 TestCompletionCallback callback2
;
4283 rv
= trans
->RestartWithAuth(
4284 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4285 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4287 rv
= callback2
.WaitForResult();
4290 load_timing_info
= LoadTimingInfo();
4291 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4292 // Retrying with HTTP AUTH is considered to be reusing a socket.
4293 TestLoadTimingReused(load_timing_info
);
4295 response
= trans
->GetResponseInfo();
4296 ASSERT_TRUE(response
!= NULL
);
4298 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4299 EXPECT_EQ(200, response
->headers
->response_code());
4300 EXPECT_EQ(100, response
->headers
->GetContentLength());
4301 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4303 // The password prompt info should not be set.
4304 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4307 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4308 const MockRead
& status
, int expected_status
) {
4309 HttpRequestInfo request
;
4310 request
.method
= "GET";
4311 request
.url
= GURL("https://www.example.org/");
4312 request
.load_flags
= 0;
4314 // Configure against proxy server "myproxy:70".
4315 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4316 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4318 // Since we have proxy, should try to establish tunnel.
4319 MockWrite data_writes
[] = {
4321 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4322 "Host: www.example.org\r\n"
4323 "Proxy-Connection: keep-alive\r\n\r\n"),
4326 MockRead data_reads
[] = {
4328 MockRead("Content-Length: 10\r\n\r\n"),
4329 // No response body because the test stops reading here.
4330 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4333 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4334 data_writes
, arraysize(data_writes
));
4335 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4337 TestCompletionCallback callback
;
4339 scoped_ptr
<HttpTransaction
> trans(
4340 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4342 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4343 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4345 rv
= callback
.WaitForResult();
4346 EXPECT_EQ(expected_status
, rv
);
4349 void HttpNetworkTransactionTest::ConnectStatusHelper(
4350 const MockRead
& status
) {
4351 ConnectStatusHelperWithExpectedStatus(
4352 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4355 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4356 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4359 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4360 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4363 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4364 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4367 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4368 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4371 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4372 ConnectStatusHelper(
4373 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4376 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4377 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4380 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4381 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4384 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4385 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4388 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4389 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4392 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4393 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4396 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4397 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4400 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4401 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4404 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4405 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4408 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4409 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4412 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4413 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4416 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4417 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4420 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4421 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4424 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4425 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4428 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4429 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4432 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4433 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4436 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4437 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4440 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4441 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4444 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4448 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4452 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4453 ConnectStatusHelperWithExpectedStatus(
4454 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4455 ERR_PROXY_AUTH_UNSUPPORTED
);
4458 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4459 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4462 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4463 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4466 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4467 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4470 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4471 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4474 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4475 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4478 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4479 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4482 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4483 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4486 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4487 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4490 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4491 ConnectStatusHelper(
4492 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4495 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4496 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4499 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4500 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4503 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4504 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4507 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4508 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4511 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4512 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4515 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4516 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4519 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4520 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4523 // Test the flow when both the proxy server AND origin server require
4524 // authentication. Again, this uses basic auth for both since that is
4525 // the simplest to mock.
4526 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4527 HttpRequestInfo request
;
4528 request
.method
= "GET";
4529 request
.url
= GURL("http://www.example.org/");
4530 request
.load_flags
= 0;
4532 // Configure against proxy server "myproxy:70".
4533 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4534 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4536 scoped_ptr
<HttpTransaction
> trans(
4537 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4539 MockWrite data_writes1
[] = {
4541 "GET http://www.example.org/ HTTP/1.1\r\n"
4542 "Host: www.example.org\r\n"
4543 "Proxy-Connection: keep-alive\r\n\r\n"),
4546 MockRead data_reads1
[] = {
4547 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4548 // Give a couple authenticate options (only the middle one is actually
4550 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4551 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4552 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4553 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4554 // Large content-length -- won't matter, as connection will be reset.
4555 MockRead("Content-Length: 10000\r\n\r\n"),
4556 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4559 // After calling trans->RestartWithAuth() the first time, this is the
4560 // request we should be issuing -- the final header line contains the
4561 // proxy's credentials.
4562 MockWrite data_writes2
[] = {
4564 "GET http://www.example.org/ HTTP/1.1\r\n"
4565 "Host: www.example.org\r\n"
4566 "Proxy-Connection: keep-alive\r\n"
4567 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4570 // Now the proxy server lets the request pass through to origin server.
4571 // The origin server responds with a 401.
4572 MockRead data_reads2
[] = {
4573 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4574 // Note: We are using the same realm-name as the proxy server. This is
4575 // completely valid, as realms are unique across hosts.
4576 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4577 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4578 MockRead("Content-Length: 2000\r\n\r\n"),
4579 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4582 // After calling trans->RestartWithAuth() the second time, we should send
4583 // the credentials for both the proxy and origin server.
4584 MockWrite data_writes3
[] = {
4586 "GET http://www.example.org/ HTTP/1.1\r\n"
4587 "Host: www.example.org\r\n"
4588 "Proxy-Connection: keep-alive\r\n"
4589 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4590 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4593 // Lastly we get the desired content.
4594 MockRead data_reads3
[] = {
4595 MockRead("HTTP/1.0 200 OK\r\n"),
4596 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4597 MockRead("Content-Length: 100\r\n\r\n"),
4598 MockRead(SYNCHRONOUS
, OK
),
4601 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4602 data_writes1
, arraysize(data_writes1
));
4603 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4604 data_writes2
, arraysize(data_writes2
));
4605 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4606 data_writes3
, arraysize(data_writes3
));
4607 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4608 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4609 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4611 TestCompletionCallback callback1
;
4613 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4614 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4616 rv
= callback1
.WaitForResult();
4619 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4620 ASSERT_TRUE(response
!= NULL
);
4621 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4623 TestCompletionCallback callback2
;
4625 rv
= trans
->RestartWithAuth(
4626 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4627 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4629 rv
= callback2
.WaitForResult();
4632 response
= trans
->GetResponseInfo();
4633 ASSERT_TRUE(response
!= NULL
);
4634 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4636 TestCompletionCallback callback3
;
4638 rv
= trans
->RestartWithAuth(
4639 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4640 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4642 rv
= callback3
.WaitForResult();
4645 response
= trans
->GetResponseInfo();
4646 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4647 EXPECT_EQ(100, response
->headers
->GetContentLength());
4650 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4651 // can't hook into its internals to cause it to generate predictable NTLM
4652 // authorization headers.
4653 #if defined(NTLM_PORTABLE)
4654 // The NTLM authentication unit tests were generated by capturing the HTTP
4655 // requests and responses using Fiddler 2 and inspecting the generated random
4656 // bytes in the debugger.
4658 // Enter the correct password and authenticate successfully.
4659 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4660 HttpRequestInfo request
;
4661 request
.method
= "GET";
4662 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4664 // Ensure load is not disrupted by flags which suppress behaviour specific
4665 // to other auth schemes.
4666 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4668 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4670 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4672 MockWrite data_writes1
[] = {
4673 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4674 "Host: 172.22.68.17\r\n"
4675 "Connection: keep-alive\r\n\r\n"),
4678 MockRead data_reads1
[] = {
4679 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4680 // Negotiate and NTLM are often requested together. However, we only want
4681 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4682 // the header that requests Negotiate for this test.
4683 MockRead("WWW-Authenticate: NTLM\r\n"),
4684 MockRead("Connection: close\r\n"),
4685 MockRead("Content-Length: 42\r\n"),
4686 MockRead("Content-Type: text/html\r\n\r\n"),
4687 // Missing content -- won't matter, as connection will be reset.
4688 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4691 MockWrite data_writes2
[] = {
4692 // After restarting with a null identity, this is the
4693 // request we should be issuing -- the final header line contains a Type
4695 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4696 "Host: 172.22.68.17\r\n"
4697 "Connection: keep-alive\r\n"
4698 "Authorization: NTLM "
4699 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4701 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4702 // (the credentials for the origin server). The second request continues
4703 // on the same connection.
4704 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4705 "Host: 172.22.68.17\r\n"
4706 "Connection: keep-alive\r\n"
4707 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4708 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4709 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4710 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4711 "ahlhx5I=\r\n\r\n"),
4714 MockRead data_reads2
[] = {
4715 // The origin server responds with a Type 2 message.
4716 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4717 MockRead("WWW-Authenticate: NTLM "
4718 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4719 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4720 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4721 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4722 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4723 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4725 MockRead("Content-Length: 42\r\n"),
4726 MockRead("Content-Type: text/html\r\n\r\n"),
4727 MockRead("You are not authorized to view this page\r\n"),
4729 // Lastly we get the desired content.
4730 MockRead("HTTP/1.1 200 OK\r\n"),
4731 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4732 MockRead("Content-Length: 13\r\n\r\n"),
4733 MockRead("Please Login\r\n"),
4734 MockRead(SYNCHRONOUS
, OK
),
4737 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4738 data_writes1
, arraysize(data_writes1
));
4739 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4740 data_writes2
, arraysize(data_writes2
));
4741 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4742 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4744 TestCompletionCallback callback1
;
4746 scoped_ptr
<HttpTransaction
> trans(
4747 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4749 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4750 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4752 rv
= callback1
.WaitForResult();
4755 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4757 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4758 ASSERT_FALSE(response
== NULL
);
4759 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4761 TestCompletionCallback callback2
;
4763 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4764 callback2
.callback());
4765 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4767 rv
= callback2
.WaitForResult();
4770 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4772 response
= trans
->GetResponseInfo();
4773 ASSERT_TRUE(response
!= NULL
);
4774 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4776 TestCompletionCallback callback3
;
4778 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4781 rv
= callback3
.WaitForResult();
4784 response
= trans
->GetResponseInfo();
4785 ASSERT_TRUE(response
!= NULL
);
4786 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4787 EXPECT_EQ(13, response
->headers
->GetContentLength());
4790 // Enter a wrong password, and then the correct one.
4791 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4792 HttpRequestInfo request
;
4793 request
.method
= "GET";
4794 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4795 request
.load_flags
= 0;
4797 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4799 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4801 MockWrite data_writes1
[] = {
4802 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4803 "Host: 172.22.68.17\r\n"
4804 "Connection: keep-alive\r\n\r\n"),
4807 MockRead data_reads1
[] = {
4808 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4809 // Negotiate and NTLM are often requested together. However, we only want
4810 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4811 // the header that requests Negotiate for this test.
4812 MockRead("WWW-Authenticate: NTLM\r\n"),
4813 MockRead("Connection: close\r\n"),
4814 MockRead("Content-Length: 42\r\n"),
4815 MockRead("Content-Type: text/html\r\n\r\n"),
4816 // Missing content -- won't matter, as connection will be reset.
4817 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4820 MockWrite data_writes2
[] = {
4821 // After restarting with a null identity, this is the
4822 // request we should be issuing -- the final header line contains a Type
4824 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4825 "Host: 172.22.68.17\r\n"
4826 "Connection: keep-alive\r\n"
4827 "Authorization: NTLM "
4828 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4830 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4831 // (the credentials for the origin server). The second request continues
4832 // on the same connection.
4833 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4834 "Host: 172.22.68.17\r\n"
4835 "Connection: keep-alive\r\n"
4836 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4837 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4838 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4839 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4840 "4Ww7b7E=\r\n\r\n"),
4843 MockRead data_reads2
[] = {
4844 // The origin server responds with a Type 2 message.
4845 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4846 MockRead("WWW-Authenticate: NTLM "
4847 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4848 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4849 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4850 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4851 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4852 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4854 MockRead("Content-Length: 42\r\n"),
4855 MockRead("Content-Type: text/html\r\n\r\n"),
4856 MockRead("You are not authorized to view this page\r\n"),
4859 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4860 MockRead("WWW-Authenticate: NTLM\r\n"),
4861 MockRead("Connection: close\r\n"),
4862 MockRead("Content-Length: 42\r\n"),
4863 MockRead("Content-Type: text/html\r\n\r\n"),
4864 // Missing content -- won't matter, as connection will be reset.
4865 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4868 MockWrite data_writes3
[] = {
4869 // After restarting with a null identity, this is the
4870 // request we should be issuing -- the final header line contains a Type
4872 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4873 "Host: 172.22.68.17\r\n"
4874 "Connection: keep-alive\r\n"
4875 "Authorization: NTLM "
4876 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4878 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4879 // (the credentials for the origin server). The second request continues
4880 // on the same connection.
4881 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4882 "Host: 172.22.68.17\r\n"
4883 "Connection: keep-alive\r\n"
4884 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4885 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4886 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4887 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4888 "+4MUm7c=\r\n\r\n"),
4891 MockRead data_reads3
[] = {
4892 // The origin server responds with a Type 2 message.
4893 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4894 MockRead("WWW-Authenticate: NTLM "
4895 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4896 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4897 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4898 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4899 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4900 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4902 MockRead("Content-Length: 42\r\n"),
4903 MockRead("Content-Type: text/html\r\n\r\n"),
4904 MockRead("You are not authorized to view this page\r\n"),
4906 // Lastly we get the desired content.
4907 MockRead("HTTP/1.1 200 OK\r\n"),
4908 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4909 MockRead("Content-Length: 13\r\n\r\n"),
4910 MockRead("Please Login\r\n"),
4911 MockRead(SYNCHRONOUS
, OK
),
4914 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4915 data_writes1
, arraysize(data_writes1
));
4916 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4917 data_writes2
, arraysize(data_writes2
));
4918 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4919 data_writes3
, arraysize(data_writes3
));
4920 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4921 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4922 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4924 TestCompletionCallback callback1
;
4926 scoped_ptr
<HttpTransaction
> trans(
4927 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4929 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4930 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4932 rv
= callback1
.WaitForResult();
4935 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4937 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4938 ASSERT_TRUE(response
!= NULL
);
4939 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4941 TestCompletionCallback callback2
;
4943 // Enter the wrong password.
4944 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4945 callback2
.callback());
4946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4948 rv
= callback2
.WaitForResult();
4951 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4952 TestCompletionCallback callback3
;
4953 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4954 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4955 rv
= callback3
.WaitForResult();
4957 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4959 response
= trans
->GetResponseInfo();
4960 ASSERT_FALSE(response
== NULL
);
4961 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4963 TestCompletionCallback callback4
;
4965 // Now enter the right password.
4966 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4967 callback4
.callback());
4968 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4970 rv
= callback4
.WaitForResult();
4973 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4975 TestCompletionCallback callback5
;
4977 // One more roundtrip
4978 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4979 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4981 rv
= callback5
.WaitForResult();
4984 response
= trans
->GetResponseInfo();
4985 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4986 EXPECT_EQ(13, response
->headers
->GetContentLength());
4988 #endif // NTLM_PORTABLE
4990 // Test reading a server response which has only headers, and no body.
4991 // After some maximum number of bytes is consumed, the transaction should
4992 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4993 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4994 HttpRequestInfo request
;
4995 request
.method
= "GET";
4996 request
.url
= GURL("http://www.example.org/");
4997 request
.load_flags
= 0;
4999 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5000 scoped_ptr
<HttpTransaction
> trans(
5001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5003 // Respond with 300 kb of headers (we should fail after 256 kb).
5004 std::string large_headers_string
;
5005 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
5007 MockRead data_reads
[] = {
5008 MockRead("HTTP/1.0 200 OK\r\n"),
5009 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
5010 MockRead("\r\nBODY"),
5011 MockRead(SYNCHRONOUS
, OK
),
5013 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5014 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5016 TestCompletionCallback callback
;
5018 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5019 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5021 rv
= callback
.WaitForResult();
5022 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5024 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5025 EXPECT_TRUE(response
== NULL
);
5028 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5029 // establish tunnel.
5030 // http://code.google.com/p/chromium/issues/detail?id=3772
5031 TEST_P(HttpNetworkTransactionTest
,
5032 DontRecycleTransportSocketForSSLTunnel
) {
5033 HttpRequestInfo request
;
5034 request
.method
= "GET";
5035 request
.url
= GURL("https://www.example.org/");
5036 request
.load_flags
= 0;
5038 // Configure against proxy server "myproxy:70".
5039 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5041 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5043 scoped_ptr
<HttpTransaction
> trans(
5044 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5046 // Since we have proxy, should try to establish tunnel.
5047 MockWrite data_writes1
[] = {
5049 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5050 "Host: www.example.org\r\n"
5051 "Proxy-Connection: keep-alive\r\n\r\n"),
5054 // The proxy responds to the connect with a 404, using a persistent
5055 // connection. Usually a proxy would return 501 (not implemented),
5056 // or 200 (tunnel established).
5057 MockRead data_reads1
[] = {
5058 MockRead("HTTP/1.1 404 Not Found\r\n"),
5059 MockRead("Content-Length: 10\r\n\r\n"),
5060 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5063 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5064 data_writes1
, arraysize(data_writes1
));
5065 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5067 TestCompletionCallback callback1
;
5069 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5070 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5072 rv
= callback1
.WaitForResult();
5073 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5075 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5076 EXPECT_TRUE(response
== NULL
);
5078 // Empty the current queue. This is necessary because idle sockets are
5079 // added to the connection pool asynchronously with a PostTask.
5080 base::MessageLoop::current()->RunUntilIdle();
5082 // We now check to make sure the TCPClientSocket was not added back to
5084 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5086 base::MessageLoop::current()->RunUntilIdle();
5087 // Make sure that the socket didn't get recycled after calling the destructor.
5088 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5091 // Make sure that we recycle a socket after reading all of the response body.
5092 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5093 HttpRequestInfo request
;
5094 request
.method
= "GET";
5095 request
.url
= GURL("http://www.example.org/");
5096 request
.load_flags
= 0;
5098 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5100 scoped_ptr
<HttpTransaction
> trans(
5101 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5103 MockRead data_reads
[] = {
5104 // A part of the response body is received with the response headers.
5105 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5106 // The rest of the response body is received in two parts.
5109 MockRead("junk"), // Should not be read!!
5110 MockRead(SYNCHRONOUS
, OK
),
5113 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5114 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5116 TestCompletionCallback callback
;
5118 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5119 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5121 rv
= callback
.WaitForResult();
5124 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5125 ASSERT_TRUE(response
!= NULL
);
5127 EXPECT_TRUE(response
->headers
.get() != NULL
);
5128 std::string status_line
= response
->headers
->GetStatusLine();
5129 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5131 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5133 std::string response_data
;
5134 rv
= ReadTransaction(trans
.get(), &response_data
);
5136 EXPECT_EQ("hello world", response_data
);
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 socket was added back to the pool.
5143 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5146 // Make sure that we recycle a SSL socket after reading all of the response
5148 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5149 HttpRequestInfo request
;
5150 request
.method
= "GET";
5151 request
.url
= GURL("https://www.example.org/");
5152 request
.load_flags
= 0;
5154 MockWrite data_writes
[] = {
5156 "GET / HTTP/1.1\r\n"
5157 "Host: www.example.org\r\n"
5158 "Connection: keep-alive\r\n\r\n"),
5161 MockRead data_reads
[] = {
5162 MockRead("HTTP/1.1 200 OK\r\n"),
5163 MockRead("Content-Length: 11\r\n\r\n"),
5164 MockRead("hello world"),
5165 MockRead(SYNCHRONOUS
, OK
),
5168 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5169 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5171 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5172 data_writes
, arraysize(data_writes
));
5173 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5175 TestCompletionCallback callback
;
5177 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5178 scoped_ptr
<HttpTransaction
> trans(
5179 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5181 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5184 EXPECT_EQ(OK
, callback
.WaitForResult());
5186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5187 ASSERT_TRUE(response
!= NULL
);
5188 ASSERT_TRUE(response
->headers
.get() != NULL
);
5189 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
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, GetIdleSocketCountInSSLSocketPool(session
.get()));
5206 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5207 // from the pool and make sure that we recover okay.
5208 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
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"),
5220 "GET / HTTP/1.1\r\n"
5221 "Host: www.example.org\r\n"
5222 "Connection: keep-alive\r\n\r\n"),
5225 MockRead data_reads
[] = {
5226 MockRead("HTTP/1.1 200 OK\r\n"),
5227 MockRead("Content-Length: 11\r\n\r\n"),
5228 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5229 MockRead("hello world"),
5230 MockRead(ASYNC
, 0, 0) // EOF
5233 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5234 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5235 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5236 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5238 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5239 data_writes
, arraysize(data_writes
));
5240 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5241 data_writes
, arraysize(data_writes
));
5242 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5243 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5245 TestCompletionCallback callback
;
5247 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5248 scoped_ptr
<HttpTransaction
> trans(
5249 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5251 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5254 EXPECT_EQ(OK
, callback
.WaitForResult());
5256 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5257 ASSERT_TRUE(response
!= NULL
);
5258 ASSERT_TRUE(response
->headers
.get() != NULL
);
5259 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5261 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5263 std::string response_data
;
5264 rv
= ReadTransaction(trans
.get(), &response_data
);
5266 EXPECT_EQ("hello world", response_data
);
5268 // Empty the current queue. This is necessary because idle sockets are
5269 // added to the connection pool asynchronously with a PostTask.
5270 base::MessageLoop::current()->RunUntilIdle();
5272 // We now check to make sure the socket was added back to the pool.
5273 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5275 // Now start the second transaction, which should reuse the previous socket.
5277 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5279 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5281 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5282 EXPECT_EQ(OK
, callback
.WaitForResult());
5284 response
= trans
->GetResponseInfo();
5285 ASSERT_TRUE(response
!= NULL
);
5286 ASSERT_TRUE(response
->headers
.get() != NULL
);
5287 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5289 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5291 rv
= ReadTransaction(trans
.get(), &response_data
);
5293 EXPECT_EQ("hello world", response_data
);
5295 // Empty the current queue. This is necessary because idle sockets are
5296 // added to the connection pool asynchronously with a PostTask.
5297 base::MessageLoop::current()->RunUntilIdle();
5299 // We now check to make sure the socket was added back to the pool.
5300 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5303 // Make sure that we recycle a socket after a zero-length response.
5304 // http://crbug.com/9880
5305 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5306 HttpRequestInfo request
;
5307 request
.method
= "GET";
5309 "http://www.example.org/csi?v=3&s=web&action=&"
5310 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5311 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5312 "rt=prt.2642,ol.2649,xjs.2951");
5313 request
.load_flags
= 0;
5315 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5317 scoped_ptr
<HttpTransaction
> trans(
5318 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5320 MockRead data_reads
[] = {
5321 MockRead("HTTP/1.1 204 No Content\r\n"
5322 "Content-Length: 0\r\n"
5323 "Content-Type: text/html\r\n\r\n"),
5324 MockRead("junk"), // Should not be read!!
5325 MockRead(SYNCHRONOUS
, OK
),
5328 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5329 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5331 TestCompletionCallback callback
;
5333 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5336 rv
= callback
.WaitForResult();
5339 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5340 ASSERT_TRUE(response
!= NULL
);
5342 EXPECT_TRUE(response
->headers
.get() != NULL
);
5343 std::string status_line
= response
->headers
->GetStatusLine();
5344 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5346 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5348 std::string response_data
;
5349 rv
= ReadTransaction(trans
.get(), &response_data
);
5351 EXPECT_EQ("", response_data
);
5353 // Empty the current queue. This is necessary because idle sockets are
5354 // added to the connection pool asynchronously with a PostTask.
5355 base::MessageLoop::current()->RunUntilIdle();
5357 // We now check to make sure the socket was added back to the pool.
5358 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5361 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5362 ScopedVector
<UploadElementReader
> element_readers
;
5363 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5364 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5366 HttpRequestInfo request
[2];
5367 // Transaction 1: a GET request that succeeds. The socket is recycled
5369 request
[0].method
= "GET";
5370 request
[0].url
= GURL("http://www.google.com/");
5371 request
[0].load_flags
= 0;
5372 // Transaction 2: a POST request. Reuses the socket kept alive from
5373 // transaction 1. The first attempts fails when writing the POST data.
5374 // This causes the transaction to retry with a new socket. The second
5375 // attempt succeeds.
5376 request
[1].method
= "POST";
5377 request
[1].url
= GURL("http://www.google.com/login.cgi");
5378 request
[1].upload_data_stream
= &upload_data_stream
;
5379 request
[1].load_flags
= 0;
5381 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5383 // The first socket is used for transaction 1 and the first attempt of
5386 // The response of transaction 1.
5387 MockRead data_reads1
[] = {
5388 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5389 MockRead("hello world"),
5390 MockRead(SYNCHRONOUS
, OK
),
5392 // The mock write results of transaction 1 and the first attempt of
5394 MockWrite data_writes1
[] = {
5395 MockWrite(SYNCHRONOUS
, 64), // GET
5396 MockWrite(SYNCHRONOUS
, 93), // POST
5397 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5399 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5400 data_writes1
, arraysize(data_writes1
));
5402 // The second socket is used for the second attempt of transaction 2.
5404 // The response of transaction 2.
5405 MockRead data_reads2
[] = {
5406 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5407 MockRead("welcome"),
5408 MockRead(SYNCHRONOUS
, OK
),
5410 // The mock write results of the second attempt of transaction 2.
5411 MockWrite data_writes2
[] = {
5412 MockWrite(SYNCHRONOUS
, 93), // POST
5413 MockWrite(SYNCHRONOUS
, 3), // POST data
5415 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5416 data_writes2
, arraysize(data_writes2
));
5418 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5419 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5421 const char* const kExpectedResponseData
[] = {
5422 "hello world", "welcome"
5425 for (int i
= 0; i
< 2; ++i
) {
5426 scoped_ptr
<HttpTransaction
> trans(
5427 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5429 TestCompletionCallback callback
;
5431 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5432 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5434 rv
= callback
.WaitForResult();
5437 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5438 ASSERT_TRUE(response
!= NULL
);
5440 EXPECT_TRUE(response
->headers
.get() != NULL
);
5441 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5443 std::string response_data
;
5444 rv
= ReadTransaction(trans
.get(), &response_data
);
5446 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5450 // Test the request-challenge-retry sequence for basic auth when there is
5451 // an identity in the URL. The request should be sent as normal, but when
5452 // it fails the identity from the URL is used to answer the challenge.
5453 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5454 HttpRequestInfo request
;
5455 request
.method
= "GET";
5456 request
.url
= GURL("http://foo:b@r@www.example.org/");
5457 request
.load_flags
= LOAD_NORMAL
;
5459 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5460 scoped_ptr
<HttpTransaction
> trans(
5461 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5463 // The password contains an escaped character -- for this test to pass it
5464 // will need to be unescaped by HttpNetworkTransaction.
5465 EXPECT_EQ("b%40r", request
.url
.password());
5467 MockWrite data_writes1
[] = {
5469 "GET / HTTP/1.1\r\n"
5470 "Host: www.example.org\r\n"
5471 "Connection: keep-alive\r\n\r\n"),
5474 MockRead data_reads1
[] = {
5475 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5476 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5477 MockRead("Content-Length: 10\r\n\r\n"),
5478 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5481 // After the challenge above, the transaction will be restarted using the
5482 // identity from the url (foo, b@r) to answer the challenge.
5483 MockWrite data_writes2
[] = {
5485 "GET / HTTP/1.1\r\n"
5486 "Host: www.example.org\r\n"
5487 "Connection: keep-alive\r\n"
5488 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5491 MockRead data_reads2
[] = {
5492 MockRead("HTTP/1.0 200 OK\r\n"),
5493 MockRead("Content-Length: 100\r\n\r\n"),
5494 MockRead(SYNCHRONOUS
, OK
),
5497 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5498 data_writes1
, arraysize(data_writes1
));
5499 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5500 data_writes2
, arraysize(data_writes2
));
5501 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5502 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5504 TestCompletionCallback callback1
;
5505 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5506 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5507 rv
= callback1
.WaitForResult();
5509 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5511 TestCompletionCallback callback2
;
5512 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5513 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5514 rv
= callback2
.WaitForResult();
5516 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5518 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5519 ASSERT_TRUE(response
!= NULL
);
5521 // There is no challenge info, since the identity in URL worked.
5522 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5524 EXPECT_EQ(100, response
->headers
->GetContentLength());
5526 // Empty the current queue.
5527 base::MessageLoop::current()->RunUntilIdle();
5530 // Test the request-challenge-retry sequence for basic auth when there is an
5531 // incorrect identity in the URL. The identity from the URL should be used only
5533 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5534 HttpRequestInfo request
;
5535 request
.method
= "GET";
5536 // Note: the URL has a username:password in it. The password "baz" is
5537 // wrong (should be "bar").
5538 request
.url
= GURL("http://foo:baz@www.example.org/");
5540 request
.load_flags
= LOAD_NORMAL
;
5542 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5543 scoped_ptr
<HttpTransaction
> trans(
5544 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5546 MockWrite data_writes1
[] = {
5548 "GET / HTTP/1.1\r\n"
5549 "Host: www.example.org\r\n"
5550 "Connection: keep-alive\r\n\r\n"),
5553 MockRead data_reads1
[] = {
5554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5556 MockRead("Content-Length: 10\r\n\r\n"),
5557 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5560 // After the challenge above, the transaction will be restarted using the
5561 // identity from the url (foo, baz) to answer the challenge.
5562 MockWrite data_writes2
[] = {
5564 "GET / HTTP/1.1\r\n"
5565 "Host: www.example.org\r\n"
5566 "Connection: keep-alive\r\n"
5567 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5570 MockRead data_reads2
[] = {
5571 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5572 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5573 MockRead("Content-Length: 10\r\n\r\n"),
5574 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5577 // After the challenge above, the transaction will be restarted using the
5578 // identity supplied by the user (foo, bar) to answer the challenge.
5579 MockWrite data_writes3
[] = {
5581 "GET / HTTP/1.1\r\n"
5582 "Host: www.example.org\r\n"
5583 "Connection: keep-alive\r\n"
5584 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5587 MockRead data_reads3
[] = {
5588 MockRead("HTTP/1.0 200 OK\r\n"),
5589 MockRead("Content-Length: 100\r\n\r\n"),
5590 MockRead(SYNCHRONOUS
, OK
),
5593 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5594 data_writes1
, arraysize(data_writes1
));
5595 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5596 data_writes2
, arraysize(data_writes2
));
5597 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5598 data_writes3
, arraysize(data_writes3
));
5599 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5600 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5601 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5603 TestCompletionCallback callback1
;
5605 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5606 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5608 rv
= callback1
.WaitForResult();
5611 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5612 TestCompletionCallback callback2
;
5613 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5614 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5615 rv
= callback2
.WaitForResult();
5617 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5619 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5620 ASSERT_TRUE(response
!= NULL
);
5621 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5623 TestCompletionCallback callback3
;
5624 rv
= trans
->RestartWithAuth(
5625 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5626 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5627 rv
= callback3
.WaitForResult();
5629 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5631 response
= trans
->GetResponseInfo();
5632 ASSERT_TRUE(response
!= NULL
);
5634 // There is no challenge info, since the identity worked.
5635 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5637 EXPECT_EQ(100, response
->headers
->GetContentLength());
5639 // Empty the current queue.
5640 base::MessageLoop::current()->RunUntilIdle();
5644 // Test the request-challenge-retry sequence for basic auth when there is a
5645 // correct identity in the URL, but its use is being suppressed. The identity
5646 // from the URL should never be used.
5647 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5648 HttpRequestInfo request
;
5649 request
.method
= "GET";
5650 request
.url
= GURL("http://foo:bar@www.example.org/");
5651 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5653 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5654 scoped_ptr
<HttpTransaction
> trans(
5655 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5657 MockWrite data_writes1
[] = {
5659 "GET / HTTP/1.1\r\n"
5660 "Host: www.example.org\r\n"
5661 "Connection: keep-alive\r\n\r\n"),
5664 MockRead data_reads1
[] = {
5665 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5666 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5667 MockRead("Content-Length: 10\r\n\r\n"),
5668 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5671 // After the challenge above, the transaction will be restarted using the
5672 // identity supplied by the user, not the one in the URL, to answer the
5674 MockWrite data_writes3
[] = {
5676 "GET / HTTP/1.1\r\n"
5677 "Host: www.example.org\r\n"
5678 "Connection: keep-alive\r\n"
5679 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5682 MockRead data_reads3
[] = {
5683 MockRead("HTTP/1.0 200 OK\r\n"),
5684 MockRead("Content-Length: 100\r\n\r\n"),
5685 MockRead(SYNCHRONOUS
, OK
),
5688 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5689 data_writes1
, arraysize(data_writes1
));
5690 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5691 data_writes3
, arraysize(data_writes3
));
5692 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5693 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5695 TestCompletionCallback callback1
;
5696 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5698 rv
= callback1
.WaitForResult();
5700 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5702 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5703 ASSERT_TRUE(response
!= NULL
);
5704 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5706 TestCompletionCallback callback3
;
5707 rv
= trans
->RestartWithAuth(
5708 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5709 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5710 rv
= callback3
.WaitForResult();
5712 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5714 response
= trans
->GetResponseInfo();
5715 ASSERT_TRUE(response
!= NULL
);
5717 // There is no challenge info, since the identity worked.
5718 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5719 EXPECT_EQ(100, response
->headers
->GetContentLength());
5721 // Empty the current queue.
5722 base::MessageLoop::current()->RunUntilIdle();
5725 // Test that previously tried username/passwords for a realm get re-used.
5726 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5727 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5729 // Transaction 1: authenticate (foo, bar) on MyRealm1
5731 HttpRequestInfo request
;
5732 request
.method
= "GET";
5733 request
.url
= GURL("http://www.example.org/x/y/z");
5734 request
.load_flags
= 0;
5736 scoped_ptr
<HttpTransaction
> trans(
5737 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5739 MockWrite data_writes1
[] = {
5741 "GET /x/y/z HTTP/1.1\r\n"
5742 "Host: www.example.org\r\n"
5743 "Connection: keep-alive\r\n\r\n"),
5746 MockRead data_reads1
[] = {
5747 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5748 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5749 MockRead("Content-Length: 10000\r\n\r\n"),
5750 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5753 // Resend with authorization (username=foo, password=bar)
5754 MockWrite data_writes2
[] = {
5756 "GET /x/y/z HTTP/1.1\r\n"
5757 "Host: www.example.org\r\n"
5758 "Connection: keep-alive\r\n"
5759 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5762 // Sever accepts the authorization.
5763 MockRead data_reads2
[] = {
5764 MockRead("HTTP/1.0 200 OK\r\n"),
5765 MockRead("Content-Length: 100\r\n\r\n"),
5766 MockRead(SYNCHRONOUS
, OK
),
5769 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5770 data_writes1
, arraysize(data_writes1
));
5771 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5772 data_writes2
, arraysize(data_writes2
));
5773 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5774 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5776 TestCompletionCallback callback1
;
5778 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5781 rv
= callback1
.WaitForResult();
5784 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5785 ASSERT_TRUE(response
!= NULL
);
5786 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5788 TestCompletionCallback callback2
;
5790 rv
= trans
->RestartWithAuth(
5791 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5792 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5794 rv
= callback2
.WaitForResult();
5797 response
= trans
->GetResponseInfo();
5798 ASSERT_TRUE(response
!= NULL
);
5799 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5800 EXPECT_EQ(100, response
->headers
->GetContentLength());
5803 // ------------------------------------------------------------------------
5805 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5807 HttpRequestInfo request
;
5808 request
.method
= "GET";
5809 // Note that Transaction 1 was at /x/y/z, so this is in the same
5810 // protection space as MyRealm1.
5811 request
.url
= GURL("http://www.example.org/x/y/a/b");
5812 request
.load_flags
= 0;
5814 scoped_ptr
<HttpTransaction
> trans(
5815 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5817 MockWrite data_writes1
[] = {
5819 "GET /x/y/a/b HTTP/1.1\r\n"
5820 "Host: www.example.org\r\n"
5821 "Connection: keep-alive\r\n"
5822 // Send preemptive authorization for MyRealm1
5823 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5826 // The server didn't like the preemptive authorization, and
5827 // challenges us for a different realm (MyRealm2).
5828 MockRead data_reads1
[] = {
5829 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5830 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5831 MockRead("Content-Length: 10000\r\n\r\n"),
5832 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5835 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5836 MockWrite data_writes2
[] = {
5838 "GET /x/y/a/b HTTP/1.1\r\n"
5839 "Host: www.example.org\r\n"
5840 "Connection: keep-alive\r\n"
5841 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5844 // Sever accepts the authorization.
5845 MockRead data_reads2
[] = {
5846 MockRead("HTTP/1.0 200 OK\r\n"),
5847 MockRead("Content-Length: 100\r\n\r\n"),
5848 MockRead(SYNCHRONOUS
, OK
),
5851 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5852 data_writes1
, arraysize(data_writes1
));
5853 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5854 data_writes2
, arraysize(data_writes2
));
5855 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5856 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5858 TestCompletionCallback callback1
;
5860 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5863 rv
= callback1
.WaitForResult();
5866 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5867 ASSERT_TRUE(response
!= NULL
);
5868 ASSERT_TRUE(response
->auth_challenge
.get());
5869 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5870 EXPECT_EQ("www.example.org:80",
5871 response
->auth_challenge
->challenger
.ToString());
5872 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5873 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5875 TestCompletionCallback callback2
;
5877 rv
= trans
->RestartWithAuth(
5878 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5881 rv
= callback2
.WaitForResult();
5884 response
= trans
->GetResponseInfo();
5885 ASSERT_TRUE(response
!= NULL
);
5886 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5887 EXPECT_EQ(100, response
->headers
->GetContentLength());
5890 // ------------------------------------------------------------------------
5892 // Transaction 3: Resend a request in MyRealm's protection space --
5893 // succeed with preemptive authorization.
5895 HttpRequestInfo request
;
5896 request
.method
= "GET";
5897 request
.url
= GURL("http://www.example.org/x/y/z2");
5898 request
.load_flags
= 0;
5900 scoped_ptr
<HttpTransaction
> trans(
5901 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5903 MockWrite data_writes1
[] = {
5905 "GET /x/y/z2 HTTP/1.1\r\n"
5906 "Host: www.example.org\r\n"
5907 "Connection: keep-alive\r\n"
5908 // The authorization for MyRealm1 gets sent preemptively
5909 // (since the url is in the same protection space)
5910 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5913 // Sever accepts the preemptive authorization
5914 MockRead data_reads1
[] = {
5915 MockRead("HTTP/1.0 200 OK\r\n"),
5916 MockRead("Content-Length: 100\r\n\r\n"),
5917 MockRead(SYNCHRONOUS
, OK
),
5920 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5921 data_writes1
, arraysize(data_writes1
));
5922 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5924 TestCompletionCallback callback1
;
5926 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5927 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5929 rv
= callback1
.WaitForResult();
5932 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5933 ASSERT_TRUE(response
!= NULL
);
5935 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5936 EXPECT_EQ(100, response
->headers
->GetContentLength());
5939 // ------------------------------------------------------------------------
5941 // Transaction 4: request another URL in MyRealm (however the
5942 // url is not known to belong to the protection space, so no pre-auth).
5944 HttpRequestInfo request
;
5945 request
.method
= "GET";
5946 request
.url
= GURL("http://www.example.org/x/1");
5947 request
.load_flags
= 0;
5949 scoped_ptr
<HttpTransaction
> trans(
5950 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5952 MockWrite data_writes1
[] = {
5954 "GET /x/1 HTTP/1.1\r\n"
5955 "Host: www.example.org\r\n"
5956 "Connection: keep-alive\r\n\r\n"),
5959 MockRead data_reads1
[] = {
5960 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5961 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5962 MockRead("Content-Length: 10000\r\n\r\n"),
5963 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5966 // Resend with authorization from MyRealm's cache.
5967 MockWrite data_writes2
[] = {
5969 "GET /x/1 HTTP/1.1\r\n"
5970 "Host: www.example.org\r\n"
5971 "Connection: keep-alive\r\n"
5972 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5975 // Sever accepts the authorization.
5976 MockRead data_reads2
[] = {
5977 MockRead("HTTP/1.0 200 OK\r\n"),
5978 MockRead("Content-Length: 100\r\n\r\n"),
5979 MockRead(SYNCHRONOUS
, OK
),
5982 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5983 data_writes1
, arraysize(data_writes1
));
5984 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5985 data_writes2
, arraysize(data_writes2
));
5986 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5987 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5989 TestCompletionCallback callback1
;
5991 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5992 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5994 rv
= callback1
.WaitForResult();
5997 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5998 TestCompletionCallback callback2
;
5999 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6001 rv
= callback2
.WaitForResult();
6003 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6005 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6006 ASSERT_TRUE(response
!= NULL
);
6007 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6008 EXPECT_EQ(100, response
->headers
->GetContentLength());
6011 // ------------------------------------------------------------------------
6013 // Transaction 5: request a URL in MyRealm, but the server rejects the
6014 // cached identity. Should invalidate and re-prompt.
6016 HttpRequestInfo request
;
6017 request
.method
= "GET";
6018 request
.url
= GURL("http://www.example.org/p/q/t");
6019 request
.load_flags
= 0;
6021 scoped_ptr
<HttpTransaction
> trans(
6022 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6024 MockWrite data_writes1
[] = {
6026 "GET /p/q/t HTTP/1.1\r\n"
6027 "Host: www.example.org\r\n"
6028 "Connection: keep-alive\r\n\r\n"),
6031 MockRead data_reads1
[] = {
6032 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6033 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6034 MockRead("Content-Length: 10000\r\n\r\n"),
6035 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6038 // Resend with authorization from cache for MyRealm.
6039 MockWrite data_writes2
[] = {
6041 "GET /p/q/t HTTP/1.1\r\n"
6042 "Host: www.example.org\r\n"
6043 "Connection: keep-alive\r\n"
6044 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6047 // Sever rejects the authorization.
6048 MockRead data_reads2
[] = {
6049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6050 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6051 MockRead("Content-Length: 10000\r\n\r\n"),
6052 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6055 // At this point we should prompt for new credentials for MyRealm.
6056 // Restart with username=foo3, password=foo4.
6057 MockWrite data_writes3
[] = {
6059 "GET /p/q/t HTTP/1.1\r\n"
6060 "Host: www.example.org\r\n"
6061 "Connection: keep-alive\r\n"
6062 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6065 // Sever accepts the authorization.
6066 MockRead data_reads3
[] = {
6067 MockRead("HTTP/1.0 200 OK\r\n"),
6068 MockRead("Content-Length: 100\r\n\r\n"),
6069 MockRead(SYNCHRONOUS
, OK
),
6072 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6073 data_writes1
, arraysize(data_writes1
));
6074 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6075 data_writes2
, arraysize(data_writes2
));
6076 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6077 data_writes3
, arraysize(data_writes3
));
6078 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6079 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6080 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6082 TestCompletionCallback callback1
;
6084 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6085 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6087 rv
= callback1
.WaitForResult();
6090 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6091 TestCompletionCallback callback2
;
6092 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6093 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6094 rv
= callback2
.WaitForResult();
6096 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6098 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6099 ASSERT_TRUE(response
!= NULL
);
6100 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6102 TestCompletionCallback callback3
;
6104 rv
= trans
->RestartWithAuth(
6105 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6108 rv
= callback3
.WaitForResult();
6111 response
= trans
->GetResponseInfo();
6112 ASSERT_TRUE(response
!= NULL
);
6113 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6114 EXPECT_EQ(100, response
->headers
->GetContentLength());
6118 // Tests that nonce count increments when multiple auth attempts
6119 // are started with the same nonce.
6120 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6121 HttpAuthHandlerDigest::Factory
* digest_factory
=
6122 new HttpAuthHandlerDigest::Factory();
6123 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6124 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6125 digest_factory
->set_nonce_generator(nonce_generator
);
6126 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6127 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6129 // Transaction 1: authenticate (foo, bar) on MyRealm1
6131 HttpRequestInfo request
;
6132 request
.method
= "GET";
6133 request
.url
= GURL("http://www.example.org/x/y/z");
6134 request
.load_flags
= 0;
6136 scoped_ptr
<HttpTransaction
> trans(
6137 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6139 MockWrite data_writes1
[] = {
6141 "GET /x/y/z HTTP/1.1\r\n"
6142 "Host: www.example.org\r\n"
6143 "Connection: keep-alive\r\n\r\n"),
6146 MockRead data_reads1
[] = {
6147 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6148 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6149 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6150 MockRead(SYNCHRONOUS
, OK
),
6153 // Resend with authorization (username=foo, password=bar)
6154 MockWrite data_writes2
[] = {
6156 "GET /x/y/z HTTP/1.1\r\n"
6157 "Host: www.example.org\r\n"
6158 "Connection: keep-alive\r\n"
6159 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6160 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6161 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6162 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6165 // Sever accepts the authorization.
6166 MockRead data_reads2
[] = {
6167 MockRead("HTTP/1.0 200 OK\r\n"),
6168 MockRead(SYNCHRONOUS
, OK
),
6171 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6172 data_writes1
, arraysize(data_writes1
));
6173 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6174 data_writes2
, arraysize(data_writes2
));
6175 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6176 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6178 TestCompletionCallback callback1
;
6180 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6181 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6183 rv
= callback1
.WaitForResult();
6186 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6187 ASSERT_TRUE(response
!= NULL
);
6188 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6190 TestCompletionCallback callback2
;
6192 rv
= trans
->RestartWithAuth(
6193 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6194 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6196 rv
= callback2
.WaitForResult();
6199 response
= trans
->GetResponseInfo();
6200 ASSERT_TRUE(response
!= NULL
);
6201 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6204 // ------------------------------------------------------------------------
6206 // Transaction 2: Request another resource in digestive's protection space.
6207 // This will preemptively add an Authorization header which should have an
6208 // "nc" value of 2 (as compared to 1 in the first use.
6210 HttpRequestInfo request
;
6211 request
.method
= "GET";
6212 // Note that Transaction 1 was at /x/y/z, so this is in the same
6213 // protection space as digest.
6214 request
.url
= GURL("http://www.example.org/x/y/a/b");
6215 request
.load_flags
= 0;
6217 scoped_ptr
<HttpTransaction
> trans(
6218 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6220 MockWrite data_writes1
[] = {
6222 "GET /x/y/a/b HTTP/1.1\r\n"
6223 "Host: www.example.org\r\n"
6224 "Connection: keep-alive\r\n"
6225 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6226 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6227 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6228 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6231 // Sever accepts the authorization.
6232 MockRead data_reads1
[] = {
6233 MockRead("HTTP/1.0 200 OK\r\n"),
6234 MockRead("Content-Length: 100\r\n\r\n"),
6235 MockRead(SYNCHRONOUS
, OK
),
6238 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6239 data_writes1
, arraysize(data_writes1
));
6240 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6242 TestCompletionCallback callback1
;
6244 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6245 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6247 rv
= callback1
.WaitForResult();
6250 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6251 ASSERT_TRUE(response
!= NULL
);
6252 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6256 // Test the ResetStateForRestart() private method.
6257 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6258 // Create a transaction (the dependencies aren't important).
6259 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6260 scoped_ptr
<HttpNetworkTransaction
> trans(
6261 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6263 // Setup some state (which we expect ResetStateForRestart() will clear).
6264 trans
->read_buf_
= new IOBuffer(15);
6265 trans
->read_buf_len_
= 15;
6266 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6268 // Setup state in response_
6269 HttpResponseInfo
* response
= &trans
->response_
;
6270 response
->auth_challenge
= new AuthChallengeInfo();
6271 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6272 response
->response_time
= base::Time::Now();
6273 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6275 { // Setup state for response_.vary_data
6276 HttpRequestInfo request
;
6277 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6278 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6279 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6280 request
.extra_headers
.SetHeader("Foo", "1");
6281 request
.extra_headers
.SetHeader("bar", "23");
6282 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6285 // Cause the above state to be reset.
6286 trans
->ResetStateForRestart();
6288 // Verify that the state that needed to be reset, has been reset.
6289 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6290 EXPECT_EQ(0, trans
->read_buf_len_
);
6291 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6292 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6293 EXPECT_TRUE(response
->headers
.get() == NULL
);
6294 EXPECT_FALSE(response
->was_cached
);
6295 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6296 EXPECT_FALSE(response
->vary_data
.is_valid());
6299 // Test HTTPS connections to a site with a bad certificate
6300 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6301 HttpRequestInfo request
;
6302 request
.method
= "GET";
6303 request
.url
= GURL("https://www.example.org/");
6304 request
.load_flags
= 0;
6306 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6307 scoped_ptr
<HttpTransaction
> trans(
6308 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6310 MockWrite data_writes
[] = {
6312 "GET / HTTP/1.1\r\n"
6313 "Host: www.example.org\r\n"
6314 "Connection: keep-alive\r\n\r\n"),
6317 MockRead data_reads
[] = {
6318 MockRead("HTTP/1.0 200 OK\r\n"),
6319 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6320 MockRead("Content-Length: 100\r\n\r\n"),
6321 MockRead(SYNCHRONOUS
, OK
),
6324 StaticSocketDataProvider ssl_bad_certificate
;
6325 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6326 data_writes
, arraysize(data_writes
));
6327 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6328 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6330 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6331 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6332 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6333 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6335 TestCompletionCallback callback
;
6337 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6338 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6340 rv
= callback
.WaitForResult();
6341 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6343 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6344 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6346 rv
= callback
.WaitForResult();
6349 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6351 ASSERT_TRUE(response
!= NULL
);
6352 EXPECT_EQ(100, response
->headers
->GetContentLength());
6355 // Test HTTPS connections to a site with a bad certificate, going through a
6357 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6358 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6360 HttpRequestInfo request
;
6361 request
.method
= "GET";
6362 request
.url
= GURL("https://www.example.org/");
6363 request
.load_flags
= 0;
6365 MockWrite proxy_writes
[] = {
6367 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6368 "Host: www.example.org\r\n"
6369 "Proxy-Connection: keep-alive\r\n\r\n"),
6372 MockRead proxy_reads
[] = {
6373 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6374 MockRead(SYNCHRONOUS
, OK
)
6377 MockWrite data_writes
[] = {
6379 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6380 "Host: www.example.org\r\n"
6381 "Proxy-Connection: keep-alive\r\n\r\n"),
6383 "GET / HTTP/1.1\r\n"
6384 "Host: www.example.org\r\n"
6385 "Connection: keep-alive\r\n\r\n"),
6388 MockRead data_reads
[] = {
6389 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6390 MockRead("HTTP/1.0 200 OK\r\n"),
6391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6392 MockRead("Content-Length: 100\r\n\r\n"),
6393 MockRead(SYNCHRONOUS
, OK
),
6396 StaticSocketDataProvider
ssl_bad_certificate(
6397 proxy_reads
, arraysize(proxy_reads
),
6398 proxy_writes
, arraysize(proxy_writes
));
6399 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6400 data_writes
, arraysize(data_writes
));
6401 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6402 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6404 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6405 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6406 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6407 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6409 TestCompletionCallback callback
;
6411 for (int i
= 0; i
< 2; i
++) {
6412 session_deps_
.socket_factory
->ResetNextMockIndexes();
6414 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6415 scoped_ptr
<HttpTransaction
> trans(
6416 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6418 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6419 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6421 rv
= callback
.WaitForResult();
6422 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6424 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6425 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6427 rv
= callback
.WaitForResult();
6430 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6432 ASSERT_TRUE(response
!= NULL
);
6433 EXPECT_EQ(100, response
->headers
->GetContentLength());
6438 // Test HTTPS connections to a site, going through an HTTPS proxy
6439 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6440 session_deps_
.proxy_service
.reset(
6441 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6443 session_deps_
.net_log
= &net_log
;
6445 HttpRequestInfo request
;
6446 request
.method
= "GET";
6447 request
.url
= GURL("https://www.example.org/");
6448 request
.load_flags
= 0;
6450 MockWrite data_writes
[] = {
6452 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6453 "Host: www.example.org\r\n"
6454 "Proxy-Connection: keep-alive\r\n\r\n"),
6456 "GET / HTTP/1.1\r\n"
6457 "Host: www.example.org\r\n"
6458 "Connection: keep-alive\r\n\r\n"),
6461 MockRead data_reads
[] = {
6462 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6463 MockRead("HTTP/1.1 200 OK\r\n"),
6464 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6465 MockRead("Content-Length: 100\r\n\r\n"),
6466 MockRead(SYNCHRONOUS
, OK
),
6469 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6470 data_writes
, arraysize(data_writes
));
6471 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6472 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6474 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6475 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6476 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6478 TestCompletionCallback callback
;
6480 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6481 scoped_ptr
<HttpTransaction
> trans(
6482 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6484 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6485 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6487 rv
= callback
.WaitForResult();
6489 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6491 ASSERT_TRUE(response
!= NULL
);
6493 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6494 EXPECT_EQ(200, response
->headers
->response_code());
6495 EXPECT_EQ(100, response
->headers
->GetContentLength());
6496 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6498 LoadTimingInfo load_timing_info
;
6499 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6500 TestLoadTimingNotReusedWithPac(load_timing_info
,
6501 CONNECT_TIMING_HAS_SSL_TIMES
);
6504 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6505 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6506 session_deps_
.proxy_service
.reset(
6507 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6509 session_deps_
.net_log
= &net_log
;
6511 HttpRequestInfo request
;
6512 request
.method
= "GET";
6513 request
.url
= GURL("https://www.example.org/");
6514 request
.load_flags
= 0;
6516 MockWrite data_writes
[] = {
6518 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6519 "Host: www.example.org\r\n"
6520 "Proxy-Connection: keep-alive\r\n\r\n"),
6523 MockRead data_reads
[] = {
6524 MockRead("HTTP/1.1 302 Redirect\r\n"),
6525 MockRead("Location: http://login.example.com/\r\n"),
6526 MockRead("Content-Length: 0\r\n\r\n"),
6527 MockRead(SYNCHRONOUS
, OK
),
6530 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6531 data_writes
, arraysize(data_writes
));
6532 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6534 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6535 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6537 TestCompletionCallback callback
;
6539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6540 scoped_ptr
<HttpTransaction
> trans(
6541 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6543 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6544 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6546 rv
= callback
.WaitForResult();
6548 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6550 ASSERT_TRUE(response
!= NULL
);
6552 EXPECT_EQ(302, response
->headers
->response_code());
6554 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6555 EXPECT_EQ("http://login.example.com/", url
);
6557 // In the case of redirects from proxies, HttpNetworkTransaction returns
6558 // timing for the proxy connection instead of the connection to the host,
6559 // and no send / receive times.
6560 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6561 LoadTimingInfo load_timing_info
;
6562 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6564 EXPECT_FALSE(load_timing_info
.socket_reused
);
6565 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6567 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6568 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6569 load_timing_info
.proxy_resolve_end
);
6570 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6571 load_timing_info
.connect_timing
.connect_start
);
6572 ExpectConnectTimingHasTimes(
6573 load_timing_info
.connect_timing
,
6574 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6576 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6577 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6578 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6581 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6582 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6583 session_deps_
.proxy_service
.reset(
6584 ProxyService::CreateFixed("https://proxy:70"));
6586 HttpRequestInfo request
;
6587 request
.method
= "GET";
6588 request
.url
= GURL("https://www.example.org/");
6589 request
.load_flags
= 0;
6591 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6592 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6593 scoped_ptr
<SpdyFrame
> goaway(
6594 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6595 MockWrite data_writes
[] = {
6596 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6597 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6600 static const char* const kExtraHeaders
[] = {
6602 "http://login.example.com/",
6604 scoped_ptr
<SpdyFrame
> resp(
6605 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6606 arraysize(kExtraHeaders
)/2, 1));
6607 MockRead data_reads
[] = {
6608 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6609 MockRead(ASYNC
, 0, 2), // EOF
6612 DelayedSocketData
data(
6613 1, // wait for one write to finish before reading.
6614 data_reads
, arraysize(data_reads
),
6615 data_writes
, arraysize(data_writes
));
6616 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6617 proxy_ssl
.SetNextProto(GetParam());
6619 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6620 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6622 TestCompletionCallback callback
;
6624 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6625 scoped_ptr
<HttpTransaction
> trans(
6626 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6628 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6629 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6631 rv
= callback
.WaitForResult();
6633 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6635 ASSERT_TRUE(response
!= NULL
);
6637 EXPECT_EQ(302, response
->headers
->response_code());
6639 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6640 EXPECT_EQ("http://login.example.com/", url
);
6643 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6644 TEST_P(HttpNetworkTransactionTest
,
6645 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6646 session_deps_
.proxy_service
.reset(
6647 ProxyService::CreateFixed("https://proxy:70"));
6649 HttpRequestInfo request
;
6650 request
.method
= "GET";
6651 request
.url
= GURL("https://www.example.org/");
6652 request
.load_flags
= 0;
6654 MockWrite data_writes
[] = {
6656 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6657 "Host: www.example.org\r\n"
6658 "Proxy-Connection: keep-alive\r\n\r\n"),
6661 MockRead data_reads
[] = {
6662 MockRead("HTTP/1.1 404 Not Found\r\n"),
6663 MockRead("Content-Length: 23\r\n\r\n"),
6664 MockRead("The host does not exist"),
6665 MockRead(SYNCHRONOUS
, OK
),
6668 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6669 data_writes
, arraysize(data_writes
));
6670 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6672 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6673 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6675 TestCompletionCallback callback
;
6677 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6678 scoped_ptr
<HttpTransaction
> trans(
6679 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6681 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6682 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6684 rv
= callback
.WaitForResult();
6685 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6687 // TODO(ttuttle): Anything else to check here?
6690 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6691 TEST_P(HttpNetworkTransactionTest
,
6692 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6693 session_deps_
.proxy_service
.reset(
6694 ProxyService::CreateFixed("https://proxy:70"));
6696 HttpRequestInfo request
;
6697 request
.method
= "GET";
6698 request
.url
= GURL("https://www.example.org/");
6699 request
.load_flags
= 0;
6701 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6702 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6703 scoped_ptr
<SpdyFrame
> rst(
6704 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6705 MockWrite data_writes
[] = {
6706 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6707 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6710 static const char* const kExtraHeaders
[] = {
6712 "http://login.example.com/",
6714 scoped_ptr
<SpdyFrame
> resp(
6715 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6716 arraysize(kExtraHeaders
)/2, 1));
6717 scoped_ptr
<SpdyFrame
> body(
6718 spdy_util_
.ConstructSpdyBodyFrame(
6719 1, "The host does not exist", 23, true));
6720 MockRead data_reads
[] = {
6721 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6722 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6723 MockRead(ASYNC
, 0, 4), // EOF
6726 DelayedSocketData
data(
6727 1, // wait for one write to finish before reading.
6728 data_reads
, arraysize(data_reads
),
6729 data_writes
, arraysize(data_writes
));
6730 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6731 proxy_ssl
.SetNextProto(GetParam());
6733 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6734 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6736 TestCompletionCallback callback
;
6738 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6739 scoped_ptr
<HttpTransaction
> trans(
6740 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6742 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6743 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6745 rv
= callback
.WaitForResult();
6746 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6748 // TODO(ttuttle): Anything else to check here?
6751 // Test the request-challenge-retry sequence for basic auth, through
6752 // a SPDY proxy over a single SPDY session.
6753 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6754 HttpRequestInfo request
;
6755 request
.method
= "GET";
6756 request
.url
= GURL("https://www.example.org/");
6757 // when the no authentication data flag is set.
6758 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6760 // Configure against https proxy server "myproxy:70".
6761 session_deps_
.proxy_service
.reset(
6762 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6763 BoundTestNetLog log
;
6764 session_deps_
.net_log
= log
.bound().net_log();
6765 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6767 // Since we have proxy, should try to establish tunnel.
6768 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6769 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6770 scoped_ptr
<SpdyFrame
> rst(
6771 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6773 // After calling trans->RestartWithAuth(), this is the request we should
6774 // be issuing -- the final header line contains the credentials.
6775 const char* const kAuthCredentials
[] = {
6776 "proxy-authorization", "Basic Zm9vOmJhcg==",
6778 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6779 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6780 HostPortPair("www.example.org", 443)));
6781 // fetch https://www.example.org/ via HTTP
6783 "GET / HTTP/1.1\r\n"
6784 "Host: www.example.org\r\n"
6785 "Connection: keep-alive\r\n\r\n";
6786 scoped_ptr
<SpdyFrame
> wrapped_get(
6787 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6789 MockWrite spdy_writes
[] = {
6790 CreateMockWrite(*req
, 1, ASYNC
),
6791 CreateMockWrite(*rst
, 4, ASYNC
),
6792 CreateMockWrite(*connect2
, 5),
6793 CreateMockWrite(*wrapped_get
, 8),
6796 // The proxy responds to the connect with a 407, using a persistent
6798 const char kAuthStatus
[] = "407";
6799 const char* const kAuthChallenge
[] = {
6800 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6802 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6803 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6805 scoped_ptr
<SpdyFrame
> conn_resp(
6806 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6807 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6808 "Content-Length: 5\r\n\r\n";
6810 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6811 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6812 scoped_ptr
<SpdyFrame
> wrapped_body(
6813 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6814 MockRead spdy_reads
[] = {
6815 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6816 CreateMockRead(*conn_resp
, 6, ASYNC
),
6817 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6818 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6819 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6822 OrderedSocketData
spdy_data(
6823 spdy_reads
, arraysize(spdy_reads
),
6824 spdy_writes
, arraysize(spdy_writes
));
6825 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6826 // Negotiate SPDY to the proxy
6827 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6828 proxy
.SetNextProto(GetParam());
6829 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6830 // Vanilla SSL to the server
6831 SSLSocketDataProvider
server(ASYNC
, OK
);
6832 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6834 TestCompletionCallback callback1
;
6836 scoped_ptr
<HttpTransaction
> trans(
6837 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6839 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6840 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6842 rv
= callback1
.WaitForResult();
6844 TestNetLog::CapturedEntryList entries
;
6845 log
.GetEntries(&entries
);
6846 size_t pos
= ExpectLogContainsSomewhere(
6847 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6848 NetLog::PHASE_NONE
);
6849 ExpectLogContainsSomewhere(
6851 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6852 NetLog::PHASE_NONE
);
6854 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6855 ASSERT_TRUE(response
!= NULL
);
6856 ASSERT_FALSE(response
->headers
.get() == NULL
);
6857 EXPECT_EQ(407, response
->headers
->response_code());
6858 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6859 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6860 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6862 TestCompletionCallback callback2
;
6864 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6865 callback2
.callback());
6866 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6868 rv
= callback2
.WaitForResult();
6871 response
= trans
->GetResponseInfo();
6872 ASSERT_TRUE(response
!= NULL
);
6874 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6875 EXPECT_EQ(200, response
->headers
->response_code());
6876 EXPECT_EQ(5, response
->headers
->GetContentLength());
6877 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6879 // The password prompt info should not be set.
6880 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6882 LoadTimingInfo load_timing_info
;
6883 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6884 TestLoadTimingNotReusedWithPac(load_timing_info
,
6885 CONNECT_TIMING_HAS_SSL_TIMES
);
6888 session
->CloseAllConnections();
6891 // Test that an explicitly trusted SPDY proxy can push a resource from an
6892 // origin that is different from that of its associated resource.
6893 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6894 HttpRequestInfo request
;
6895 HttpRequestInfo push_request
;
6897 request
.method
= "GET";
6898 request
.url
= GURL("http://www.example.org/");
6899 push_request
.method
= "GET";
6900 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6902 // Configure against https proxy server "myproxy:70".
6903 session_deps_
.proxy_service
.reset(
6904 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6905 BoundTestNetLog log
;
6906 session_deps_
.net_log
= log
.bound().net_log();
6908 // Enable cross-origin push.
6909 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6911 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6913 scoped_ptr
<SpdyFrame
> stream1_syn(
6914 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6916 MockWrite spdy_writes
[] = {
6917 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6920 scoped_ptr
<SpdyFrame
>
6921 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6923 scoped_ptr
<SpdyFrame
>
6924 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6926 scoped_ptr
<SpdyFrame
>
6927 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6931 "http://www.another-origin.com/foo.dat"));
6932 const char kPushedData
[] = "pushed";
6933 scoped_ptr
<SpdyFrame
> stream2_body(
6934 spdy_util_
.ConstructSpdyBodyFrame(
6935 2, kPushedData
, strlen(kPushedData
), true));
6937 MockRead spdy_reads
[] = {
6938 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6939 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6940 CreateMockRead(*stream1_body
, 4, ASYNC
),
6941 CreateMockRead(*stream2_body
, 5, ASYNC
),
6942 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6945 OrderedSocketData
spdy_data(
6946 spdy_reads
, arraysize(spdy_reads
),
6947 spdy_writes
, arraysize(spdy_writes
));
6948 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6949 // Negotiate SPDY to the proxy
6950 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6951 proxy
.SetNextProto(GetParam());
6952 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6954 scoped_ptr
<HttpTransaction
> trans(
6955 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6956 TestCompletionCallback callback
;
6957 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6958 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6960 rv
= callback
.WaitForResult();
6962 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6964 scoped_ptr
<HttpTransaction
> push_trans(
6965 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6966 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6967 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6969 rv
= callback
.WaitForResult();
6971 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6973 ASSERT_TRUE(response
!= NULL
);
6974 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6976 EXPECT_EQ(200, response
->headers
->response_code());
6977 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6979 std::string response_data
;
6980 rv
= ReadTransaction(trans
.get(), &response_data
);
6982 EXPECT_EQ("hello!", response_data
);
6984 LoadTimingInfo load_timing_info
;
6985 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6986 TestLoadTimingNotReusedWithPac(load_timing_info
,
6987 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6989 // Verify the pushed stream.
6990 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6991 EXPECT_EQ(200, push_response
->headers
->response_code());
6993 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6995 EXPECT_EQ("pushed", response_data
);
6997 LoadTimingInfo push_load_timing_info
;
6998 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6999 TestLoadTimingReusedWithPac(push_load_timing_info
);
7000 // The transactions should share a socket ID, despite being for different
7002 EXPECT_EQ(load_timing_info
.socket_log_id
,
7003 push_load_timing_info
.socket_log_id
);
7007 session
->CloseAllConnections();
7010 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7011 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
7012 HttpRequestInfo request
;
7014 request
.method
= "GET";
7015 request
.url
= GURL("http://www.example.org/");
7017 // Configure against https proxy server "myproxy:70".
7018 session_deps_
.proxy_service
.reset(
7019 ProxyService::CreateFixed("https://myproxy:70"));
7020 BoundTestNetLog log
;
7021 session_deps_
.net_log
= log
.bound().net_log();
7023 // Enable cross-origin push.
7024 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
7026 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7028 scoped_ptr
<SpdyFrame
> stream1_syn(
7029 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
7031 scoped_ptr
<SpdyFrame
> push_rst(
7032 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7034 MockWrite spdy_writes
[] = {
7035 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
7036 CreateMockWrite(*push_rst
, 4),
7039 scoped_ptr
<SpdyFrame
>
7040 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7042 scoped_ptr
<SpdyFrame
>
7043 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7045 scoped_ptr
<SpdyFrame
>
7046 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7050 "https://www.another-origin.com/foo.dat"));
7052 MockRead spdy_reads
[] = {
7053 CreateMockRead(*stream1_reply
, 2, ASYNC
),
7054 CreateMockRead(*stream2_syn
, 3, ASYNC
),
7055 CreateMockRead(*stream1_body
, 5, ASYNC
),
7056 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
7059 OrderedSocketData
spdy_data(
7060 spdy_reads
, arraysize(spdy_reads
),
7061 spdy_writes
, arraysize(spdy_writes
));
7062 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7063 // Negotiate SPDY to the proxy
7064 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7065 proxy
.SetNextProto(GetParam());
7066 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7068 scoped_ptr
<HttpTransaction
> trans(
7069 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7070 TestCompletionCallback callback
;
7071 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7072 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7074 rv
= callback
.WaitForResult();
7076 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7078 ASSERT_TRUE(response
!= NULL
);
7079 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7081 EXPECT_EQ(200, response
->headers
->response_code());
7082 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7084 std::string response_data
;
7085 rv
= ReadTransaction(trans
.get(), &response_data
);
7087 EXPECT_EQ("hello!", response_data
);
7090 session
->CloseAllConnections();
7093 // Test HTTPS connections to a site with a bad certificate, going through an
7095 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7096 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7097 "https://proxy:70"));
7099 HttpRequestInfo request
;
7100 request
.method
= "GET";
7101 request
.url
= GURL("https://www.example.org/");
7102 request
.load_flags
= 0;
7104 // Attempt to fetch the URL from a server with a bad cert
7105 MockWrite bad_cert_writes
[] = {
7107 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7108 "Host: www.example.org\r\n"
7109 "Proxy-Connection: keep-alive\r\n\r\n"),
7112 MockRead bad_cert_reads
[] = {
7113 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7114 MockRead(SYNCHRONOUS
, OK
)
7117 // Attempt to fetch the URL with a good cert
7118 MockWrite good_data_writes
[] = {
7120 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7121 "Host: www.example.org\r\n"
7122 "Proxy-Connection: keep-alive\r\n\r\n"),
7124 "GET / HTTP/1.1\r\n"
7125 "Host: www.example.org\r\n"
7126 "Connection: keep-alive\r\n\r\n"),
7129 MockRead good_cert_reads
[] = {
7130 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7131 MockRead("HTTP/1.0 200 OK\r\n"),
7132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7133 MockRead("Content-Length: 100\r\n\r\n"),
7134 MockRead(SYNCHRONOUS
, OK
),
7137 StaticSocketDataProvider
ssl_bad_certificate(
7138 bad_cert_reads
, arraysize(bad_cert_reads
),
7139 bad_cert_writes
, arraysize(bad_cert_writes
));
7140 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7141 good_data_writes
, arraysize(good_data_writes
));
7142 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7143 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7145 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7146 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7147 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7148 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7150 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7151 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7152 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7153 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7155 TestCompletionCallback callback
;
7157 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7158 scoped_ptr
<HttpTransaction
> trans(
7159 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7161 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7162 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7164 rv
= callback
.WaitForResult();
7165 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7167 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7168 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7170 rv
= callback
.WaitForResult();
7173 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7175 ASSERT_TRUE(response
!= NULL
);
7176 EXPECT_EQ(100, response
->headers
->GetContentLength());
7179 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7180 HttpRequestInfo request
;
7181 request
.method
= "GET";
7182 request
.url
= GURL("http://www.example.org/");
7183 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7184 "Chromium Ultra Awesome X Edition");
7186 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7187 scoped_ptr
<HttpTransaction
> trans(
7188 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7190 MockWrite data_writes
[] = {
7192 "GET / HTTP/1.1\r\n"
7193 "Host: www.example.org\r\n"
7194 "Connection: keep-alive\r\n"
7195 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7198 // Lastly, the server responds with the actual content.
7199 MockRead data_reads
[] = {
7200 MockRead("HTTP/1.0 200 OK\r\n"),
7201 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7202 MockRead("Content-Length: 100\r\n\r\n"),
7203 MockRead(SYNCHRONOUS
, OK
),
7206 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7207 data_writes
, arraysize(data_writes
));
7208 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7210 TestCompletionCallback callback
;
7212 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7213 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7215 rv
= callback
.WaitForResult();
7219 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7220 HttpRequestInfo request
;
7221 request
.method
= "GET";
7222 request
.url
= GURL("https://www.example.org/");
7223 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7224 "Chromium Ultra Awesome X Edition");
7226 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7227 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7228 scoped_ptr
<HttpTransaction
> trans(
7229 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7231 MockWrite data_writes
[] = {
7233 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7234 "Host: www.example.org\r\n"
7235 "Proxy-Connection: keep-alive\r\n"
7236 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7238 MockRead data_reads
[] = {
7239 // Return an error, so the transaction stops here (this test isn't
7240 // interested in the rest).
7241 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7242 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7243 MockRead("Proxy-Connection: close\r\n\r\n"),
7246 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7247 data_writes
, arraysize(data_writes
));
7248 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7250 TestCompletionCallback callback
;
7252 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7255 rv
= callback
.WaitForResult();
7259 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7260 HttpRequestInfo request
;
7261 request
.method
= "GET";
7262 request
.url
= GURL("http://www.example.org/");
7263 request
.load_flags
= 0;
7264 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7265 "http://the.previous.site.com/");
7267 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7268 scoped_ptr
<HttpTransaction
> trans(
7269 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7271 MockWrite data_writes
[] = {
7273 "GET / HTTP/1.1\r\n"
7274 "Host: www.example.org\r\n"
7275 "Connection: keep-alive\r\n"
7276 "Referer: http://the.previous.site.com/\r\n\r\n"),
7279 // Lastly, the server responds with the actual content.
7280 MockRead data_reads
[] = {
7281 MockRead("HTTP/1.0 200 OK\r\n"),
7282 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7283 MockRead("Content-Length: 100\r\n\r\n"),
7284 MockRead(SYNCHRONOUS
, OK
),
7287 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7288 data_writes
, arraysize(data_writes
));
7289 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7291 TestCompletionCallback callback
;
7293 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7294 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7296 rv
= callback
.WaitForResult();
7300 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7301 HttpRequestInfo request
;
7302 request
.method
= "POST";
7303 request
.url
= GURL("http://www.example.org/");
7305 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7306 scoped_ptr
<HttpTransaction
> trans(
7307 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7309 MockWrite data_writes
[] = {
7311 "POST / HTTP/1.1\r\n"
7312 "Host: www.example.org\r\n"
7313 "Connection: keep-alive\r\n"
7314 "Content-Length: 0\r\n\r\n"),
7317 // Lastly, the server responds with the actual content.
7318 MockRead data_reads
[] = {
7319 MockRead("HTTP/1.0 200 OK\r\n"),
7320 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7321 MockRead("Content-Length: 100\r\n\r\n"),
7322 MockRead(SYNCHRONOUS
, OK
),
7325 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7326 data_writes
, arraysize(data_writes
));
7327 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7329 TestCompletionCallback callback
;
7331 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7332 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7334 rv
= callback
.WaitForResult();
7338 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7339 HttpRequestInfo request
;
7340 request
.method
= "PUT";
7341 request
.url
= GURL("http://www.example.org/");
7343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7344 scoped_ptr
<HttpTransaction
> trans(
7345 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7347 MockWrite data_writes
[] = {
7349 "PUT / HTTP/1.1\r\n"
7350 "Host: www.example.org\r\n"
7351 "Connection: keep-alive\r\n"
7352 "Content-Length: 0\r\n\r\n"),
7355 // Lastly, the server responds with the actual content.
7356 MockRead data_reads
[] = {
7357 MockRead("HTTP/1.0 200 OK\r\n"),
7358 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7359 MockRead("Content-Length: 100\r\n\r\n"),
7360 MockRead(SYNCHRONOUS
, OK
),
7363 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7364 data_writes
, arraysize(data_writes
));
7365 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7367 TestCompletionCallback callback
;
7369 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7370 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7372 rv
= callback
.WaitForResult();
7376 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7377 HttpRequestInfo request
;
7378 request
.method
= "HEAD";
7379 request
.url
= GURL("http://www.example.org/");
7381 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7382 scoped_ptr
<HttpTransaction
> trans(
7383 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7385 MockWrite data_writes
[] = {
7387 "HEAD / HTTP/1.1\r\n"
7388 "Host: www.example.org\r\n"
7389 "Connection: keep-alive\r\n"
7390 "Content-Length: 0\r\n\r\n"),
7393 // Lastly, the server responds with the actual content.
7394 MockRead data_reads
[] = {
7395 MockRead("HTTP/1.0 200 OK\r\n"),
7396 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7397 MockRead("Content-Length: 100\r\n\r\n"),
7398 MockRead(SYNCHRONOUS
, OK
),
7401 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7402 data_writes
, arraysize(data_writes
));
7403 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7405 TestCompletionCallback callback
;
7407 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7408 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7410 rv
= callback
.WaitForResult();
7414 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7415 HttpRequestInfo request
;
7416 request
.method
= "GET";
7417 request
.url
= GURL("http://www.example.org/");
7418 request
.load_flags
= LOAD_BYPASS_CACHE
;
7420 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7421 scoped_ptr
<HttpTransaction
> trans(
7422 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7424 MockWrite data_writes
[] = {
7426 "GET / HTTP/1.1\r\n"
7427 "Host: www.example.org\r\n"
7428 "Connection: keep-alive\r\n"
7429 "Pragma: no-cache\r\n"
7430 "Cache-Control: no-cache\r\n\r\n"),
7433 // Lastly, the server responds with the actual content.
7434 MockRead data_reads
[] = {
7435 MockRead("HTTP/1.0 200 OK\r\n"),
7436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7437 MockRead("Content-Length: 100\r\n\r\n"),
7438 MockRead(SYNCHRONOUS
, OK
),
7441 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7442 data_writes
, arraysize(data_writes
));
7443 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7445 TestCompletionCallback callback
;
7447 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7448 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7450 rv
= callback
.WaitForResult();
7454 TEST_P(HttpNetworkTransactionTest
,
7455 BuildRequest_CacheControlValidateCache
) {
7456 HttpRequestInfo request
;
7457 request
.method
= "GET";
7458 request
.url
= GURL("http://www.example.org/");
7459 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7461 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7462 scoped_ptr
<HttpTransaction
> trans(
7463 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7465 MockWrite data_writes
[] = {
7467 "GET / HTTP/1.1\r\n"
7468 "Host: www.example.org\r\n"
7469 "Connection: keep-alive\r\n"
7470 "Cache-Control: max-age=0\r\n\r\n"),
7473 // Lastly, the server responds with the actual content.
7474 MockRead data_reads
[] = {
7475 MockRead("HTTP/1.0 200 OK\r\n"),
7476 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7477 MockRead("Content-Length: 100\r\n\r\n"),
7478 MockRead(SYNCHRONOUS
, OK
),
7481 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7482 data_writes
, arraysize(data_writes
));
7483 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7485 TestCompletionCallback callback
;
7487 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7488 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7490 rv
= callback
.WaitForResult();
7494 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7495 HttpRequestInfo request
;
7496 request
.method
= "GET";
7497 request
.url
= GURL("http://www.example.org/");
7498 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7500 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7501 scoped_ptr
<HttpTransaction
> trans(
7502 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7504 MockWrite data_writes
[] = {
7506 "GET / HTTP/1.1\r\n"
7507 "Host: www.example.org\r\n"
7508 "Connection: keep-alive\r\n"
7509 "FooHeader: Bar\r\n\r\n"),
7512 // Lastly, the server responds with the actual content.
7513 MockRead data_reads
[] = {
7514 MockRead("HTTP/1.0 200 OK\r\n"),
7515 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7516 MockRead("Content-Length: 100\r\n\r\n"),
7517 MockRead(SYNCHRONOUS
, OK
),
7520 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7521 data_writes
, arraysize(data_writes
));
7522 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7524 TestCompletionCallback callback
;
7526 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7527 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7529 rv
= callback
.WaitForResult();
7533 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7534 HttpRequestInfo request
;
7535 request
.method
= "GET";
7536 request
.url
= GURL("http://www.example.org/");
7537 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7538 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7539 request
.extra_headers
.SetHeader("FoO", "bar");
7541 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7542 scoped_ptr
<HttpTransaction
> trans(
7543 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7545 MockWrite data_writes
[] = {
7547 "GET / HTTP/1.1\r\n"
7548 "Host: www.example.org\r\n"
7549 "Connection: keep-alive\r\n"
7550 "referer: www.foo.com\r\n"
7552 "FoO: bar\r\n\r\n"),
7555 // Lastly, the server responds with the actual content.
7556 MockRead data_reads
[] = {
7557 MockRead("HTTP/1.0 200 OK\r\n"),
7558 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7559 MockRead("Content-Length: 100\r\n\r\n"),
7560 MockRead(SYNCHRONOUS
, OK
),
7563 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7564 data_writes
, arraysize(data_writes
));
7565 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7567 TestCompletionCallback callback
;
7569 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7570 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7572 rv
= callback
.WaitForResult();
7576 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7577 HttpRequestInfo request
;
7578 request
.method
= "GET";
7579 request
.url
= GURL("http://www.example.org/");
7580 request
.load_flags
= 0;
7582 session_deps_
.proxy_service
.reset(
7583 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7585 session_deps_
.net_log
= &net_log
;
7587 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7588 scoped_ptr
<HttpTransaction
> trans(
7589 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7591 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7592 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7594 MockWrite data_writes
[] = {
7595 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7597 "GET / HTTP/1.1\r\n"
7598 "Host: www.example.org\r\n"
7599 "Connection: keep-alive\r\n\r\n")};
7601 MockRead data_reads
[] = {
7602 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7603 MockRead("HTTP/1.0 200 OK\r\n"),
7604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7605 MockRead("Payload"),
7606 MockRead(SYNCHRONOUS
, OK
)
7609 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7610 data_writes
, arraysize(data_writes
));
7611 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7613 TestCompletionCallback callback
;
7615 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7616 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7618 rv
= callback
.WaitForResult();
7621 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7622 ASSERT_TRUE(response
!= NULL
);
7624 LoadTimingInfo load_timing_info
;
7625 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7626 TestLoadTimingNotReusedWithPac(load_timing_info
,
7627 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7629 std::string response_text
;
7630 rv
= ReadTransaction(trans
.get(), &response_text
);
7632 EXPECT_EQ("Payload", response_text
);
7635 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7636 HttpRequestInfo request
;
7637 request
.method
= "GET";
7638 request
.url
= GURL("https://www.example.org/");
7639 request
.load_flags
= 0;
7641 session_deps_
.proxy_service
.reset(
7642 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7644 session_deps_
.net_log
= &net_log
;
7646 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7647 scoped_ptr
<HttpTransaction
> trans(
7648 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7650 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7651 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7653 MockWrite data_writes
[] = {
7654 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7655 arraysize(write_buffer
)),
7657 "GET / HTTP/1.1\r\n"
7658 "Host: www.example.org\r\n"
7659 "Connection: keep-alive\r\n\r\n")};
7661 MockRead data_reads
[] = {
7662 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7663 arraysize(read_buffer
)),
7664 MockRead("HTTP/1.0 200 OK\r\n"),
7665 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7666 MockRead("Payload"),
7667 MockRead(SYNCHRONOUS
, OK
)
7670 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7671 data_writes
, arraysize(data_writes
));
7672 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7674 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7675 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7677 TestCompletionCallback callback
;
7679 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7682 rv
= callback
.WaitForResult();
7685 LoadTimingInfo load_timing_info
;
7686 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7687 TestLoadTimingNotReusedWithPac(load_timing_info
,
7688 CONNECT_TIMING_HAS_SSL_TIMES
);
7690 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7691 ASSERT_TRUE(response
!= NULL
);
7693 std::string response_text
;
7694 rv
= ReadTransaction(trans
.get(), &response_text
);
7696 EXPECT_EQ("Payload", response_text
);
7699 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7700 HttpRequestInfo request
;
7701 request
.method
= "GET";
7702 request
.url
= GURL("http://www.example.org/");
7703 request
.load_flags
= 0;
7705 session_deps_
.proxy_service
.reset(
7706 ProxyService::CreateFixed("socks4://myproxy:1080"));
7708 session_deps_
.net_log
= &net_log
;
7710 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7711 scoped_ptr
<HttpTransaction
> trans(
7712 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7714 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7715 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7717 MockWrite data_writes
[] = {
7718 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7720 "GET / HTTP/1.1\r\n"
7721 "Host: www.example.org\r\n"
7722 "Connection: keep-alive\r\n\r\n")};
7724 MockRead data_reads
[] = {
7725 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7726 MockRead("HTTP/1.0 200 OK\r\n"),
7727 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7728 MockRead("Payload"),
7729 MockRead(SYNCHRONOUS
, OK
)
7732 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7733 data_writes
, arraysize(data_writes
));
7734 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7736 TestCompletionCallback callback
;
7738 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7741 rv
= callback
.WaitForResult();
7744 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7745 ASSERT_TRUE(response
!= NULL
);
7747 LoadTimingInfo load_timing_info
;
7748 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7749 TestLoadTimingNotReused(load_timing_info
,
7750 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7752 std::string response_text
;
7753 rv
= ReadTransaction(trans
.get(), &response_text
);
7755 EXPECT_EQ("Payload", response_text
);
7758 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7759 HttpRequestInfo request
;
7760 request
.method
= "GET";
7761 request
.url
= GURL("http://www.example.org/");
7762 request
.load_flags
= 0;
7764 session_deps_
.proxy_service
.reset(
7765 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7767 session_deps_
.net_log
= &net_log
;
7769 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7770 scoped_ptr
<HttpTransaction
> trans(
7771 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7773 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7774 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7775 const char kSOCKS5OkRequest
[] = {
7777 0x01, // Command (CONNECT)
7779 0x03, // Address type (DOMAINNAME).
7780 0x0F, // Length of domain (15)
7781 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7782 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7784 const char kSOCKS5OkResponse
[] =
7785 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7787 MockWrite data_writes
[] = {
7788 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7789 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7791 "GET / HTTP/1.1\r\n"
7792 "Host: www.example.org\r\n"
7793 "Connection: keep-alive\r\n\r\n")};
7795 MockRead data_reads
[] = {
7796 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7797 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7798 MockRead("HTTP/1.0 200 OK\r\n"),
7799 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7800 MockRead("Payload"),
7801 MockRead(SYNCHRONOUS
, OK
)
7804 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7805 data_writes
, arraysize(data_writes
));
7806 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7808 TestCompletionCallback callback
;
7810 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7811 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7813 rv
= callback
.WaitForResult();
7816 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7817 ASSERT_TRUE(response
!= NULL
);
7819 LoadTimingInfo load_timing_info
;
7820 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7821 TestLoadTimingNotReusedWithPac(load_timing_info
,
7822 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7824 std::string response_text
;
7825 rv
= ReadTransaction(trans
.get(), &response_text
);
7827 EXPECT_EQ("Payload", response_text
);
7830 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7831 HttpRequestInfo request
;
7832 request
.method
= "GET";
7833 request
.url
= GURL("https://www.example.org/");
7834 request
.load_flags
= 0;
7836 session_deps_
.proxy_service
.reset(
7837 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7839 session_deps_
.net_log
= &net_log
;
7841 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7842 scoped_ptr
<HttpTransaction
> trans(
7843 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7845 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7846 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7847 const unsigned char kSOCKS5OkRequest
[] = {
7849 0x01, // Command (CONNECT)
7851 0x03, // Address type (DOMAINNAME).
7852 0x0F, // Length of domain (15)
7853 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7854 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7857 const char kSOCKS5OkResponse
[] =
7858 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7860 MockWrite data_writes
[] = {
7861 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7862 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7863 arraysize(kSOCKS5OkRequest
)),
7865 "GET / HTTP/1.1\r\n"
7866 "Host: www.example.org\r\n"
7867 "Connection: keep-alive\r\n\r\n")};
7869 MockRead data_reads
[] = {
7870 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7871 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7872 MockRead("HTTP/1.0 200 OK\r\n"),
7873 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7874 MockRead("Payload"),
7875 MockRead(SYNCHRONOUS
, OK
)
7878 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7879 data_writes
, arraysize(data_writes
));
7880 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7882 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7883 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7885 TestCompletionCallback callback
;
7887 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7888 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7890 rv
= callback
.WaitForResult();
7893 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7894 ASSERT_TRUE(response
!= NULL
);
7896 LoadTimingInfo load_timing_info
;
7897 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7898 TestLoadTimingNotReusedWithPac(load_timing_info
,
7899 CONNECT_TIMING_HAS_SSL_TIMES
);
7901 std::string response_text
;
7902 rv
= ReadTransaction(trans
.get(), &response_text
);
7904 EXPECT_EQ("Payload", response_text
);
7909 // Tests that for connection endpoints the group names are correctly set.
7911 struct GroupNameTest
{
7912 std::string proxy_server
;
7914 std::string expected_group_name
;
7918 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7919 NextProto next_proto
,
7920 SpdySessionDependencies
* session_deps_
) {
7921 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7923 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7924 session
->http_server_properties();
7925 AlternativeService
alternative_service(
7926 AlternateProtocolFromNextProto(next_proto
), "", 443);
7927 http_server_properties
->SetAlternativeService(
7928 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0);
7933 int GroupNameTransactionHelper(
7934 const std::string
& url
,
7935 const scoped_refptr
<HttpNetworkSession
>& session
) {
7936 HttpRequestInfo request
;
7937 request
.method
= "GET";
7938 request
.url
= GURL(url
);
7939 request
.load_flags
= 0;
7941 scoped_ptr
<HttpTransaction
> trans(
7942 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7944 TestCompletionCallback callback
;
7946 // We do not complete this request, the dtor will clean the transaction up.
7947 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7952 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7953 const GroupNameTest tests
[] = {
7956 "http://www.example.org/direct",
7957 "www.example.org:80",
7962 "http://[2001:1418:13:1::25]/direct",
7963 "[2001:1418:13:1::25]:80",
7970 "https://www.example.org/direct_ssl",
7971 "ssl/www.example.org:443",
7976 "https://[2001:1418:13:1::25]/direct",
7977 "ssl/[2001:1418:13:1::25]:443",
7982 "http://host.with.alternate/direct",
7983 "ssl/host.with.alternate:443",
7988 session_deps_
.use_alternate_protocols
= true;
7990 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7991 session_deps_
.proxy_service
.reset(
7992 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7993 scoped_refptr
<HttpNetworkSession
> session(
7994 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7996 HttpNetworkSessionPeer
peer(session
);
7997 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7998 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7999 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8000 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8001 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8002 new MockClientSocketPoolManager
);
8003 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
8004 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
8005 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8007 EXPECT_EQ(ERR_IO_PENDING
,
8008 GroupNameTransactionHelper(tests
[i
].url
, session
));
8010 EXPECT_EQ(tests
[i
].expected_group_name
,
8011 ssl_conn_pool
->last_group_name_received());
8013 EXPECT_EQ(tests
[i
].expected_group_name
,
8014 transport_conn_pool
->last_group_name_received());
8019 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
8020 const GroupNameTest tests
[] = {
8023 "http://www.example.org/http_proxy_normal",
8024 "www.example.org:80",
8031 "https://www.example.org/http_connect_ssl",
8032 "ssl/www.example.org:443",
8038 "http://host.with.alternate/direct",
8039 "ssl/host.with.alternate:443",
8045 "ftp://ftp.google.com/http_proxy_normal",
8046 "ftp/ftp.google.com:21",
8051 session_deps_
.use_alternate_protocols
= true;
8053 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8054 session_deps_
.proxy_service
.reset(
8055 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8056 scoped_refptr
<HttpNetworkSession
> session(
8057 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8059 HttpNetworkSessionPeer
peer(session
);
8061 HostPortPair
proxy_host("http_proxy", 80);
8062 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8063 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8064 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8065 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8067 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8068 new MockClientSocketPoolManager
);
8069 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8070 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8071 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8073 EXPECT_EQ(ERR_IO_PENDING
,
8074 GroupNameTransactionHelper(tests
[i
].url
, session
));
8076 EXPECT_EQ(tests
[i
].expected_group_name
,
8077 ssl_conn_pool
->last_group_name_received());
8079 EXPECT_EQ(tests
[i
].expected_group_name
,
8080 http_proxy_pool
->last_group_name_received());
8084 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8085 const GroupNameTest tests
[] = {
8087 "socks4://socks_proxy:1080",
8088 "http://www.example.org/socks4_direct",
8089 "socks4/www.example.org:80",
8093 "socks5://socks_proxy:1080",
8094 "http://www.example.org/socks5_direct",
8095 "socks5/www.example.org:80",
8101 "socks4://socks_proxy:1080",
8102 "https://www.example.org/socks4_ssl",
8103 "socks4/ssl/www.example.org:443",
8107 "socks5://socks_proxy:1080",
8108 "https://www.example.org/socks5_ssl",
8109 "socks5/ssl/www.example.org:443",
8114 "socks4://socks_proxy:1080",
8115 "http://host.with.alternate/direct",
8116 "socks4/ssl/host.with.alternate:443",
8121 session_deps_
.use_alternate_protocols
= true;
8123 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8124 session_deps_
.proxy_service
.reset(
8125 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8126 scoped_refptr
<HttpNetworkSession
> session(
8127 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8129 HttpNetworkSessionPeer
peer(session
);
8131 HostPortPair
proxy_host("socks_proxy", 1080);
8132 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8133 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8134 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8135 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8137 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8138 new MockClientSocketPoolManager
);
8139 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8140 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8141 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8143 scoped_ptr
<HttpTransaction
> trans(
8144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8146 EXPECT_EQ(ERR_IO_PENDING
,
8147 GroupNameTransactionHelper(tests
[i
].url
, session
));
8149 EXPECT_EQ(tests
[i
].expected_group_name
,
8150 ssl_conn_pool
->last_group_name_received());
8152 EXPECT_EQ(tests
[i
].expected_group_name
,
8153 socks_conn_pool
->last_group_name_received());
8157 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8158 HttpRequestInfo request
;
8159 request
.method
= "GET";
8160 request
.url
= GURL("http://www.example.org/");
8162 session_deps_
.proxy_service
.reset(
8163 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8165 // This simulates failure resolving all hostnames; that means we will fail
8166 // connecting to both proxies (myproxy:70 and foobar:80).
8167 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8169 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8170 scoped_ptr
<HttpTransaction
> trans(
8171 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8173 TestCompletionCallback callback
;
8175 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8176 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8178 rv
= callback
.WaitForResult();
8179 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8182 // Base test to make sure that when the load flags for a request specify to
8183 // bypass the cache, the DNS cache is not used.
8184 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8186 // Issue a request, asking to bypass the cache(s).
8187 HttpRequestInfo request
;
8188 request
.method
= "GET";
8189 request
.load_flags
= load_flags
;
8190 request
.url
= GURL("http://www.example.org/");
8192 // Select a host resolver that does caching.
8193 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8195 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8196 scoped_ptr
<HttpTransaction
> trans(
8197 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8199 // Warm up the host cache so it has an entry for "www.example.org".
8200 AddressList addrlist
;
8201 TestCompletionCallback callback
;
8202 int rv
= session_deps_
.host_resolver
->Resolve(
8203 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8204 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8206 rv
= callback
.WaitForResult();
8209 // Verify that it was added to host cache, by doing a subsequent async lookup
8210 // and confirming it completes synchronously.
8211 rv
= session_deps_
.host_resolver
->Resolve(
8212 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8213 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8216 // Inject a failure the next time that "www.example.org" is resolved. This way
8217 // we can tell if the next lookup hit the cache, or the "network".
8218 // (cache --> success, "network" --> failure).
8219 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8221 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8222 // first read -- this won't be reached as the host resolution will fail first.
8223 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8224 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8225 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8228 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8229 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8230 rv
= callback
.WaitForResult();
8232 // If we bypassed the cache, we would have gotten a failure while resolving
8233 // "www.example.org".
8234 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8237 // There are multiple load flags that should trigger the host cache bypass.
8238 // Test each in isolation:
8239 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8240 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8243 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8244 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8247 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8248 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8251 // Make sure we can handle an error when writing the request.
8252 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8253 HttpRequestInfo request
;
8254 request
.method
= "GET";
8255 request
.url
= GURL("http://www.foo.com/");
8256 request
.load_flags
= 0;
8258 MockWrite write_failure
[] = {
8259 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8261 StaticSocketDataProvider
data(NULL
, 0,
8262 write_failure
, arraysize(write_failure
));
8263 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8264 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8266 TestCompletionCallback callback
;
8268 scoped_ptr
<HttpTransaction
> trans(
8269 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8271 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8272 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8274 rv
= callback
.WaitForResult();
8275 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8278 // Check that a connection closed after the start of the headers finishes ok.
8279 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8280 HttpRequestInfo request
;
8281 request
.method
= "GET";
8282 request
.url
= GURL("http://www.foo.com/");
8283 request
.load_flags
= 0;
8285 MockRead data_reads
[] = {
8286 MockRead("HTTP/1."),
8287 MockRead(SYNCHRONOUS
, OK
),
8290 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8291 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8292 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8294 TestCompletionCallback callback
;
8296 scoped_ptr
<HttpTransaction
> trans(
8297 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8299 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8300 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8302 rv
= callback
.WaitForResult();
8305 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8306 ASSERT_TRUE(response
!= NULL
);
8308 EXPECT_TRUE(response
->headers
.get() != NULL
);
8309 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8311 std::string response_data
;
8312 rv
= ReadTransaction(trans
.get(), &response_data
);
8314 EXPECT_EQ("", response_data
);
8317 // Make sure that a dropped connection while draining the body for auth
8318 // restart does the right thing.
8319 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8320 HttpRequestInfo request
;
8321 request
.method
= "GET";
8322 request
.url
= GURL("http://www.example.org/");
8323 request
.load_flags
= 0;
8325 MockWrite data_writes1
[] = {
8327 "GET / HTTP/1.1\r\n"
8328 "Host: www.example.org\r\n"
8329 "Connection: keep-alive\r\n\r\n"),
8332 MockRead data_reads1
[] = {
8333 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8334 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8335 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8336 MockRead("Content-Length: 14\r\n\r\n"),
8338 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8341 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8342 data_writes1
, arraysize(data_writes1
));
8343 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8345 // After calling trans->RestartWithAuth(), this is the request we should
8346 // be issuing -- the final header line contains the credentials.
8347 MockWrite data_writes2
[] = {
8349 "GET / HTTP/1.1\r\n"
8350 "Host: www.example.org\r\n"
8351 "Connection: keep-alive\r\n"
8352 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8355 // Lastly, the server responds with the actual content.
8356 MockRead data_reads2
[] = {
8357 MockRead("HTTP/1.1 200 OK\r\n"),
8358 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8359 MockRead("Content-Length: 100\r\n\r\n"),
8360 MockRead(SYNCHRONOUS
, OK
),
8363 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8364 data_writes2
, arraysize(data_writes2
));
8365 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8366 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8368 TestCompletionCallback callback1
;
8370 scoped_ptr
<HttpTransaction
> trans(
8371 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8373 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8374 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8376 rv
= callback1
.WaitForResult();
8379 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8380 ASSERT_TRUE(response
!= NULL
);
8381 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8383 TestCompletionCallback callback2
;
8385 rv
= trans
->RestartWithAuth(
8386 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8387 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8389 rv
= callback2
.WaitForResult();
8392 response
= trans
->GetResponseInfo();
8393 ASSERT_TRUE(response
!= NULL
);
8394 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8395 EXPECT_EQ(100, response
->headers
->GetContentLength());
8398 // Test HTTPS connections going through a proxy that sends extra data.
8399 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8400 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8402 HttpRequestInfo request
;
8403 request
.method
= "GET";
8404 request
.url
= GURL("https://www.example.org/");
8405 request
.load_flags
= 0;
8407 MockRead proxy_reads
[] = {
8408 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8409 MockRead(SYNCHRONOUS
, OK
)
8412 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8413 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8415 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8416 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8418 TestCompletionCallback callback
;
8420 session_deps_
.socket_factory
->ResetNextMockIndexes();
8422 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8423 scoped_ptr
<HttpTransaction
> trans(
8424 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8426 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8427 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8429 rv
= callback
.WaitForResult();
8430 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8433 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8434 HttpRequestInfo request
;
8435 request
.method
= "GET";
8436 request
.url
= GURL("http://www.example.org/");
8437 request
.load_flags
= 0;
8439 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8440 scoped_ptr
<HttpTransaction
> trans(
8441 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8443 MockRead data_reads
[] = {
8444 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8445 MockRead(SYNCHRONOUS
, OK
),
8448 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8449 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8451 TestCompletionCallback callback
;
8453 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8456 EXPECT_EQ(OK
, callback
.WaitForResult());
8458 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8459 ASSERT_TRUE(response
!= NULL
);
8461 EXPECT_TRUE(response
->headers
.get() != NULL
);
8462 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8464 std::string response_data
;
8465 rv
= ReadTransaction(trans
.get(), &response_data
);
8466 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8469 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8470 base::FilePath temp_file_path
;
8471 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8472 const uint64 kFakeSize
= 100000; // file is actually blank
8473 UploadFileElementReader::ScopedOverridingContentLengthForTests
8474 overriding_content_length(kFakeSize
);
8476 ScopedVector
<UploadElementReader
> element_readers
;
8477 element_readers
.push_back(
8478 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8483 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8485 HttpRequestInfo request
;
8486 request
.method
= "POST";
8487 request
.url
= GURL("http://www.example.org/upload");
8488 request
.upload_data_stream
= &upload_data_stream
;
8489 request
.load_flags
= 0;
8491 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8492 scoped_ptr
<HttpTransaction
> trans(
8493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8495 MockRead data_reads
[] = {
8496 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8497 MockRead("hello world"),
8498 MockRead(SYNCHRONOUS
, OK
),
8500 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8501 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8503 TestCompletionCallback callback
;
8505 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8506 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8508 rv
= callback
.WaitForResult();
8511 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8512 ASSERT_TRUE(response
!= NULL
);
8514 EXPECT_TRUE(response
->headers
.get() != NULL
);
8515 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8517 std::string response_data
;
8518 rv
= ReadTransaction(trans
.get(), &response_data
);
8520 EXPECT_EQ("hello world", response_data
);
8522 base::DeleteFile(temp_file_path
, false);
8525 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8526 base::FilePath temp_file
;
8527 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8528 std::string
temp_file_content("Unreadable file.");
8529 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8530 temp_file_content
.length()));
8531 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8533 ScopedVector
<UploadElementReader
> element_readers
;
8534 element_readers
.push_back(
8535 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8540 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8542 HttpRequestInfo request
;
8543 request
.method
= "POST";
8544 request
.url
= GURL("http://www.example.org/upload");
8545 request
.upload_data_stream
= &upload_data_stream
;
8546 request
.load_flags
= 0;
8548 // If we try to upload an unreadable file, the transaction should fail.
8549 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8550 scoped_ptr
<HttpTransaction
> trans(
8551 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8553 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8554 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8556 TestCompletionCallback callback
;
8558 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8559 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8561 rv
= callback
.WaitForResult();
8562 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8564 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8565 EXPECT_FALSE(response
);
8567 base::DeleteFile(temp_file
, false);
8570 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8571 class FakeUploadElementReader
: public UploadElementReader
{
8573 FakeUploadElementReader() {}
8574 ~FakeUploadElementReader() override
{}
8576 const CompletionCallback
& callback() const { return callback_
; }
8578 // UploadElementReader overrides:
8579 int Init(const CompletionCallback
& callback
) override
{
8580 callback_
= callback
;
8581 return ERR_IO_PENDING
;
8583 uint64
GetContentLength() const override
{ return 0; }
8584 uint64
BytesRemaining() const override
{ return 0; }
8585 int Read(IOBuffer
* buf
,
8587 const CompletionCallback
& callback
) override
{
8592 CompletionCallback callback_
;
8595 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8596 ScopedVector
<UploadElementReader
> element_readers
;
8597 element_readers
.push_back(fake_reader
);
8598 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8600 HttpRequestInfo request
;
8601 request
.method
= "POST";
8602 request
.url
= GURL("http://www.example.org/upload");
8603 request
.upload_data_stream
= &upload_data_stream
;
8604 request
.load_flags
= 0;
8606 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8607 scoped_ptr
<HttpTransaction
> trans(
8608 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8610 StaticSocketDataProvider data
;
8611 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8613 TestCompletionCallback callback
;
8614 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8615 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8616 base::MessageLoop::current()->RunUntilIdle();
8618 // Transaction is pending on request body initialization.
8619 ASSERT_FALSE(fake_reader
->callback().is_null());
8621 // Return Init()'s result after the transaction gets destroyed.
8623 fake_reader
->callback().Run(OK
); // Should not crash.
8626 // Tests that changes to Auth realms are treated like auth rejections.
8627 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8629 HttpRequestInfo request
;
8630 request
.method
= "GET";
8631 request
.url
= GURL("http://www.example.org/");
8632 request
.load_flags
= 0;
8634 // First transaction will request a resource and receive a Basic challenge
8635 // with realm="first_realm".
8636 MockWrite data_writes1
[] = {
8638 "GET / HTTP/1.1\r\n"
8639 "Host: www.example.org\r\n"
8640 "Connection: keep-alive\r\n"
8643 MockRead data_reads1
[] = {
8644 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8645 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8649 // After calling trans->RestartWithAuth(), provide an Authentication header
8650 // for first_realm. The server will reject and provide a challenge with
8652 MockWrite data_writes2
[] = {
8654 "GET / HTTP/1.1\r\n"
8655 "Host: www.example.org\r\n"
8656 "Connection: keep-alive\r\n"
8657 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8660 MockRead data_reads2
[] = {
8661 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8662 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8666 // This again fails, and goes back to first_realm. Make sure that the
8667 // entry is removed from cache.
8668 MockWrite data_writes3
[] = {
8670 "GET / HTTP/1.1\r\n"
8671 "Host: www.example.org\r\n"
8672 "Connection: keep-alive\r\n"
8673 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8676 MockRead data_reads3
[] = {
8677 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8678 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8682 // Try one last time (with the correct password) and get the resource.
8683 MockWrite data_writes4
[] = {
8685 "GET / HTTP/1.1\r\n"
8686 "Host: www.example.org\r\n"
8687 "Connection: keep-alive\r\n"
8688 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8691 MockRead data_reads4
[] = {
8692 MockRead("HTTP/1.1 200 OK\r\n"
8693 "Content-Type: text/html; charset=iso-8859-1\r\n"
8694 "Content-Length: 5\r\n"
8699 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8700 data_writes1
, arraysize(data_writes1
));
8701 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8702 data_writes2
, arraysize(data_writes2
));
8703 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8704 data_writes3
, arraysize(data_writes3
));
8705 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8706 data_writes4
, arraysize(data_writes4
));
8707 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8708 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8709 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8710 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8712 TestCompletionCallback callback1
;
8714 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8715 scoped_ptr
<HttpTransaction
> trans(
8716 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8718 // Issue the first request with Authorize headers. There should be a
8719 // password prompt for first_realm waiting to be filled in after the
8720 // transaction completes.
8721 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8723 rv
= callback1
.WaitForResult();
8725 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8726 ASSERT_TRUE(response
!= NULL
);
8727 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8728 ASSERT_FALSE(challenge
== NULL
);
8729 EXPECT_FALSE(challenge
->is_proxy
);
8730 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8731 EXPECT_EQ("first_realm", challenge
->realm
);
8732 EXPECT_EQ("basic", challenge
->scheme
);
8734 // Issue the second request with an incorrect password. There should be a
8735 // password prompt for second_realm waiting to be filled in after the
8736 // transaction completes.
8737 TestCompletionCallback callback2
;
8738 rv
= trans
->RestartWithAuth(
8739 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8740 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8741 rv
= callback2
.WaitForResult();
8743 response
= trans
->GetResponseInfo();
8744 ASSERT_TRUE(response
!= NULL
);
8745 challenge
= response
->auth_challenge
.get();
8746 ASSERT_FALSE(challenge
== NULL
);
8747 EXPECT_FALSE(challenge
->is_proxy
);
8748 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8749 EXPECT_EQ("second_realm", challenge
->realm
);
8750 EXPECT_EQ("basic", challenge
->scheme
);
8752 // Issue the third request with another incorrect password. There should be
8753 // a password prompt for first_realm waiting to be filled in. If the password
8754 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8755 // first_realm was not correctly removed.
8756 TestCompletionCallback callback3
;
8757 rv
= trans
->RestartWithAuth(
8758 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8760 rv
= callback3
.WaitForResult();
8762 response
= trans
->GetResponseInfo();
8763 ASSERT_TRUE(response
!= NULL
);
8764 challenge
= response
->auth_challenge
.get();
8765 ASSERT_FALSE(challenge
== NULL
);
8766 EXPECT_FALSE(challenge
->is_proxy
);
8767 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8768 EXPECT_EQ("first_realm", challenge
->realm
);
8769 EXPECT_EQ("basic", challenge
->scheme
);
8771 // Issue the fourth request with the correct password and username.
8772 TestCompletionCallback callback4
;
8773 rv
= trans
->RestartWithAuth(
8774 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8776 rv
= callback4
.WaitForResult();
8778 response
= trans
->GetResponseInfo();
8779 ASSERT_TRUE(response
!= NULL
);
8780 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8783 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8784 session_deps_
.next_protos
= SpdyNextProtos();
8785 session_deps_
.use_alternate_protocols
= true;
8787 std::string alternate_protocol_http_header
=
8788 GetAlternateProtocolHttpHeader();
8790 MockRead data_reads
[] = {
8791 MockRead("HTTP/1.1 200 OK\r\n"),
8792 MockRead(alternate_protocol_http_header
.c_str()),
8793 MockRead("hello world"),
8794 MockRead(SYNCHRONOUS
, OK
),
8797 HttpRequestInfo request
;
8798 request
.method
= "GET";
8799 request
.url
= GURL("http://www.example.org/");
8800 request
.load_flags
= 0;
8802 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8804 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8806 TestCompletionCallback callback
;
8808 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8809 scoped_ptr
<HttpTransaction
> trans(
8810 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8812 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8813 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8815 HostPortPair
http_host_port_pair("www.example.org", 80);
8816 HttpServerProperties
& http_server_properties
=
8817 *session
->http_server_properties();
8818 AlternativeService alternative_service
=
8819 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8820 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8822 EXPECT_EQ(OK
, callback
.WaitForResult());
8824 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8825 ASSERT_TRUE(response
!= NULL
);
8826 ASSERT_TRUE(response
->headers
.get() != NULL
);
8827 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8828 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8829 EXPECT_FALSE(response
->was_npn_negotiated
);
8831 std::string response_data
;
8832 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8833 EXPECT_EQ("hello world", response_data
);
8835 alternative_service
=
8836 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8837 EXPECT_EQ(443, alternative_service
.port
);
8838 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8839 alternative_service
.protocol
);
8842 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8843 session_deps_
.next_protos
= SpdyNextProtos();
8844 session_deps_
.use_alternate_protocols
= true;
8846 MockRead data_reads
[] = {
8847 MockRead("HTTP/1.1 200 OK\r\n"),
8848 MockRead("Alternate-Protocol: \r\n\r\n"),
8849 MockRead("hello world"),
8850 MockRead(SYNCHRONOUS
, OK
),
8853 HttpRequestInfo request
;
8854 request
.method
= "GET";
8855 request
.url
= GURL("http://www.example.org/");
8856 request
.load_flags
= 0;
8858 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8860 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8862 TestCompletionCallback callback
;
8864 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8866 HostPortPair
http_host_port_pair("www.example.org", 80);
8867 HttpServerProperties
& http_server_properties
=
8868 *session
->http_server_properties();
8869 AlternativeService
alternative_service(QUIC
, "", 80);
8870 http_server_properties
.SetAlternativeService(http_host_port_pair
,
8871 alternative_service
, 1.0);
8873 alternative_service
=
8874 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8875 EXPECT_EQ(alternative_service
.protocol
, QUIC
);
8877 scoped_ptr
<HttpTransaction
> trans(
8878 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8880 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8883 EXPECT_EQ(OK
, callback
.WaitForResult());
8885 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8886 ASSERT_TRUE(response
!= NULL
);
8887 ASSERT_TRUE(response
->headers
.get() != NULL
);
8888 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8889 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8890 EXPECT_FALSE(response
->was_npn_negotiated
);
8892 std::string response_data
;
8893 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8894 EXPECT_EQ("hello world", response_data
);
8896 alternative_service
=
8897 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8898 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8901 TEST_P(HttpNetworkTransactionTest
,
8902 MarkBrokenAlternateProtocolAndFallback
) {
8903 session_deps_
.use_alternate_protocols
= true;
8905 HttpRequestInfo request
;
8906 request
.method
= "GET";
8907 request
.url
= GURL("http://www.example.org/");
8908 request
.load_flags
= 0;
8910 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8911 StaticSocketDataProvider first_data
;
8912 first_data
.set_connect_data(mock_connect
);
8913 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8915 MockRead data_reads
[] = {
8916 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8917 MockRead("hello world"),
8918 MockRead(ASYNC
, OK
),
8920 StaticSocketDataProvider
second_data(
8921 data_reads
, arraysize(data_reads
), NULL
, 0);
8922 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8924 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8926 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8927 session
->http_server_properties();
8928 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
8929 // Port must be < 1024, or the header will be ignored (since initial port was
8930 // port 80 (another restricted port).
8931 AlternativeService
alternative_service(
8932 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8933 666); /* port is ignored by MockConnect anyway */
8934 http_server_properties
->SetAlternativeService(host_port_pair
,
8935 alternative_service
, 1.0);
8937 scoped_ptr
<HttpTransaction
> trans(
8938 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8939 TestCompletionCallback callback
;
8941 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8943 EXPECT_EQ(OK
, callback
.WaitForResult());
8945 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8946 ASSERT_TRUE(response
!= NULL
);
8947 ASSERT_TRUE(response
->headers
.get() != NULL
);
8948 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8950 std::string response_data
;
8951 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8952 EXPECT_EQ("hello world", response_data
);
8954 alternative_service
=
8955 http_server_properties
->GetAlternativeService(host_port_pair
);
8956 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL
, alternative_service
.protocol
);
8958 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
8961 TEST_P(HttpNetworkTransactionTest
,
8962 AlternateProtocolPortRestrictedBlocked
) {
8963 // Ensure that we're not allowed to redirect traffic via an alternate
8964 // protocol to an unrestricted (port >= 1024) when the original traffic was
8965 // on a restricted port (port < 1024). Ensure that we can redirect in all
8967 session_deps_
.use_alternate_protocols
= true;
8969 HttpRequestInfo restricted_port_request
;
8970 restricted_port_request
.method
= "GET";
8971 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8972 restricted_port_request
.load_flags
= 0;
8974 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8975 StaticSocketDataProvider first_data
;
8976 first_data
.set_connect_data(mock_connect
);
8977 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8979 MockRead data_reads
[] = {
8980 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8981 MockRead("hello world"),
8982 MockRead(ASYNC
, OK
),
8984 StaticSocketDataProvider
second_data(
8985 data_reads
, arraysize(data_reads
), NULL
, 0);
8986 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8988 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8990 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8991 session
->http_server_properties();
8992 const int kUnrestrictedAlternatePort
= 1024;
8993 AlternativeService
alternative_service(
8994 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8995 kUnrestrictedAlternatePort
);
8996 http_server_properties
->SetAlternativeService(
8997 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9000 scoped_ptr
<HttpTransaction
> trans(
9001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9002 TestCompletionCallback callback
;
9004 int rv
= trans
->Start(
9005 &restricted_port_request
,
9006 callback
.callback(), BoundNetLog());
9007 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9008 // Invalid change to unrestricted port should fail.
9009 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9012 TEST_P(HttpNetworkTransactionTest
,
9013 AlternateProtocolPortRestrictedPermitted
) {
9014 // Ensure that we're allowed to redirect traffic via an alternate
9015 // protocol to an unrestricted (port >= 1024) when the original traffic was
9016 // on a restricted port (port < 1024) if we set
9017 // enable_user_alternate_protocol_ports.
9019 session_deps_
.use_alternate_protocols
= true;
9020 session_deps_
.enable_user_alternate_protocol_ports
= true;
9022 HttpRequestInfo restricted_port_request
;
9023 restricted_port_request
.method
= "GET";
9024 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9025 restricted_port_request
.load_flags
= 0;
9027 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9028 StaticSocketDataProvider first_data
;
9029 first_data
.set_connect_data(mock_connect
);
9030 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9032 MockRead data_reads
[] = {
9033 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9034 MockRead("hello world"),
9035 MockRead(ASYNC
, OK
),
9037 StaticSocketDataProvider
second_data(
9038 data_reads
, arraysize(data_reads
), NULL
, 0);
9039 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9041 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9043 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9044 session
->http_server_properties();
9045 const int kUnrestrictedAlternatePort
= 1024;
9046 AlternativeService
alternative_service(
9047 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9048 kUnrestrictedAlternatePort
);
9049 http_server_properties
->SetAlternativeService(
9050 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9053 scoped_ptr
<HttpTransaction
> trans(
9054 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9055 TestCompletionCallback callback
;
9057 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9058 &restricted_port_request
,
9059 callback
.callback(), BoundNetLog()));
9060 // Change to unrestricted port should succeed.
9061 EXPECT_EQ(OK
, callback
.WaitForResult());
9064 TEST_P(HttpNetworkTransactionTest
,
9065 AlternateProtocolPortRestrictedAllowed
) {
9066 // Ensure that we're not allowed to redirect traffic via an alternate
9067 // protocol to an unrestricted (port >= 1024) when the original traffic was
9068 // on a restricted port (port < 1024). Ensure that we can redirect in all
9070 session_deps_
.use_alternate_protocols
= true;
9072 HttpRequestInfo restricted_port_request
;
9073 restricted_port_request
.method
= "GET";
9074 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9075 restricted_port_request
.load_flags
= 0;
9077 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9078 StaticSocketDataProvider first_data
;
9079 first_data
.set_connect_data(mock_connect
);
9080 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9082 MockRead data_reads
[] = {
9083 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9084 MockRead("hello world"),
9085 MockRead(ASYNC
, OK
),
9087 StaticSocketDataProvider
second_data(
9088 data_reads
, arraysize(data_reads
), NULL
, 0);
9089 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9091 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9093 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9094 session
->http_server_properties();
9095 const int kRestrictedAlternatePort
= 80;
9096 AlternativeService
alternative_service(
9097 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9098 kRestrictedAlternatePort
);
9099 http_server_properties
->SetAlternativeService(
9100 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9103 scoped_ptr
<HttpTransaction
> trans(
9104 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9105 TestCompletionCallback callback
;
9107 int rv
= trans
->Start(
9108 &restricted_port_request
,
9109 callback
.callback(), BoundNetLog());
9110 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9111 // Valid change to restricted port should pass.
9112 EXPECT_EQ(OK
, callback
.WaitForResult());
9115 TEST_P(HttpNetworkTransactionTest
,
9116 AlternateProtocolPortUnrestrictedAllowed1
) {
9117 // Ensure that we're not allowed to redirect traffic via an alternate
9118 // protocol to an unrestricted (port >= 1024) when the original traffic was
9119 // on a restricted port (port < 1024). Ensure that we can redirect in all
9121 session_deps_
.use_alternate_protocols
= true;
9123 HttpRequestInfo unrestricted_port_request
;
9124 unrestricted_port_request
.method
= "GET";
9125 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9126 unrestricted_port_request
.load_flags
= 0;
9128 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9129 StaticSocketDataProvider first_data
;
9130 first_data
.set_connect_data(mock_connect
);
9131 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9133 MockRead data_reads
[] = {
9134 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9135 MockRead("hello world"),
9136 MockRead(ASYNC
, OK
),
9138 StaticSocketDataProvider
second_data(
9139 data_reads
, arraysize(data_reads
), NULL
, 0);
9140 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9142 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9144 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9145 session
->http_server_properties();
9146 const int kRestrictedAlternatePort
= 80;
9147 AlternativeService
alternative_service(
9148 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9149 kRestrictedAlternatePort
);
9150 http_server_properties
->SetAlternativeService(
9151 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9154 scoped_ptr
<HttpTransaction
> trans(
9155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9156 TestCompletionCallback callback
;
9158 int rv
= trans
->Start(
9159 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9160 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9161 // Valid change to restricted port should pass.
9162 EXPECT_EQ(OK
, callback
.WaitForResult());
9165 TEST_P(HttpNetworkTransactionTest
,
9166 AlternateProtocolPortUnrestrictedAllowed2
) {
9167 // Ensure that we're not allowed to redirect traffic via an alternate
9168 // protocol to an unrestricted (port >= 1024) when the original traffic was
9169 // on a restricted port (port < 1024). Ensure that we can redirect in all
9171 session_deps_
.use_alternate_protocols
= true;
9173 HttpRequestInfo unrestricted_port_request
;
9174 unrestricted_port_request
.method
= "GET";
9175 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9176 unrestricted_port_request
.load_flags
= 0;
9178 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9179 StaticSocketDataProvider first_data
;
9180 first_data
.set_connect_data(mock_connect
);
9181 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9183 MockRead data_reads
[] = {
9184 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9185 MockRead("hello world"),
9186 MockRead(ASYNC
, OK
),
9188 StaticSocketDataProvider
second_data(
9189 data_reads
, arraysize(data_reads
), NULL
, 0);
9190 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9192 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9194 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9195 session
->http_server_properties();
9196 const int kUnrestrictedAlternatePort
= 1024;
9197 AlternativeService
alternative_service(
9198 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9199 kUnrestrictedAlternatePort
);
9200 http_server_properties
->SetAlternativeService(
9201 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9204 scoped_ptr
<HttpTransaction
> trans(
9205 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9206 TestCompletionCallback callback
;
9208 int rv
= trans
->Start(
9209 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9211 // Valid change to an unrestricted port should pass.
9212 EXPECT_EQ(OK
, callback
.WaitForResult());
9215 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9216 // Ensure that we're not allowed to redirect traffic via an alternate
9217 // protocol to an unsafe port, and that we resume the second
9218 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9219 session_deps_
.use_alternate_protocols
= true;
9221 HttpRequestInfo request
;
9222 request
.method
= "GET";
9223 request
.url
= GURL("http://www.example.org/");
9224 request
.load_flags
= 0;
9226 // The alternate protocol request will error out before we attempt to connect,
9227 // so only the standard HTTP request will try to connect.
9228 MockRead data_reads
[] = {
9229 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9230 MockRead("hello world"),
9231 MockRead(ASYNC
, OK
),
9233 StaticSocketDataProvider
data(
9234 data_reads
, arraysize(data_reads
), NULL
, 0);
9235 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9237 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9239 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9240 session
->http_server_properties();
9241 const int kUnsafePort
= 7;
9242 AlternativeService
alternative_service(
9243 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9245 http_server_properties
->SetAlternativeService(
9246 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0);
9248 scoped_ptr
<HttpTransaction
> trans(
9249 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9250 TestCompletionCallback callback
;
9252 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9254 // The HTTP request should succeed.
9255 EXPECT_EQ(OK
, callback
.WaitForResult());
9257 // Disable alternate protocol before the asserts.
9258 // HttpStreamFactory::set_use_alternate_protocols(false);
9260 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9261 ASSERT_TRUE(response
!= NULL
);
9262 ASSERT_TRUE(response
->headers
.get() != NULL
);
9263 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9265 std::string response_data
;
9266 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9267 EXPECT_EQ("hello world", response_data
);
9270 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9271 session_deps_
.use_alternate_protocols
= true;
9272 session_deps_
.next_protos
= SpdyNextProtos();
9274 HttpRequestInfo request
;
9275 request
.method
= "GET";
9276 request
.url
= GURL("http://www.example.org/");
9277 request
.load_flags
= 0;
9279 std::string alternate_protocol_http_header
=
9280 GetAlternateProtocolHttpHeader();
9282 MockRead data_reads
[] = {
9283 MockRead("HTTP/1.1 200 OK\r\n"),
9284 MockRead(alternate_protocol_http_header
.c_str()),
9285 MockRead("hello world"),
9286 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9290 StaticSocketDataProvider
first_transaction(
9291 data_reads
, arraysize(data_reads
), NULL
, 0);
9292 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9294 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9295 ssl
.SetNextProto(GetParam());
9296 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9297 ASSERT_TRUE(ssl
.cert
.get());
9298 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9300 scoped_ptr
<SpdyFrame
> req(
9301 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9302 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9304 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9305 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9306 MockRead spdy_reads
[] = {
9307 CreateMockRead(*resp
),
9308 CreateMockRead(*data
),
9309 MockRead(ASYNC
, 0, 0),
9312 DelayedSocketData
spdy_data(
9313 1, // wait for one write to finish before reading.
9314 spdy_reads
, arraysize(spdy_reads
),
9315 spdy_writes
, arraysize(spdy_writes
));
9316 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9318 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9319 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9321 hanging_non_alternate_protocol_socket
.set_connect_data(
9322 never_finishing_connect
);
9323 session_deps_
.socket_factory
->AddSocketDataProvider(
9324 &hanging_non_alternate_protocol_socket
);
9326 TestCompletionCallback callback
;
9328 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9329 scoped_ptr
<HttpTransaction
> trans(
9330 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9332 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9333 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9334 EXPECT_EQ(OK
, callback
.WaitForResult());
9336 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9337 ASSERT_TRUE(response
!= NULL
);
9338 ASSERT_TRUE(response
->headers
.get() != NULL
);
9339 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9341 std::string response_data
;
9342 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9343 EXPECT_EQ("hello world", response_data
);
9345 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9347 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9348 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9349 EXPECT_EQ(OK
, callback
.WaitForResult());
9351 response
= trans
->GetResponseInfo();
9352 ASSERT_TRUE(response
!= NULL
);
9353 ASSERT_TRUE(response
->headers
.get() != NULL
);
9354 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9355 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9356 EXPECT_TRUE(response
->was_npn_negotiated
);
9358 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9359 EXPECT_EQ("hello!", response_data
);
9362 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9363 session_deps_
.use_alternate_protocols
= true;
9364 session_deps_
.next_protos
= SpdyNextProtos();
9366 HttpRequestInfo request
;
9367 request
.method
= "GET";
9368 request
.url
= GURL("http://www.example.org/");
9369 request
.load_flags
= 0;
9371 std::string alternate_protocol_http_header
=
9372 GetAlternateProtocolHttpHeader();
9374 MockRead data_reads
[] = {
9375 MockRead("HTTP/1.1 200 OK\r\n"),
9376 MockRead(alternate_protocol_http_header
.c_str()),
9377 MockRead("hello world"),
9378 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9379 MockRead(ASYNC
, OK
),
9382 StaticSocketDataProvider
first_transaction(
9383 data_reads
, arraysize(data_reads
), NULL
, 0);
9384 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9385 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9387 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9388 StaticSocketDataProvider
hanging_socket(
9390 hanging_socket
.set_connect_data(never_finishing_connect
);
9391 // Socket 2 and 3 are the hanging Alternate-Protocol and
9392 // non-Alternate-Protocol jobs from the 2nd transaction.
9393 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9394 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9396 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9397 ssl
.SetNextProto(GetParam());
9398 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9399 ASSERT_TRUE(ssl
.cert
.get());
9400 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9402 scoped_ptr
<SpdyFrame
> req1(
9403 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9404 scoped_ptr
<SpdyFrame
> req2(
9405 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9406 MockWrite spdy_writes
[] = {
9407 CreateMockWrite(*req1
),
9408 CreateMockWrite(*req2
),
9410 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9411 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9412 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9413 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9414 MockRead spdy_reads
[] = {
9415 CreateMockRead(*resp1
),
9416 CreateMockRead(*data1
),
9417 CreateMockRead(*resp2
),
9418 CreateMockRead(*data2
),
9419 MockRead(ASYNC
, 0, 0),
9422 DelayedSocketData
spdy_data(
9423 2, // wait for writes to finish before reading.
9424 spdy_reads
, arraysize(spdy_reads
),
9425 spdy_writes
, arraysize(spdy_writes
));
9426 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9427 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9429 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9430 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9432 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9433 TestCompletionCallback callback1
;
9434 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9436 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9438 EXPECT_EQ(OK
, callback1
.WaitForResult());
9440 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9441 ASSERT_TRUE(response
!= NULL
);
9442 ASSERT_TRUE(response
->headers
.get() != NULL
);
9443 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9445 std::string response_data
;
9446 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9447 EXPECT_EQ("hello world", response_data
);
9449 TestCompletionCallback callback2
;
9450 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9451 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9452 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9454 TestCompletionCallback callback3
;
9455 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9456 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9457 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9459 EXPECT_EQ(OK
, callback2
.WaitForResult());
9460 EXPECT_EQ(OK
, callback3
.WaitForResult());
9462 response
= trans2
.GetResponseInfo();
9463 ASSERT_TRUE(response
!= NULL
);
9464 ASSERT_TRUE(response
->headers
.get() != NULL
);
9465 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9466 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9467 EXPECT_TRUE(response
->was_npn_negotiated
);
9468 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9469 EXPECT_EQ("hello!", response_data
);
9471 response
= trans3
.GetResponseInfo();
9472 ASSERT_TRUE(response
!= NULL
);
9473 ASSERT_TRUE(response
->headers
.get() != NULL
);
9474 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9475 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9476 EXPECT_TRUE(response
->was_npn_negotiated
);
9477 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9478 EXPECT_EQ("hello!", response_data
);
9481 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9482 session_deps_
.use_alternate_protocols
= true;
9483 session_deps_
.next_protos
= SpdyNextProtos();
9485 HttpRequestInfo request
;
9486 request
.method
= "GET";
9487 request
.url
= GURL("http://www.example.org/");
9488 request
.load_flags
= 0;
9490 std::string alternate_protocol_http_header
=
9491 GetAlternateProtocolHttpHeader();
9493 MockRead data_reads
[] = {
9494 MockRead("HTTP/1.1 200 OK\r\n"),
9495 MockRead(alternate_protocol_http_header
.c_str()),
9496 MockRead("hello world"),
9497 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9498 MockRead(ASYNC
, OK
),
9501 StaticSocketDataProvider
first_transaction(
9502 data_reads
, arraysize(data_reads
), NULL
, 0);
9503 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9505 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9506 ssl
.SetNextProto(GetParam());
9507 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9509 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9510 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9512 hanging_alternate_protocol_socket
.set_connect_data(
9513 never_finishing_connect
);
9514 session_deps_
.socket_factory
->AddSocketDataProvider(
9515 &hanging_alternate_protocol_socket
);
9517 // 2nd request is just a copy of the first one, over HTTP again.
9518 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9520 TestCompletionCallback callback
;
9522 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9523 scoped_ptr
<HttpTransaction
> trans(
9524 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9526 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9527 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9528 EXPECT_EQ(OK
, callback
.WaitForResult());
9530 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9531 ASSERT_TRUE(response
!= NULL
);
9532 ASSERT_TRUE(response
->headers
.get() != NULL
);
9533 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9535 std::string response_data
;
9536 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9537 EXPECT_EQ("hello world", response_data
);
9539 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9541 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9542 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9543 EXPECT_EQ(OK
, callback
.WaitForResult());
9545 response
= trans
->GetResponseInfo();
9546 ASSERT_TRUE(response
!= NULL
);
9547 ASSERT_TRUE(response
->headers
.get() != NULL
);
9548 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9549 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9550 EXPECT_FALSE(response
->was_npn_negotiated
);
9552 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9553 EXPECT_EQ("hello world", response_data
);
9556 class CapturingProxyResolver
: public ProxyResolver
{
9558 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9559 ~CapturingProxyResolver() override
{}
9561 int GetProxyForURL(const GURL
& url
,
9563 const CompletionCallback
& callback
,
9564 RequestHandle
* request
,
9565 const BoundNetLog
& net_log
) override
{
9566 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9567 HostPortPair("myproxy", 80));
9568 results
->UseProxyServer(proxy_server
);
9569 resolved_
.push_back(url
);
9573 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9575 LoadState
GetLoadState(RequestHandle request
) const override
{
9577 return LOAD_STATE_IDLE
;
9580 void CancelSetPacScript() override
{ NOTREACHED(); }
9582 int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9583 const CompletionCallback
& /*callback*/) override
{
9587 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9590 std::vector
<GURL
> resolved_
;
9592 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9595 TEST_P(HttpNetworkTransactionTest
,
9596 UseAlternateProtocolForTunneledNpnSpdy
) {
9597 session_deps_
.use_alternate_protocols
= true;
9598 session_deps_
.next_protos
= SpdyNextProtos();
9600 ProxyConfig proxy_config
;
9601 proxy_config
.set_auto_detect(true);
9602 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9604 CapturingProxyResolver capturing_proxy_resolver
;
9605 session_deps_
.proxy_service
.reset(new ProxyService(
9606 new ProxyConfigServiceFixed(proxy_config
),
9608 new ForwardingProxyResolverFactory(&capturing_proxy_resolver
)),
9611 session_deps_
.net_log
= &net_log
;
9613 HttpRequestInfo request
;
9614 request
.method
= "GET";
9615 request
.url
= GURL("http://www.example.org/");
9616 request
.load_flags
= 0;
9618 std::string alternate_protocol_http_header
=
9619 GetAlternateProtocolHttpHeader();
9621 MockRead data_reads
[] = {
9622 MockRead("HTTP/1.1 200 OK\r\n"),
9623 MockRead(alternate_protocol_http_header
.c_str()),
9624 MockRead("hello world"),
9625 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9626 MockRead(ASYNC
, OK
),
9629 StaticSocketDataProvider
first_transaction(
9630 data_reads
, arraysize(data_reads
), NULL
, 0);
9631 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9633 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9634 ssl
.SetNextProto(GetParam());
9635 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9636 ASSERT_TRUE(ssl
.cert
.get());
9637 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9639 scoped_ptr
<SpdyFrame
> req(
9640 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9641 MockWrite spdy_writes
[] = {
9643 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9644 "Host: www.example.org\r\n"
9645 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9646 CreateMockWrite(*req
), // 3
9649 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9651 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9652 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9653 MockRead spdy_reads
[] = {
9654 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9655 CreateMockRead(*resp
.get(), 4), // 2, 4
9656 CreateMockRead(*data
.get(), 4), // 5
9657 MockRead(ASYNC
, 0, 0, 4), // 6
9660 OrderedSocketData
spdy_data(
9661 spdy_reads
, arraysize(spdy_reads
),
9662 spdy_writes
, arraysize(spdy_writes
));
9663 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9665 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9666 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9668 hanging_non_alternate_protocol_socket
.set_connect_data(
9669 never_finishing_connect
);
9670 session_deps_
.socket_factory
->AddSocketDataProvider(
9671 &hanging_non_alternate_protocol_socket
);
9673 TestCompletionCallback callback
;
9675 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9676 scoped_ptr
<HttpTransaction
> trans(
9677 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9679 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9681 EXPECT_EQ(OK
, callback
.WaitForResult());
9683 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9684 ASSERT_TRUE(response
!= NULL
);
9685 ASSERT_TRUE(response
->headers
.get() != NULL
);
9686 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9687 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9688 EXPECT_FALSE(response
->was_npn_negotiated
);
9690 std::string response_data
;
9691 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9692 EXPECT_EQ("hello world", response_data
);
9694 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9696 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9698 EXPECT_EQ(OK
, callback
.WaitForResult());
9700 response
= trans
->GetResponseInfo();
9701 ASSERT_TRUE(response
!= NULL
);
9702 ASSERT_TRUE(response
->headers
.get() != NULL
);
9703 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9704 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9705 EXPECT_TRUE(response
->was_npn_negotiated
);
9707 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9708 EXPECT_EQ("hello!", response_data
);
9709 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9710 EXPECT_EQ("http://www.example.org/",
9711 capturing_proxy_resolver
.resolved()[0].spec());
9712 EXPECT_EQ("https://www.example.org/",
9713 capturing_proxy_resolver
.resolved()[1].spec());
9715 LoadTimingInfo load_timing_info
;
9716 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9717 TestLoadTimingNotReusedWithPac(load_timing_info
,
9718 CONNECT_TIMING_HAS_SSL_TIMES
);
9721 TEST_P(HttpNetworkTransactionTest
,
9722 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9723 session_deps_
.use_alternate_protocols
= true;
9724 session_deps_
.next_protos
= SpdyNextProtos();
9726 HttpRequestInfo request
;
9727 request
.method
= "GET";
9728 request
.url
= GURL("http://www.example.org/");
9729 request
.load_flags
= 0;
9731 std::string alternate_protocol_http_header
=
9732 GetAlternateProtocolHttpHeader();
9734 MockRead data_reads
[] = {
9735 MockRead("HTTP/1.1 200 OK\r\n"),
9736 MockRead(alternate_protocol_http_header
.c_str()),
9737 MockRead("hello world"),
9738 MockRead(ASYNC
, OK
),
9741 StaticSocketDataProvider
first_transaction(
9742 data_reads
, arraysize(data_reads
), NULL
, 0);
9743 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9745 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9746 ssl
.SetNextProto(GetParam());
9747 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9748 ASSERT_TRUE(ssl
.cert
.get());
9749 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9751 scoped_ptr
<SpdyFrame
> req(
9752 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9753 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9755 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9756 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9757 MockRead spdy_reads
[] = {
9758 CreateMockRead(*resp
),
9759 CreateMockRead(*data
),
9760 MockRead(ASYNC
, 0, 0),
9763 DelayedSocketData
spdy_data(
9764 1, // wait for one write to finish before reading.
9765 spdy_reads
, arraysize(spdy_reads
),
9766 spdy_writes
, arraysize(spdy_writes
));
9767 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9769 TestCompletionCallback callback
;
9771 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9773 scoped_ptr
<HttpTransaction
> trans(
9774 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9776 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9778 EXPECT_EQ(OK
, callback
.WaitForResult());
9780 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9781 ASSERT_TRUE(response
!= NULL
);
9782 ASSERT_TRUE(response
->headers
.get() != NULL
);
9783 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9785 std::string response_data
;
9786 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9787 EXPECT_EQ("hello world", response_data
);
9789 // Set up an initial SpdySession in the pool to reuse.
9790 HostPortPair
host_port_pair("www.example.org", 443);
9791 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9792 PRIVACY_MODE_DISABLED
);
9793 base::WeakPtr
<SpdySession
> spdy_session
=
9794 CreateSecureSpdySession(session
, key
, BoundNetLog());
9796 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9798 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9799 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9800 EXPECT_EQ(OK
, callback
.WaitForResult());
9802 response
= trans
->GetResponseInfo();
9803 ASSERT_TRUE(response
!= NULL
);
9804 ASSERT_TRUE(response
->headers
.get() != NULL
);
9805 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9806 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9807 EXPECT_TRUE(response
->was_npn_negotiated
);
9809 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9810 EXPECT_EQ("hello!", response_data
);
9813 // GenerateAuthToken is a mighty big test.
9814 // It tests all permutation of GenerateAuthToken behavior:
9815 // - Synchronous and Asynchronous completion.
9816 // - OK or error on completion.
9817 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9818 // - HTTP or HTTPS backend (to include proxy tunneling).
9819 // - Non-authenticating and authenticating backend.
9821 // In all, there are 44 reasonable permuations (for example, if there are
9822 // problems generating an auth token for an authenticating proxy, we don't
9823 // need to test all permutations of the backend server).
9825 // The test proceeds by going over each of the configuration cases, and
9826 // potentially running up to three rounds in each of the tests. The TestConfig
9827 // specifies both the configuration for the test as well as the expectations
9829 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9830 static const char kServer
[] = "http://www.example.com";
9831 static const char kSecureServer
[] = "https://www.example.com";
9832 static const char kProxy
[] = "myproxy:70";
9833 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9841 const MockWrite
kGet(
9842 "GET / HTTP/1.1\r\n"
9843 "Host: www.example.com\r\n"
9844 "Connection: keep-alive\r\n\r\n");
9845 const MockWrite
kGetProxy(
9846 "GET http://www.example.com/ HTTP/1.1\r\n"
9847 "Host: www.example.com\r\n"
9848 "Proxy-Connection: keep-alive\r\n\r\n");
9849 const MockWrite
kGetAuth(
9850 "GET / HTTP/1.1\r\n"
9851 "Host: www.example.com\r\n"
9852 "Connection: keep-alive\r\n"
9853 "Authorization: auth_token\r\n\r\n");
9854 const MockWrite
kGetProxyAuth(
9855 "GET http://www.example.com/ HTTP/1.1\r\n"
9856 "Host: www.example.com\r\n"
9857 "Proxy-Connection: keep-alive\r\n"
9858 "Proxy-Authorization: auth_token\r\n\r\n");
9859 const MockWrite
kGetAuthThroughProxy(
9860 "GET http://www.example.com/ HTTP/1.1\r\n"
9861 "Host: www.example.com\r\n"
9862 "Proxy-Connection: keep-alive\r\n"
9863 "Authorization: auth_token\r\n\r\n");
9864 const MockWrite
kGetAuthWithProxyAuth(
9865 "GET http://www.example.com/ HTTP/1.1\r\n"
9866 "Host: www.example.com\r\n"
9867 "Proxy-Connection: keep-alive\r\n"
9868 "Proxy-Authorization: auth_token\r\n"
9869 "Authorization: auth_token\r\n\r\n");
9870 const MockWrite
kConnect(
9871 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9872 "Host: www.example.com\r\n"
9873 "Proxy-Connection: keep-alive\r\n\r\n");
9874 const MockWrite
kConnectProxyAuth(
9875 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9876 "Host: www.example.com\r\n"
9877 "Proxy-Connection: keep-alive\r\n"
9878 "Proxy-Authorization: auth_token\r\n\r\n");
9880 const MockRead
kSuccess(
9881 "HTTP/1.1 200 OK\r\n"
9882 "Content-Type: text/html; charset=iso-8859-1\r\n"
9883 "Content-Length: 3\r\n\r\n"
9885 const MockRead
kFailure(
9886 "Should not be called.");
9887 const MockRead
kServerChallenge(
9888 "HTTP/1.1 401 Unauthorized\r\n"
9889 "WWW-Authenticate: Mock realm=server\r\n"
9890 "Content-Type: text/html; charset=iso-8859-1\r\n"
9891 "Content-Length: 14\r\n\r\n"
9892 "Unauthorized\r\n");
9893 const MockRead
kProxyChallenge(
9894 "HTTP/1.1 407 Unauthorized\r\n"
9895 "Proxy-Authenticate: Mock realm=proxy\r\n"
9896 "Proxy-Connection: close\r\n"
9897 "Content-Type: text/html; charset=iso-8859-1\r\n"
9898 "Content-Length: 14\r\n\r\n"
9899 "Unauthorized\r\n");
9900 const MockRead
kProxyConnected(
9901 "HTTP/1.1 200 Connection Established\r\n\r\n");
9903 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9904 // no constructors, but the C++ compiler on Windows warns about
9905 // unspecified data in compound literals. So, moved to using constructors,
9906 // and TestRound's created with the default constructor should not be used.
9909 : expected_rv(ERR_UNEXPECTED
),
9913 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9914 int expected_rv_arg
)
9917 expected_rv(expected_rv_arg
),
9921 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9922 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9923 const MockRead
* extra_read_arg
)
9926 expected_rv(expected_rv_arg
),
9927 extra_write(extra_write_arg
),
9928 extra_read(extra_read_arg
) {
9933 const MockWrite
* extra_write
;
9934 const MockRead
* extra_read
;
9937 static const int kNoSSL
= 500;
9940 const char* const proxy_url
;
9941 AuthTiming proxy_auth_timing
;
9943 const char* const server_url
;
9944 AuthTiming server_auth_timing
;
9946 int num_auth_rounds
;
9947 int first_ssl_round
;
9948 TestRound rounds
[3];
9949 } test_configs
[] = {
9950 // Non-authenticating HTTP server with a direct connection.
9951 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9952 { TestRound(kGet
, kSuccess
, OK
)}},
9953 // Authenticating HTTP server with a direct connection.
9954 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9955 { TestRound(kGet
, kServerChallenge
, OK
),
9956 TestRound(kGetAuth
, kSuccess
, OK
)}},
9957 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9958 { TestRound(kGet
, kServerChallenge
, OK
),
9959 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9960 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9961 { TestRound(kGet
, kServerChallenge
, OK
),
9962 TestRound(kGetAuth
, kSuccess
, OK
)}},
9963 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9964 { TestRound(kGet
, kServerChallenge
, OK
),
9965 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9966 // Non-authenticating HTTP server through a non-authenticating proxy.
9967 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9968 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9969 // Authenticating HTTP server through a non-authenticating proxy.
9970 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9971 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9972 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9973 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9974 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9975 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9976 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9977 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9978 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9979 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9980 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9981 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9982 // Non-authenticating HTTP server through an authenticating proxy.
9983 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9984 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9985 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9986 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9987 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9988 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9989 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9990 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9991 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9992 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9993 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9994 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9995 // Authenticating HTTP server through an authenticating proxy.
9996 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9997 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9998 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9999 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10000 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10001 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10002 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10003 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10004 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10005 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10006 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10007 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10008 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10009 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10010 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10011 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10012 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10013 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10014 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10015 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10016 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10017 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10018 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10019 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10020 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10021 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10022 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10023 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10024 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10025 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10026 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10027 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10028 // Non-authenticating HTTPS server with a direct connection.
10029 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10030 { TestRound(kGet
, kSuccess
, OK
)}},
10031 // Authenticating HTTPS server with a direct connection.
10032 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10033 { TestRound(kGet
, kServerChallenge
, OK
),
10034 TestRound(kGetAuth
, kSuccess
, OK
)}},
10035 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10036 { TestRound(kGet
, kServerChallenge
, OK
),
10037 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10038 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10039 { TestRound(kGet
, kServerChallenge
, OK
),
10040 TestRound(kGetAuth
, kSuccess
, OK
)}},
10041 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10042 { TestRound(kGet
, kServerChallenge
, OK
),
10043 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10044 // Non-authenticating HTTPS server with a non-authenticating proxy.
10045 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10046 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10047 // Authenticating HTTPS server through a non-authenticating proxy.
10048 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10049 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10050 TestRound(kGetAuth
, kSuccess
, OK
)}},
10051 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10052 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10053 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10054 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10055 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10056 TestRound(kGetAuth
, kSuccess
, OK
)}},
10057 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10058 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10059 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10060 // Non-Authenticating HTTPS server through an authenticating proxy.
10061 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10062 { TestRound(kConnect
, kProxyChallenge
, OK
),
10063 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10064 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10065 { TestRound(kConnect
, kProxyChallenge
, OK
),
10066 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10067 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10068 { TestRound(kConnect
, kProxyChallenge
, OK
),
10069 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10070 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10071 { TestRound(kConnect
, kProxyChallenge
, OK
),
10072 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10073 // Authenticating HTTPS server through an authenticating proxy.
10074 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10075 { TestRound(kConnect
, kProxyChallenge
, OK
),
10076 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10077 &kGet
, &kServerChallenge
),
10078 TestRound(kGetAuth
, kSuccess
, OK
)}},
10079 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10080 { TestRound(kConnect
, kProxyChallenge
, OK
),
10081 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10082 &kGet
, &kServerChallenge
),
10083 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10084 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10085 { TestRound(kConnect
, kProxyChallenge
, OK
),
10086 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10087 &kGet
, &kServerChallenge
),
10088 TestRound(kGetAuth
, kSuccess
, OK
)}},
10089 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10090 { TestRound(kConnect
, kProxyChallenge
, OK
),
10091 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10092 &kGet
, &kServerChallenge
),
10093 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10094 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10095 { TestRound(kConnect
, kProxyChallenge
, OK
),
10096 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10097 &kGet
, &kServerChallenge
),
10098 TestRound(kGetAuth
, kSuccess
, OK
)}},
10099 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10100 { TestRound(kConnect
, kProxyChallenge
, OK
),
10101 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10102 &kGet
, &kServerChallenge
),
10103 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10104 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10105 { TestRound(kConnect
, kProxyChallenge
, OK
),
10106 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10107 &kGet
, &kServerChallenge
),
10108 TestRound(kGetAuth
, kSuccess
, OK
)}},
10109 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10110 { TestRound(kConnect
, kProxyChallenge
, OK
),
10111 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10112 &kGet
, &kServerChallenge
),
10113 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10116 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10117 HttpAuthHandlerMock::Factory
* auth_factory(
10118 new HttpAuthHandlerMock::Factory());
10119 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10120 const TestConfig
& test_config
= test_configs
[i
];
10122 // Set up authentication handlers as necessary.
10123 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10124 for (int n
= 0; n
< 2; n
++) {
10125 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10126 std::string auth_challenge
= "Mock realm=proxy";
10127 GURL
origin(test_config
.proxy_url
);
10128 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10129 auth_challenge
.end());
10130 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10131 origin
, BoundNetLog());
10132 auth_handler
->SetGenerateExpectation(
10133 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10134 test_config
.proxy_auth_rv
);
10135 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10138 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10139 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10140 std::string auth_challenge
= "Mock realm=server";
10141 GURL
origin(test_config
.server_url
);
10142 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10143 auth_challenge
.end());
10144 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10145 origin
, BoundNetLog());
10146 auth_handler
->SetGenerateExpectation(
10147 test_config
.server_auth_timing
== AUTH_ASYNC
,
10148 test_config
.server_auth_rv
);
10149 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10151 if (test_config
.proxy_url
) {
10152 session_deps_
.proxy_service
.reset(
10153 ProxyService::CreateFixed(test_config
.proxy_url
));
10155 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10158 HttpRequestInfo request
;
10159 request
.method
= "GET";
10160 request
.url
= GURL(test_config
.server_url
);
10161 request
.load_flags
= 0;
10163 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10164 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10166 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10167 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10169 // Set up expected reads and writes.
10171 reads
[0] = read_write_round
.read
;
10172 size_t length_reads
= 1;
10173 if (read_write_round
.extra_read
) {
10174 reads
[1] = *read_write_round
.extra_read
;
10178 MockWrite writes
[2];
10179 writes
[0] = read_write_round
.write
;
10180 size_t length_writes
= 1;
10181 if (read_write_round
.extra_write
) {
10182 writes
[1] = *read_write_round
.extra_write
;
10185 StaticSocketDataProvider
data_provider(
10186 reads
, length_reads
, writes
, length_writes
);
10187 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10189 // Add an SSL sequence if necessary.
10190 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10191 if (round
>= test_config
.first_ssl_round
)
10192 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10193 &ssl_socket_data_provider
);
10195 // Start or restart the transaction.
10196 TestCompletionCallback callback
;
10199 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10201 rv
= trans
.RestartWithAuth(
10202 AuthCredentials(kFoo
, kBar
), callback
.callback());
10204 if (rv
== ERR_IO_PENDING
)
10205 rv
= callback
.WaitForResult();
10207 // Compare results with expected data.
10208 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10209 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10210 if (read_write_round
.expected_rv
== OK
) {
10211 ASSERT_TRUE(response
!= NULL
);
10213 EXPECT_TRUE(response
== NULL
);
10214 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10217 if (round
+ 1 < test_config
.num_auth_rounds
) {
10218 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10220 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10226 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10227 // Do multi-round authentication and make sure it works correctly.
10228 HttpAuthHandlerMock::Factory
* auth_factory(
10229 new HttpAuthHandlerMock::Factory());
10230 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10231 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10232 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10233 session_deps_
.host_resolver
->set_synchronous_mode(true);
10235 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10236 auth_handler
->set_connection_based(true);
10237 std::string auth_challenge
= "Mock realm=server";
10238 GURL
origin("http://www.example.com");
10239 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10240 auth_challenge
.end());
10241 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10242 origin
, BoundNetLog());
10243 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10246 const HttpResponseInfo
* response
= NULL
;
10247 HttpRequestInfo request
;
10248 request
.method
= "GET";
10249 request
.url
= origin
;
10250 request
.load_flags
= 0;
10252 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10254 // Use a TCP Socket Pool with only one connection per group. This is used
10255 // to validate that the TCP socket is not released to the pool between
10256 // each round of multi-round authentication.
10257 HttpNetworkSessionPeer
session_peer(session
);
10258 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10259 50, // Max sockets for pool
10260 1, // Max sockets per group
10261 session_deps_
.host_resolver
.get(),
10262 session_deps_
.socket_factory
.get(),
10263 session_deps_
.net_log
);
10264 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10265 new MockClientSocketPoolManager
);
10266 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10267 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10269 scoped_ptr
<HttpTransaction
> trans(
10270 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10271 TestCompletionCallback callback
;
10273 const MockWrite
kGet(
10274 "GET / HTTP/1.1\r\n"
10275 "Host: www.example.com\r\n"
10276 "Connection: keep-alive\r\n\r\n");
10277 const MockWrite
kGetAuth(
10278 "GET / HTTP/1.1\r\n"
10279 "Host: www.example.com\r\n"
10280 "Connection: keep-alive\r\n"
10281 "Authorization: auth_token\r\n\r\n");
10283 const MockRead
kServerChallenge(
10284 "HTTP/1.1 401 Unauthorized\r\n"
10285 "WWW-Authenticate: Mock realm=server\r\n"
10286 "Content-Type: text/html; charset=iso-8859-1\r\n"
10287 "Content-Length: 14\r\n\r\n"
10288 "Unauthorized\r\n");
10289 const MockRead
kSuccess(
10290 "HTTP/1.1 200 OK\r\n"
10291 "Content-Type: text/html; charset=iso-8859-1\r\n"
10292 "Content-Length: 3\r\n\r\n"
10295 MockWrite writes
[] = {
10304 // Competing request
10307 MockRead reads
[] = {
10316 // Competing response
10319 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10320 writes
, arraysize(writes
));
10321 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10323 const char kSocketGroup
[] = "www.example.com:80";
10325 // First round of authentication.
10326 auth_handler
->SetGenerateExpectation(false, OK
);
10327 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10328 if (rv
== ERR_IO_PENDING
)
10329 rv
= callback
.WaitForResult();
10331 response
= trans
->GetResponseInfo();
10332 ASSERT_TRUE(response
!= NULL
);
10333 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10334 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10336 // In between rounds, another request comes in for the same domain.
10337 // It should not be able to grab the TCP socket that trans has already
10339 scoped_ptr
<HttpTransaction
> trans_compete(
10340 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10341 TestCompletionCallback callback_compete
;
10342 rv
= trans_compete
->Start(
10343 &request
, callback_compete
.callback(), BoundNetLog());
10344 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10345 // callback_compete.WaitForResult at this point would stall forever,
10346 // since the HttpNetworkTransaction does not release the request back to
10347 // the pool until after authentication completes.
10349 // Second round of authentication.
10350 auth_handler
->SetGenerateExpectation(false, OK
);
10351 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10352 if (rv
== ERR_IO_PENDING
)
10353 rv
= callback
.WaitForResult();
10355 response
= trans
->GetResponseInfo();
10356 ASSERT_TRUE(response
!= NULL
);
10357 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10358 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10360 // Third round of authentication.
10361 auth_handler
->SetGenerateExpectation(false, OK
);
10362 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10363 if (rv
== ERR_IO_PENDING
)
10364 rv
= callback
.WaitForResult();
10366 response
= trans
->GetResponseInfo();
10367 ASSERT_TRUE(response
!= NULL
);
10368 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10369 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10371 // Fourth round of authentication, which completes successfully.
10372 auth_handler
->SetGenerateExpectation(false, OK
);
10373 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10374 if (rv
== ERR_IO_PENDING
)
10375 rv
= callback
.WaitForResult();
10377 response
= trans
->GetResponseInfo();
10378 ASSERT_TRUE(response
!= NULL
);
10379 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10380 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10382 // Read the body since the fourth round was successful. This will also
10383 // release the socket back to the pool.
10384 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10385 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10386 if (rv
== ERR_IO_PENDING
)
10387 rv
= callback
.WaitForResult();
10389 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10391 // There are still 0 idle sockets, since the trans_compete transaction
10392 // will be handed it immediately after trans releases it to the group.
10393 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10395 // The competing request can now finish. Wait for the headers and then
10397 rv
= callback_compete
.WaitForResult();
10399 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10400 if (rv
== ERR_IO_PENDING
)
10401 rv
= callback
.WaitForResult();
10403 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10406 // Finally, the socket is released to the group.
10407 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10410 // This tests the case that a request is issued via http instead of spdy after
10411 // npn is negotiated.
10412 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10413 session_deps_
.use_alternate_protocols
= true;
10414 NextProtoVector next_protos
;
10415 next_protos
.push_back(kProtoHTTP11
);
10416 session_deps_
.next_protos
= next_protos
;
10418 HttpRequestInfo request
;
10419 request
.method
= "GET";
10420 request
.url
= GURL("https://www.example.org/");
10421 request
.load_flags
= 0;
10423 MockWrite data_writes
[] = {
10425 "GET / HTTP/1.1\r\n"
10426 "Host: www.example.org\r\n"
10427 "Connection: keep-alive\r\n\r\n"),
10430 std::string alternate_protocol_http_header
=
10431 GetAlternateProtocolHttpHeader();
10433 MockRead data_reads
[] = {
10434 MockRead("HTTP/1.1 200 OK\r\n"),
10435 MockRead(alternate_protocol_http_header
.c_str()),
10436 MockRead("hello world"),
10437 MockRead(SYNCHRONOUS
, OK
),
10440 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10441 ssl
.next_proto_status
= SSLClientSocket::kNextProtoNegotiated
;
10442 ssl
.next_proto
= "http/1.1";
10443 ssl
.protocol_negotiated
= kProtoHTTP11
;
10445 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10447 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10448 data_writes
, arraysize(data_writes
));
10449 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10451 TestCompletionCallback callback
;
10453 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10454 scoped_ptr
<HttpTransaction
> trans(
10455 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10457 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10459 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10460 EXPECT_EQ(OK
, callback
.WaitForResult());
10462 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10463 ASSERT_TRUE(response
!= NULL
);
10464 ASSERT_TRUE(response
->headers
.get() != NULL
);
10465 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10467 std::string response_data
;
10468 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10469 EXPECT_EQ("hello world", response_data
);
10471 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10472 EXPECT_TRUE(response
->was_npn_negotiated
);
10475 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10476 // Simulate the SSL handshake completing with an NPN negotiation
10477 // followed by an immediate server closing of the socket.
10478 // Fix crash: http://crbug.com/46369
10479 session_deps_
.use_alternate_protocols
= true;
10480 session_deps_
.next_protos
= SpdyNextProtos();
10482 HttpRequestInfo request
;
10483 request
.method
= "GET";
10484 request
.url
= GURL("https://www.example.org/");
10485 request
.load_flags
= 0;
10487 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10488 ssl
.SetNextProto(GetParam());
10489 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10491 scoped_ptr
<SpdyFrame
> req(
10492 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10493 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10495 MockRead spdy_reads
[] = {
10496 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10499 DelayedSocketData
spdy_data(
10500 0, // don't wait in this case, immediate hangup.
10501 spdy_reads
, arraysize(spdy_reads
),
10502 spdy_writes
, arraysize(spdy_writes
));
10503 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10505 TestCompletionCallback callback
;
10507 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10508 scoped_ptr
<HttpTransaction
> trans(
10509 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10511 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10512 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10513 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10516 // A subclass of HttpAuthHandlerMock that records the request URL when
10517 // it gets it. This is needed since the auth handler may get destroyed
10518 // before we get a chance to query it.
10519 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10521 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10523 ~UrlRecordingHttpAuthHandlerMock() override
{}
10526 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10527 const HttpRequestInfo
* request
,
10528 const CompletionCallback
& callback
,
10529 std::string
* auth_token
) override
{
10530 *url_
= request
->url
;
10531 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10532 credentials
, request
, callback
, auth_token
);
10539 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10540 // This test ensures that the URL passed into the proxy is upgraded
10541 // to https when doing an Alternate Protocol upgrade.
10542 session_deps_
.use_alternate_protocols
= true;
10543 session_deps_
.next_protos
= SpdyNextProtos();
10545 session_deps_
.proxy_service
.reset(
10546 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10547 TestNetLog net_log
;
10548 session_deps_
.net_log
= &net_log
;
10551 HttpAuthHandlerMock::Factory
* auth_factory
=
10552 new HttpAuthHandlerMock::Factory();
10553 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10554 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10555 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10556 auth_factory
->set_do_init_from_challenge(true);
10557 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10560 HttpRequestInfo request
;
10561 request
.method
= "GET";
10562 request
.url
= GURL("http://www.example.org");
10563 request
.load_flags
= 0;
10565 // First round goes unauthenticated through the proxy.
10566 MockWrite data_writes_1
[] = {
10568 "GET http://www.example.org/ HTTP/1.1\r\n"
10569 "Host: www.example.org\r\n"
10570 "Proxy-Connection: keep-alive\r\n"
10573 MockRead data_reads_1
[] = {
10574 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10575 MockRead("HTTP/1.1 200 OK\r\n"),
10576 MockRead("Alternate-Protocol: 443:"),
10577 MockRead(GetAlternateProtocolFromParam()),
10579 MockRead("Proxy-Connection: close\r\n"),
10582 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10583 data_writes_1
, arraysize(data_writes_1
));
10585 // Second round tries to tunnel to www.example.org due to the
10586 // Alternate-Protocol announcement in the first round. It fails due
10587 // to a proxy authentication challenge.
10588 // After the failure, a tunnel is established to www.example.org using
10589 // Proxy-Authorization headers. There is then a SPDY request round.
10591 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10592 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10593 // does a Disconnect and Connect on the same socket, rather than trying
10594 // to obtain a new one.
10596 // NOTE: Originally, the proxy response to the second CONNECT request
10597 // simply returned another 407 so the unit test could skip the SSL connection
10598 // establishment and SPDY framing issues. Alas, the
10599 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10600 // complicated to set up expectations for than the SPDY session.
10602 scoped_ptr
<SpdyFrame
> req(
10603 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10604 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10605 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10607 MockWrite data_writes_2
[] = {
10608 // First connection attempt without Proxy-Authorization.
10610 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10611 "Host: www.example.org\r\n"
10612 "Proxy-Connection: keep-alive\r\n"
10615 // Second connection attempt with Proxy-Authorization.
10617 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10618 "Host: www.example.org\r\n"
10619 "Proxy-Connection: keep-alive\r\n"
10620 "Proxy-Authorization: auth_token\r\n"
10624 CreateMockWrite(*req
),
10626 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10627 "Proxy-Authenticate: Mock\r\n"
10628 "Proxy-Connection: close\r\n"
10630 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10631 MockRead data_reads_2
[] = {
10632 // First connection attempt fails
10633 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10634 MockRead(ASYNC
, kRejectConnectResponse
,
10635 arraysize(kRejectConnectResponse
) - 1, 1),
10637 // Second connection attempt passes
10638 MockRead(ASYNC
, kAcceptConnectResponse
,
10639 arraysize(kAcceptConnectResponse
) -1, 4),
10642 CreateMockRead(*resp
.get(), 6),
10643 CreateMockRead(*data
.get(), 6),
10644 MockRead(ASYNC
, 0, 0, 6),
10646 OrderedSocketData
data_2(
10647 data_reads_2
, arraysize(data_reads_2
),
10648 data_writes_2
, arraysize(data_writes_2
));
10650 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10651 ssl
.SetNextProto(GetParam());
10652 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10653 ASSERT_TRUE(ssl
.cert
.get());
10655 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10656 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10658 hanging_non_alternate_protocol_socket
.set_connect_data(
10659 never_finishing_connect
);
10661 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10662 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10663 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10664 session_deps_
.socket_factory
->AddSocketDataProvider(
10665 &hanging_non_alternate_protocol_socket
);
10666 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10668 // First round should work and provide the Alternate-Protocol state.
10669 TestCompletionCallback callback_1
;
10670 scoped_ptr
<HttpTransaction
> trans_1(
10671 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10672 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10674 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10676 // Second round should attempt a tunnel connect and get an auth challenge.
10677 TestCompletionCallback callback_2
;
10678 scoped_ptr
<HttpTransaction
> trans_2(
10679 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10680 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10681 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10682 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10683 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10684 ASSERT_TRUE(response
!= NULL
);
10685 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10687 // Restart with auth. Tunnel should work and response received.
10688 TestCompletionCallback callback_3
;
10689 rv
= trans_2
->RestartWithAuth(
10690 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10691 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10692 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10694 // After all that work, these two lines (or actually, just the scheme) are
10695 // what this test is all about. Make sure it happens correctly.
10696 EXPECT_EQ("https", request_url
.scheme());
10697 EXPECT_EQ("www.example.org", request_url
.host());
10699 LoadTimingInfo load_timing_info
;
10700 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10701 TestLoadTimingNotReusedWithPac(load_timing_info
,
10702 CONNECT_TIMING_HAS_SSL_TIMES
);
10705 // Test that if we cancel the transaction as the connection is completing, that
10706 // everything tears down correctly.
10707 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10708 // Setup everything about the connection to complete synchronously, so that
10709 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10710 // for is the callback from the HttpStreamRequest.
10711 // Then cancel the transaction.
10712 // Verify that we don't crash.
10713 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10714 MockRead data_reads
[] = {
10715 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10716 MockRead(SYNCHRONOUS
, "hello world"),
10717 MockRead(SYNCHRONOUS
, OK
),
10720 HttpRequestInfo request
;
10721 request
.method
= "GET";
10722 request
.url
= GURL("http://www.example.org/");
10723 request
.load_flags
= 0;
10725 session_deps_
.host_resolver
->set_synchronous_mode(true);
10726 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10727 scoped_ptr
<HttpTransaction
> trans(
10728 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10730 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10731 data
.set_connect_data(mock_connect
);
10732 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10734 TestCompletionCallback callback
;
10736 BoundTestNetLog log
;
10737 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10738 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10739 trans
.reset(); // Cancel the transaction here.
10741 base::MessageLoop::current()->RunUntilIdle();
10744 // Test that if a transaction is cancelled after receiving the headers, the
10745 // stream is drained properly and added back to the socket pool. The main
10746 // purpose of this test is to make sure that an HttpStreamParser can be read
10747 // from after the HttpNetworkTransaction and the objects it owns have been
10749 // See http://crbug.com/368418
10750 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10751 MockRead data_reads
[] = {
10752 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10753 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10754 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10755 MockRead(ASYNC
, "1"),
10756 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10757 // HttpNetworkTransaction has been deleted.
10758 MockRead(ASYNC
, "2"),
10759 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10761 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10762 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10764 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10767 HttpRequestInfo request
;
10768 request
.method
= "GET";
10769 request
.url
= GURL("http://www.example.org/");
10770 request
.load_flags
= 0;
10772 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10773 TestCompletionCallback callback
;
10775 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10777 callback
.WaitForResult();
10779 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10780 ASSERT_TRUE(response
!= NULL
);
10781 EXPECT_TRUE(response
->headers
.get() != NULL
);
10782 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10784 // The transaction and HttpRequestInfo are deleted.
10787 // Let the HttpResponseBodyDrainer drain the socket.
10788 base::MessageLoop::current()->RunUntilIdle();
10790 // Socket should now be idle, waiting to be reused.
10791 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10794 // Test a basic GET request through a proxy.
10795 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10796 session_deps_
.proxy_service
.reset(
10797 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10798 BoundTestNetLog log
;
10799 session_deps_
.net_log
= log
.bound().net_log();
10800 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10802 HttpRequestInfo request
;
10803 request
.method
= "GET";
10804 request
.url
= GURL("http://www.example.org/");
10806 MockWrite data_writes1
[] = {
10808 "GET http://www.example.org/ HTTP/1.1\r\n"
10809 "Host: www.example.org\r\n"
10810 "Proxy-Connection: keep-alive\r\n\r\n"),
10813 MockRead data_reads1
[] = {
10814 MockRead("HTTP/1.1 200 OK\r\n"),
10815 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10816 MockRead("Content-Length: 100\r\n\r\n"),
10817 MockRead(SYNCHRONOUS
, OK
),
10820 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10821 data_writes1
, arraysize(data_writes1
));
10822 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10824 TestCompletionCallback callback1
;
10826 scoped_ptr
<HttpTransaction
> trans(
10827 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10828 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10829 trans
->SetBeforeProxyHeadersSentCallback(
10830 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10831 base::Unretained(&proxy_headers_handler
)));
10833 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10834 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10836 rv
= callback1
.WaitForResult();
10839 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10840 ASSERT_TRUE(response
!= NULL
);
10842 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10843 EXPECT_EQ(200, response
->headers
->response_code());
10844 EXPECT_EQ(100, response
->headers
->GetContentLength());
10845 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10847 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10848 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10849 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10850 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10852 LoadTimingInfo load_timing_info
;
10853 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10854 TestLoadTimingNotReusedWithPac(load_timing_info
,
10855 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10858 // Test a basic HTTPS GET request through a proxy.
10859 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10860 session_deps_
.proxy_service
.reset(
10861 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10862 BoundTestNetLog log
;
10863 session_deps_
.net_log
= log
.bound().net_log();
10864 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10866 HttpRequestInfo request
;
10867 request
.method
= "GET";
10868 request
.url
= GURL("https://www.example.org/");
10870 // Since we have proxy, should try to establish tunnel.
10871 MockWrite data_writes1
[] = {
10873 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10874 "Host: www.example.org\r\n"
10875 "Proxy-Connection: keep-alive\r\n\r\n"),
10878 "GET / HTTP/1.1\r\n"
10879 "Host: www.example.org\r\n"
10880 "Connection: keep-alive\r\n\r\n"),
10883 MockRead data_reads1
[] = {
10884 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10886 MockRead("HTTP/1.1 200 OK\r\n"),
10887 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10888 MockRead("Content-Length: 100\r\n\r\n"),
10889 MockRead(SYNCHRONOUS
, OK
),
10892 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10893 data_writes1
, arraysize(data_writes1
));
10894 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10895 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10896 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10898 TestCompletionCallback callback1
;
10900 scoped_ptr
<HttpTransaction
> trans(
10901 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10903 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10904 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10906 rv
= callback1
.WaitForResult();
10908 TestNetLog::CapturedEntryList entries
;
10909 log
.GetEntries(&entries
);
10910 size_t pos
= ExpectLogContainsSomewhere(
10911 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10912 NetLog::PHASE_NONE
);
10913 ExpectLogContainsSomewhere(
10915 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10916 NetLog::PHASE_NONE
);
10918 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10919 ASSERT_TRUE(response
!= NULL
);
10921 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10922 EXPECT_EQ(200, response
->headers
->response_code());
10923 EXPECT_EQ(100, response
->headers
->GetContentLength());
10924 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10925 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10927 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10929 LoadTimingInfo load_timing_info
;
10930 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10931 TestLoadTimingNotReusedWithPac(load_timing_info
,
10932 CONNECT_TIMING_HAS_SSL_TIMES
);
10935 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10936 // while establishing the tunnel.
10937 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10938 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10939 BoundTestNetLog log
;
10940 session_deps_
.net_log
= log
.bound().net_log();
10941 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10943 HttpRequestInfo request
;
10944 request
.method
= "GET";
10945 request
.url
= GURL("https://www.example.org/");
10947 // Since we have proxy, should try to establish tunnel.
10948 MockWrite data_writes1
[] = {
10950 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10951 "Host: www.example.org\r\n"
10952 "Proxy-Connection: keep-alive\r\n\r\n"),
10955 "GET / HTTP/1.1\r\n"
10956 "Host: www.example.org\r\n"
10957 "Connection: keep-alive\r\n\r\n"),
10960 MockRead data_reads1
[] = {
10961 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10962 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10963 MockRead(ASYNC
, 0, 0), // EOF
10966 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10967 data_writes1
, arraysize(data_writes1
));
10968 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10969 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10970 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10972 TestCompletionCallback callback1
;
10974 scoped_ptr
<HttpTransaction
> trans(
10975 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10977 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10978 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10980 rv
= callback1
.WaitForResult();
10981 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10982 TestNetLog::CapturedEntryList entries
;
10983 log
.GetEntries(&entries
);
10984 size_t pos
= ExpectLogContainsSomewhere(
10985 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10986 NetLog::PHASE_NONE
);
10987 ExpectLogContainsSomewhere(
10989 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10990 NetLog::PHASE_NONE
);
10993 // Test for crbug.com/55424.
10994 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10995 scoped_ptr
<SpdyFrame
> req(
10996 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
10997 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10999 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11000 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11001 MockRead spdy_reads
[] = {
11002 CreateMockRead(*resp
),
11003 CreateMockRead(*data
),
11004 MockRead(ASYNC
, 0, 0),
11007 DelayedSocketData
spdy_data(
11008 1, // wait for one write to finish before reading.
11009 spdy_reads
, arraysize(spdy_reads
),
11010 spdy_writes
, arraysize(spdy_writes
));
11011 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11013 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11014 ssl
.SetNextProto(GetParam());
11015 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11017 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11019 // Set up an initial SpdySession in the pool to reuse.
11020 HostPortPair
host_port_pair("www.example.org", 443);
11021 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11022 PRIVACY_MODE_DISABLED
);
11023 base::WeakPtr
<SpdySession
> spdy_session
=
11024 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11026 HttpRequestInfo request
;
11027 request
.method
= "GET";
11028 request
.url
= GURL("https://www.example.org/");
11029 request
.load_flags
= 0;
11031 // This is the important line that marks this as a preconnect.
11032 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11034 scoped_ptr
<HttpTransaction
> trans(
11035 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11037 TestCompletionCallback callback
;
11038 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11039 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11040 EXPECT_EQ(OK
, callback
.WaitForResult());
11043 // Given a net error, cause that error to be returned from the first Write()
11044 // call and verify that the HttpTransaction fails with that error.
11045 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11046 int error
, IoMode mode
) {
11047 HttpRequestInfo request_info
;
11048 request_info
.url
= GURL("https://www.example.com/");
11049 request_info
.method
= "GET";
11050 request_info
.load_flags
= LOAD_NORMAL
;
11052 SSLSocketDataProvider
ssl_data(mode
, OK
);
11053 MockWrite data_writes
[] = {
11054 MockWrite(mode
, error
),
11056 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11057 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11058 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11060 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11061 scoped_ptr
<HttpTransaction
> trans(
11062 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11064 TestCompletionCallback callback
;
11065 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11066 if (rv
== ERR_IO_PENDING
)
11067 rv
= callback
.WaitForResult();
11068 ASSERT_EQ(error
, rv
);
11071 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11072 // Just check a grab bag of cert errors.
11073 static const int kErrors
[] = {
11074 ERR_CERT_COMMON_NAME_INVALID
,
11075 ERR_CERT_AUTHORITY_INVALID
,
11076 ERR_CERT_DATE_INVALID
,
11078 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11079 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11080 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11084 // Ensure that a client certificate is removed from the SSL client auth
11086 // 1) No proxy is involved.
11087 // 2) TLS False Start is disabled.
11088 // 3) The initial TLS handshake requests a client certificate.
11089 // 4) The client supplies an invalid/unacceptable certificate.
11090 TEST_P(HttpNetworkTransactionTest
,
11091 ClientAuthCertCache_Direct_NoFalseStart
) {
11092 HttpRequestInfo request_info
;
11093 request_info
.url
= GURL("https://www.example.com/");
11094 request_info
.method
= "GET";
11095 request_info
.load_flags
= LOAD_NORMAL
;
11097 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11098 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11100 // [ssl_]data1 contains the data for the first SSL handshake. When a
11101 // CertificateRequest is received for the first time, the handshake will
11102 // be aborted to allow the caller to provide a certificate.
11103 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11104 ssl_data1
.cert_request_info
= cert_request
.get();
11105 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11106 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11107 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11109 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11110 // False Start is not being used, the result of the SSL handshake will be
11111 // returned as part of the SSLClientSocket::Connect() call. This test
11112 // matches the result of a server sending a handshake_failure alert,
11113 // rather than a Finished message, because it requires a client
11114 // certificate and none was supplied.
11115 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11116 ssl_data2
.cert_request_info
= cert_request
.get();
11117 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11118 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11119 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11121 // [ssl_]data3 contains the data for the third SSL handshake. When a
11122 // connection to a server fails during an SSL handshake,
11123 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11124 // connection was attempted with TLSv1.1. This is transparent to the caller
11125 // of the HttpNetworkTransaction. Because this test failure is due to
11126 // requiring a client certificate, this fallback handshake should also
11128 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11129 ssl_data3
.cert_request_info
= cert_request
.get();
11130 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11131 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11132 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11134 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11135 // connection to a server fails during an SSL handshake,
11136 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
11137 // connection was attempted with TLSv1. This is transparent to the caller
11138 // of the HttpNetworkTransaction. Because this test failure is due to
11139 // requiring a client certificate, this fallback handshake should also
11141 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11142 ssl_data4
.cert_request_info
= cert_request
.get();
11143 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11144 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11145 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11147 // Need one more if TLSv1.2 is enabled.
11148 SSLSocketDataProvider
ssl_data5(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11149 ssl_data5
.cert_request_info
= cert_request
.get();
11150 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11151 StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
11152 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11154 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11155 scoped_ptr
<HttpTransaction
> trans(
11156 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11158 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11159 TestCompletionCallback callback
;
11160 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11161 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11163 // Complete the SSL handshake, which should abort due to requiring a
11164 // client certificate.
11165 rv
= callback
.WaitForResult();
11166 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11168 // Indicate that no certificate should be supplied. From the perspective
11169 // of SSLClientCertCache, NULL is just as meaningful as a real
11170 // certificate, so this is the same as supply a
11171 // legitimate-but-unacceptable certificate.
11172 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11173 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11175 // Ensure the certificate was added to the client auth cache before
11176 // allowing the connection to continue restarting.
11177 scoped_refptr
<X509Certificate
> client_cert
;
11178 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11179 HostPortPair("www.example.com", 443), &client_cert
));
11180 ASSERT_EQ(NULL
, client_cert
.get());
11182 // Restart the handshake. This will consume ssl_data2, which fails, and
11183 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11184 // The result code is checked against what ssl_data4 should return.
11185 rv
= callback
.WaitForResult();
11186 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11188 // Ensure that the client certificate is removed from the cache on a
11189 // handshake failure.
11190 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11191 HostPortPair("www.example.com", 443), &client_cert
));
11194 // Ensure that a client certificate is removed from the SSL client auth
11196 // 1) No proxy is involved.
11197 // 2) TLS False Start is enabled.
11198 // 3) The initial TLS handshake requests a client certificate.
11199 // 4) The client supplies an invalid/unacceptable certificate.
11200 TEST_P(HttpNetworkTransactionTest
,
11201 ClientAuthCertCache_Direct_FalseStart
) {
11202 HttpRequestInfo request_info
;
11203 request_info
.url
= GURL("https://www.example.com/");
11204 request_info
.method
= "GET";
11205 request_info
.load_flags
= LOAD_NORMAL
;
11207 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11208 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11210 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11211 // return successfully after reading up to the peer's Certificate message.
11212 // This is to allow the caller to call SSLClientSocket::Write(), which can
11213 // enqueue application data to be sent in the same packet as the
11214 // ChangeCipherSpec and Finished messages.
11215 // The actual handshake will be finished when SSLClientSocket::Read() is
11216 // called, which expects to process the peer's ChangeCipherSpec and
11217 // Finished messages. If there was an error negotiating with the peer,
11218 // such as due to the peer requiring a client certificate when none was
11219 // supplied, the alert sent by the peer won't be processed until Read() is
11222 // Like the non-False Start case, when a client certificate is requested by
11223 // the peer, the handshake is aborted during the Connect() call.
11224 // [ssl_]data1 represents the initial SSL handshake with the peer.
11225 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11226 ssl_data1
.cert_request_info
= cert_request
.get();
11227 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11228 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11229 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11231 // When a client certificate is supplied, Connect() will not be aborted
11232 // when the peer requests the certificate. Instead, the handshake will
11233 // artificially succeed, allowing the caller to write the HTTP request to
11234 // the socket. The handshake messages are not processed until Read() is
11235 // called, which then detects that the handshake was aborted, due to the
11236 // peer sending a handshake_failure because it requires a client
11238 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11239 ssl_data2
.cert_request_info
= cert_request
.get();
11240 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11241 MockRead data2_reads
[] = {
11242 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11244 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11245 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11247 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11248 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11249 // TLSv1. It has the same behaviour as [ssl_]data2.
11250 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11251 ssl_data3
.cert_request_info
= cert_request
.get();
11252 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11253 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11254 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11256 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11257 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11258 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11259 ssl_data4
.cert_request_info
= cert_request
.get();
11260 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11261 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11262 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11264 // Need one more if TLSv1.2 is enabled.
11265 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11266 ssl_data5
.cert_request_info
= cert_request
.get();
11267 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11268 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11269 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11271 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11272 scoped_ptr
<HttpTransaction
> trans(
11273 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11275 // Begin the initial SSL handshake.
11276 TestCompletionCallback callback
;
11277 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11278 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11280 // Complete the SSL handshake, which should abort due to requiring a
11281 // client certificate.
11282 rv
= callback
.WaitForResult();
11283 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11285 // Indicate that no certificate should be supplied. From the perspective
11286 // of SSLClientCertCache, NULL is just as meaningful as a real
11287 // certificate, so this is the same as supply a
11288 // legitimate-but-unacceptable certificate.
11289 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11290 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11292 // Ensure the certificate was added to the client auth cache before
11293 // allowing the connection to continue restarting.
11294 scoped_refptr
<X509Certificate
> client_cert
;
11295 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11296 HostPortPair("www.example.com", 443), &client_cert
));
11297 ASSERT_EQ(NULL
, client_cert
.get());
11299 // Restart the handshake. This will consume ssl_data2, which fails, and
11300 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11301 // The result code is checked against what ssl_data4 should return.
11302 rv
= callback
.WaitForResult();
11303 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11305 // Ensure that the client certificate is removed from the cache on a
11306 // handshake failure.
11307 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11308 HostPortPair("www.example.com", 443), &client_cert
));
11311 // Ensure that a client certificate is removed from the SSL client auth
11313 // 1) An HTTPS proxy is involved.
11314 // 3) The HTTPS proxy requests a client certificate.
11315 // 4) The client supplies an invalid/unacceptable certificate for the
11317 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11318 // then for connecting to an HTTP endpoint.
11319 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11320 session_deps_
.proxy_service
.reset(
11321 ProxyService::CreateFixed("https://proxy:70"));
11322 BoundTestNetLog log
;
11323 session_deps_
.net_log
= log
.bound().net_log();
11325 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11326 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11328 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11329 // [ssl_]data[1-3]. Rather than represending the endpoint
11330 // (www.example.com:443), they represent failures with the HTTPS proxy
11332 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11333 ssl_data1
.cert_request_info
= cert_request
.get();
11334 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11335 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11336 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11338 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11339 ssl_data2
.cert_request_info
= cert_request
.get();
11340 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11341 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11342 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11344 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11346 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11347 ssl_data3
.cert_request_info
= cert_request
.get();
11348 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11349 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11350 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11353 HttpRequestInfo requests
[2];
11354 requests
[0].url
= GURL("https://www.example.com/");
11355 requests
[0].method
= "GET";
11356 requests
[0].load_flags
= LOAD_NORMAL
;
11358 requests
[1].url
= GURL("http://www.example.com/");
11359 requests
[1].method
= "GET";
11360 requests
[1].load_flags
= LOAD_NORMAL
;
11362 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11363 session_deps_
.socket_factory
->ResetNextMockIndexes();
11364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11365 scoped_ptr
<HttpNetworkTransaction
> trans(
11366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11368 // Begin the SSL handshake with the proxy.
11369 TestCompletionCallback callback
;
11370 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11371 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11373 // Complete the SSL handshake, which should abort due to requiring a
11374 // client certificate.
11375 rv
= callback
.WaitForResult();
11376 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11378 // Indicate that no certificate should be supplied. From the perspective
11379 // of SSLClientCertCache, NULL is just as meaningful as a real
11380 // certificate, so this is the same as supply a
11381 // legitimate-but-unacceptable certificate.
11382 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11383 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11385 // Ensure the certificate was added to the client auth cache before
11386 // allowing the connection to continue restarting.
11387 scoped_refptr
<X509Certificate
> client_cert
;
11388 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11389 HostPortPair("proxy", 70), &client_cert
));
11390 ASSERT_EQ(NULL
, client_cert
.get());
11391 // Ensure the certificate was NOT cached for the endpoint. This only
11392 // applies to HTTPS requests, but is fine to check for HTTP requests.
11393 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11394 HostPortPair("www.example.com", 443), &client_cert
));
11396 // Restart the handshake. This will consume ssl_data2, which fails, and
11397 // then consume ssl_data3, which should also fail. The result code is
11398 // checked against what ssl_data3 should return.
11399 rv
= callback
.WaitForResult();
11400 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11402 // Now that the new handshake has failed, ensure that the client
11403 // certificate was removed from the client auth cache.
11404 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11405 HostPortPair("proxy", 70), &client_cert
));
11406 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11407 HostPortPair("www.example.com", 443), &client_cert
));
11411 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11412 // TEST_P is a macro that expands directly to code that stringizes the
11413 // arguments. As a result, macros passed as parameters (such as prefix
11414 // or test_case_name) will not be expanded by the preprocessor. To
11415 // work around this, indirect the macro for TEST_P, so that the
11416 // pre-processor will expand macros such as MAYBE_test_name before
11417 // instantiating the test.
11418 #define WRAPPED_TEST_P(test_case_name, test_name) \
11419 TEST_P(test_case_name, test_name)
11421 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11422 #if defined(OS_WIN)
11423 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11425 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11427 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
11428 session_deps_
.use_alternate_protocols
= true;
11429 session_deps_
.next_protos
= SpdyNextProtos();
11431 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11432 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11433 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11434 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11435 pool_peer
.DisableDomainAuthenticationVerification();
11437 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11438 ssl
.SetNextProto(GetParam());
11439 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11441 scoped_ptr
<SpdyFrame
> host1_req(
11442 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11443 scoped_ptr
<SpdyFrame
> host2_req(
11444 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11445 MockWrite spdy_writes
[] = {
11446 CreateMockWrite(*host1_req
, 1),
11447 CreateMockWrite(*host2_req
, 4),
11449 scoped_ptr
<SpdyFrame
> host1_resp(
11450 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11451 scoped_ptr
<SpdyFrame
> host1_resp_body(
11452 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11453 scoped_ptr
<SpdyFrame
> host2_resp(
11454 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11455 scoped_ptr
<SpdyFrame
> host2_resp_body(
11456 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11457 MockRead spdy_reads
[] = {
11458 CreateMockRead(*host1_resp
, 2),
11459 CreateMockRead(*host1_resp_body
, 3),
11460 CreateMockRead(*host2_resp
, 5),
11461 CreateMockRead(*host2_resp_body
, 6),
11462 MockRead(ASYNC
, 0, 7),
11465 IPAddressNumber ip
;
11466 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11467 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11468 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11469 OrderedSocketData
spdy_data(
11471 spdy_reads
, arraysize(spdy_reads
),
11472 spdy_writes
, arraysize(spdy_writes
));
11473 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11475 TestCompletionCallback callback
;
11476 HttpRequestInfo request1
;
11477 request1
.method
= "GET";
11478 request1
.url
= GURL("https://www.example.org/");
11479 request1
.load_flags
= 0;
11480 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11482 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11483 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11484 EXPECT_EQ(OK
, callback
.WaitForResult());
11486 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11487 ASSERT_TRUE(response
!= NULL
);
11488 ASSERT_TRUE(response
->headers
.get() != NULL
);
11489 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11491 std::string response_data
;
11492 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11493 EXPECT_EQ("hello!", response_data
);
11495 // Preload www.gmail.com into HostCache.
11496 HostPortPair
host_port("www.gmail.com", 443);
11497 HostResolver::RequestInfo
resolve_info(host_port
);
11498 AddressList ignored
;
11499 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11502 callback
.callback(),
11505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11506 rv
= callback
.WaitForResult();
11509 HttpRequestInfo request2
;
11510 request2
.method
= "GET";
11511 request2
.url
= GURL("https://www.gmail.com/");
11512 request2
.load_flags
= 0;
11513 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11515 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11516 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11517 EXPECT_EQ(OK
, callback
.WaitForResult());
11519 response
= trans2
.GetResponseInfo();
11520 ASSERT_TRUE(response
!= NULL
);
11521 ASSERT_TRUE(response
->headers
.get() != NULL
);
11522 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11523 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11524 EXPECT_TRUE(response
->was_npn_negotiated
);
11525 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11526 EXPECT_EQ("hello!", response_data
);
11528 #undef MAYBE_UseIPConnectionPooling
11530 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11531 session_deps_
.use_alternate_protocols
= true;
11532 session_deps_
.next_protos
= SpdyNextProtos();
11534 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11535 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11536 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11537 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11538 pool_peer
.DisableDomainAuthenticationVerification();
11540 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11541 ssl
.SetNextProto(GetParam());
11542 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11544 scoped_ptr
<SpdyFrame
> host1_req(
11545 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11546 scoped_ptr
<SpdyFrame
> host2_req(
11547 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11548 MockWrite spdy_writes
[] = {
11549 CreateMockWrite(*host1_req
, 1),
11550 CreateMockWrite(*host2_req
, 4),
11552 scoped_ptr
<SpdyFrame
> host1_resp(
11553 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11554 scoped_ptr
<SpdyFrame
> host1_resp_body(
11555 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11556 scoped_ptr
<SpdyFrame
> host2_resp(
11557 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11558 scoped_ptr
<SpdyFrame
> host2_resp_body(
11559 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11560 MockRead spdy_reads
[] = {
11561 CreateMockRead(*host1_resp
, 2),
11562 CreateMockRead(*host1_resp_body
, 3),
11563 CreateMockRead(*host2_resp
, 5),
11564 CreateMockRead(*host2_resp_body
, 6),
11565 MockRead(ASYNC
, 0, 7),
11568 IPAddressNumber ip
;
11569 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11570 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11571 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11572 OrderedSocketData
spdy_data(
11574 spdy_reads
, arraysize(spdy_reads
),
11575 spdy_writes
, arraysize(spdy_writes
));
11576 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11578 TestCompletionCallback callback
;
11579 HttpRequestInfo request1
;
11580 request1
.method
= "GET";
11581 request1
.url
= GURL("https://www.example.org/");
11582 request1
.load_flags
= 0;
11583 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11585 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11586 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11587 EXPECT_EQ(OK
, callback
.WaitForResult());
11589 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11590 ASSERT_TRUE(response
!= NULL
);
11591 ASSERT_TRUE(response
->headers
.get() != NULL
);
11592 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11594 std::string response_data
;
11595 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11596 EXPECT_EQ("hello!", response_data
);
11598 HttpRequestInfo request2
;
11599 request2
.method
= "GET";
11600 request2
.url
= GURL("https://www.gmail.com/");
11601 request2
.load_flags
= 0;
11602 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11604 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11605 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11606 EXPECT_EQ(OK
, callback
.WaitForResult());
11608 response
= trans2
.GetResponseInfo();
11609 ASSERT_TRUE(response
!= NULL
);
11610 ASSERT_TRUE(response
->headers
.get() != NULL
);
11611 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11612 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11613 EXPECT_TRUE(response
->was_npn_negotiated
);
11614 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11615 EXPECT_EQ("hello!", response_data
);
11618 class OneTimeCachingHostResolver
: public HostResolver
{
11620 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11621 : host_port_(host_port
) {}
11622 ~OneTimeCachingHostResolver() override
{}
11624 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11626 // HostResolver methods:
11627 int Resolve(const RequestInfo
& info
,
11628 RequestPriority priority
,
11629 AddressList
* addresses
,
11630 const CompletionCallback
& callback
,
11631 RequestHandle
* out_req
,
11632 const BoundNetLog
& net_log
) override
{
11633 return host_resolver_
.Resolve(
11634 info
, priority
, addresses
, callback
, out_req
, net_log
);
11637 int ResolveFromCache(const RequestInfo
& info
,
11638 AddressList
* addresses
,
11639 const BoundNetLog
& net_log
) override
{
11640 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11641 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11642 host_resolver_
.GetHostCache()->clear();
11646 void CancelRequest(RequestHandle req
) override
{
11647 host_resolver_
.CancelRequest(req
);
11650 MockCachingHostResolver
* GetMockHostResolver() {
11651 return &host_resolver_
;
11655 MockCachingHostResolver host_resolver_
;
11656 const HostPortPair host_port_
;
11659 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11660 #if defined(OS_WIN)
11661 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11662 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11664 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11665 UseIPConnectionPoolingWithHostCacheExpiration
11667 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11668 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11669 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11670 // prefix doesn't work with parametrized tests).
11671 #if defined(OS_WIN)
11674 session_deps_
.use_alternate_protocols
= true;
11675 session_deps_
.next_protos
= SpdyNextProtos();
11677 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11678 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11679 HttpNetworkSession::Params params
=
11680 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11681 params
.host_resolver
= &host_resolver
;
11682 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11683 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11684 pool_peer
.DisableDomainAuthenticationVerification();
11686 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11687 ssl
.SetNextProto(GetParam());
11688 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11690 scoped_ptr
<SpdyFrame
> host1_req(
11691 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11692 scoped_ptr
<SpdyFrame
> host2_req(
11693 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11694 MockWrite spdy_writes
[] = {
11695 CreateMockWrite(*host1_req
, 1),
11696 CreateMockWrite(*host2_req
, 4),
11698 scoped_ptr
<SpdyFrame
> host1_resp(
11699 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11700 scoped_ptr
<SpdyFrame
> host1_resp_body(
11701 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11702 scoped_ptr
<SpdyFrame
> host2_resp(
11703 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11704 scoped_ptr
<SpdyFrame
> host2_resp_body(
11705 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11706 MockRead spdy_reads
[] = {
11707 CreateMockRead(*host1_resp
, 2),
11708 CreateMockRead(*host1_resp_body
, 3),
11709 CreateMockRead(*host2_resp
, 5),
11710 CreateMockRead(*host2_resp_body
, 6),
11711 MockRead(ASYNC
, 0, 7),
11714 IPAddressNumber ip
;
11715 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11716 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11717 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11718 OrderedSocketData
spdy_data(
11720 spdy_reads
, arraysize(spdy_reads
),
11721 spdy_writes
, arraysize(spdy_writes
));
11722 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11724 TestCompletionCallback callback
;
11725 HttpRequestInfo request1
;
11726 request1
.method
= "GET";
11727 request1
.url
= GURL("https://www.example.org/");
11728 request1
.load_flags
= 0;
11729 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11731 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11733 EXPECT_EQ(OK
, callback
.WaitForResult());
11735 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11736 ASSERT_TRUE(response
!= NULL
);
11737 ASSERT_TRUE(response
->headers
.get() != NULL
);
11738 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11740 std::string response_data
;
11741 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11742 EXPECT_EQ("hello!", response_data
);
11744 // Preload cache entries into HostCache.
11745 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11746 AddressList ignored
;
11747 rv
= host_resolver
.Resolve(resolve_info
,
11750 callback
.callback(),
11753 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11754 rv
= callback
.WaitForResult();
11757 HttpRequestInfo request2
;
11758 request2
.method
= "GET";
11759 request2
.url
= GURL("https://www.gmail.com/");
11760 request2
.load_flags
= 0;
11761 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11763 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11764 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11765 EXPECT_EQ(OK
, callback
.WaitForResult());
11767 response
= trans2
.GetResponseInfo();
11768 ASSERT_TRUE(response
!= NULL
);
11769 ASSERT_TRUE(response
->headers
.get() != NULL
);
11770 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11771 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11772 EXPECT_TRUE(response
->was_npn_negotiated
);
11773 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11774 EXPECT_EQ("hello!", response_data
);
11777 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11779 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11780 const std::string https_url
= "https://www.example.org:8080/";
11781 const std::string http_url
= "http://www.example.org:8080/";
11783 // SPDY GET for HTTPS URL
11784 scoped_ptr
<SpdyFrame
> req1(
11785 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11787 MockWrite writes1
[] = {
11788 CreateMockWrite(*req1
, 0),
11791 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11792 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11793 MockRead reads1
[] = {
11794 CreateMockRead(*resp1
, 1),
11795 CreateMockRead(*body1
, 2),
11796 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11799 DelayedSocketData
data1(
11800 1, reads1
, arraysize(reads1
),
11801 writes1
, arraysize(writes1
));
11802 MockConnect
connect_data1(ASYNC
, OK
);
11803 data1
.set_connect_data(connect_data1
);
11805 // HTTP GET for the HTTP URL
11806 MockWrite writes2
[] = {
11807 MockWrite(ASYNC
, 4,
11808 "GET / HTTP/1.1\r\n"
11809 "Host: www.example.org:8080\r\n"
11810 "Connection: keep-alive\r\n\r\n"),
11813 MockRead reads2
[] = {
11814 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11815 MockRead(ASYNC
, 6, "hello"),
11816 MockRead(ASYNC
, 7, OK
),
11819 DelayedSocketData
data2(
11820 1, reads2
, arraysize(reads2
),
11821 writes2
, arraysize(writes2
));
11823 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11824 ssl
.SetNextProto(GetParam());
11825 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11826 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11827 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11829 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11831 // Start the first transaction to set up the SpdySession
11832 HttpRequestInfo request1
;
11833 request1
.method
= "GET";
11834 request1
.url
= GURL(https_url
);
11835 request1
.load_flags
= 0;
11836 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11837 TestCompletionCallback callback1
;
11838 EXPECT_EQ(ERR_IO_PENDING
,
11839 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11840 base::MessageLoop::current()->RunUntilIdle();
11842 EXPECT_EQ(OK
, callback1
.WaitForResult());
11843 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11845 // Now, start the HTTP request
11846 HttpRequestInfo request2
;
11847 request2
.method
= "GET";
11848 request2
.url
= GURL(http_url
);
11849 request2
.load_flags
= 0;
11850 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11851 TestCompletionCallback callback2
;
11852 EXPECT_EQ(ERR_IO_PENDING
,
11853 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11854 base::MessageLoop::current()->RunUntilIdle();
11856 EXPECT_EQ(OK
, callback2
.WaitForResult());
11857 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11860 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11861 const std::string https_url
= "https://www.example.org:8080/";
11862 const std::string http_url
= "http://www.example.org:8080/";
11864 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11865 const HostPortPair
host_port_pair("www.example.org", 8080);
11866 scoped_ptr
<SpdyFrame
> connect(
11867 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
11868 scoped_ptr
<SpdyFrame
> req1(
11869 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11870 scoped_ptr
<SpdyFrame
> wrapped_req1(
11871 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11873 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11874 SpdyHeaderBlock req2_block
;
11875 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11876 req2_block
[spdy_util_
.GetPathKey()] = "/";
11877 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
11878 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11879 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11880 scoped_ptr
<SpdyFrame
> req2(
11881 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11883 MockWrite writes1
[] = {
11884 CreateMockWrite(*connect
, 0),
11885 CreateMockWrite(*wrapped_req1
, 2),
11886 CreateMockWrite(*req2
, 5),
11889 scoped_ptr
<SpdyFrame
> conn_resp(
11890 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11891 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11892 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11893 scoped_ptr
<SpdyFrame
> wrapped_resp1(
11894 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
11895 scoped_ptr
<SpdyFrame
> wrapped_body1(
11896 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
11897 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11898 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11899 MockRead reads1
[] = {
11900 CreateMockRead(*conn_resp
, 1),
11901 CreateMockRead(*wrapped_resp1
, 3),
11902 CreateMockRead(*wrapped_body1
, 4),
11903 CreateMockRead(*resp2
, 6),
11904 CreateMockRead(*body2
, 7),
11905 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
11908 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
11909 writes1
, arraysize(writes1
));
11910 MockConnect
connect_data1(ASYNC
, OK
);
11911 data1
.set_connect_data(connect_data1
);
11913 session_deps_
.proxy_service
.reset(
11914 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
11916 session_deps_
.net_log
= &log
;
11917 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
11918 ssl1
.SetNextProto(GetParam());
11919 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
11920 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
11921 ssl2
.SetNextProto(GetParam());
11922 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
11923 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
11925 scoped_refptr
<HttpNetworkSession
> session(
11926 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
11928 // Start the first transaction to set up the SpdySession
11929 HttpRequestInfo request1
;
11930 request1
.method
= "GET";
11931 request1
.url
= GURL(https_url
);
11932 request1
.load_flags
= 0;
11933 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11934 TestCompletionCallback callback1
;
11935 EXPECT_EQ(ERR_IO_PENDING
,
11936 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11937 base::MessageLoop::current()->RunUntilIdle();
11940 EXPECT_EQ(OK
, callback1
.WaitForResult());
11941 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11943 LoadTimingInfo load_timing_info1
;
11944 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
11945 TestLoadTimingNotReusedWithPac(load_timing_info1
,
11946 CONNECT_TIMING_HAS_SSL_TIMES
);
11948 // Now, start the HTTP request
11949 HttpRequestInfo request2
;
11950 request2
.method
= "GET";
11951 request2
.url
= GURL(http_url
);
11952 request2
.load_flags
= 0;
11953 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11954 TestCompletionCallback callback2
;
11955 EXPECT_EQ(ERR_IO_PENDING
,
11956 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11957 base::MessageLoop::current()->RunUntilIdle();
11960 EXPECT_EQ(OK
, callback2
.WaitForResult());
11961 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11963 LoadTimingInfo load_timing_info2
;
11964 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
11965 // The established SPDY sessions is considered reused by the HTTP request.
11966 TestLoadTimingReusedWithPac(load_timing_info2
);
11967 // HTTP requests over a SPDY session should have a different connection
11968 // socket_log_id than requests over a tunnel.
11969 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
11972 // Test that in the case where we have a SPDY session to a SPDY proxy
11973 // that we do not pool other origins that resolve to the same IP when
11974 // the certificate does not match the new origin.
11975 // http://crbug.com/134690
11976 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
11977 const std::string url1
= "http://www.example.org/";
11978 const std::string url2
= "https://news.example.org/";
11979 const std::string ip_addr
= "1.2.3.4";
11981 // SPDY GET for HTTP URL (through SPDY proxy)
11982 scoped_ptr
<SpdyHeaderBlock
> headers(
11983 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
11984 scoped_ptr
<SpdyFrame
> req1(
11985 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
11987 MockWrite writes1
[] = {
11988 CreateMockWrite(*req1
, 0),
11991 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11992 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11993 MockRead reads1
[] = {
11994 CreateMockRead(*resp1
, 1),
11995 CreateMockRead(*body1
, 2),
11996 MockRead(ASYNC
, OK
, 3) // EOF
11999 scoped_ptr
<DeterministicSocketData
> data1(
12000 new DeterministicSocketData(reads1
, arraysize(reads1
),
12001 writes1
, arraysize(writes1
)));
12002 IPAddressNumber ip
;
12003 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12004 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12005 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12006 data1
->set_connect_data(connect_data1
);
12008 // SPDY GET for HTTPS URL (direct)
12009 scoped_ptr
<SpdyFrame
> req2(
12010 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12012 MockWrite writes2
[] = {
12013 CreateMockWrite(*req2
, 0),
12016 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12017 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12018 MockRead reads2
[] = {
12019 CreateMockRead(*resp2
, 1),
12020 CreateMockRead(*body2
, 2),
12021 MockRead(ASYNC
, OK
, 3) // EOF
12024 scoped_ptr
<DeterministicSocketData
> data2(
12025 new DeterministicSocketData(reads2
, arraysize(reads2
),
12026 writes2
, arraysize(writes2
)));
12027 MockConnect
connect_data2(ASYNC
, OK
);
12028 data2
->set_connect_data(connect_data2
);
12030 // Set up a proxy config that sends HTTP requests to a proxy, and
12031 // all others direct.
12032 ProxyConfig proxy_config
;
12033 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12034 session_deps_
.proxy_service
.reset(new ProxyService(
12035 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12037 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12038 ssl1
.SetNextProto(GetParam());
12039 // Load a valid cert. Note, that this does not need to
12040 // be valid for proxy because the MockSSLClientSocket does
12041 // not actually verify it. But SpdySession will use this
12042 // to see if it is valid for the new origin
12043 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12044 ASSERT_TRUE(ssl1
.cert
.get());
12045 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12046 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12049 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12050 ssl2
.SetNextProto(GetParam());
12051 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12052 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12055 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12056 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12057 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12059 scoped_refptr
<HttpNetworkSession
> session(
12060 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12062 // Start the first transaction to set up the SpdySession
12063 HttpRequestInfo request1
;
12064 request1
.method
= "GET";
12065 request1
.url
= GURL(url1
);
12066 request1
.load_flags
= 0;
12067 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12068 TestCompletionCallback callback1
;
12069 ASSERT_EQ(ERR_IO_PENDING
,
12070 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12073 ASSERT_TRUE(callback1
.have_result());
12074 EXPECT_EQ(OK
, callback1
.WaitForResult());
12075 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12077 // Now, start the HTTP request
12078 HttpRequestInfo request2
;
12079 request2
.method
= "GET";
12080 request2
.url
= GURL(url2
);
12081 request2
.load_flags
= 0;
12082 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12083 TestCompletionCallback callback2
;
12084 EXPECT_EQ(ERR_IO_PENDING
,
12085 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12086 base::MessageLoop::current()->RunUntilIdle();
12089 ASSERT_TRUE(callback2
.have_result());
12090 EXPECT_EQ(OK
, callback2
.WaitForResult());
12091 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12094 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12095 // error) in SPDY session, removes the socket from pool and closes the SPDY
12096 // session. Verify that new url's from the same HttpNetworkSession (and a new
12097 // SpdySession) do work. http://crbug.com/224701
12098 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12099 const std::string https_url
= "https://www.example.org/";
12101 MockRead reads1
[] = {
12102 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12105 scoped_ptr
<DeterministicSocketData
> data1(
12106 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
12109 scoped_ptr
<SpdyFrame
> req2(
12110 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12111 MockWrite writes2
[] = {
12112 CreateMockWrite(*req2
, 0),
12115 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12116 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12117 MockRead reads2
[] = {
12118 CreateMockRead(*resp2
, 1),
12119 CreateMockRead(*body2
, 2),
12120 MockRead(ASYNC
, OK
, 3) // EOF
12123 scoped_ptr
<DeterministicSocketData
> data2(
12124 new DeterministicSocketData(reads2
, arraysize(reads2
),
12125 writes2
, arraysize(writes2
)));
12127 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12128 ssl1
.SetNextProto(GetParam());
12129 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12130 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12133 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12134 ssl2
.SetNextProto(GetParam());
12135 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12136 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12139 scoped_refptr
<HttpNetworkSession
> session(
12140 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12142 // Start the first transaction to set up the SpdySession and verify that
12143 // connection was closed.
12144 HttpRequestInfo request1
;
12145 request1
.method
= "GET";
12146 request1
.url
= GURL(https_url
);
12147 request1
.load_flags
= 0;
12148 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12149 TestCompletionCallback callback1
;
12150 EXPECT_EQ(ERR_IO_PENDING
,
12151 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12152 base::MessageLoop::current()->RunUntilIdle();
12153 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12155 // Now, start the second request and make sure it succeeds.
12156 HttpRequestInfo request2
;
12157 request2
.method
= "GET";
12158 request2
.url
= GURL(https_url
);
12159 request2
.load_flags
= 0;
12160 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12161 TestCompletionCallback callback2
;
12162 EXPECT_EQ(ERR_IO_PENDING
,
12163 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12164 base::MessageLoop::current()->RunUntilIdle();
12167 ASSERT_TRUE(callback2
.have_result());
12168 EXPECT_EQ(OK
, callback2
.WaitForResult());
12169 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12172 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12173 session_deps_
.next_protos
= SpdyNextProtos();
12174 ClientSocketPoolManager::set_max_sockets_per_group(
12175 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12176 ClientSocketPoolManager::set_max_sockets_per_pool(
12177 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12179 // Use two different hosts with different IPs so they don't get pooled.
12180 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12181 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12182 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12184 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12185 ssl1
.SetNextProto(GetParam());
12186 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12187 ssl2
.SetNextProto(GetParam());
12188 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12189 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12191 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12192 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12193 MockWrite spdy1_writes
[] = {
12194 CreateMockWrite(*host1_req
, 1),
12196 scoped_ptr
<SpdyFrame
> host1_resp(
12197 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12198 scoped_ptr
<SpdyFrame
> host1_resp_body(
12199 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12200 MockRead spdy1_reads
[] = {
12201 CreateMockRead(*host1_resp
, 2),
12202 CreateMockRead(*host1_resp_body
, 3),
12203 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
12206 scoped_ptr
<OrderedSocketData
> spdy1_data(
12207 new OrderedSocketData(
12208 spdy1_reads
, arraysize(spdy1_reads
),
12209 spdy1_writes
, arraysize(spdy1_writes
)));
12210 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12212 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12213 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12214 MockWrite spdy2_writes
[] = {
12215 CreateMockWrite(*host2_req
, 1),
12217 scoped_ptr
<SpdyFrame
> host2_resp(
12218 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12219 scoped_ptr
<SpdyFrame
> host2_resp_body(
12220 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12221 MockRead spdy2_reads
[] = {
12222 CreateMockRead(*host2_resp
, 2),
12223 CreateMockRead(*host2_resp_body
, 3),
12224 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
12227 scoped_ptr
<OrderedSocketData
> spdy2_data(
12228 new OrderedSocketData(
12229 spdy2_reads
, arraysize(spdy2_reads
),
12230 spdy2_writes
, arraysize(spdy2_writes
)));
12231 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12233 MockWrite http_write
[] = {
12234 MockWrite("GET / HTTP/1.1\r\n"
12235 "Host: www.a.com\r\n"
12236 "Connection: keep-alive\r\n\r\n"),
12239 MockRead http_read
[] = {
12240 MockRead("HTTP/1.1 200 OK\r\n"),
12241 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12242 MockRead("Content-Length: 6\r\n\r\n"),
12243 MockRead("hello!"),
12245 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12246 http_write
, arraysize(http_write
));
12247 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12249 HostPortPair
host_port_pair_a("www.a.com", 443);
12250 SpdySessionKey
spdy_session_key_a(
12251 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12253 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12255 TestCompletionCallback callback
;
12256 HttpRequestInfo request1
;
12257 request1
.method
= "GET";
12258 request1
.url
= GURL("https://www.a.com/");
12259 request1
.load_flags
= 0;
12260 scoped_ptr
<HttpNetworkTransaction
> trans(
12261 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12263 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12264 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12265 EXPECT_EQ(OK
, callback
.WaitForResult());
12267 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12268 ASSERT_TRUE(response
!= NULL
);
12269 ASSERT_TRUE(response
->headers
.get() != NULL
);
12270 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12271 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12272 EXPECT_TRUE(response
->was_npn_negotiated
);
12274 std::string response_data
;
12275 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12276 EXPECT_EQ("hello!", response_data
);
12279 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12281 HostPortPair
host_port_pair_b("www.b.com", 443);
12282 SpdySessionKey
spdy_session_key_b(
12283 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12285 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12286 HttpRequestInfo request2
;
12287 request2
.method
= "GET";
12288 request2
.url
= GURL("https://www.b.com/");
12289 request2
.load_flags
= 0;
12290 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12292 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12294 EXPECT_EQ(OK
, callback
.WaitForResult());
12296 response
= trans
->GetResponseInfo();
12297 ASSERT_TRUE(response
!= NULL
);
12298 ASSERT_TRUE(response
->headers
.get() != NULL
);
12299 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12300 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12301 EXPECT_TRUE(response
->was_npn_negotiated
);
12302 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12303 EXPECT_EQ("hello!", response_data
);
12305 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12307 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12309 HostPortPair
host_port_pair_a1("www.a.com", 80);
12310 SpdySessionKey
spdy_session_key_a1(
12311 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12313 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12314 HttpRequestInfo request3
;
12315 request3
.method
= "GET";
12316 request3
.url
= GURL("http://www.a.com/");
12317 request3
.load_flags
= 0;
12318 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12320 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12321 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12322 EXPECT_EQ(OK
, callback
.WaitForResult());
12324 response
= trans
->GetResponseInfo();
12325 ASSERT_TRUE(response
!= NULL
);
12326 ASSERT_TRUE(response
->headers
.get() != NULL
);
12327 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12328 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12329 EXPECT_FALSE(response
->was_npn_negotiated
);
12330 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12331 EXPECT_EQ("hello!", response_data
);
12333 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12335 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12338 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12339 HttpRequestInfo request
;
12340 request
.method
= "GET";
12341 request
.url
= GURL("http://www.example.org/");
12342 request
.load_flags
= 0;
12344 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12345 scoped_ptr
<HttpTransaction
> trans(
12346 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12348 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12349 StaticSocketDataProvider data
;
12350 data
.set_connect_data(mock_connect
);
12351 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12353 TestCompletionCallback callback
;
12355 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12358 rv
= callback
.WaitForResult();
12359 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12361 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12363 // We don't care whether this succeeds or fails, but it shouldn't crash.
12364 HttpRequestHeaders request_headers
;
12365 trans
->GetFullRequestHeaders(&request_headers
);
12368 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12369 HttpRequestInfo request
;
12370 request
.method
= "GET";
12371 request
.url
= GURL("http://www.example.org/");
12372 request
.load_flags
= 0;
12374 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12375 scoped_ptr
<HttpTransaction
> trans(
12376 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12378 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12379 StaticSocketDataProvider data
;
12380 data
.set_connect_data(mock_connect
);
12381 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12383 TestCompletionCallback callback
;
12385 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12386 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12388 rv
= callback
.WaitForResult();
12389 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12391 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12393 // We don't care whether this succeeds or fails, but it shouldn't crash.
12394 HttpRequestHeaders request_headers
;
12395 trans
->GetFullRequestHeaders(&request_headers
);
12398 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12399 HttpRequestInfo request
;
12400 request
.method
= "GET";
12401 request
.url
= GURL("http://www.example.org/");
12402 request
.load_flags
= 0;
12404 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12405 scoped_ptr
<HttpTransaction
> trans(
12406 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12408 MockWrite data_writes
[] = {
12409 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12411 MockRead data_reads
[] = {
12412 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12415 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12416 data_writes
, arraysize(data_writes
));
12417 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12419 TestCompletionCallback callback
;
12421 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12424 rv
= callback
.WaitForResult();
12425 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12427 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12429 HttpRequestHeaders request_headers
;
12430 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12431 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12434 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12435 HttpRequestInfo request
;
12436 request
.method
= "GET";
12437 request
.url
= GURL("http://www.example.org/");
12438 request
.load_flags
= 0;
12440 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12441 scoped_ptr
<HttpTransaction
> trans(
12442 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12444 MockWrite data_writes
[] = {
12445 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12447 MockRead data_reads
[] = {
12448 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12451 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12452 data_writes
, arraysize(data_writes
));
12453 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12455 TestCompletionCallback callback
;
12457 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12458 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12460 rv
= callback
.WaitForResult();
12461 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12463 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12465 HttpRequestHeaders request_headers
;
12466 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12467 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12470 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12471 HttpRequestInfo request
;
12472 request
.method
= "GET";
12473 request
.url
= GURL("http://www.example.org/");
12474 request
.load_flags
= 0;
12476 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12477 scoped_ptr
<HttpTransaction
> trans(
12478 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12480 MockWrite data_writes
[] = {
12482 "GET / HTTP/1.1\r\n"
12483 "Host: www.example.org\r\n"
12484 "Connection: keep-alive\r\n\r\n"),
12486 MockRead data_reads
[] = {
12487 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12490 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12491 data_writes
, arraysize(data_writes
));
12492 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12494 TestCompletionCallback callback
;
12496 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12497 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12499 rv
= callback
.WaitForResult();
12500 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12502 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12504 HttpRequestHeaders request_headers
;
12505 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12506 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12509 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12510 HttpRequestInfo request
;
12511 request
.method
= "GET";
12512 request
.url
= GURL("http://www.example.org/");
12513 request
.load_flags
= 0;
12515 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12516 scoped_ptr
<HttpTransaction
> trans(
12517 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12519 MockWrite data_writes
[] = {
12521 "GET / HTTP/1.1\r\n"
12522 "Host: www.example.org\r\n"
12523 "Connection: keep-alive\r\n\r\n"),
12525 MockRead data_reads
[] = {
12526 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12529 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12530 data_writes
, arraysize(data_writes
));
12531 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12533 TestCompletionCallback callback
;
12535 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12536 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12538 rv
= callback
.WaitForResult();
12539 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12541 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12543 HttpRequestHeaders request_headers
;
12544 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12545 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12548 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12549 HttpRequestInfo request
;
12550 request
.method
= "GET";
12551 request
.url
= GURL("http://www.example.org/");
12552 request
.load_flags
= 0;
12553 request
.extra_headers
.SetHeader("X-Foo", "bar");
12555 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12556 scoped_ptr
<HttpTransaction
> trans(
12557 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12559 MockWrite data_writes
[] = {
12561 "GET / HTTP/1.1\r\n"
12562 "Host: www.example.org\r\n"
12563 "Connection: keep-alive\r\n"
12564 "X-Foo: bar\r\n\r\n"),
12566 MockRead data_reads
[] = {
12567 MockRead("HTTP/1.1 200 OK\r\n"
12568 "Content-Length: 5\r\n\r\n"
12570 MockRead(ASYNC
, ERR_UNEXPECTED
),
12573 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12574 data_writes
, arraysize(data_writes
));
12575 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12577 TestCompletionCallback callback
;
12579 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12582 rv
= callback
.WaitForResult();
12585 HttpRequestHeaders request_headers
;
12586 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12588 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12589 EXPECT_EQ("bar", foo
);
12594 // Fake HttpStream that simply records calls to SetPriority().
12595 class FakeStream
: public HttpStream
,
12596 public base::SupportsWeakPtr
<FakeStream
> {
12598 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12599 ~FakeStream() override
{}
12601 RequestPriority
priority() const { return priority_
; }
12603 int InitializeStream(const HttpRequestInfo
* request_info
,
12604 RequestPriority priority
,
12605 const BoundNetLog
& net_log
,
12606 const CompletionCallback
& callback
) override
{
12607 return ERR_IO_PENDING
;
12610 int SendRequest(const HttpRequestHeaders
& request_headers
,
12611 HttpResponseInfo
* response
,
12612 const CompletionCallback
& callback
) override
{
12614 return ERR_UNEXPECTED
;
12617 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12619 return ERR_UNEXPECTED
;
12622 int ReadResponseBody(IOBuffer
* buf
,
12624 const CompletionCallback
& callback
) override
{
12626 return ERR_UNEXPECTED
;
12629 void Close(bool not_reusable
) override
{}
12631 bool IsResponseBodyComplete() const override
{
12636 bool CanFindEndOfResponse() const override
{ return false; }
12638 bool IsConnectionReused() const override
{
12643 void SetConnectionReused() override
{ ADD_FAILURE(); }
12645 bool IsConnectionReusable() const override
{
12650 int64
GetTotalReceivedBytes() const override
{
12655 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12660 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
12662 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12666 bool IsSpdyHttpStream() const override
{
12671 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
12673 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12675 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
12677 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
12680 RequestPriority priority_
;
12682 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12685 // Fake HttpStreamRequest that simply records calls to SetPriority()
12686 // and vends FakeStreams with its current priority.
12687 class FakeStreamRequest
: public HttpStreamRequest
,
12688 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12690 FakeStreamRequest(RequestPriority priority
,
12691 HttpStreamRequest::Delegate
* delegate
)
12692 : priority_(priority
),
12693 delegate_(delegate
),
12694 websocket_stream_create_helper_(NULL
) {}
12696 FakeStreamRequest(RequestPriority priority
,
12697 HttpStreamRequest::Delegate
* delegate
,
12698 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12699 : priority_(priority
),
12700 delegate_(delegate
),
12701 websocket_stream_create_helper_(create_helper
) {}
12703 ~FakeStreamRequest() override
{}
12705 RequestPriority
priority() const { return priority_
; }
12707 const WebSocketHandshakeStreamBase::CreateHelper
*
12708 websocket_stream_create_helper() const {
12709 return websocket_stream_create_helper_
;
12712 // Create a new FakeStream and pass it to the request's
12713 // delegate. Returns a weak pointer to the FakeStream.
12714 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12715 FakeStream
* fake_stream
= new FakeStream(priority_
);
12716 // Do this before calling OnStreamReady() as OnStreamReady() may
12717 // immediately delete |fake_stream|.
12718 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12719 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12720 return weak_stream
;
12723 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
12725 return ERR_UNEXPECTED
;
12728 LoadState
GetLoadState() const override
{
12730 return LoadState();
12733 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12735 bool was_npn_negotiated() const override
{ return false; }
12737 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
12739 bool using_spdy() const override
{ return false; }
12742 RequestPriority priority_
;
12743 HttpStreamRequest::Delegate
* const delegate_
;
12744 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12746 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12749 // Fake HttpStreamFactory that vends FakeStreamRequests.
12750 class FakeStreamFactory
: public HttpStreamFactory
{
12752 FakeStreamFactory() {}
12753 ~FakeStreamFactory() override
{}
12755 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12756 // RequestStream() (which may be NULL if it was destroyed already).
12757 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12758 return last_stream_request_
;
12761 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
12762 RequestPriority priority
,
12763 const SSLConfig
& server_ssl_config
,
12764 const SSLConfig
& proxy_ssl_config
,
12765 HttpStreamRequest::Delegate
* delegate
,
12766 const BoundNetLog
& net_log
) override
{
12767 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12768 last_stream_request_
= fake_request
->AsWeakPtr();
12769 return fake_request
;
12772 HttpStreamRequest
* RequestWebSocketHandshakeStream(
12773 const HttpRequestInfo
& info
,
12774 RequestPriority priority
,
12775 const SSLConfig
& server_ssl_config
,
12776 const SSLConfig
& proxy_ssl_config
,
12777 HttpStreamRequest::Delegate
* delegate
,
12778 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12779 const BoundNetLog
& net_log
) override
{
12780 FakeStreamRequest
* fake_request
=
12781 new FakeStreamRequest(priority
, delegate
, create_helper
);
12782 last_stream_request_
= fake_request
->AsWeakPtr();
12783 return fake_request
;
12786 void PreconnectStreams(int num_streams
,
12787 const HttpRequestInfo
& info
,
12788 RequestPriority priority
,
12789 const SSLConfig
& server_ssl_config
,
12790 const SSLConfig
& proxy_ssl_config
) override
{
12794 const HostMappingRules
* GetHostMappingRules() const override
{
12800 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12802 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12805 // TODO(ricea): Maybe unify this with the one in
12806 // url_request_http_job_unittest.cc ?
12807 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
12809 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
12811 : state_(connection
.release(), using_proxy
) {}
12813 // Fake implementation of HttpStreamBase methods.
12814 // This ends up being quite "real" because this object has to really send data
12815 // on the mock socket. It might be easier to use the real implementation, but
12816 // the fact that the WebSocket code is not compiled on iOS makes that
12818 int InitializeStream(const HttpRequestInfo
* request_info
,
12819 RequestPriority priority
,
12820 const BoundNetLog
& net_log
,
12821 const CompletionCallback
& callback
) override
{
12822 state_
.Initialize(request_info
, priority
, net_log
, callback
);
12826 int SendRequest(const HttpRequestHeaders
& request_headers
,
12827 HttpResponseInfo
* response
,
12828 const CompletionCallback
& callback
) override
{
12829 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
12830 response
, callback
);
12833 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12834 return parser()->ReadResponseHeaders(callback
);
12837 int ReadResponseBody(IOBuffer
* buf
,
12839 const CompletionCallback
& callback
) override
{
12841 return ERR_IO_PENDING
;
12844 void Close(bool not_reusable
) override
{
12846 parser()->Close(true);
12849 bool IsResponseBodyComplete() const override
{
12854 bool CanFindEndOfResponse() const override
{
12855 return parser()->CanFindEndOfResponse();
12858 bool IsConnectionReused() const override
{
12862 void SetConnectionReused() override
{ NOTREACHED(); }
12864 bool IsConnectionReusable() const override
{
12869 int64
GetTotalReceivedBytes() const override
{
12874 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12879 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
12881 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12885 bool IsSpdyHttpStream() const override
{
12890 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
12892 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
12894 UploadProgress
GetUploadProgress() const override
{
12896 return UploadProgress();
12899 HttpStream
* RenewStreamForAuth() override
{
12904 // Fake implementation of WebSocketHandshakeStreamBase method(s)
12905 scoped_ptr
<WebSocketStream
> Upgrade() override
{
12907 return scoped_ptr
<WebSocketStream
>();
12911 HttpStreamParser
* parser() const { return state_
.parser(); }
12912 HttpBasicState state_
;
12914 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
12917 // TODO(yhirano): Split this class out into a net/websockets file, if it is
12919 class FakeWebSocketStreamCreateHelper
:
12920 public WebSocketHandshakeStreamBase::CreateHelper
{
12922 WebSocketHandshakeStreamBase
* CreateBasicStream(
12923 scoped_ptr
<ClientSocketHandle
> connection
,
12924 bool using_proxy
) override
{
12925 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
12929 WebSocketHandshakeStreamBase
* CreateSpdyStream(
12930 const base::WeakPtr
<SpdySession
>& session
,
12931 bool use_relative_url
) override
{
12936 ~FakeWebSocketStreamCreateHelper() override
{}
12938 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
12940 return scoped_ptr
<WebSocketStream
>();
12946 // Make sure that HttpNetworkTransaction passes on its priority to its
12947 // stream request on start.
12948 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
12949 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12950 HttpNetworkSessionPeer
peer(session
);
12951 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12952 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12954 HttpNetworkTransaction
trans(LOW
, session
.get());
12956 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
12958 HttpRequestInfo request
;
12959 TestCompletionCallback callback
;
12960 EXPECT_EQ(ERR_IO_PENDING
,
12961 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12963 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12964 fake_factory
->last_stream_request();
12965 ASSERT_TRUE(fake_request
!= NULL
);
12966 EXPECT_EQ(LOW
, fake_request
->priority());
12969 // Make sure that HttpNetworkTransaction passes on its priority
12970 // updates to its stream request.
12971 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
12972 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12973 HttpNetworkSessionPeer
peer(session
);
12974 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
12975 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
12977 HttpNetworkTransaction
trans(LOW
, session
.get());
12979 HttpRequestInfo request
;
12980 TestCompletionCallback callback
;
12981 EXPECT_EQ(ERR_IO_PENDING
,
12982 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
12984 base::WeakPtr
<FakeStreamRequest
> fake_request
=
12985 fake_factory
->last_stream_request();
12986 ASSERT_TRUE(fake_request
!= NULL
);
12987 EXPECT_EQ(LOW
, fake_request
->priority());
12989 trans
.SetPriority(LOWEST
);
12990 ASSERT_TRUE(fake_request
!= NULL
);
12991 EXPECT_EQ(LOWEST
, fake_request
->priority());
12994 // Make sure that HttpNetworkTransaction passes on its priority
12995 // updates to its stream.
12996 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
12997 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12998 HttpNetworkSessionPeer
peer(session
);
12999 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13000 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13002 HttpNetworkTransaction
trans(LOW
, session
.get());
13004 HttpRequestInfo request
;
13005 TestCompletionCallback callback
;
13006 EXPECT_EQ(ERR_IO_PENDING
,
13007 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13009 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13010 fake_factory
->last_stream_request();
13011 ASSERT_TRUE(fake_request
!= NULL
);
13012 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13013 ASSERT_TRUE(fake_stream
!= NULL
);
13014 EXPECT_EQ(LOW
, fake_stream
->priority());
13016 trans
.SetPriority(LOWEST
);
13017 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13020 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13021 // The same logic needs to be tested for both ws: and wss: schemes, but this
13022 // test is already parameterised on NextProto, so it uses a loop to verify
13023 // that the different schemes work.
13024 std::string test_cases
[] = {"ws://www.example.org/",
13025 "wss://www.example.org/"};
13026 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13027 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13028 HttpNetworkSessionPeer
peer(session
);
13029 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13030 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13031 peer
.SetHttpStreamFactoryForWebSocket(
13032 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13034 HttpNetworkTransaction
trans(LOW
, session
.get());
13035 trans
.SetWebSocketHandshakeStreamCreateHelper(
13036 &websocket_stream_create_helper
);
13038 HttpRequestInfo request
;
13039 TestCompletionCallback callback
;
13040 request
.method
= "GET";
13041 request
.url
= GURL(test_cases
[i
]);
13043 EXPECT_EQ(ERR_IO_PENDING
,
13044 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13046 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13047 fake_factory
->last_stream_request();
13048 ASSERT_TRUE(fake_request
!= NULL
);
13049 EXPECT_EQ(&websocket_stream_create_helper
,
13050 fake_request
->websocket_stream_create_helper());
13054 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13055 // if the transport socket pool is stalled on the global socket limit.
13056 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13057 ClientSocketPoolManager::set_max_sockets_per_group(
13058 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13059 ClientSocketPoolManager::set_max_sockets_per_pool(
13060 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13062 // Set up SSL request.
13064 HttpRequestInfo ssl_request
;
13065 ssl_request
.method
= "GET";
13066 ssl_request
.url
= GURL("https://www.example.org/");
13068 MockWrite ssl_writes
[] = {
13070 "GET / HTTP/1.1\r\n"
13071 "Host: www.example.org\r\n"
13072 "Connection: keep-alive\r\n\r\n"),
13074 MockRead ssl_reads
[] = {
13075 MockRead("HTTP/1.1 200 OK\r\n"),
13076 MockRead("Content-Length: 11\r\n\r\n"),
13077 MockRead("hello world"),
13078 MockRead(SYNCHRONOUS
, OK
),
13080 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13081 ssl_writes
, arraysize(ssl_writes
));
13082 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13084 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13085 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13087 // Set up HTTP request.
13089 HttpRequestInfo http_request
;
13090 http_request
.method
= "GET";
13091 http_request
.url
= GURL("http://www.example.org/");
13093 MockWrite http_writes
[] = {
13095 "GET / HTTP/1.1\r\n"
13096 "Host: www.example.org\r\n"
13097 "Connection: keep-alive\r\n\r\n"),
13099 MockRead http_reads
[] = {
13100 MockRead("HTTP/1.1 200 OK\r\n"),
13101 MockRead("Content-Length: 7\r\n\r\n"),
13102 MockRead("falafel"),
13103 MockRead(SYNCHRONOUS
, OK
),
13105 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13106 http_writes
, arraysize(http_writes
));
13107 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13109 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13111 // Start the SSL request.
13112 TestCompletionCallback ssl_callback
;
13113 scoped_ptr
<HttpTransaction
> ssl_trans(
13114 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13115 ASSERT_EQ(ERR_IO_PENDING
,
13116 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13119 // Start the HTTP request. Pool should stall.
13120 TestCompletionCallback http_callback
;
13121 scoped_ptr
<HttpTransaction
> http_trans(
13122 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13123 ASSERT_EQ(ERR_IO_PENDING
,
13124 http_trans
->Start(&http_request
, http_callback
.callback(),
13126 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13128 // Wait for response from SSL request.
13129 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13130 std::string response_data
;
13131 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13132 EXPECT_EQ("hello world", response_data
);
13134 // The SSL socket should automatically be closed, so the HTTP request can
13136 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13137 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13139 // The HTTP request can now complete.
13140 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13141 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13142 EXPECT_EQ("falafel", response_data
);
13144 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13147 // Tests that when a SSL connection is established but there's no corresponding
13148 // request that needs it, the new socket is closed if the transport socket pool
13149 // is stalled on the global socket limit.
13150 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13151 ClientSocketPoolManager::set_max_sockets_per_group(
13152 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13153 ClientSocketPoolManager::set_max_sockets_per_pool(
13154 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13156 // Set up an ssl request.
13158 HttpRequestInfo ssl_request
;
13159 ssl_request
.method
= "GET";
13160 ssl_request
.url
= GURL("https://www.foopy.com/");
13162 // No data will be sent on the SSL socket.
13163 StaticSocketDataProvider ssl_data
;
13164 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13166 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13167 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13169 // Set up HTTP request.
13171 HttpRequestInfo http_request
;
13172 http_request
.method
= "GET";
13173 http_request
.url
= GURL("http://www.example.org/");
13175 MockWrite http_writes
[] = {
13177 "GET / HTTP/1.1\r\n"
13178 "Host: www.example.org\r\n"
13179 "Connection: keep-alive\r\n\r\n"),
13181 MockRead http_reads
[] = {
13182 MockRead("HTTP/1.1 200 OK\r\n"),
13183 MockRead("Content-Length: 7\r\n\r\n"),
13184 MockRead("falafel"),
13185 MockRead(SYNCHRONOUS
, OK
),
13187 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13188 http_writes
, arraysize(http_writes
));
13189 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13191 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13193 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13194 // cancelled when a normal transaction is cancelled.
13195 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13196 SSLConfig ssl_config
;
13197 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13198 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
13199 ssl_config
, ssl_config
);
13200 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13202 // Start the HTTP request. Pool should stall.
13203 TestCompletionCallback http_callback
;
13204 scoped_ptr
<HttpTransaction
> http_trans(
13205 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13206 ASSERT_EQ(ERR_IO_PENDING
,
13207 http_trans
->Start(&http_request
, http_callback
.callback(),
13209 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13211 // The SSL connection will automatically be closed once the connection is
13212 // established, to let the HTTP request start.
13213 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13214 std::string response_data
;
13215 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13216 EXPECT_EQ("falafel", response_data
);
13218 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13221 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13222 ScopedVector
<UploadElementReader
> element_readers
;
13223 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13224 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13226 HttpRequestInfo request
;
13227 request
.method
= "POST";
13228 request
.url
= GURL("http://www.foo.com/");
13229 request
.upload_data_stream
= &upload_data_stream
;
13230 request
.load_flags
= 0;
13232 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13233 scoped_ptr
<HttpTransaction
> trans(
13234 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13235 // Send headers successfully, but get an error while sending the body.
13236 MockWrite data_writes
[] = {
13237 MockWrite("POST / HTTP/1.1\r\n"
13238 "Host: www.foo.com\r\n"
13239 "Connection: keep-alive\r\n"
13240 "Content-Length: 3\r\n\r\n"),
13241 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13244 MockRead data_reads
[] = {
13245 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13246 MockRead("hello world"),
13247 MockRead(SYNCHRONOUS
, OK
),
13249 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13250 arraysize(data_writes
));
13251 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13253 TestCompletionCallback callback
;
13255 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13256 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13258 rv
= callback
.WaitForResult();
13261 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13262 ASSERT_TRUE(response
!= NULL
);
13264 EXPECT_TRUE(response
->headers
.get() != NULL
);
13265 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13267 std::string response_data
;
13268 rv
= ReadTransaction(trans
.get(), &response_data
);
13270 EXPECT_EQ("hello world", response_data
);
13273 // This test makes sure the retry logic doesn't trigger when reading an error
13274 // response from a server that rejected a POST with a CONNECTION_RESET.
13275 TEST_P(HttpNetworkTransactionTest
,
13276 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13277 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13278 MockWrite data_writes
[] = {
13279 MockWrite("GET / HTTP/1.1\r\n"
13280 "Host: www.foo.com\r\n"
13281 "Connection: keep-alive\r\n\r\n"),
13282 MockWrite("POST / HTTP/1.1\r\n"
13283 "Host: www.foo.com\r\n"
13284 "Connection: keep-alive\r\n"
13285 "Content-Length: 3\r\n\r\n"),
13286 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13289 MockRead data_reads
[] = {
13290 MockRead("HTTP/1.1 200 Peachy\r\n"
13291 "Content-Length: 14\r\n\r\n"),
13292 MockRead("first response"),
13293 MockRead("HTTP/1.1 400 Not OK\r\n"
13294 "Content-Length: 15\r\n\r\n"),
13295 MockRead("second response"),
13296 MockRead(SYNCHRONOUS
, OK
),
13298 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13299 arraysize(data_writes
));
13300 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13302 TestCompletionCallback callback
;
13303 HttpRequestInfo request1
;
13304 request1
.method
= "GET";
13305 request1
.url
= GURL("http://www.foo.com/");
13306 request1
.load_flags
= 0;
13308 scoped_ptr
<HttpTransaction
> trans1(
13309 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13310 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13311 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13313 rv
= callback
.WaitForResult();
13316 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13317 ASSERT_TRUE(response1
!= NULL
);
13319 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13320 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13322 std::string response_data1
;
13323 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13325 EXPECT_EQ("first response", response_data1
);
13326 // Delete the transaction to release the socket back into the socket pool.
13329 ScopedVector
<UploadElementReader
> element_readers
;
13330 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13331 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13333 HttpRequestInfo request2
;
13334 request2
.method
= "POST";
13335 request2
.url
= GURL("http://www.foo.com/");
13336 request2
.upload_data_stream
= &upload_data_stream
;
13337 request2
.load_flags
= 0;
13339 scoped_ptr
<HttpTransaction
> trans2(
13340 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13341 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13342 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13344 rv
= callback
.WaitForResult();
13347 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13348 ASSERT_TRUE(response2
!= NULL
);
13350 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13351 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13353 std::string response_data2
;
13354 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13356 EXPECT_EQ("second response", response_data2
);
13359 TEST_P(HttpNetworkTransactionTest
,
13360 PostReadsErrorResponseAfterResetPartialBodySent
) {
13361 ScopedVector
<UploadElementReader
> element_readers
;
13362 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13363 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13365 HttpRequestInfo request
;
13366 request
.method
= "POST";
13367 request
.url
= GURL("http://www.foo.com/");
13368 request
.upload_data_stream
= &upload_data_stream
;
13369 request
.load_flags
= 0;
13371 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13372 scoped_ptr
<HttpTransaction
> trans(
13373 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13374 // Send headers successfully, but get an error while sending the body.
13375 MockWrite data_writes
[] = {
13376 MockWrite("POST / HTTP/1.1\r\n"
13377 "Host: www.foo.com\r\n"
13378 "Connection: keep-alive\r\n"
13379 "Content-Length: 3\r\n\r\n"
13381 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13384 MockRead data_reads
[] = {
13385 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13386 MockRead("hello world"),
13387 MockRead(SYNCHRONOUS
, OK
),
13389 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13390 arraysize(data_writes
));
13391 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13393 TestCompletionCallback callback
;
13395 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13396 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13398 rv
= callback
.WaitForResult();
13401 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13402 ASSERT_TRUE(response
!= NULL
);
13404 EXPECT_TRUE(response
->headers
.get() != NULL
);
13405 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13407 std::string response_data
;
13408 rv
= ReadTransaction(trans
.get(), &response_data
);
13410 EXPECT_EQ("hello world", response_data
);
13413 // This tests the more common case than the previous test, where headers and
13414 // body are not merged into a single request.
13415 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13416 ScopedVector
<UploadElementReader
> element_readers
;
13417 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13418 ChunkedUploadDataStream
upload_data_stream(0);
13420 HttpRequestInfo request
;
13421 request
.method
= "POST";
13422 request
.url
= GURL("http://www.foo.com/");
13423 request
.upload_data_stream
= &upload_data_stream
;
13424 request
.load_flags
= 0;
13426 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13427 scoped_ptr
<HttpTransaction
> trans(
13428 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13429 // Send headers successfully, but get an error while sending the body.
13430 MockWrite data_writes
[] = {
13431 MockWrite("POST / HTTP/1.1\r\n"
13432 "Host: www.foo.com\r\n"
13433 "Connection: keep-alive\r\n"
13434 "Transfer-Encoding: chunked\r\n\r\n"),
13435 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13438 MockRead data_reads
[] = {
13439 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13440 MockRead("hello world"),
13441 MockRead(SYNCHRONOUS
, OK
),
13443 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13444 arraysize(data_writes
));
13445 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13447 TestCompletionCallback callback
;
13449 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13450 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13451 // Make sure the headers are sent before adding a chunk. This ensures that
13452 // they can't be merged with the body in a single send. Not currently
13453 // necessary since a chunked body is never merged with headers, but this makes
13454 // the test more future proof.
13455 base::RunLoop().RunUntilIdle();
13457 upload_data_stream
.AppendData("last chunk", 10, true);
13459 rv
= callback
.WaitForResult();
13462 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13463 ASSERT_TRUE(response
!= NULL
);
13465 EXPECT_TRUE(response
->headers
.get() != NULL
);
13466 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13468 std::string response_data
;
13469 rv
= ReadTransaction(trans
.get(), &response_data
);
13471 EXPECT_EQ("hello world", response_data
);
13474 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13475 ScopedVector
<UploadElementReader
> element_readers
;
13476 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13477 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13479 HttpRequestInfo request
;
13480 request
.method
= "POST";
13481 request
.url
= GURL("http://www.foo.com/");
13482 request
.upload_data_stream
= &upload_data_stream
;
13483 request
.load_flags
= 0;
13485 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13486 scoped_ptr
<HttpTransaction
> trans(
13487 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13489 MockWrite data_writes
[] = {
13490 MockWrite("POST / HTTP/1.1\r\n"
13491 "Host: www.foo.com\r\n"
13492 "Connection: keep-alive\r\n"
13493 "Content-Length: 3\r\n\r\n"),
13494 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13497 MockRead data_reads
[] = {
13498 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13499 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13500 MockRead("hello world"),
13501 MockRead(SYNCHRONOUS
, OK
),
13503 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13504 arraysize(data_writes
));
13505 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13507 TestCompletionCallback callback
;
13509 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13510 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13512 rv
= callback
.WaitForResult();
13515 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13516 ASSERT_TRUE(response
!= NULL
);
13518 EXPECT_TRUE(response
->headers
.get() != NULL
);
13519 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13521 std::string response_data
;
13522 rv
= ReadTransaction(trans
.get(), &response_data
);
13524 EXPECT_EQ("hello world", response_data
);
13527 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13528 ScopedVector
<UploadElementReader
> element_readers
;
13529 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13530 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13532 HttpRequestInfo request
;
13533 request
.method
= "POST";
13534 request
.url
= GURL("http://www.foo.com/");
13535 request
.upload_data_stream
= &upload_data_stream
;
13536 request
.load_flags
= 0;
13538 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13539 scoped_ptr
<HttpTransaction
> trans(
13540 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13541 // Send headers successfully, but get an error while sending the body.
13542 MockWrite data_writes
[] = {
13543 MockWrite("POST / HTTP/1.1\r\n"
13544 "Host: www.foo.com\r\n"
13545 "Connection: keep-alive\r\n"
13546 "Content-Length: 3\r\n\r\n"),
13547 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13550 MockRead data_reads
[] = {
13551 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13552 MockRead("hello world"),
13553 MockRead(SYNCHRONOUS
, OK
),
13555 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13556 arraysize(data_writes
));
13557 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13559 TestCompletionCallback callback
;
13561 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13562 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13564 rv
= callback
.WaitForResult();
13565 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13567 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13568 EXPECT_TRUE(response
== NULL
);
13571 TEST_P(HttpNetworkTransactionTest
,
13572 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13573 ScopedVector
<UploadElementReader
> element_readers
;
13574 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13575 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13577 HttpRequestInfo request
;
13578 request
.method
= "POST";
13579 request
.url
= GURL("http://www.foo.com/");
13580 request
.upload_data_stream
= &upload_data_stream
;
13581 request
.load_flags
= 0;
13583 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13584 scoped_ptr
<HttpTransaction
> trans(
13585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13586 // Send headers successfully, but get an error while sending the body.
13587 MockWrite data_writes
[] = {
13588 MockWrite("POST / HTTP/1.1\r\n"
13589 "Host: www.foo.com\r\n"
13590 "Connection: keep-alive\r\n"
13591 "Content-Length: 3\r\n\r\n"),
13592 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13595 MockRead data_reads
[] = {
13596 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13597 MockRead("HTTP/1.0 302 Redirect\r\n"),
13598 MockRead("Location: http://somewhere-else.com/\r\n"),
13599 MockRead("Content-Length: 0\r\n\r\n"),
13600 MockRead(SYNCHRONOUS
, OK
),
13602 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13603 arraysize(data_writes
));
13604 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13606 TestCompletionCallback callback
;
13608 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13609 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13611 rv
= callback
.WaitForResult();
13612 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13614 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13615 EXPECT_TRUE(response
== NULL
);
13618 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13619 ScopedVector
<UploadElementReader
> element_readers
;
13620 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13621 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13623 HttpRequestInfo request
;
13624 request
.method
= "POST";
13625 request
.url
= GURL("http://www.foo.com/");
13626 request
.upload_data_stream
= &upload_data_stream
;
13627 request
.load_flags
= 0;
13629 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13630 scoped_ptr
<HttpTransaction
> trans(
13631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13632 // Send headers successfully, but get an error while sending the body.
13633 MockWrite data_writes
[] = {
13634 MockWrite("POST / HTTP/1.1\r\n"
13635 "Host: www.foo.com\r\n"
13636 "Connection: keep-alive\r\n"
13637 "Content-Length: 3\r\n\r\n"),
13638 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13641 MockRead data_reads
[] = {
13642 MockRead("HTTP 0.9 rocks!"),
13643 MockRead(SYNCHRONOUS
, OK
),
13645 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13646 arraysize(data_writes
));
13647 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13649 TestCompletionCallback callback
;
13651 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13652 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13654 rv
= callback
.WaitForResult();
13655 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13657 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13658 EXPECT_TRUE(response
== NULL
);
13661 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13662 ScopedVector
<UploadElementReader
> element_readers
;
13663 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13664 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13666 HttpRequestInfo request
;
13667 request
.method
= "POST";
13668 request
.url
= GURL("http://www.foo.com/");
13669 request
.upload_data_stream
= &upload_data_stream
;
13670 request
.load_flags
= 0;
13672 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13673 scoped_ptr
<HttpTransaction
> trans(
13674 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13675 // Send headers successfully, but get an error while sending the body.
13676 MockWrite data_writes
[] = {
13677 MockWrite("POST / HTTP/1.1\r\n"
13678 "Host: www.foo.com\r\n"
13679 "Connection: keep-alive\r\n"
13680 "Content-Length: 3\r\n\r\n"),
13681 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13684 MockRead data_reads
[] = {
13685 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13686 MockRead(SYNCHRONOUS
, OK
),
13688 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13689 arraysize(data_writes
));
13690 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13692 TestCompletionCallback callback
;
13694 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13697 rv
= callback
.WaitForResult();
13698 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13700 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13701 EXPECT_TRUE(response
== NULL
);
13704 // Verify that proxy headers are not sent to the destination server when
13705 // establishing a tunnel for a secure WebSocket connection.
13706 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
13707 HttpRequestInfo request
;
13708 request
.method
= "GET";
13709 request
.url
= GURL("wss://www.example.org/");
13710 AddWebSocketHeaders(&request
.extra_headers
);
13712 // Configure against proxy server "myproxy:70".
13713 session_deps_
.proxy_service
.reset(
13714 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13716 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13718 // Since a proxy is configured, try to establish a tunnel.
13719 MockWrite data_writes
[] = {
13721 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13722 "Host: www.example.org\r\n"
13723 "Proxy-Connection: keep-alive\r\n\r\n"),
13725 // After calling trans->RestartWithAuth(), this is the request we should
13726 // be issuing -- the final header line contains the credentials.
13728 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13729 "Host: www.example.org\r\n"
13730 "Proxy-Connection: keep-alive\r\n"
13731 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13734 "GET / HTTP/1.1\r\n"
13735 "Host: www.example.org\r\n"
13736 "Connection: Upgrade\r\n"
13737 "Upgrade: websocket\r\n"
13738 "Origin: http://www.example.org\r\n"
13739 "Sec-WebSocket-Version: 13\r\n"
13740 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13743 // The proxy responds to the connect with a 407, using a persistent
13745 MockRead data_reads
[] = {
13747 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
13748 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13749 MockRead("Proxy-Connection: close\r\n\r\n"),
13751 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13753 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13754 MockRead("Upgrade: websocket\r\n"),
13755 MockRead("Connection: Upgrade\r\n"),
13756 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13759 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13760 arraysize(data_writes
));
13761 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13762 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13763 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13765 scoped_ptr
<HttpTransaction
> trans(
13766 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13767 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13768 trans
->SetWebSocketHandshakeStreamCreateHelper(
13769 &websocket_stream_create_helper
);
13772 TestCompletionCallback callback
;
13774 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13777 rv
= callback
.WaitForResult();
13781 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13782 ASSERT_TRUE(response
);
13783 ASSERT_TRUE(response
->headers
.get());
13784 EXPECT_EQ(407, response
->headers
->response_code());
13787 TestCompletionCallback callback
;
13789 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
13790 callback
.callback());
13791 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13793 rv
= callback
.WaitForResult();
13797 response
= trans
->GetResponseInfo();
13798 ASSERT_TRUE(response
);
13799 ASSERT_TRUE(response
->headers
.get());
13801 EXPECT_EQ(101, response
->headers
->response_code());
13804 session
->CloseAllConnections();
13807 // Verify that proxy headers are not sent to the destination server when
13808 // establishing a tunnel for an insecure WebSocket connection.
13809 // This requires the authentication info to be injected into the auth cache
13810 // due to crbug.com/395064
13811 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
13812 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
13813 HttpRequestInfo request
;
13814 request
.method
= "GET";
13815 request
.url
= GURL("ws://www.example.org/");
13816 AddWebSocketHeaders(&request
.extra_headers
);
13818 // Configure against proxy server "myproxy:70".
13819 session_deps_
.proxy_service
.reset(
13820 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13822 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13824 MockWrite data_writes
[] = {
13825 // Try to establish a tunnel for the WebSocket connection, with
13826 // credentials. Because WebSockets have a separate set of socket pools,
13827 // they cannot and will not use the same TCP/IP connection as the
13828 // preflight HTTP request.
13830 "CONNECT www.example.org:80 HTTP/1.1\r\n"
13831 "Host: www.example.org:80\r\n"
13832 "Proxy-Connection: keep-alive\r\n"
13833 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13836 "GET / HTTP/1.1\r\n"
13837 "Host: www.example.org\r\n"
13838 "Connection: Upgrade\r\n"
13839 "Upgrade: websocket\r\n"
13840 "Origin: http://www.example.org\r\n"
13841 "Sec-WebSocket-Version: 13\r\n"
13842 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13845 MockRead data_reads
[] = {
13846 // HTTP CONNECT with credentials.
13847 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13849 // WebSocket connection established inside tunnel.
13850 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13851 MockRead("Upgrade: websocket\r\n"),
13852 MockRead("Connection: Upgrade\r\n"),
13853 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13856 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13857 arraysize(data_writes
));
13858 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13860 session
->http_auth_cache()->Add(
13861 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
13862 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
13864 scoped_ptr
<HttpTransaction
> trans(
13865 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13866 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13867 trans
->SetWebSocketHandshakeStreamCreateHelper(
13868 &websocket_stream_create_helper
);
13870 TestCompletionCallback callback
;
13872 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13873 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13875 rv
= callback
.WaitForResult();
13878 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13879 ASSERT_TRUE(response
);
13880 ASSERT_TRUE(response
->headers
.get());
13882 EXPECT_EQ(101, response
->headers
->response_code());
13885 session
->CloseAllConnections();