1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/test_file_util.h"
25 #include "net/base/auth.h"
26 #include "net/base/chunked_upload_data_stream.h"
27 #include "net/base/completion_callback.h"
28 #include "net/base/elements_upload_data_stream.h"
29 #include "net/base/load_timing_info.h"
30 #include "net/base/load_timing_info_test_util.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/request_priority.h"
33 #include "net/base/test_completion_callback.h"
34 #include "net/base/test_data_directory.h"
35 #include "net/base/upload_bytes_element_reader.h"
36 #include "net/base/upload_file_element_reader.h"
37 #include "net/cert/mock_cert_verifier.h"
38 #include "net/dns/host_cache.h"
39 #include "net/dns/mock_host_resolver.h"
40 #include "net/http/http_auth_challenge_tokenizer.h"
41 #include "net/http/http_auth_handler_digest.h"
42 #include "net/http/http_auth_handler_mock.h"
43 #include "net/http/http_auth_handler_ntlm.h"
44 #include "net/http/http_basic_state.h"
45 #include "net/http/http_basic_stream.h"
46 #include "net/http/http_network_session.h"
47 #include "net/http/http_network_session_peer.h"
48 #include "net/http/http_request_headers.h"
49 #include "net/http/http_server_properties_impl.h"
50 #include "net/http/http_stream.h"
51 #include "net/http/http_stream_factory.h"
52 #include "net/http/http_stream_parser.h"
53 #include "net/http/http_transaction_test_util.h"
54 #include "net/log/net_log.h"
55 #include "net/log/test_net_log.h"
56 #include "net/log/test_net_log_entry.h"
57 #include "net/log/test_net_log_util.h"
58 #include "net/proxy/mock_proxy_resolver.h"
59 #include "net/proxy/proxy_config_service_fixed.h"
60 #include "net/proxy/proxy_info.h"
61 #include "net/proxy/proxy_resolver.h"
62 #include "net/proxy/proxy_service.h"
63 #include "net/socket/client_socket_factory.h"
64 #include "net/socket/client_socket_pool_manager.h"
65 #include "net/socket/connection_attempts.h"
66 #include "net/socket/mock_client_socket_pool_manager.h"
67 #include "net/socket/next_proto.h"
68 #include "net/socket/socket_test_util.h"
69 #include "net/socket/ssl_client_socket.h"
70 #include "net/spdy/spdy_framer.h"
71 #include "net/spdy/spdy_session.h"
72 #include "net/spdy/spdy_session_pool.h"
73 #include "net/spdy/spdy_test_util_common.h"
74 #include "net/ssl/ssl_cert_request_info.h"
75 #include "net/ssl/ssl_config_service.h"
76 #include "net/ssl/ssl_config_service_defaults.h"
77 #include "net/ssl/ssl_info.h"
78 #include "net/test/cert_test_util.h"
79 #include "net/websockets/websocket_handshake_stream_base.h"
80 #include "testing/gtest/include/gtest/gtest.h"
81 #include "testing/platform_test.h"
84 using base::ASCIIToUTF16
;
86 //-----------------------------------------------------------------------------
92 const base::string16
kBar(ASCIIToUTF16("bar"));
93 const base::string16
kBar2(ASCIIToUTF16("bar2"));
94 const base::string16
kBar3(ASCIIToUTF16("bar3"));
95 const base::string16
kBaz(ASCIIToUTF16("baz"));
96 const base::string16
kFirst(ASCIIToUTF16("first"));
97 const base::string16
kFoo(ASCIIToUTF16("foo"));
98 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
99 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
100 const base::string16
kFou(ASCIIToUTF16("fou"));
101 const base::string16
kSecond(ASCIIToUTF16("second"));
102 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
103 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
105 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession
* session
) {
106 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
110 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession
* session
) {
111 return session
->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
115 bool IsTransportSocketPoolStalled(HttpNetworkSession
* session
) {
116 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
120 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
121 // a JSONified list of headers as a single string. Uses single quotes instead
122 // of double quotes for easier comparison. Returns false on failure.
123 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
126 base::ListValue
* header_list
;
127 if (!params
->GetList("headers", &header_list
))
129 std::string double_quote_headers
;
130 base::JSONWriter::Write(*header_list
, &double_quote_headers
);
131 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
135 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
137 void TestLoadTimingReused(const LoadTimingInfo
& load_timing_info
) {
138 EXPECT_TRUE(load_timing_info
.socket_reused
);
139 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
141 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
142 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
144 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
145 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
147 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
149 // Set at a higher level.
150 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
151 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
152 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
155 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
157 void TestLoadTimingNotReused(const LoadTimingInfo
& load_timing_info
,
158 int connect_timing_flags
) {
159 EXPECT_FALSE(load_timing_info
.socket_reused
);
160 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
162 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
163 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
165 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
166 connect_timing_flags
);
167 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
168 load_timing_info
.send_start
);
170 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
172 // Set at a higher level.
173 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
174 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
175 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
178 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
180 void TestLoadTimingReusedWithPac(const LoadTimingInfo
& load_timing_info
) {
181 EXPECT_TRUE(load_timing_info
.socket_reused
);
182 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
184 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
186 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
187 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
188 load_timing_info
.proxy_resolve_end
);
189 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
190 load_timing_info
.send_start
);
191 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
193 // Set at a higher level.
194 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
195 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
196 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
199 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
201 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo
& load_timing_info
,
202 int connect_timing_flags
) {
203 EXPECT_FALSE(load_timing_info
.socket_reused
);
204 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
206 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
207 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
208 load_timing_info
.proxy_resolve_end
);
209 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
210 load_timing_info
.connect_timing
.connect_start
);
211 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
212 connect_timing_flags
);
213 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
214 load_timing_info
.send_start
);
216 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
218 // Set at a higher level.
219 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
220 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
221 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
224 void AddWebSocketHeaders(HttpRequestHeaders
* headers
) {
225 headers
->SetHeader("Connection", "Upgrade");
226 headers
->SetHeader("Upgrade", "websocket");
227 headers
->SetHeader("Origin", "http://www.example.org");
228 headers
->SetHeader("Sec-WebSocket-Version", "13");
229 headers
->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
232 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
233 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
238 class HttpNetworkTransactionTest
239 : public PlatformTest
,
240 public ::testing::WithParamInterface
<NextProto
> {
242 virtual ~HttpNetworkTransactionTest() {
243 // Important to restore the per-pool limit first, since the pool limit must
244 // always be greater than group limit, and the tests reduce both limits.
245 ClientSocketPoolManager::set_max_sockets_per_pool(
246 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
247 ClientSocketPoolManager::set_max_sockets_per_group(
248 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
252 HttpNetworkTransactionTest()
253 : spdy_util_(GetParam()),
254 session_deps_(GetParam()),
255 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
256 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
257 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
258 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
261 struct SimpleGetHelperResult
{
263 std::string status_line
;
264 std::string response_data
;
265 int64 totalReceivedBytes
;
266 LoadTimingInfo load_timing_info
;
267 ConnectionAttempts connection_attempts
;
270 void SetUp() override
{
271 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
272 base::MessageLoop::current()->RunUntilIdle();
275 void TearDown() override
{
276 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
277 base::MessageLoop::current()->RunUntilIdle();
278 // Empty the current queue.
279 base::MessageLoop::current()->RunUntilIdle();
280 PlatformTest::TearDown();
281 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
282 base::MessageLoop::current()->RunUntilIdle();
285 const char* GetAlternateProtocolFromParam() {
287 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
290 // This is the expected return from a current server advertising SPDY.
291 std::string
GetAlternateProtocolHttpHeader() {
292 return std::string("Alternate-Protocol: 443:") +
293 GetAlternateProtocolFromParam() + "\r\n\r\n";
296 // Either |write_failure| specifies a write failure or |read_failure|
297 // specifies a read failure when using a reused socket. In either case, the
298 // failure should cause the network transaction to resend the request, and the
299 // other argument should be NULL.
300 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
301 const MockRead
* read_failure
);
303 // Either |write_failure| specifies a write failure or |read_failure|
304 // specifies a read failure when using a reused socket. In either case, the
305 // failure should cause the network transaction to resend the request, and the
306 // other argument should be NULL.
307 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
308 const MockRead
* read_failure
,
311 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
313 SimpleGetHelperResult out
;
315 HttpRequestInfo request
;
316 request
.method
= "GET";
317 request
.url
= GURL("http://www.example.org/");
318 request
.load_flags
= 0;
321 session_deps_
.net_log
= log
.bound().net_log();
322 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
323 scoped_ptr
<HttpTransaction
> trans(
324 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
326 for (size_t i
= 0; i
< data_count
; ++i
) {
327 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
330 TestCompletionCallback callback
;
332 EXPECT_TRUE(log
.bound().IsCapturing());
333 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
334 EXPECT_EQ(ERR_IO_PENDING
, rv
);
336 out
.rv
= callback
.WaitForResult();
338 // Even in the failure cases that use this function, connections are always
339 // successfully established before the error.
340 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
341 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
346 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
347 // Can't use ASSERT_* inside helper functions like this, so
349 if (response
== NULL
|| response
->headers
.get() == NULL
) {
350 out
.rv
= ERR_UNEXPECTED
;
353 out
.status_line
= response
->headers
->GetStatusLine();
355 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
356 EXPECT_EQ(80, response
->socket_address
.port());
358 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
361 TestNetLogEntry::List entries
;
362 log
.GetEntries(&entries
);
363 size_t pos
= ExpectLogContainsSomewhere(
364 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
366 ExpectLogContainsSomewhere(
368 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
372 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
373 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
375 HttpRequestHeaders request_headers
;
376 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
378 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
379 EXPECT_EQ("www.example.org", value
);
380 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
381 EXPECT_EQ("keep-alive", value
);
383 std::string response_headers
;
384 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
385 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
388 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
389 trans
->GetConnectionAttempts(&out
.connection_attempts
);
393 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
394 size_t reads_count
) {
395 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
396 StaticSocketDataProvider
* data
[] = { &reads
};
397 return SimpleGetHelperForData(data
, 1);
400 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
402 for (size_t i
= 0; i
< reads_count
; ++i
)
403 size
+= data_reads
[i
].data_len
;
407 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
408 int expected_status
);
410 void ConnectStatusHelper(const MockRead
& status
);
412 void BypassHostCacheOnRefreshHelper(int load_flags
);
414 void CheckErrorIsPassedBack(int error
, IoMode mode
);
416 SpdyTestUtil spdy_util_
;
417 SpdySessionDependencies session_deps_
;
419 // Original socket limits. Some tests set these. Safest to always restore
420 // them once each test has been run.
421 int old_max_group_sockets_
;
422 int old_max_pool_sockets_
;
425 INSTANTIATE_TEST_CASE_P(NextProto
,
426 HttpNetworkTransactionTest
,
427 testing::Values(kProtoSPDY31
,
433 class BeforeNetworkStartHandler
{
435 explicit BeforeNetworkStartHandler(bool defer
)
436 : defer_on_before_network_start_(defer
),
437 observed_before_network_start_(false) {}
439 void OnBeforeNetworkStart(bool* defer
) {
440 *defer
= defer_on_before_network_start_
;
441 observed_before_network_start_
= true;
444 bool observed_before_network_start() const {
445 return observed_before_network_start_
;
449 const bool defer_on_before_network_start_
;
450 bool observed_before_network_start_
;
452 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
455 class BeforeProxyHeadersSentHandler
{
457 BeforeProxyHeadersSentHandler()
458 : observed_before_proxy_headers_sent_(false) {}
460 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
461 HttpRequestHeaders
* request_headers
) {
462 observed_before_proxy_headers_sent_
= true;
463 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
466 bool observed_before_proxy_headers_sent() const {
467 return observed_before_proxy_headers_sent_
;
470 std::string
observed_proxy_server_uri() const {
471 return observed_proxy_server_uri_
;
475 bool observed_before_proxy_headers_sent_
;
476 std::string observed_proxy_server_uri_
;
478 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
481 // Fill |str| with a long header list that consumes >= |size| bytes.
482 void FillLargeHeadersString(std::string
* str
, int size
) {
484 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
485 const int sizeof_row
= strlen(row
);
486 const int num_rows
= static_cast<int>(
487 ceil(static_cast<float>(size
) / sizeof_row
));
488 const int sizeof_data
= num_rows
* sizeof_row
;
489 DCHECK(sizeof_data
>= size
);
490 str
->reserve(sizeof_data
);
492 for (int i
= 0; i
< num_rows
; ++i
)
493 str
->append(row
, sizeof_row
);
496 // Alternative functions that eliminate randomness and dependency on the local
497 // host name so that the generated NTLM messages are reproducible.
498 void MockGenerateRandom1(uint8
* output
, size_t n
) {
499 static const uint8 bytes
[] = {
500 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
502 static size_t current_byte
= 0;
503 for (size_t i
= 0; i
< n
; ++i
) {
504 output
[i
] = bytes
[current_byte
++];
505 current_byte
%= arraysize(bytes
);
509 void MockGenerateRandom2(uint8
* output
, size_t n
) {
510 static const uint8 bytes
[] = {
511 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
512 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
514 static size_t current_byte
= 0;
515 for (size_t i
= 0; i
< n
; ++i
) {
516 output
[i
] = bytes
[current_byte
++];
517 current_byte
%= arraysize(bytes
);
521 std::string
MockGetHostName() {
525 template<typename ParentPool
>
526 class CaptureGroupNameSocketPool
: public ParentPool
{
528 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
529 CertVerifier
* cert_verifier
);
531 const std::string
last_group_name_received() const {
532 return last_group_name_
;
535 int RequestSocket(const std::string
& group_name
,
536 const void* socket_params
,
537 RequestPriority priority
,
538 ClientSocketHandle
* handle
,
539 const CompletionCallback
& callback
,
540 const BoundNetLog
& net_log
) override
{
541 last_group_name_
= group_name
;
542 return ERR_IO_PENDING
;
544 void CancelRequest(const std::string
& group_name
,
545 ClientSocketHandle
* handle
) override
{}
546 void ReleaseSocket(const std::string
& group_name
,
547 scoped_ptr
<StreamSocket
> socket
,
549 void CloseIdleSockets() override
{}
550 int IdleSocketCount() const override
{ return 0; }
551 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
554 LoadState
GetLoadState(const std::string
& group_name
,
555 const ClientSocketHandle
* handle
) const override
{
556 return LOAD_STATE_IDLE
;
558 base::TimeDelta
ConnectionTimeout() const override
{
559 return base::TimeDelta();
563 std::string last_group_name_
;
566 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
567 CaptureGroupNameTransportSocketPool
;
568 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
569 CaptureGroupNameHttpProxySocketPool
;
570 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
571 CaptureGroupNameSOCKSSocketPool
;
572 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
573 CaptureGroupNameSSLSocketPool
;
575 template <typename ParentPool
>
576 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
577 HostResolver
* host_resolver
,
578 CertVerifier
* /* cert_verifier */)
579 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
583 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
584 HostResolver
* /* host_resolver */,
585 CertVerifier
* /* cert_verifier */)
586 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
590 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
591 HostResolver
* /* host_resolver */,
592 CertVerifier
* cert_verifier
)
593 : SSLClientSocketPool(0,
609 //-----------------------------------------------------------------------------
611 // Helper functions for validating that AuthChallengeInfo's are correctly
612 // configured for common cases.
613 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
616 EXPECT_FALSE(auth_challenge
->is_proxy
);
617 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
618 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
619 EXPECT_EQ("basic", auth_challenge
->scheme
);
623 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
626 EXPECT_TRUE(auth_challenge
->is_proxy
);
627 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
628 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
629 EXPECT_EQ("basic", auth_challenge
->scheme
);
633 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
636 EXPECT_FALSE(auth_challenge
->is_proxy
);
637 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
638 EXPECT_EQ("digestive", auth_challenge
->realm
);
639 EXPECT_EQ("digest", auth_challenge
->scheme
);
643 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
646 EXPECT_FALSE(auth_challenge
->is_proxy
);
647 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
648 EXPECT_EQ(std::string(), auth_challenge
->realm
);
649 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
655 TEST_P(HttpNetworkTransactionTest
, Basic
) {
656 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
657 scoped_ptr
<HttpTransaction
> trans(
658 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
661 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
662 MockRead data_reads
[] = {
663 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
664 MockRead("hello world"),
665 MockRead(SYNCHRONOUS
, OK
),
667 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
668 arraysize(data_reads
));
669 EXPECT_EQ(OK
, out
.rv
);
670 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
671 EXPECT_EQ("hello world", out
.response_data
);
672 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
673 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
674 EXPECT_EQ(0u, out
.connection_attempts
.size());
677 // Response with no status line.
678 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
679 MockRead data_reads
[] = {
680 MockRead("hello world"),
681 MockRead(SYNCHRONOUS
, OK
),
683 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
684 arraysize(data_reads
));
685 EXPECT_EQ(OK
, out
.rv
);
686 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
687 EXPECT_EQ("hello world", out
.response_data
);
688 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
689 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
692 // Allow up to 4 bytes of junk to precede status line.
693 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
694 MockRead data_reads
[] = {
695 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
696 MockRead(SYNCHRONOUS
, OK
),
698 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
699 arraysize(data_reads
));
700 EXPECT_EQ(OK
, out
.rv
);
701 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
702 EXPECT_EQ("DATA", out
.response_data
);
703 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
704 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
707 // Allow up to 4 bytes of junk to precede status line.
708 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
709 MockRead data_reads
[] = {
710 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
711 MockRead(SYNCHRONOUS
, OK
),
713 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
714 arraysize(data_reads
));
715 EXPECT_EQ(OK
, out
.rv
);
716 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
717 EXPECT_EQ("DATA", out
.response_data
);
718 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
719 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
722 // Beyond 4 bytes of slop and it should fail to find a status line.
723 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
724 MockRead data_reads
[] = {
725 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
726 MockRead(SYNCHRONOUS
, OK
),
728 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
729 arraysize(data_reads
));
730 EXPECT_EQ(OK
, out
.rv
);
731 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
732 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
733 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
734 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
737 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
738 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
739 MockRead data_reads
[] = {
744 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
745 MockRead(SYNCHRONOUS
, OK
),
747 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
748 arraysize(data_reads
));
749 EXPECT_EQ(OK
, out
.rv
);
750 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
751 EXPECT_EQ("DATA", out
.response_data
);
752 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
753 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
756 // Close the connection before enough bytes to have a status line.
757 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
758 MockRead data_reads
[] = {
760 MockRead(SYNCHRONOUS
, OK
),
762 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
763 arraysize(data_reads
));
764 EXPECT_EQ(OK
, out
.rv
);
765 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
766 EXPECT_EQ("HTT", out
.response_data
);
767 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
768 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
771 // Simulate a 204 response, lacking a Content-Length header, sent over a
772 // persistent connection. The response should still terminate since a 204
773 // cannot have a response body.
774 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
775 char junk
[] = "junk";
776 MockRead data_reads
[] = {
777 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
778 MockRead(junk
), // Should not be read!!
779 MockRead(SYNCHRONOUS
, OK
),
781 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
782 arraysize(data_reads
));
783 EXPECT_EQ(OK
, out
.rv
);
784 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
785 EXPECT_EQ("", out
.response_data
);
786 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
787 int64 response_size
= reads_size
- strlen(junk
);
788 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
791 // A simple request using chunked encoding with some extra data after.
792 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
793 std::string final_chunk
= "0\r\n\r\n";
794 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
795 std::string last_read
= final_chunk
+ extra_data
;
796 MockRead data_reads
[] = {
797 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
798 MockRead("5\r\nHello\r\n"),
801 MockRead("5\r\nworld\r\n"),
802 MockRead(last_read
.data()),
803 MockRead(SYNCHRONOUS
, OK
),
805 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
806 arraysize(data_reads
));
807 EXPECT_EQ(OK
, out
.rv
);
808 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
809 EXPECT_EQ("Hello world", out
.response_data
);
810 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
811 int64 response_size
= reads_size
- extra_data
.size();
812 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
815 // Next tests deal with http://crbug.com/56344.
817 TEST_P(HttpNetworkTransactionTest
,
818 MultipleContentLengthHeadersNoTransferEncoding
) {
819 MockRead data_reads
[] = {
820 MockRead("HTTP/1.1 200 OK\r\n"),
821 MockRead("Content-Length: 10\r\n"),
822 MockRead("Content-Length: 5\r\n\r\n"),
824 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
825 arraysize(data_reads
));
826 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
829 TEST_P(HttpNetworkTransactionTest
,
830 DuplicateContentLengthHeadersNoTransferEncoding
) {
831 MockRead data_reads
[] = {
832 MockRead("HTTP/1.1 200 OK\r\n"),
833 MockRead("Content-Length: 5\r\n"),
834 MockRead("Content-Length: 5\r\n\r\n"),
837 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
838 arraysize(data_reads
));
839 EXPECT_EQ(OK
, out
.rv
);
840 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
841 EXPECT_EQ("Hello", out
.response_data
);
844 TEST_P(HttpNetworkTransactionTest
,
845 ComplexContentLengthHeadersNoTransferEncoding
) {
846 // More than 2 dupes.
848 MockRead data_reads
[] = {
849 MockRead("HTTP/1.1 200 OK\r\n"),
850 MockRead("Content-Length: 5\r\n"),
851 MockRead("Content-Length: 5\r\n"),
852 MockRead("Content-Length: 5\r\n\r\n"),
855 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
856 arraysize(data_reads
));
857 EXPECT_EQ(OK
, out
.rv
);
858 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
859 EXPECT_EQ("Hello", out
.response_data
);
863 MockRead data_reads
[] = {
864 MockRead("HTTP/1.0 200 OK\r\n"),
865 MockRead("Content-Length: 5\r\n"),
866 MockRead("Content-Length: 5\r\n"),
867 MockRead("Content-Length: 5\r\n\r\n"),
870 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
871 arraysize(data_reads
));
872 EXPECT_EQ(OK
, out
.rv
);
873 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
874 EXPECT_EQ("Hello", out
.response_data
);
876 // 2 dupes and one mismatched.
878 MockRead data_reads
[] = {
879 MockRead("HTTP/1.1 200 OK\r\n"),
880 MockRead("Content-Length: 10\r\n"),
881 MockRead("Content-Length: 10\r\n"),
882 MockRead("Content-Length: 5\r\n\r\n"),
884 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
885 arraysize(data_reads
));
886 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
890 TEST_P(HttpNetworkTransactionTest
,
891 MultipleContentLengthHeadersTransferEncoding
) {
892 MockRead data_reads
[] = {
893 MockRead("HTTP/1.1 200 OK\r\n"),
894 MockRead("Content-Length: 666\r\n"),
895 MockRead("Content-Length: 1337\r\n"),
896 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
897 MockRead("5\r\nHello\r\n"),
900 MockRead("5\r\nworld\r\n"),
901 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
902 MockRead(SYNCHRONOUS
, OK
),
904 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
905 arraysize(data_reads
));
906 EXPECT_EQ(OK
, out
.rv
);
907 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
908 EXPECT_EQ("Hello world", out
.response_data
);
911 // Next tests deal with http://crbug.com/98895.
913 // Checks that a single Content-Disposition header results in no error.
914 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
915 MockRead data_reads
[] = {
916 MockRead("HTTP/1.1 200 OK\r\n"),
917 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
918 MockRead("Content-Length: 5\r\n\r\n"),
921 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
922 arraysize(data_reads
));
923 EXPECT_EQ(OK
, out
.rv
);
924 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
925 EXPECT_EQ("Hello", out
.response_data
);
928 // Checks that two identical Content-Disposition headers result in no error.
929 TEST_P(HttpNetworkTransactionTest
,
930 TwoIdenticalContentDispositionHeaders
) {
931 MockRead data_reads
[] = {
932 MockRead("HTTP/1.1 200 OK\r\n"),
933 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
934 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
935 MockRead("Content-Length: 5\r\n\r\n"),
938 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
939 arraysize(data_reads
));
940 EXPECT_EQ(OK
, out
.rv
);
941 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
942 EXPECT_EQ("Hello", out
.response_data
);
945 // Checks that two distinct Content-Disposition headers result in an error.
946 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
947 MockRead data_reads
[] = {
948 MockRead("HTTP/1.1 200 OK\r\n"),
949 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
950 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
951 MockRead("Content-Length: 5\r\n\r\n"),
954 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
955 arraysize(data_reads
));
956 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
959 // Checks that two identical Location headers result in no error.
960 // Also tests Location header behavior.
961 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
962 MockRead data_reads
[] = {
963 MockRead("HTTP/1.1 302 Redirect\r\n"),
964 MockRead("Location: http://good.com/\r\n"),
965 MockRead("Location: http://good.com/\r\n"),
966 MockRead("Content-Length: 0\r\n\r\n"),
967 MockRead(SYNCHRONOUS
, OK
),
970 HttpRequestInfo request
;
971 request
.method
= "GET";
972 request
.url
= GURL("http://redirect.com/");
973 request
.load_flags
= 0;
975 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
976 scoped_ptr
<HttpTransaction
> trans(
977 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
979 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
980 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
982 TestCompletionCallback callback
;
984 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
985 EXPECT_EQ(ERR_IO_PENDING
, rv
);
987 EXPECT_EQ(OK
, callback
.WaitForResult());
989 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
990 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
991 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
993 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
994 EXPECT_EQ("http://good.com/", url
);
995 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
998 // Checks that two distinct Location headers result in an error.
999 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
1000 MockRead data_reads
[] = {
1001 MockRead("HTTP/1.1 302 Redirect\r\n"),
1002 MockRead("Location: http://good.com/\r\n"),
1003 MockRead("Location: http://evil.com/\r\n"),
1004 MockRead("Content-Length: 0\r\n\r\n"),
1005 MockRead(SYNCHRONOUS
, OK
),
1007 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1008 arraysize(data_reads
));
1009 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1012 // Do a request using the HEAD method. Verify that we don't try to read the
1013 // message body (since HEAD has none).
1014 TEST_P(HttpNetworkTransactionTest
, Head
) {
1015 HttpRequestInfo request
;
1016 request
.method
= "HEAD";
1017 request
.url
= GURL("http://www.example.org/");
1018 request
.load_flags
= 0;
1020 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1021 scoped_ptr
<HttpTransaction
> trans(
1022 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1023 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1024 trans
->SetBeforeProxyHeadersSentCallback(
1025 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1026 base::Unretained(&proxy_headers_handler
)));
1028 MockWrite data_writes1
[] = {
1030 "HEAD / HTTP/1.1\r\n"
1031 "Host: www.example.org\r\n"
1032 "Connection: keep-alive\r\n"
1033 "Content-Length: 0\r\n\r\n"),
1035 MockRead data_reads1
[] = {
1036 MockRead("HTTP/1.1 404 Not Found\r\n"),
1037 MockRead("Server: Blah\r\n"),
1038 MockRead("Content-Length: 1234\r\n\r\n"),
1040 // No response body because the test stops reading here.
1041 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1044 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1045 data_writes1
, arraysize(data_writes1
));
1046 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1048 TestCompletionCallback callback1
;
1050 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1051 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1053 rv
= callback1
.WaitForResult();
1056 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1057 ASSERT_TRUE(response
!= NULL
);
1059 // Check that the headers got parsed.
1060 EXPECT_TRUE(response
->headers
.get() != NULL
);
1061 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1062 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1063 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1064 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1066 std::string server_header
;
1068 bool has_server_header
= response
->headers
->EnumerateHeader(
1069 &iter
, "Server", &server_header
);
1070 EXPECT_TRUE(has_server_header
);
1071 EXPECT_EQ("Blah", server_header
);
1073 // Reading should give EOF right away, since there is no message body
1074 // (despite non-zero content-length).
1075 std::string response_data
;
1076 rv
= ReadTransaction(trans
.get(), &response_data
);
1078 EXPECT_EQ("", response_data
);
1081 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1082 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1084 MockRead data_reads
[] = {
1085 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1087 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1089 MockRead(SYNCHRONOUS
, OK
),
1091 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1092 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1094 const char* const kExpectedResponseData
[] = {
1098 for (int i
= 0; i
< 2; ++i
) {
1099 HttpRequestInfo request
;
1100 request
.method
= "GET";
1101 request
.url
= GURL("http://www.example.org/");
1102 request
.load_flags
= 0;
1104 scoped_ptr
<HttpTransaction
> trans(
1105 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1107 TestCompletionCallback callback
;
1109 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1110 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1112 rv
= callback
.WaitForResult();
1115 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1116 ASSERT_TRUE(response
!= NULL
);
1118 EXPECT_TRUE(response
->headers
.get() != NULL
);
1119 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1120 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1122 std::string response_data
;
1123 rv
= ReadTransaction(trans
.get(), &response_data
);
1125 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1129 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1130 ScopedVector
<UploadElementReader
> element_readers
;
1131 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1132 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1134 HttpRequestInfo request
;
1135 request
.method
= "POST";
1136 request
.url
= GURL("http://www.foo.com/");
1137 request
.upload_data_stream
= &upload_data_stream
;
1138 request
.load_flags
= 0;
1140 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1141 scoped_ptr
<HttpTransaction
> trans(
1142 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1144 MockRead data_reads
[] = {
1145 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1146 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1147 MockRead("hello world"),
1148 MockRead(SYNCHRONOUS
, OK
),
1150 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1151 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1153 TestCompletionCallback callback
;
1155 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1156 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1158 rv
= callback
.WaitForResult();
1161 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1162 ASSERT_TRUE(response
!= NULL
);
1164 EXPECT_TRUE(response
->headers
.get() != NULL
);
1165 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1167 std::string response_data
;
1168 rv
= ReadTransaction(trans
.get(), &response_data
);
1170 EXPECT_EQ("hello world", response_data
);
1173 // This test is almost the same as Ignores100 above, but the response contains
1174 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1175 // HTTP/1.1 and the two status headers are read in one read.
1176 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1177 HttpRequestInfo request
;
1178 request
.method
= "GET";
1179 request
.url
= GURL("http://www.foo.com/");
1180 request
.load_flags
= 0;
1182 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1183 scoped_ptr
<HttpTransaction
> trans(
1184 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1186 MockRead data_reads
[] = {
1187 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1188 "HTTP/1.1 200 OK\r\n\r\n"),
1189 MockRead("hello world"),
1190 MockRead(SYNCHRONOUS
, OK
),
1192 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1193 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1195 TestCompletionCallback callback
;
1197 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1198 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1200 rv
= callback
.WaitForResult();
1203 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1204 ASSERT_TRUE(response
!= NULL
);
1206 EXPECT_TRUE(response
->headers
.get() != NULL
);
1207 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1209 std::string response_data
;
1210 rv
= ReadTransaction(trans
.get(), &response_data
);
1212 EXPECT_EQ("hello world", response_data
);
1215 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1216 HttpRequestInfo request
;
1217 request
.method
= "POST";
1218 request
.url
= GURL("http://www.foo.com/");
1219 request
.load_flags
= 0;
1221 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1222 scoped_ptr
<HttpTransaction
> trans(
1223 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1225 MockRead data_reads
[] = {
1226 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1229 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1230 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1232 TestCompletionCallback callback
;
1234 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1235 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1237 rv
= callback
.WaitForResult();
1240 std::string response_data
;
1241 rv
= ReadTransaction(trans
.get(), &response_data
);
1243 EXPECT_EQ("", response_data
);
1246 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1247 HttpRequestInfo request
;
1248 request
.method
= "POST";
1249 request
.url
= GURL("http://www.foo.com/");
1250 request
.load_flags
= 0;
1252 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1253 scoped_ptr
<HttpTransaction
> trans(
1254 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1256 MockRead data_reads
[] = {
1259 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1260 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1262 TestCompletionCallback callback
;
1264 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1265 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1267 rv
= callback
.WaitForResult();
1268 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1271 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1272 const MockWrite
* write_failure
,
1273 const MockRead
* read_failure
) {
1274 HttpRequestInfo request
;
1275 request
.method
= "GET";
1276 request
.url
= GURL("http://www.foo.com/");
1277 request
.load_flags
= 0;
1280 session_deps_
.net_log
= &net_log
;
1281 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1283 // Written data for successfully sending both requests.
1284 MockWrite data1_writes
[] = {
1285 MockWrite("GET / HTTP/1.1\r\n"
1286 "Host: www.foo.com\r\n"
1287 "Connection: keep-alive\r\n\r\n"),
1288 MockWrite("GET / HTTP/1.1\r\n"
1289 "Host: www.foo.com\r\n"
1290 "Connection: keep-alive\r\n\r\n")
1293 // Read results for the first request.
1294 MockRead data1_reads
[] = {
1295 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1297 MockRead(ASYNC
, OK
),
1300 if (write_failure
) {
1301 ASSERT_FALSE(read_failure
);
1302 data1_writes
[1] = *write_failure
;
1304 ASSERT_TRUE(read_failure
);
1305 data1_reads
[2] = *read_failure
;
1308 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1309 data1_writes
, arraysize(data1_writes
));
1310 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1312 MockRead data2_reads
[] = {
1313 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1315 MockRead(ASYNC
, OK
),
1317 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1318 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1320 const char* const kExpectedResponseData
[] = {
1324 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1325 for (int i
= 0; i
< 2; ++i
) {
1326 TestCompletionCallback callback
;
1328 scoped_ptr
<HttpTransaction
> trans(
1329 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1331 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1332 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1334 rv
= callback
.WaitForResult();
1337 LoadTimingInfo load_timing_info
;
1338 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1339 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1341 first_socket_log_id
= load_timing_info
.socket_log_id
;
1343 // The second request should be using a new socket.
1344 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1347 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1348 ASSERT_TRUE(response
!= NULL
);
1350 EXPECT_TRUE(response
->headers
.get() != NULL
);
1351 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1353 std::string response_data
;
1354 rv
= ReadTransaction(trans
.get(), &response_data
);
1356 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1360 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1361 const MockWrite
* write_failure
,
1362 const MockRead
* read_failure
,
1364 HttpRequestInfo request
;
1365 request
.method
= "GET";
1366 request
.url
= GURL("https://www.foo.com/");
1367 request
.load_flags
= 0;
1370 session_deps_
.net_log
= &net_log
;
1371 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1373 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1374 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1376 ssl1
.SetNextProto(GetParam());
1377 ssl2
.SetNextProto(GetParam());
1379 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1380 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1382 // SPDY versions of the request and response.
1383 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1384 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1385 scoped_ptr
<SpdyFrame
> spdy_response(
1386 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1387 scoped_ptr
<SpdyFrame
> spdy_data(
1388 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1390 // HTTP/1.1 versions of the request and response.
1391 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1392 "Host: www.foo.com\r\n"
1393 "Connection: keep-alive\r\n\r\n";
1394 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1395 const char kHttpData
[] = "hello";
1397 std::vector
<MockRead
> data1_reads
;
1398 std::vector
<MockWrite
> data1_writes
;
1399 if (write_failure
) {
1400 ASSERT_FALSE(read_failure
);
1401 data1_writes
.push_back(*write_failure
);
1402 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1404 ASSERT_TRUE(read_failure
);
1406 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1408 data1_writes
.push_back(MockWrite(kHttpRequest
));
1410 data1_reads
.push_back(*read_failure
);
1413 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1414 &data1_writes
[0], data1_writes
.size());
1415 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1417 std::vector
<MockRead
> data2_reads
;
1418 std::vector
<MockWrite
> data2_writes
;
1421 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1423 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1424 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1425 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1427 data2_writes
.push_back(
1428 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1430 data2_reads
.push_back(
1431 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1432 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1433 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1435 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1436 &data2_writes
[0], data2_writes
.size());
1437 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1439 // Preconnect a socket.
1440 SSLConfig ssl_config
;
1441 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1442 session
->GetNextProtos(&ssl_config
.next_protos
);
1443 session
->http_stream_factory()->PreconnectStreams(
1444 1, request
, DEFAULT_PRIORITY
, ssl_config
, ssl_config
);
1445 // Wait for the preconnect to complete.
1446 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1447 base::RunLoop().RunUntilIdle();
1448 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1450 // Make the request.
1451 TestCompletionCallback callback
;
1453 scoped_ptr
<HttpTransaction
> trans(
1454 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1456 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1457 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1459 rv
= callback
.WaitForResult();
1462 LoadTimingInfo load_timing_info
;
1463 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1464 TestLoadTimingNotReused(
1466 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1468 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1469 ASSERT_TRUE(response
!= NULL
);
1471 EXPECT_TRUE(response
->headers
.get() != NULL
);
1472 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1474 std::string response_data
;
1475 rv
= ReadTransaction(trans
.get(), &response_data
);
1477 EXPECT_EQ(kHttpData
, response_data
);
1480 TEST_P(HttpNetworkTransactionTest
,
1481 KeepAliveConnectionNotConnectedOnWrite
) {
1482 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1483 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1486 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1487 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1488 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1491 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1492 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1493 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1496 // Make sure that on a 408 response (Request Timeout), the request is retried,
1497 // if the socket was a reused keep alive socket.
1498 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1499 MockRead
read_failure(SYNCHRONOUS
,
1500 "HTTP/1.1 408 Request Timeout\r\n"
1501 "Connection: Keep-Alive\r\n"
1502 "Content-Length: 6\r\n\r\n"
1504 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1507 TEST_P(HttpNetworkTransactionTest
,
1508 PreconnectErrorNotConnectedOnWrite
) {
1509 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1510 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1513 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1514 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1515 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1518 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1519 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1520 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1523 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1524 MockRead
read_failure(ASYNC
, OK
); // EOF
1525 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1528 // Make sure that on a 408 response (Request Timeout), the request is retried,
1529 // if the socket was a preconnected (UNUSED_IDLE) socket.
1530 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1531 MockRead
read_failure(SYNCHRONOUS
,
1532 "HTTP/1.1 408 Request Timeout\r\n"
1533 "Connection: Keep-Alive\r\n"
1534 "Content-Length: 6\r\n\r\n"
1536 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1537 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1540 TEST_P(HttpNetworkTransactionTest
,
1541 SpdyPreconnectErrorNotConnectedOnWrite
) {
1542 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1543 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1546 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1547 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1548 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1551 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1552 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1553 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1556 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1557 MockRead
read_failure(ASYNC
, OK
); // EOF
1558 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1561 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1562 HttpRequestInfo request
;
1563 request
.method
= "GET";
1564 request
.url
= GURL("http://www.example.org/");
1565 request
.load_flags
= 0;
1567 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1568 scoped_ptr
<HttpTransaction
> trans(
1569 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1571 MockRead data_reads
[] = {
1572 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1573 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1574 MockRead("hello world"),
1575 MockRead(SYNCHRONOUS
, OK
),
1577 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1578 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1580 TestCompletionCallback callback
;
1582 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1583 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1585 rv
= callback
.WaitForResult();
1586 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1589 // What do various browsers do when the server closes a non-keepalive
1590 // connection without sending any response header or body?
1593 // Safari 3.1.2 (Windows): error page
1594 // Firefox 3.0.1: blank page
1595 // Opera 9.52: after five attempts, blank page
1596 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1597 // Us: error page (EMPTY_RESPONSE)
1598 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1599 MockRead data_reads
[] = {
1600 MockRead(SYNCHRONOUS
, OK
), // EOF
1601 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1602 MockRead("hello world"),
1603 MockRead(SYNCHRONOUS
, OK
),
1605 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1606 arraysize(data_reads
));
1607 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1610 // Test that network access can be deferred and resumed.
1611 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1612 HttpRequestInfo request
;
1613 request
.method
= "GET";
1614 request
.url
= GURL("http://www.example.org/");
1615 request
.load_flags
= 0;
1617 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1618 scoped_ptr
<HttpTransaction
> trans(
1619 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1621 // Defer on OnBeforeNetworkStart.
1622 BeforeNetworkStartHandler
net_start_handler(true); // defer
1623 trans
->SetBeforeNetworkStartCallback(
1624 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1625 base::Unretained(&net_start_handler
)));
1627 MockRead data_reads
[] = {
1628 MockRead("HTTP/1.0 200 OK\r\n"),
1629 MockRead("Content-Length: 5\r\n\r\n"),
1631 MockRead(SYNCHRONOUS
, 0),
1633 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1634 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1636 TestCompletionCallback callback
;
1638 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1640 base::MessageLoop::current()->RunUntilIdle();
1642 // Should have deferred for network start.
1643 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1644 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1646 trans
->ResumeNetworkStart();
1647 rv
= callback
.WaitForResult();
1649 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1651 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1652 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1653 if (rv
== ERR_IO_PENDING
)
1654 rv
= callback
.WaitForResult();
1659 // Test that network use can be deferred and canceled.
1660 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1661 HttpRequestInfo request
;
1662 request
.method
= "GET";
1663 request
.url
= GURL("http://www.example.org/");
1664 request
.load_flags
= 0;
1666 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1667 scoped_ptr
<HttpTransaction
> trans(
1668 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1670 // Defer on OnBeforeNetworkStart.
1671 BeforeNetworkStartHandler
net_start_handler(true); // defer
1672 trans
->SetBeforeNetworkStartCallback(
1673 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1674 base::Unretained(&net_start_handler
)));
1676 TestCompletionCallback callback
;
1678 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1679 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1680 base::MessageLoop::current()->RunUntilIdle();
1682 // Should have deferred for network start.
1683 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1684 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1687 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1688 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1689 // destructor in such situations.
1690 // See http://crbug.com/154712 and http://crbug.com/156609.
1691 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1692 HttpRequestInfo request
;
1693 request
.method
= "GET";
1694 request
.url
= GURL("http://www.example.org/");
1695 request
.load_flags
= 0;
1697 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1698 scoped_ptr
<HttpTransaction
> trans(
1699 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1701 MockRead data_reads
[] = {
1702 MockRead("HTTP/1.0 200 OK\r\n"),
1703 MockRead("Connection: keep-alive\r\n"),
1704 MockRead("Content-Length: 100\r\n\r\n"),
1706 MockRead(SYNCHRONOUS
, 0),
1708 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1709 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1711 TestCompletionCallback callback
;
1713 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1714 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1716 rv
= callback
.WaitForResult();
1719 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1720 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1721 if (rv
== ERR_IO_PENDING
)
1722 rv
= callback
.WaitForResult();
1724 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1725 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1728 base::MessageLoop::current()->RunUntilIdle();
1729 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1732 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1733 HttpRequestInfo request
;
1734 request
.method
= "GET";
1735 request
.url
= GURL("http://www.example.org/");
1736 request
.load_flags
= 0;
1738 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1739 scoped_ptr
<HttpTransaction
> trans(
1740 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1742 MockRead data_reads
[] = {
1743 MockRead("HTTP/1.0 200 OK\r\n"),
1744 MockRead("Connection: keep-alive\r\n"),
1745 MockRead("Content-Length: 100\r\n\r\n"),
1746 MockRead(SYNCHRONOUS
, 0),
1748 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1749 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1751 TestCompletionCallback callback
;
1753 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1754 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1756 rv
= callback
.WaitForResult();
1759 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1760 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1761 if (rv
== ERR_IO_PENDING
)
1762 rv
= callback
.WaitForResult();
1763 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1766 base::MessageLoop::current()->RunUntilIdle();
1767 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1770 // Test that we correctly reuse a keep-alive connection after not explicitly
1771 // reading the body.
1772 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1773 HttpRequestInfo request
;
1774 request
.method
= "GET";
1775 request
.url
= GURL("http://www.foo.com/");
1776 request
.load_flags
= 0;
1779 session_deps_
.net_log
= &net_log
;
1780 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1782 // Note that because all these reads happen in the same
1783 // StaticSocketDataProvider, it shows that the same socket is being reused for
1784 // all transactions.
1785 MockRead data1_reads
[] = {
1786 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1787 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1788 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1789 MockRead("HTTP/1.1 302 Found\r\n"
1790 "Content-Length: 0\r\n\r\n"),
1791 MockRead("HTTP/1.1 302 Found\r\n"
1792 "Content-Length: 5\r\n\r\n"
1794 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1795 "Content-Length: 0\r\n\r\n"),
1796 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1797 "Content-Length: 5\r\n\r\n"
1799 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1802 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1803 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1805 MockRead data2_reads
[] = {
1806 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1808 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1809 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1811 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1812 std::string response_lines
[kNumUnreadBodies
];
1814 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1815 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1816 TestCompletionCallback callback
;
1818 scoped_ptr
<HttpTransaction
> trans(
1819 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1821 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1822 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1824 rv
= callback
.WaitForResult();
1827 LoadTimingInfo load_timing_info
;
1828 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1830 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1831 first_socket_log_id
= load_timing_info
.socket_log_id
;
1833 TestLoadTimingReused(load_timing_info
);
1834 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1837 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1838 ASSERT_TRUE(response
!= NULL
);
1840 ASSERT_TRUE(response
->headers
.get() != NULL
);
1841 response_lines
[i
] = response
->headers
->GetStatusLine();
1843 // We intentionally don't read the response bodies.
1846 const char* const kStatusLines
[] = {
1847 "HTTP/1.1 204 No Content",
1848 "HTTP/1.1 205 Reset Content",
1849 "HTTP/1.1 304 Not Modified",
1850 "HTTP/1.1 302 Found",
1851 "HTTP/1.1 302 Found",
1852 "HTTP/1.1 301 Moved Permanently",
1853 "HTTP/1.1 301 Moved Permanently",
1856 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1857 "forgot to update kStatusLines");
1859 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1860 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1862 TestCompletionCallback callback
;
1863 scoped_ptr
<HttpTransaction
> trans(
1864 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1865 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1866 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1867 rv
= callback
.WaitForResult();
1869 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1870 ASSERT_TRUE(response
!= NULL
);
1871 ASSERT_TRUE(response
->headers
.get() != NULL
);
1872 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1873 std::string response_data
;
1874 rv
= ReadTransaction(trans
.get(), &response_data
);
1876 EXPECT_EQ("hello", response_data
);
1879 // Test the request-challenge-retry sequence for basic auth.
1880 // (basic auth is the easiest to mock, because it has no randomness).
1881 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1882 HttpRequestInfo request
;
1883 request
.method
= "GET";
1884 request
.url
= GURL("http://www.example.org/");
1885 request
.load_flags
= 0;
1888 session_deps_
.net_log
= &log
;
1889 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1890 scoped_ptr
<HttpTransaction
> trans(
1891 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1893 MockWrite data_writes1
[] = {
1895 "GET / HTTP/1.1\r\n"
1896 "Host: www.example.org\r\n"
1897 "Connection: keep-alive\r\n\r\n"),
1900 MockRead data_reads1
[] = {
1901 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1902 // Give a couple authenticate options (only the middle one is actually
1904 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1905 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1906 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1907 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1908 // Large content-length -- won't matter, as connection will be reset.
1909 MockRead("Content-Length: 10000\r\n\r\n"),
1910 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1913 // After calling trans->RestartWithAuth(), this is the request we should
1914 // be issuing -- the final header line contains the credentials.
1915 MockWrite data_writes2
[] = {
1917 "GET / HTTP/1.1\r\n"
1918 "Host: www.example.org\r\n"
1919 "Connection: keep-alive\r\n"
1920 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1923 // Lastly, the server responds with the actual content.
1924 MockRead data_reads2
[] = {
1925 MockRead("HTTP/1.0 200 OK\r\n"),
1926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1927 MockRead("Content-Length: 100\r\n\r\n"),
1928 MockRead(SYNCHRONOUS
, OK
),
1931 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1932 data_writes1
, arraysize(data_writes1
));
1933 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1934 data_writes2
, arraysize(data_writes2
));
1935 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1936 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1938 TestCompletionCallback callback1
;
1940 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1943 rv
= callback1
.WaitForResult();
1946 LoadTimingInfo load_timing_info1
;
1947 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1948 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1950 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1951 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1953 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1954 ASSERT_TRUE(response
!= NULL
);
1955 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1957 TestCompletionCallback callback2
;
1959 rv
= trans
->RestartWithAuth(
1960 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1961 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1963 rv
= callback2
.WaitForResult();
1966 LoadTimingInfo load_timing_info2
;
1967 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1968 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1969 // The load timing after restart should have a new socket ID, and times after
1970 // those of the first load timing.
1971 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1972 load_timing_info2
.connect_timing
.connect_start
);
1973 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1975 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1976 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1978 response
= trans
->GetResponseInfo();
1979 ASSERT_TRUE(response
!= NULL
);
1980 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1981 EXPECT_EQ(100, response
->headers
->GetContentLength());
1984 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1985 HttpRequestInfo request
;
1986 request
.method
= "GET";
1987 request
.url
= GURL("http://www.example.org/");
1988 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1990 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1991 scoped_ptr
<HttpTransaction
> trans(
1992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1994 MockWrite data_writes
[] = {
1996 "GET / HTTP/1.1\r\n"
1997 "Host: www.example.org\r\n"
1998 "Connection: keep-alive\r\n\r\n"),
2001 MockRead data_reads
[] = {
2002 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2003 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2004 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2005 // Large content-length -- won't matter, as connection will be reset.
2006 MockRead("Content-Length: 10000\r\n\r\n"),
2007 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2010 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2011 data_writes
, arraysize(data_writes
));
2012 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2013 TestCompletionCallback callback
;
2015 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2016 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2018 rv
= callback
.WaitForResult();
2021 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2022 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2024 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2025 ASSERT_TRUE(response
!= NULL
);
2026 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2029 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2031 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2032 HttpRequestInfo request
;
2033 request
.method
= "GET";
2034 request
.url
= GURL("http://www.example.org/");
2035 request
.load_flags
= 0;
2038 session_deps_
.net_log
= &log
;
2039 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2041 MockWrite data_writes1
[] = {
2043 "GET / HTTP/1.1\r\n"
2044 "Host: www.example.org\r\n"
2045 "Connection: keep-alive\r\n\r\n"),
2047 // After calling trans->RestartWithAuth(), this is the request we should
2048 // be issuing -- the final header line contains the credentials.
2050 "GET / HTTP/1.1\r\n"
2051 "Host: www.example.org\r\n"
2052 "Connection: keep-alive\r\n"
2053 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2056 MockRead data_reads1
[] = {
2057 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2058 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2059 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2060 MockRead("Content-Length: 14\r\n\r\n"),
2061 MockRead("Unauthorized\r\n"),
2063 // Lastly, the server responds with the actual content.
2064 MockRead("HTTP/1.1 200 OK\r\n"),
2065 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2066 MockRead("Content-Length: 5\r\n\r\n"),
2070 // If there is a regression where we disconnect a Keep-Alive
2071 // connection during an auth roundtrip, we'll end up reading this.
2072 MockRead data_reads2
[] = {
2073 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2076 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2077 data_writes1
, arraysize(data_writes1
));
2078 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2080 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2081 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2083 TestCompletionCallback callback1
;
2085 scoped_ptr
<HttpTransaction
> trans(
2086 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2087 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2088 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2090 rv
= callback1
.WaitForResult();
2093 LoadTimingInfo load_timing_info1
;
2094 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2095 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2097 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2098 ASSERT_TRUE(response
!= NULL
);
2099 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2101 TestCompletionCallback callback2
;
2103 rv
= trans
->RestartWithAuth(
2104 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2105 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2107 rv
= callback2
.WaitForResult();
2110 LoadTimingInfo load_timing_info2
;
2111 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2112 TestLoadTimingReused(load_timing_info2
);
2113 // The load timing after restart should have the same socket ID, and times
2114 // those of the first load timing.
2115 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2116 load_timing_info2
.send_start
);
2117 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2119 response
= trans
->GetResponseInfo();
2120 ASSERT_TRUE(response
!= NULL
);
2121 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2122 EXPECT_EQ(5, response
->headers
->GetContentLength());
2124 std::string response_data
;
2125 rv
= ReadTransaction(trans
.get(), &response_data
);
2127 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2128 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2131 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2132 // connection and with no response body to drain.
2133 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2134 HttpRequestInfo request
;
2135 request
.method
= "GET";
2136 request
.url
= GURL("http://www.example.org/");
2137 request
.load_flags
= 0;
2139 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2141 MockWrite data_writes1
[] = {
2143 "GET / HTTP/1.1\r\n"
2144 "Host: www.example.org\r\n"
2145 "Connection: keep-alive\r\n\r\n"),
2147 // After calling trans->RestartWithAuth(), this is the request we should
2148 // be issuing -- the final header line contains the credentials.
2150 "GET / HTTP/1.1\r\n"
2151 "Host: www.example.org\r\n"
2152 "Connection: keep-alive\r\n"
2153 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2156 MockRead data_reads1
[] = {
2157 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2158 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2159 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2161 // Lastly, the server responds with the actual content.
2162 MockRead("HTTP/1.1 200 OK\r\n"),
2163 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2164 MockRead("Content-Length: 5\r\n\r\n"),
2168 // An incorrect reconnect would cause this to be read.
2169 MockRead data_reads2
[] = {
2170 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2173 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2174 data_writes1
, arraysize(data_writes1
));
2175 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2177 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2178 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2180 TestCompletionCallback callback1
;
2182 scoped_ptr
<HttpTransaction
> trans(
2183 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2184 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2185 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2187 rv
= callback1
.WaitForResult();
2190 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2191 ASSERT_TRUE(response
!= NULL
);
2192 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2194 TestCompletionCallback callback2
;
2196 rv
= trans
->RestartWithAuth(
2197 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2198 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2200 rv
= callback2
.WaitForResult();
2203 response
= trans
->GetResponseInfo();
2204 ASSERT_TRUE(response
!= NULL
);
2205 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2206 EXPECT_EQ(5, response
->headers
->GetContentLength());
2209 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2210 // connection and with a large response body to drain.
2211 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2212 HttpRequestInfo request
;
2213 request
.method
= "GET";
2214 request
.url
= GURL("http://www.example.org/");
2215 request
.load_flags
= 0;
2217 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2219 MockWrite data_writes1
[] = {
2221 "GET / HTTP/1.1\r\n"
2222 "Host: www.example.org\r\n"
2223 "Connection: keep-alive\r\n\r\n"),
2225 // After calling trans->RestartWithAuth(), this is the request we should
2226 // be issuing -- the final header line contains the credentials.
2228 "GET / HTTP/1.1\r\n"
2229 "Host: www.example.org\r\n"
2230 "Connection: keep-alive\r\n"
2231 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2234 // Respond with 5 kb of response body.
2235 std::string
large_body_string("Unauthorized");
2236 large_body_string
.append(5 * 1024, ' ');
2237 large_body_string
.append("\r\n");
2239 MockRead data_reads1
[] = {
2240 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2241 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2242 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2243 // 5134 = 12 + 5 * 1024 + 2
2244 MockRead("Content-Length: 5134\r\n\r\n"),
2245 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2247 // Lastly, the server responds with the actual content.
2248 MockRead("HTTP/1.1 200 OK\r\n"),
2249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2250 MockRead("Content-Length: 5\r\n\r\n"),
2254 // An incorrect reconnect would cause this to be read.
2255 MockRead data_reads2
[] = {
2256 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2259 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2260 data_writes1
, arraysize(data_writes1
));
2261 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2263 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2264 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2266 TestCompletionCallback callback1
;
2268 scoped_ptr
<HttpTransaction
> trans(
2269 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2270 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2271 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2273 rv
= callback1
.WaitForResult();
2276 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2277 ASSERT_TRUE(response
!= NULL
);
2278 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2280 TestCompletionCallback callback2
;
2282 rv
= trans
->RestartWithAuth(
2283 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2284 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2286 rv
= callback2
.WaitForResult();
2289 response
= trans
->GetResponseInfo();
2290 ASSERT_TRUE(response
!= NULL
);
2291 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2292 EXPECT_EQ(5, response
->headers
->GetContentLength());
2295 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2296 // connection, but the server gets impatient and closes the connection.
2297 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2298 HttpRequestInfo request
;
2299 request
.method
= "GET";
2300 request
.url
= GURL("http://www.example.org/");
2301 request
.load_flags
= 0;
2303 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2305 MockWrite data_writes1
[] = {
2307 "GET / HTTP/1.1\r\n"
2308 "Host: www.example.org\r\n"
2309 "Connection: keep-alive\r\n\r\n"),
2310 // This simulates the seemingly successful write to a closed connection
2311 // if the bug is not fixed.
2313 "GET / HTTP/1.1\r\n"
2314 "Host: www.example.org\r\n"
2315 "Connection: keep-alive\r\n"
2316 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2319 MockRead data_reads1
[] = {
2320 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2321 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2322 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2323 MockRead("Content-Length: 14\r\n\r\n"),
2324 // Tell MockTCPClientSocket to simulate the server closing the connection.
2325 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2326 MockRead("Unauthorized\r\n"),
2327 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2330 // After calling trans->RestartWithAuth(), this is the request we should
2331 // be issuing -- the final header line contains the credentials.
2332 MockWrite data_writes2
[] = {
2334 "GET / HTTP/1.1\r\n"
2335 "Host: www.example.org\r\n"
2336 "Connection: keep-alive\r\n"
2337 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2340 // Lastly, the server responds with the actual content.
2341 MockRead data_reads2
[] = {
2342 MockRead("HTTP/1.1 200 OK\r\n"),
2343 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2344 MockRead("Content-Length: 5\r\n\r\n"),
2348 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2349 data_writes1
, arraysize(data_writes1
));
2350 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2351 data_writes2
, arraysize(data_writes2
));
2352 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2353 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2355 TestCompletionCallback callback1
;
2357 scoped_ptr
<HttpTransaction
> trans(
2358 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2359 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2360 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2362 rv
= callback1
.WaitForResult();
2365 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2366 ASSERT_TRUE(response
!= NULL
);
2367 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2369 TestCompletionCallback callback2
;
2371 rv
= trans
->RestartWithAuth(
2372 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2373 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2375 rv
= callback2
.WaitForResult();
2378 response
= trans
->GetResponseInfo();
2379 ASSERT_TRUE(response
!= NULL
);
2380 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2381 EXPECT_EQ(5, response
->headers
->GetContentLength());
2384 // Test the request-challenge-retry sequence for basic auth, over a connection
2385 // that requires a restart when setting up an SSL tunnel.
2386 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2387 HttpRequestInfo request
;
2388 request
.method
= "GET";
2389 request
.url
= GURL("https://www.example.org/");
2390 // when the no authentication data flag is set.
2391 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2393 // Configure against proxy server "myproxy:70".
2394 session_deps_
.proxy_service
.reset(
2395 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2396 BoundTestNetLog log
;
2397 session_deps_
.net_log
= log
.bound().net_log();
2398 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2400 // Since we have proxy, should try to establish tunnel.
2401 MockWrite data_writes1
[] = {
2403 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2404 "Host: www.example.org\r\n"
2405 "Proxy-Connection: keep-alive\r\n\r\n"),
2407 // After calling trans->RestartWithAuth(), this is the request we should
2408 // be issuing -- the final header line contains the credentials.
2410 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2411 "Host: www.example.org\r\n"
2412 "Proxy-Connection: keep-alive\r\n"
2413 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2416 "GET / HTTP/1.1\r\n"
2417 "Host: www.example.org\r\n"
2418 "Connection: keep-alive\r\n\r\n"),
2421 // The proxy responds to the connect with a 407, using a persistent
2423 MockRead data_reads1
[] = {
2425 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2426 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2428 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2430 MockRead("HTTP/1.1 200 OK\r\n"),
2431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2432 MockRead("Content-Length: 5\r\n\r\n"),
2433 MockRead(SYNCHRONOUS
, "hello"),
2436 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2437 data_writes1
, arraysize(data_writes1
));
2438 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2439 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2440 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2442 TestCompletionCallback callback1
;
2444 scoped_ptr
<HttpTransaction
> trans(
2445 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2447 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2448 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2450 rv
= callback1
.WaitForResult();
2452 TestNetLogEntry::List entries
;
2453 log
.GetEntries(&entries
);
2454 size_t pos
= ExpectLogContainsSomewhere(
2455 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2456 NetLog::PHASE_NONE
);
2457 ExpectLogContainsSomewhere(
2458 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2459 NetLog::PHASE_NONE
);
2461 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2462 ASSERT_TRUE(response
!= NULL
);
2463 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2464 ASSERT_FALSE(response
->headers
.get() == NULL
);
2465 EXPECT_EQ(407, response
->headers
->response_code());
2466 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2467 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2469 LoadTimingInfo load_timing_info
;
2470 // CONNECT requests and responses are handled at the connect job level, so
2471 // the transaction does not yet have a connection.
2472 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2474 TestCompletionCallback callback2
;
2477 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2478 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2480 rv
= callback2
.WaitForResult();
2483 response
= trans
->GetResponseInfo();
2484 ASSERT_TRUE(response
!= NULL
);
2486 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2487 EXPECT_EQ(200, response
->headers
->response_code());
2488 EXPECT_EQ(5, response
->headers
->GetContentLength());
2489 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2491 // The password prompt info should not be set.
2492 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2494 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2495 TestLoadTimingNotReusedWithPac(load_timing_info
,
2496 CONNECT_TIMING_HAS_SSL_TIMES
);
2499 session
->CloseAllConnections();
2502 // Test the request-challenge-retry sequence for basic auth, over a connection
2503 // that requires a restart when setting up an SSL tunnel.
2504 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2505 HttpRequestInfo request
;
2506 request
.method
= "GET";
2507 request
.url
= GURL("https://www.example.org/");
2508 // when the no authentication data flag is set.
2509 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2511 // Configure against proxy server "myproxy:70".
2512 session_deps_
.proxy_service
.reset(
2513 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2514 BoundTestNetLog log
;
2515 session_deps_
.net_log
= log
.bound().net_log();
2516 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2518 // Since we have proxy, should try to establish tunnel.
2519 MockWrite data_writes1
[] = {
2521 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2522 "Host: www.example.org\r\n"
2523 "Proxy-Connection: keep-alive\r\n\r\n"),
2525 // After calling trans->RestartWithAuth(), this is the request we should
2526 // be issuing -- the final header line contains the credentials.
2528 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2529 "Host: www.example.org\r\n"
2530 "Proxy-Connection: keep-alive\r\n"
2531 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2534 "GET / HTTP/1.1\r\n"
2535 "Host: www.example.org\r\n"
2536 "Connection: keep-alive\r\n\r\n"),
2539 // The proxy responds to the connect with a 407, using a persistent
2541 MockRead data_reads1
[] = {
2543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2544 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2545 MockRead("Proxy-Connection: close\r\n\r\n"),
2547 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2549 MockRead("HTTP/1.1 200 OK\r\n"),
2550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2551 MockRead("Content-Length: 5\r\n\r\n"),
2552 MockRead(SYNCHRONOUS
, "hello"),
2555 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2556 data_writes1
, arraysize(data_writes1
));
2557 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2558 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2559 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2561 TestCompletionCallback callback1
;
2563 scoped_ptr
<HttpTransaction
> trans(
2564 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2566 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2567 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2569 rv
= callback1
.WaitForResult();
2571 TestNetLogEntry::List entries
;
2572 log
.GetEntries(&entries
);
2573 size_t pos
= ExpectLogContainsSomewhere(
2574 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2575 NetLog::PHASE_NONE
);
2576 ExpectLogContainsSomewhere(
2578 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2579 NetLog::PHASE_NONE
);
2581 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2582 ASSERT_TRUE(response
!= NULL
);
2583 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2584 ASSERT_FALSE(response
->headers
.get() == NULL
);
2585 EXPECT_EQ(407, response
->headers
->response_code());
2586 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2587 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2589 LoadTimingInfo load_timing_info
;
2590 // CONNECT requests and responses are handled at the connect job level, so
2591 // the transaction does not yet have a connection.
2592 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2594 TestCompletionCallback callback2
;
2596 rv
= trans
->RestartWithAuth(
2597 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2598 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2600 rv
= callback2
.WaitForResult();
2603 response
= trans
->GetResponseInfo();
2604 ASSERT_TRUE(response
!= NULL
);
2606 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2607 EXPECT_EQ(200, response
->headers
->response_code());
2608 EXPECT_EQ(5, response
->headers
->GetContentLength());
2609 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2611 // The password prompt info should not be set.
2612 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2614 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2615 TestLoadTimingNotReusedWithPac(load_timing_info
,
2616 CONNECT_TIMING_HAS_SSL_TIMES
);
2619 session
->CloseAllConnections();
2622 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2623 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2624 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2625 HttpRequestInfo request
;
2626 request
.method
= "GET";
2627 request
.url
= GURL("https://www.example.org/");
2628 // Ensure that proxy authentication is attempted even
2629 // when the no authentication data flag is set.
2630 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2632 // Configure against proxy server "myproxy:70".
2633 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2634 BoundTestNetLog log
;
2635 session_deps_
.net_log
= log
.bound().net_log();
2636 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2638 scoped_ptr
<HttpTransaction
> trans(
2639 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2641 // Since we have proxy, should try to establish tunnel.
2642 MockWrite data_writes1
[] = {
2644 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2645 "Host: www.example.org\r\n"
2646 "Proxy-Connection: keep-alive\r\n\r\n"),
2648 // After calling trans->RestartWithAuth(), this is the request we should
2649 // be issuing -- the final header line contains the credentials.
2651 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2652 "Host: www.example.org\r\n"
2653 "Proxy-Connection: keep-alive\r\n"
2654 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2657 // The proxy responds to the connect with a 407, using a persistent
2658 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2659 MockRead data_reads1
[] = {
2661 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2662 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2663 MockRead("Proxy-Connection: keep-alive\r\n"),
2664 MockRead("Content-Length: 10\r\n\r\n"),
2665 MockRead("0123456789"),
2667 // Wrong credentials (wrong password).
2668 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2669 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2670 MockRead("Proxy-Connection: keep-alive\r\n"),
2671 MockRead("Content-Length: 10\r\n\r\n"),
2672 // No response body because the test stops reading here.
2673 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2676 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2677 data_writes1
, arraysize(data_writes1
));
2678 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2680 TestCompletionCallback callback1
;
2682 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2683 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2685 rv
= callback1
.WaitForResult();
2687 TestNetLogEntry::List entries
;
2688 log
.GetEntries(&entries
);
2689 size_t pos
= ExpectLogContainsSomewhere(
2690 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2691 NetLog::PHASE_NONE
);
2692 ExpectLogContainsSomewhere(
2693 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2694 NetLog::PHASE_NONE
);
2696 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2697 ASSERT_TRUE(response
);
2698 ASSERT_TRUE(response
->headers
);
2699 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2700 EXPECT_EQ(407, response
->headers
->response_code());
2701 EXPECT_EQ(10, response
->headers
->GetContentLength());
2702 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2703 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2705 TestCompletionCallback callback2
;
2707 // Wrong password (should be "bar").
2709 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2710 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2712 rv
= callback2
.WaitForResult();
2715 response
= trans
->GetResponseInfo();
2716 ASSERT_TRUE(response
);
2717 ASSERT_TRUE(response
->headers
);
2718 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2719 EXPECT_EQ(407, response
->headers
->response_code());
2720 EXPECT_EQ(10, response
->headers
->GetContentLength());
2721 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2722 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2724 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2726 session
->CloseAllConnections();
2729 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2730 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2731 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2732 HttpRequestInfo request
;
2733 request
.method
= "GET";
2734 request
.url
= GURL("https://www.example.org/");
2735 // Ensure that proxy authentication is attempted even
2736 // when the no authentication data flag is set.
2737 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2739 // Configure against proxy server "myproxy:70".
2740 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2741 BoundTestNetLog log
;
2742 session_deps_
.net_log
= log
.bound().net_log();
2743 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2745 scoped_ptr
<HttpTransaction
> trans(
2746 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2748 // Since we have proxy, should try to establish tunnel.
2749 MockWrite data_writes1
[] = {
2751 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2752 "Host: www.example.org\r\n"
2753 "Proxy-Connection: keep-alive\r\n\r\n"),
2755 // After calling trans->RestartWithAuth(), this is the request we should
2756 // be issuing -- the final header line contains the credentials.
2758 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2759 "Host: www.example.org\r\n"
2760 "Proxy-Connection: keep-alive\r\n"
2761 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2764 // The proxy responds to the connect with a 407, using a persistent
2766 MockRead data_reads1
[] = {
2768 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2769 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2770 MockRead("Content-Length: 10\r\n\r\n"),
2771 MockRead("0123456789"),
2773 // Wrong credentials (wrong password).
2774 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2775 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2776 MockRead("Content-Length: 10\r\n\r\n"),
2777 // No response body because the test stops reading here.
2778 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2781 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2782 data_writes1
, arraysize(data_writes1
));
2783 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2785 TestCompletionCallback callback1
;
2787 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2790 rv
= callback1
.WaitForResult();
2792 TestNetLogEntry::List entries
;
2793 log
.GetEntries(&entries
);
2794 size_t pos
= ExpectLogContainsSomewhere(
2795 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2796 NetLog::PHASE_NONE
);
2797 ExpectLogContainsSomewhere(
2799 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2800 NetLog::PHASE_NONE
);
2802 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2803 ASSERT_TRUE(response
);
2804 ASSERT_TRUE(response
->headers
);
2805 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2806 EXPECT_EQ(407, response
->headers
->response_code());
2807 EXPECT_EQ(10, response
->headers
->GetContentLength());
2808 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2809 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2811 TestCompletionCallback callback2
;
2813 // Wrong password (should be "bar").
2814 rv
= trans
->RestartWithAuth(
2815 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2816 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2818 rv
= callback2
.WaitForResult();
2821 response
= trans
->GetResponseInfo();
2822 ASSERT_TRUE(response
);
2823 ASSERT_TRUE(response
->headers
);
2824 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2825 EXPECT_EQ(407, response
->headers
->response_code());
2826 EXPECT_EQ(10, response
->headers
->GetContentLength());
2827 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2828 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2830 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2832 session
->CloseAllConnections();
2835 // Test that we don't read the response body when we fail to establish a tunnel,
2836 // even if the user cancels the proxy's auth attempt.
2837 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2838 HttpRequestInfo request
;
2839 request
.method
= "GET";
2840 request
.url
= GURL("https://www.example.org/");
2841 request
.load_flags
= 0;
2843 // Configure against proxy server "myproxy:70".
2844 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2846 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2848 scoped_ptr
<HttpTransaction
> trans(
2849 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2851 // Since we have proxy, should try to establish tunnel.
2852 MockWrite data_writes
[] = {
2854 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2855 "Host: www.example.org\r\n"
2856 "Proxy-Connection: keep-alive\r\n\r\n"),
2859 // The proxy responds to the connect with a 407.
2860 MockRead data_reads
[] = {
2861 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2862 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2863 MockRead("Content-Length: 10\r\n\r\n"),
2864 MockRead("0123456789"), // Should not be reached.
2865 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2868 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2869 data_writes
, arraysize(data_writes
));
2870 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2872 TestCompletionCallback callback
;
2874 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2875 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2877 rv
= callback
.WaitForResult();
2880 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2881 ASSERT_TRUE(response
);
2882 ASSERT_TRUE(response
->headers
);
2883 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2884 EXPECT_EQ(407, response
->headers
->response_code());
2885 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2887 std::string response_data
;
2888 rv
= ReadTransaction(trans
.get(), &response_data
);
2889 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2891 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2892 session
->CloseAllConnections();
2895 // Test that we don't pass extraneous headers from the proxy's response to the
2896 // caller when the proxy responds to CONNECT with 407.
2897 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2898 HttpRequestInfo request
;
2899 request
.method
= "GET";
2900 request
.url
= GURL("https://www.example.org/");
2901 request
.load_flags
= 0;
2903 // Configure against proxy server "myproxy:70".
2904 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2906 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2908 scoped_ptr
<HttpTransaction
> trans(
2909 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2911 // Since we have proxy, should try to establish tunnel.
2912 MockWrite data_writes
[] = {
2914 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2915 "Host: www.example.org\r\n"
2916 "Proxy-Connection: keep-alive\r\n\r\n"),
2919 // The proxy responds to the connect with a 407.
2920 MockRead data_reads
[] = {
2921 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2922 MockRead("X-Foo: bar\r\n"),
2923 MockRead("Set-Cookie: foo=bar\r\n"),
2924 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2925 MockRead("Content-Length: 10\r\n\r\n"),
2926 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2929 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2930 arraysize(data_writes
));
2931 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2933 TestCompletionCallback callback
;
2935 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2938 rv
= callback
.WaitForResult();
2941 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2942 ASSERT_TRUE(response
);
2943 ASSERT_TRUE(response
->headers
);
2944 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2945 EXPECT_EQ(407, response
->headers
->response_code());
2946 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2947 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2948 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2950 std::string response_data
;
2951 rv
= ReadTransaction(trans
.get(), &response_data
);
2952 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2954 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2955 session
->CloseAllConnections();
2958 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2959 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2960 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2961 HttpRequestInfo request
;
2962 request
.method
= "GET";
2963 request
.url
= GURL("http://www.example.org/");
2964 request
.load_flags
= 0;
2966 // We are using a DIRECT connection (i.e. no proxy) for this session.
2967 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2968 scoped_ptr
<HttpTransaction
> trans(
2969 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2971 MockWrite data_writes1
[] = {
2973 "GET / HTTP/1.1\r\n"
2974 "Host: www.example.org\r\n"
2975 "Connection: keep-alive\r\n\r\n"),
2978 MockRead data_reads1
[] = {
2979 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2980 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2981 // Large content-length -- won't matter, as connection will be reset.
2982 MockRead("Content-Length: 10000\r\n\r\n"),
2983 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2986 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2987 data_writes1
, arraysize(data_writes1
));
2988 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2990 TestCompletionCallback callback
;
2992 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2993 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2995 rv
= callback
.WaitForResult();
2996 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
2999 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3000 // through a non-authenticating proxy. The request should fail with
3001 // ERR_UNEXPECTED_PROXY_AUTH.
3002 // Note that it is impossible to detect if an HTTP server returns a 407 through
3003 // a non-authenticating proxy - there is nothing to indicate whether the
3004 // response came from the proxy or the server, so it is treated as if the proxy
3005 // issued the challenge.
3006 TEST_P(HttpNetworkTransactionTest
,
3007 HttpsServerRequestsProxyAuthThroughProxy
) {
3008 HttpRequestInfo request
;
3009 request
.method
= "GET";
3010 request
.url
= GURL("https://www.example.org/");
3012 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3013 BoundTestNetLog log
;
3014 session_deps_
.net_log
= log
.bound().net_log();
3015 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3017 // Since we have proxy, should try to establish tunnel.
3018 MockWrite data_writes1
[] = {
3020 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3021 "Host: www.example.org\r\n"
3022 "Proxy-Connection: keep-alive\r\n\r\n"),
3025 "GET / HTTP/1.1\r\n"
3026 "Host: www.example.org\r\n"
3027 "Connection: keep-alive\r\n\r\n"),
3030 MockRead data_reads1
[] = {
3031 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3033 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3034 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3036 MockRead(SYNCHRONOUS
, OK
),
3039 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3040 data_writes1
, arraysize(data_writes1
));
3041 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3042 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3043 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3045 TestCompletionCallback callback1
;
3047 scoped_ptr
<HttpTransaction
> trans(
3048 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3050 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3051 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3053 rv
= callback1
.WaitForResult();
3054 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3055 TestNetLogEntry::List entries
;
3056 log
.GetEntries(&entries
);
3057 size_t pos
= ExpectLogContainsSomewhere(
3058 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3059 NetLog::PHASE_NONE
);
3060 ExpectLogContainsSomewhere(
3062 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3063 NetLog::PHASE_NONE
);
3066 // Test the load timing for HTTPS requests with an HTTP proxy.
3067 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3068 HttpRequestInfo request1
;
3069 request1
.method
= "GET";
3070 request1
.url
= GURL("https://www.example.org/1");
3072 HttpRequestInfo request2
;
3073 request2
.method
= "GET";
3074 request2
.url
= GURL("https://www.example.org/2");
3076 // Configure against proxy server "myproxy:70".
3077 session_deps_
.proxy_service
.reset(
3078 ProxyService::CreateFixed("PROXY myproxy:70"));
3079 BoundTestNetLog log
;
3080 session_deps_
.net_log
= log
.bound().net_log();
3081 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3083 // Since we have proxy, should try to establish tunnel.
3084 MockWrite data_writes1
[] = {
3086 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3087 "Host: www.example.org\r\n"
3088 "Proxy-Connection: keep-alive\r\n\r\n"),
3091 "GET /1 HTTP/1.1\r\n"
3092 "Host: www.example.org\r\n"
3093 "Connection: keep-alive\r\n\r\n"),
3096 "GET /2 HTTP/1.1\r\n"
3097 "Host: www.example.org\r\n"
3098 "Connection: keep-alive\r\n\r\n"),
3101 // The proxy responds to the connect with a 407, using a persistent
3103 MockRead data_reads1
[] = {
3104 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3106 MockRead("HTTP/1.1 200 OK\r\n"),
3107 MockRead("Content-Length: 1\r\n\r\n"),
3108 MockRead(SYNCHRONOUS
, "1"),
3110 MockRead("HTTP/1.1 200 OK\r\n"),
3111 MockRead("Content-Length: 2\r\n\r\n"),
3112 MockRead(SYNCHRONOUS
, "22"),
3115 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3116 data_writes1
, arraysize(data_writes1
));
3117 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3118 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3119 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3121 TestCompletionCallback callback1
;
3122 scoped_ptr
<HttpTransaction
> trans1(
3123 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3125 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3126 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3128 rv
= callback1
.WaitForResult();
3131 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3132 ASSERT_TRUE(response1
!= NULL
);
3133 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3134 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3136 LoadTimingInfo load_timing_info1
;
3137 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3138 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3142 TestCompletionCallback callback2
;
3143 scoped_ptr
<HttpTransaction
> trans2(
3144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3146 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3147 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3149 rv
= callback2
.WaitForResult();
3152 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3153 ASSERT_TRUE(response2
!= NULL
);
3154 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3155 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3157 LoadTimingInfo load_timing_info2
;
3158 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3159 TestLoadTimingReused(load_timing_info2
);
3161 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3164 session
->CloseAllConnections();
3167 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3168 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3169 HttpRequestInfo request1
;
3170 request1
.method
= "GET";
3171 request1
.url
= GURL("https://www.example.org/1");
3173 HttpRequestInfo request2
;
3174 request2
.method
= "GET";
3175 request2
.url
= GURL("https://www.example.org/2");
3177 // Configure against proxy server "myproxy:70".
3178 session_deps_
.proxy_service
.reset(
3179 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3180 BoundTestNetLog log
;
3181 session_deps_
.net_log
= log
.bound().net_log();
3182 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3184 // Since we have proxy, should try to establish tunnel.
3185 MockWrite data_writes1
[] = {
3187 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3188 "Host: www.example.org\r\n"
3189 "Proxy-Connection: keep-alive\r\n\r\n"),
3192 "GET /1 HTTP/1.1\r\n"
3193 "Host: www.example.org\r\n"
3194 "Connection: keep-alive\r\n\r\n"),
3197 "GET /2 HTTP/1.1\r\n"
3198 "Host: www.example.org\r\n"
3199 "Connection: keep-alive\r\n\r\n"),
3202 // The proxy responds to the connect with a 407, using a persistent
3204 MockRead data_reads1
[] = {
3205 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3207 MockRead("HTTP/1.1 200 OK\r\n"),
3208 MockRead("Content-Length: 1\r\n\r\n"),
3209 MockRead(SYNCHRONOUS
, "1"),
3211 MockRead("HTTP/1.1 200 OK\r\n"),
3212 MockRead("Content-Length: 2\r\n\r\n"),
3213 MockRead(SYNCHRONOUS
, "22"),
3216 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3217 data_writes1
, arraysize(data_writes1
));
3218 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3219 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3220 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3222 TestCompletionCallback callback1
;
3223 scoped_ptr
<HttpTransaction
> trans1(
3224 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3226 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3227 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3229 rv
= callback1
.WaitForResult();
3232 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3233 ASSERT_TRUE(response1
!= NULL
);
3234 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3235 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3237 LoadTimingInfo load_timing_info1
;
3238 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3239 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3240 CONNECT_TIMING_HAS_SSL_TIMES
);
3244 TestCompletionCallback callback2
;
3245 scoped_ptr
<HttpTransaction
> trans2(
3246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3248 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3249 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3251 rv
= callback2
.WaitForResult();
3254 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3255 ASSERT_TRUE(response2
!= NULL
);
3256 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3257 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3259 LoadTimingInfo load_timing_info2
;
3260 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3261 TestLoadTimingReusedWithPac(load_timing_info2
);
3263 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3266 session
->CloseAllConnections();
3269 // Test a simple get through an HTTPS Proxy.
3270 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3271 HttpRequestInfo request
;
3272 request
.method
= "GET";
3273 request
.url
= GURL("http://www.example.org/");
3275 // Configure against https proxy server "proxy:70".
3276 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3277 "https://proxy:70"));
3278 BoundTestNetLog log
;
3279 session_deps_
.net_log
= log
.bound().net_log();
3280 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3282 // Since we have proxy, should use full url
3283 MockWrite data_writes1
[] = {
3285 "GET http://www.example.org/ HTTP/1.1\r\n"
3286 "Host: www.example.org\r\n"
3287 "Proxy-Connection: keep-alive\r\n\r\n"),
3290 MockRead data_reads1
[] = {
3291 MockRead("HTTP/1.1 200 OK\r\n"),
3292 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3293 MockRead("Content-Length: 100\r\n\r\n"),
3294 MockRead(SYNCHRONOUS
, OK
),
3297 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3298 data_writes1
, arraysize(data_writes1
));
3299 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3300 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3301 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3303 TestCompletionCallback callback1
;
3305 scoped_ptr
<HttpTransaction
> trans(
3306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3308 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3311 rv
= callback1
.WaitForResult();
3314 LoadTimingInfo load_timing_info
;
3315 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3316 TestLoadTimingNotReused(load_timing_info
,
3317 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3319 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3320 ASSERT_TRUE(response
!= NULL
);
3322 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3323 EXPECT_EQ(200, response
->headers
->response_code());
3324 EXPECT_EQ(100, response
->headers
->GetContentLength());
3325 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3327 // The password prompt info should not be set.
3328 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3331 // Test a SPDY get through an HTTPS Proxy.
3332 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3333 HttpRequestInfo request
;
3334 request
.method
= "GET";
3335 request
.url
= GURL("http://www.example.org/");
3336 request
.load_flags
= 0;
3338 // Configure against https proxy server "proxy:70".
3339 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3340 "https://proxy:70"));
3341 BoundTestNetLog log
;
3342 session_deps_
.net_log
= log
.bound().net_log();
3343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3345 // fetch http://www.example.org/ via SPDY
3346 scoped_ptr
<SpdyFrame
> req(
3347 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3348 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3350 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3351 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3352 MockRead spdy_reads
[] = {
3353 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3356 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3357 arraysize(spdy_writes
));
3358 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3360 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3361 ssl
.SetNextProto(GetParam());
3362 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3364 TestCompletionCallback callback1
;
3366 scoped_ptr
<HttpTransaction
> trans(
3367 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3369 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3370 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3372 rv
= callback1
.WaitForResult();
3375 LoadTimingInfo load_timing_info
;
3376 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3377 TestLoadTimingNotReused(load_timing_info
,
3378 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3380 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3381 ASSERT_TRUE(response
!= NULL
);
3382 ASSERT_TRUE(response
->headers
.get() != NULL
);
3383 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3385 std::string response_data
;
3386 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3387 EXPECT_EQ(kUploadData
, response_data
);
3390 // Verifies that a session which races and wins against the owning transaction
3391 // (completing prior to host resolution), doesn't fail the transaction.
3392 // Regression test for crbug.com/334413.
3393 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3394 HttpRequestInfo request
;
3395 request
.method
= "GET";
3396 request
.url
= GURL("http://www.example.org/");
3397 request
.load_flags
= 0;
3399 // Configure SPDY proxy server "proxy:70".
3400 session_deps_
.proxy_service
.reset(
3401 ProxyService::CreateFixed("https://proxy:70"));
3402 BoundTestNetLog log
;
3403 session_deps_
.net_log
= log
.bound().net_log();
3404 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3406 // Fetch http://www.example.org/ through the SPDY proxy.
3407 scoped_ptr
<SpdyFrame
> req(
3408 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3409 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3411 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3412 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3413 MockRead spdy_reads
[] = {
3414 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3417 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3418 arraysize(spdy_writes
));
3419 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3421 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3422 ssl
.SetNextProto(GetParam());
3423 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3425 TestCompletionCallback callback1
;
3427 scoped_ptr
<HttpTransaction
> trans(
3428 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3430 // Stall the hostname resolution begun by the transaction.
3431 session_deps_
.host_resolver
->set_synchronous_mode(false);
3432 session_deps_
.host_resolver
->set_ondemand_mode(true);
3434 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3435 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3437 // Race a session to the proxy, which completes first.
3438 session_deps_
.host_resolver
->set_ondemand_mode(false);
3440 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3441 base::WeakPtr
<SpdySession
> spdy_session
=
3442 CreateSecureSpdySession(session
, key
, log
.bound());
3444 // Unstall the resolution begun by the transaction.
3445 session_deps_
.host_resolver
->set_ondemand_mode(true);
3446 session_deps_
.host_resolver
->ResolveAllPending();
3448 EXPECT_FALSE(callback1
.have_result());
3449 rv
= callback1
.WaitForResult();
3452 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3453 ASSERT_TRUE(response
!= NULL
);
3454 ASSERT_TRUE(response
->headers
.get() != NULL
);
3455 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3457 std::string response_data
;
3458 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3459 EXPECT_EQ(kUploadData
, response_data
);
3462 // Test a SPDY get through an HTTPS Proxy.
3463 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3464 HttpRequestInfo request
;
3465 request
.method
= "GET";
3466 request
.url
= GURL("http://www.example.org/");
3467 request
.load_flags
= 0;
3469 // Configure against https proxy server "myproxy:70".
3470 session_deps_
.proxy_service
.reset(
3471 ProxyService::CreateFixed("https://myproxy:70"));
3472 BoundTestNetLog log
;
3473 session_deps_
.net_log
= log
.bound().net_log();
3474 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3476 // The first request will be a bare GET, the second request will be a
3477 // GET with a Proxy-Authorization header.
3478 scoped_ptr
<SpdyFrame
> req_get(
3479 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3480 const char* const kExtraAuthorizationHeaders
[] = {
3481 "proxy-authorization", "Basic Zm9vOmJhcg=="
3483 scoped_ptr
<SpdyFrame
> req_get_authorization(
3484 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3485 arraysize(kExtraAuthorizationHeaders
) / 2,
3490 MockWrite spdy_writes
[] = {
3491 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3494 // The first response is a 407 proxy authentication challenge, and the second
3495 // response will be a 200 response since the second request includes a valid
3496 // Authorization header.
3497 const char* const kExtraAuthenticationHeaders
[] = {
3498 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3500 scoped_ptr
<SpdyFrame
> resp_authentication(
3501 spdy_util_
.ConstructSpdySynReplyError(
3502 "407 Proxy Authentication Required",
3503 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3505 scoped_ptr
<SpdyFrame
> body_authentication(
3506 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3507 scoped_ptr
<SpdyFrame
> resp_data(
3508 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3509 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3510 MockRead spdy_reads
[] = {
3511 CreateMockRead(*resp_authentication
, 1),
3512 CreateMockRead(*body_authentication
, 2),
3513 CreateMockRead(*resp_data
, 4),
3514 CreateMockRead(*body_data
, 5),
3515 MockRead(ASYNC
, 0, 6),
3518 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3519 arraysize(spdy_writes
));
3520 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3522 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3523 ssl
.SetNextProto(GetParam());
3524 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3526 TestCompletionCallback callback1
;
3528 scoped_ptr
<HttpTransaction
> trans(
3529 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3531 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3532 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3534 rv
= callback1
.WaitForResult();
3537 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3539 ASSERT_TRUE(response
!= NULL
);
3540 ASSERT_TRUE(response
->headers
.get() != NULL
);
3541 EXPECT_EQ(407, response
->headers
->response_code());
3542 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3543 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3545 TestCompletionCallback callback2
;
3547 rv
= trans
->RestartWithAuth(
3548 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3549 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3551 rv
= callback2
.WaitForResult();
3554 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3556 ASSERT_TRUE(response_restart
!= NULL
);
3557 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3558 EXPECT_EQ(200, response_restart
->headers
->response_code());
3559 // The password prompt info should not be set.
3560 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3563 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3564 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3565 HttpRequestInfo request
;
3566 request
.method
= "GET";
3567 request
.url
= GURL("https://www.example.org/");
3568 request
.load_flags
= 0;
3570 // Configure against https proxy server "proxy:70".
3571 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3572 "https://proxy:70"));
3573 BoundTestNetLog log
;
3574 session_deps_
.net_log
= log
.bound().net_log();
3575 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3577 scoped_ptr
<HttpTransaction
> trans(
3578 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3580 // CONNECT to www.example.org:443 via SPDY
3581 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3582 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3583 // fetch https://www.example.org/ via HTTP
3586 "GET / HTTP/1.1\r\n"
3587 "Host: www.example.org\r\n"
3588 "Connection: keep-alive\r\n\r\n";
3589 scoped_ptr
<SpdyFrame
> wrapped_get(
3590 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3591 scoped_ptr
<SpdyFrame
> conn_resp(
3592 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3593 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3594 "Content-Length: 10\r\n\r\n";
3595 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3596 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3597 scoped_ptr
<SpdyFrame
> wrapped_body(
3598 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3599 scoped_ptr
<SpdyFrame
> window_update(
3600 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3602 MockWrite spdy_writes
[] = {
3603 CreateMockWrite(*connect
, 0),
3604 CreateMockWrite(*wrapped_get
, 2),
3605 CreateMockWrite(*window_update
, 6),
3608 MockRead spdy_reads
[] = {
3609 CreateMockRead(*conn_resp
, 1, ASYNC
),
3610 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3611 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3612 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3613 MockRead(ASYNC
, 0, 7),
3616 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3617 arraysize(spdy_writes
));
3618 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3620 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3621 ssl
.SetNextProto(GetParam());
3622 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3623 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3624 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3626 TestCompletionCallback callback1
;
3628 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3629 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3631 rv
= callback1
.WaitForResult();
3634 LoadTimingInfo load_timing_info
;
3635 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3636 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3638 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3639 ASSERT_TRUE(response
!= NULL
);
3640 ASSERT_TRUE(response
->headers
.get() != NULL
);
3641 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3643 std::string response_data
;
3644 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3645 EXPECT_EQ("1234567890", response_data
);
3648 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3649 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3650 HttpRequestInfo request
;
3651 request
.method
= "GET";
3652 request
.url
= GURL("https://www.example.org/");
3653 request
.load_flags
= 0;
3655 // Configure against https proxy server "proxy:70".
3656 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3657 "https://proxy:70"));
3658 BoundTestNetLog log
;
3659 session_deps_
.net_log
= log
.bound().net_log();
3660 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3662 scoped_ptr
<HttpTransaction
> trans(
3663 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3665 // CONNECT to www.example.org:443 via SPDY
3666 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3667 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3668 // fetch https://www.example.org/ via SPDY
3669 const char kMyUrl
[] = "https://www.example.org/";
3670 scoped_ptr
<SpdyFrame
> get(
3671 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3672 scoped_ptr
<SpdyFrame
> wrapped_get(
3673 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3674 scoped_ptr
<SpdyFrame
> conn_resp(
3675 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3676 scoped_ptr
<SpdyFrame
> get_resp(
3677 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3678 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3679 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3680 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3681 scoped_ptr
<SpdyFrame
> wrapped_body(
3682 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3683 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3684 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3685 scoped_ptr
<SpdyFrame
> window_update_body(
3686 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3688 MockWrite spdy_writes
[] = {
3689 CreateMockWrite(*connect
, 0),
3690 CreateMockWrite(*wrapped_get
, 2),
3691 CreateMockWrite(*window_update_get_resp
, 6),
3692 CreateMockWrite(*window_update_body
, 7),
3695 MockRead spdy_reads
[] = {
3696 CreateMockRead(*conn_resp
, 1, ASYNC
),
3697 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3698 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3699 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3700 MockRead(ASYNC
, 0, 8),
3703 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3704 arraysize(spdy_writes
));
3705 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3707 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3708 ssl
.SetNextProto(GetParam());
3709 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3710 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3711 ssl2
.SetNextProto(GetParam());
3712 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3714 TestCompletionCallback callback1
;
3716 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3717 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3719 // Allow the SpdyProxyClientSocket's write callback to complete.
3720 base::MessageLoop::current()->RunUntilIdle();
3721 // Now allow the read of the response to complete.
3722 spdy_data
.CompleteRead();
3723 rv
= callback1
.WaitForResult();
3726 LoadTimingInfo load_timing_info
;
3727 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3728 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3730 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3731 ASSERT_TRUE(response
!= NULL
);
3732 ASSERT_TRUE(response
->headers
.get() != NULL
);
3733 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3735 std::string response_data
;
3736 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3737 EXPECT_EQ(kUploadData
, response_data
);
3740 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3741 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3742 HttpRequestInfo request
;
3743 request
.method
= "GET";
3744 request
.url
= GURL("https://www.example.org/");
3745 request
.load_flags
= 0;
3747 // Configure against https proxy server "proxy:70".
3748 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3749 "https://proxy:70"));
3750 BoundTestNetLog log
;
3751 session_deps_
.net_log
= log
.bound().net_log();
3752 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3754 scoped_ptr
<HttpTransaction
> trans(
3755 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3757 // CONNECT to www.example.org:443 via SPDY
3758 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3759 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3760 scoped_ptr
<SpdyFrame
> get(
3761 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3763 MockWrite spdy_writes
[] = {
3764 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3767 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3768 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3769 MockRead spdy_reads
[] = {
3770 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3773 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3774 arraysize(spdy_writes
));
3775 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3777 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3778 ssl
.SetNextProto(GetParam());
3779 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3780 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3781 ssl2
.SetNextProto(GetParam());
3782 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3784 TestCompletionCallback callback1
;
3786 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3787 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3789 rv
= callback1
.WaitForResult();
3790 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3792 // TODO(ttuttle): Anything else to check here?
3795 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3796 // HTTPS Proxy to different servers.
3797 TEST_P(HttpNetworkTransactionTest
,
3798 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3799 // Configure against https proxy server "proxy:70".
3800 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3801 "https://proxy:70"));
3802 BoundTestNetLog log
;
3803 session_deps_
.net_log
= log
.bound().net_log();
3804 scoped_refptr
<HttpNetworkSession
> session(
3805 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3807 HttpRequestInfo request1
;
3808 request1
.method
= "GET";
3809 request1
.url
= GURL("https://www.example.org/");
3810 request1
.load_flags
= 0;
3812 HttpRequestInfo request2
;
3813 request2
.method
= "GET";
3814 request2
.url
= GURL("https://mail.example.org/");
3815 request2
.load_flags
= 0;
3817 // CONNECT to www.example.org:443 via SPDY.
3818 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3819 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3820 scoped_ptr
<SpdyFrame
> conn_resp1(
3821 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3823 // Fetch https://www.example.org/ via HTTP.
3825 "GET / HTTP/1.1\r\n"
3826 "Host: www.example.org\r\n"
3827 "Connection: keep-alive\r\n\r\n";
3828 scoped_ptr
<SpdyFrame
> wrapped_get1(
3829 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3830 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3831 "Content-Length: 1\r\n\r\n";
3832 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3833 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3834 scoped_ptr
<SpdyFrame
> wrapped_body1(
3835 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3836 scoped_ptr
<SpdyFrame
> window_update(
3837 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3839 // CONNECT to mail.example.org:443 via SPDY.
3840 SpdyHeaderBlock connect2_block
;
3841 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3842 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3843 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3844 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3845 scoped_ptr
<SpdyFrame
> connect2(
3846 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3848 scoped_ptr
<SpdyFrame
> conn_resp2(
3849 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3851 // Fetch https://mail.example.org/ via HTTP.
3853 "GET / HTTP/1.1\r\n"
3854 "Host: mail.example.org\r\n"
3855 "Connection: keep-alive\r\n\r\n";
3856 scoped_ptr
<SpdyFrame
> wrapped_get2(
3857 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3858 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3859 "Content-Length: 2\r\n\r\n";
3860 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3861 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3862 scoped_ptr
<SpdyFrame
> wrapped_body2(
3863 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3865 MockWrite spdy_writes
[] = {
3866 CreateMockWrite(*connect1
, 0),
3867 CreateMockWrite(*wrapped_get1
, 2),
3868 CreateMockWrite(*connect2
, 5),
3869 CreateMockWrite(*wrapped_get2
, 7),
3872 MockRead spdy_reads
[] = {
3873 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3874 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3875 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3876 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3877 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3878 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3879 MockRead(ASYNC
, 0, 10),
3882 DeterministicSocketData
spdy_data(
3883 spdy_reads
, arraysize(spdy_reads
),
3884 spdy_writes
, arraysize(spdy_writes
));
3885 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3887 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3888 ssl
.SetNextProto(GetParam());
3889 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3890 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3891 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3892 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3893 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3895 TestCompletionCallback callback
;
3897 scoped_ptr
<HttpTransaction
> trans(
3898 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3899 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3900 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3901 // The first connect and request, each of their responses, and the body.
3902 spdy_data
.RunFor(5);
3904 rv
= callback
.WaitForResult();
3907 LoadTimingInfo load_timing_info
;
3908 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3909 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3911 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3912 ASSERT_TRUE(response
!= NULL
);
3913 ASSERT_TRUE(response
->headers
.get() != NULL
);
3914 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3916 std::string response_data
;
3917 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3918 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3920 scoped_ptr
<HttpTransaction
> trans2(
3921 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3922 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3923 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3925 // The second connect and request, each of their responses, and the body.
3926 spdy_data
.RunFor(5);
3927 rv
= callback
.WaitForResult();
3930 LoadTimingInfo load_timing_info2
;
3931 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3932 // Even though the SPDY connection is reused, a new tunnelled connection has
3933 // to be created, so the socket's load timing looks like a fresh connection.
3934 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3936 // The requests should have different IDs, since they each are using their own
3938 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3940 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3943 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3944 // HTTPS Proxy to the same server.
3945 TEST_P(HttpNetworkTransactionTest
,
3946 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3947 // Configure against https proxy server "proxy:70".
3948 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3949 "https://proxy:70"));
3950 BoundTestNetLog log
;
3951 session_deps_
.net_log
= log
.bound().net_log();
3952 scoped_refptr
<HttpNetworkSession
> session(
3953 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3955 HttpRequestInfo request1
;
3956 request1
.method
= "GET";
3957 request1
.url
= GURL("https://www.example.org/");
3958 request1
.load_flags
= 0;
3960 HttpRequestInfo request2
;
3961 request2
.method
= "GET";
3962 request2
.url
= GURL("https://www.example.org/2");
3963 request2
.load_flags
= 0;
3965 // CONNECT to www.example.org:443 via SPDY.
3966 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3967 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3968 scoped_ptr
<SpdyFrame
> conn_resp1(
3969 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3971 // Fetch https://www.example.org/ via HTTP.
3973 "GET / HTTP/1.1\r\n"
3974 "Host: www.example.org\r\n"
3975 "Connection: keep-alive\r\n\r\n";
3976 scoped_ptr
<SpdyFrame
> wrapped_get1(
3977 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3978 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3979 "Content-Length: 1\r\n\r\n";
3980 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3981 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3982 scoped_ptr
<SpdyFrame
> wrapped_body1(
3983 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3984 scoped_ptr
<SpdyFrame
> window_update(
3985 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3987 // Fetch https://www.example.org/2 via HTTP.
3989 "GET /2 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_get2(
3993 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3994 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3995 "Content-Length: 2\r\n\r\n";
3996 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3997 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3998 scoped_ptr
<SpdyFrame
> wrapped_body2(
3999 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4001 MockWrite spdy_writes
[] = {
4002 CreateMockWrite(*connect1
, 0),
4003 CreateMockWrite(*wrapped_get1
, 2),
4004 CreateMockWrite(*wrapped_get2
, 5),
4007 MockRead spdy_reads
[] = {
4008 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4009 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4010 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4011 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4012 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4013 MockRead(ASYNC
, 0, 8),
4016 DeterministicSocketData
spdy_data(
4017 spdy_reads
, arraysize(spdy_reads
),
4018 spdy_writes
, arraysize(spdy_writes
));
4019 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4021 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4022 ssl
.SetNextProto(GetParam());
4023 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4024 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4025 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4027 TestCompletionCallback callback
;
4029 scoped_ptr
<HttpTransaction
> trans(
4030 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4031 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4033 // The first connect and request, each of their responses, and the body.
4034 spdy_data
.RunFor(5);
4036 rv
= callback
.WaitForResult();
4039 LoadTimingInfo load_timing_info
;
4040 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4041 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4043 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4044 ASSERT_TRUE(response
!= NULL
);
4045 ASSERT_TRUE(response
->headers
.get() != NULL
);
4046 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4048 std::string response_data
;
4049 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4050 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4053 scoped_ptr
<HttpTransaction
> trans2(
4054 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4055 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4056 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4058 // The second request, response, and body. There should not be a second
4060 spdy_data
.RunFor(3);
4061 rv
= callback
.WaitForResult();
4064 LoadTimingInfo load_timing_info2
;
4065 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4066 TestLoadTimingReused(load_timing_info2
);
4068 // The requests should have the same ID.
4069 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4071 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4074 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4075 // Proxy to different servers.
4076 TEST_P(HttpNetworkTransactionTest
,
4077 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4078 // Configure against https proxy server "proxy:70".
4079 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4080 "https://proxy:70"));
4081 BoundTestNetLog log
;
4082 session_deps_
.net_log
= log
.bound().net_log();
4083 scoped_refptr
<HttpNetworkSession
> session(
4084 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
4086 HttpRequestInfo request1
;
4087 request1
.method
= "GET";
4088 request1
.url
= GURL("http://www.example.org/");
4089 request1
.load_flags
= 0;
4091 HttpRequestInfo request2
;
4092 request2
.method
= "GET";
4093 request2
.url
= GURL("http://mail.example.org/");
4094 request2
.load_flags
= 0;
4096 // http://www.example.org/
4097 scoped_ptr
<SpdyHeaderBlock
> headers(
4098 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4099 scoped_ptr
<SpdyFrame
> get1(
4100 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4101 scoped_ptr
<SpdyFrame
> get_resp1(
4102 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4103 scoped_ptr
<SpdyFrame
> body1(
4104 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4106 // http://mail.example.org/
4107 scoped_ptr
<SpdyHeaderBlock
> headers2(
4108 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4109 scoped_ptr
<SpdyFrame
> get2(
4110 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4111 scoped_ptr
<SpdyFrame
> get_resp2(
4112 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4113 scoped_ptr
<SpdyFrame
> body2(
4114 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4116 MockWrite spdy_writes
[] = {
4117 CreateMockWrite(*get1
, 0),
4118 CreateMockWrite(*get2
, 3),
4121 MockRead spdy_reads
[] = {
4122 CreateMockRead(*get_resp1
, 1, ASYNC
),
4123 CreateMockRead(*body1
, 2, ASYNC
),
4124 CreateMockRead(*get_resp2
, 4, ASYNC
),
4125 CreateMockRead(*body2
, 5, ASYNC
),
4126 MockRead(ASYNC
, 0, 6),
4129 DeterministicSocketData
spdy_data(
4130 spdy_reads
, arraysize(spdy_reads
),
4131 spdy_writes
, arraysize(spdy_writes
));
4132 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4134 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4135 ssl
.SetNextProto(GetParam());
4136 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4138 TestCompletionCallback callback
;
4140 scoped_ptr
<HttpTransaction
> trans(
4141 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4142 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4143 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4144 spdy_data
.RunFor(2);
4146 rv
= callback
.WaitForResult();
4149 LoadTimingInfo load_timing_info
;
4150 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4151 TestLoadTimingNotReused(load_timing_info
,
4152 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4154 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4155 ASSERT_TRUE(response
!= NULL
);
4156 ASSERT_TRUE(response
->headers
.get() != NULL
);
4157 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4159 std::string response_data
;
4160 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4161 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
4162 spdy_data
.RunFor(1);
4163 EXPECT_EQ(1, callback
.WaitForResult());
4164 // Delete the first request, so the second one can reuse the socket.
4167 scoped_ptr
<HttpTransaction
> trans2(
4168 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4169 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4172 spdy_data
.RunFor(2);
4173 rv
= callback
.WaitForResult();
4176 LoadTimingInfo load_timing_info2
;
4177 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4178 TestLoadTimingReused(load_timing_info2
);
4180 // The requests should have the same ID.
4181 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4183 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
4184 spdy_data
.RunFor(1);
4185 EXPECT_EQ(2, callback
.WaitForResult());
4188 // Test the challenge-response-retry sequence through an HTTPS Proxy
4189 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4190 HttpRequestInfo request
;
4191 request
.method
= "GET";
4192 request
.url
= GURL("http://www.example.org/");
4193 // when the no authentication data flag is set.
4194 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4196 // Configure against https proxy server "myproxy:70".
4197 session_deps_
.proxy_service
.reset(
4198 ProxyService::CreateFixed("https://myproxy:70"));
4199 BoundTestNetLog log
;
4200 session_deps_
.net_log
= log
.bound().net_log();
4201 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4203 // Since we have proxy, should use full url
4204 MockWrite data_writes1
[] = {
4206 "GET http://www.example.org/ HTTP/1.1\r\n"
4207 "Host: www.example.org\r\n"
4208 "Proxy-Connection: keep-alive\r\n\r\n"),
4210 // After calling trans->RestartWithAuth(), this is the request we should
4211 // be issuing -- the final header line contains the credentials.
4213 "GET http://www.example.org/ HTTP/1.1\r\n"
4214 "Host: www.example.org\r\n"
4215 "Proxy-Connection: keep-alive\r\n"
4216 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4219 // The proxy responds to the GET with a 407, using a persistent
4221 MockRead data_reads1
[] = {
4223 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4224 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4225 MockRead("Proxy-Connection: keep-alive\r\n"),
4226 MockRead("Content-Length: 0\r\n\r\n"),
4228 MockRead("HTTP/1.1 200 OK\r\n"),
4229 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4230 MockRead("Content-Length: 100\r\n\r\n"),
4231 MockRead(SYNCHRONOUS
, OK
),
4234 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4235 data_writes1
, arraysize(data_writes1
));
4236 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4237 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4238 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4240 TestCompletionCallback callback1
;
4242 scoped_ptr
<HttpTransaction
> trans(
4243 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4245 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4246 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4248 rv
= callback1
.WaitForResult();
4251 LoadTimingInfo load_timing_info
;
4252 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4253 TestLoadTimingNotReused(load_timing_info
,
4254 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4256 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4257 ASSERT_TRUE(response
!= NULL
);
4258 ASSERT_FALSE(response
->headers
.get() == NULL
);
4259 EXPECT_EQ(407, response
->headers
->response_code());
4260 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4261 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4263 TestCompletionCallback callback2
;
4265 rv
= trans
->RestartWithAuth(
4266 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4269 rv
= callback2
.WaitForResult();
4272 load_timing_info
= LoadTimingInfo();
4273 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4274 // Retrying with HTTP AUTH is considered to be reusing a socket.
4275 TestLoadTimingReused(load_timing_info
);
4277 response
= trans
->GetResponseInfo();
4278 ASSERT_TRUE(response
!= NULL
);
4280 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4281 EXPECT_EQ(200, response
->headers
->response_code());
4282 EXPECT_EQ(100, response
->headers
->GetContentLength());
4283 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4285 // The password prompt info should not be set.
4286 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4289 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4290 const MockRead
& status
, int expected_status
) {
4291 HttpRequestInfo request
;
4292 request
.method
= "GET";
4293 request
.url
= GURL("https://www.example.org/");
4294 request
.load_flags
= 0;
4296 // Configure against proxy server "myproxy:70".
4297 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4298 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4300 // Since we have proxy, should try to establish tunnel.
4301 MockWrite data_writes
[] = {
4303 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4304 "Host: www.example.org\r\n"
4305 "Proxy-Connection: keep-alive\r\n\r\n"),
4308 MockRead data_reads
[] = {
4310 MockRead("Content-Length: 10\r\n\r\n"),
4311 // No response body because the test stops reading here.
4312 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4315 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4316 data_writes
, arraysize(data_writes
));
4317 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4319 TestCompletionCallback callback
;
4321 scoped_ptr
<HttpTransaction
> trans(
4322 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4324 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4325 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4327 rv
= callback
.WaitForResult();
4328 EXPECT_EQ(expected_status
, rv
);
4331 void HttpNetworkTransactionTest::ConnectStatusHelper(
4332 const MockRead
& status
) {
4333 ConnectStatusHelperWithExpectedStatus(
4334 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4337 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4338 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4341 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4342 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4345 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4346 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4349 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4350 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4353 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4354 ConnectStatusHelper(
4355 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4358 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4359 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4362 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4363 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4366 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4367 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4370 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4371 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4374 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4375 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4378 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4379 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4382 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4383 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4386 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4387 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4390 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4391 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4394 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4395 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4398 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4399 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4402 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4403 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4406 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4407 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4410 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4411 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4414 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4415 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4418 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4419 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4422 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4423 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4426 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4427 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4430 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4434 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4435 ConnectStatusHelperWithExpectedStatus(
4436 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4437 ERR_PROXY_AUTH_UNSUPPORTED
);
4440 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4441 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4444 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4445 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4448 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4449 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4452 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4453 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4456 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4457 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4460 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4461 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4464 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4465 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4468 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4469 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4472 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4473 ConnectStatusHelper(
4474 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4477 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4478 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4481 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4482 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4485 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4486 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4489 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4490 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4493 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4494 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4497 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4498 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4501 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4502 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4505 // Test the flow when both the proxy server AND origin server require
4506 // authentication. Again, this uses basic auth for both since that is
4507 // the simplest to mock.
4508 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4509 HttpRequestInfo request
;
4510 request
.method
= "GET";
4511 request
.url
= GURL("http://www.example.org/");
4512 request
.load_flags
= 0;
4514 // Configure against proxy server "myproxy:70".
4515 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4516 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4518 scoped_ptr
<HttpTransaction
> trans(
4519 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4521 MockWrite data_writes1
[] = {
4523 "GET http://www.example.org/ HTTP/1.1\r\n"
4524 "Host: www.example.org\r\n"
4525 "Proxy-Connection: keep-alive\r\n\r\n"),
4528 MockRead data_reads1
[] = {
4529 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4530 // Give a couple authenticate options (only the middle one is actually
4532 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4533 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4534 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4535 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4536 // Large content-length -- won't matter, as connection will be reset.
4537 MockRead("Content-Length: 10000\r\n\r\n"),
4538 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4541 // After calling trans->RestartWithAuth() the first time, this is the
4542 // request we should be issuing -- the final header line contains the
4543 // proxy's credentials.
4544 MockWrite data_writes2
[] = {
4546 "GET http://www.example.org/ HTTP/1.1\r\n"
4547 "Host: www.example.org\r\n"
4548 "Proxy-Connection: keep-alive\r\n"
4549 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4552 // Now the proxy server lets the request pass through to origin server.
4553 // The origin server responds with a 401.
4554 MockRead data_reads2
[] = {
4555 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4556 // Note: We are using the same realm-name as the proxy server. This is
4557 // completely valid, as realms are unique across hosts.
4558 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4560 MockRead("Content-Length: 2000\r\n\r\n"),
4561 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4564 // After calling trans->RestartWithAuth() the second time, we should send
4565 // the credentials for both the proxy and origin server.
4566 MockWrite data_writes3
[] = {
4568 "GET http://www.example.org/ HTTP/1.1\r\n"
4569 "Host: www.example.org\r\n"
4570 "Proxy-Connection: keep-alive\r\n"
4571 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4572 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4575 // Lastly we get the desired content.
4576 MockRead data_reads3
[] = {
4577 MockRead("HTTP/1.0 200 OK\r\n"),
4578 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4579 MockRead("Content-Length: 100\r\n\r\n"),
4580 MockRead(SYNCHRONOUS
, OK
),
4583 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4584 data_writes1
, arraysize(data_writes1
));
4585 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4586 data_writes2
, arraysize(data_writes2
));
4587 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4588 data_writes3
, arraysize(data_writes3
));
4589 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4590 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4591 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4593 TestCompletionCallback callback1
;
4595 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4596 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4598 rv
= callback1
.WaitForResult();
4601 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4602 ASSERT_TRUE(response
!= NULL
);
4603 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4605 TestCompletionCallback callback2
;
4607 rv
= trans
->RestartWithAuth(
4608 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4609 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4611 rv
= callback2
.WaitForResult();
4614 response
= trans
->GetResponseInfo();
4615 ASSERT_TRUE(response
!= NULL
);
4616 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4618 TestCompletionCallback callback3
;
4620 rv
= trans
->RestartWithAuth(
4621 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4622 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4624 rv
= callback3
.WaitForResult();
4627 response
= trans
->GetResponseInfo();
4628 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4629 EXPECT_EQ(100, response
->headers
->GetContentLength());
4632 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4633 // can't hook into its internals to cause it to generate predictable NTLM
4634 // authorization headers.
4635 #if defined(NTLM_PORTABLE)
4636 // The NTLM authentication unit tests were generated by capturing the HTTP
4637 // requests and responses using Fiddler 2 and inspecting the generated random
4638 // bytes in the debugger.
4640 // Enter the correct password and authenticate successfully.
4641 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4642 HttpRequestInfo request
;
4643 request
.method
= "GET";
4644 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4646 // Ensure load is not disrupted by flags which suppress behaviour specific
4647 // to other auth schemes.
4648 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4650 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4652 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4654 MockWrite data_writes1
[] = {
4655 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4656 "Host: 172.22.68.17\r\n"
4657 "Connection: keep-alive\r\n\r\n"),
4660 MockRead data_reads1
[] = {
4661 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4662 // Negotiate and NTLM are often requested together. However, we only want
4663 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4664 // the header that requests Negotiate for this test.
4665 MockRead("WWW-Authenticate: NTLM\r\n"),
4666 MockRead("Connection: close\r\n"),
4667 MockRead("Content-Length: 42\r\n"),
4668 MockRead("Content-Type: text/html\r\n\r\n"),
4669 // Missing content -- won't matter, as connection will be reset.
4670 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4673 MockWrite data_writes2
[] = {
4674 // After restarting with a null identity, this is the
4675 // request we should be issuing -- the final header line contains a Type
4677 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4678 "Host: 172.22.68.17\r\n"
4679 "Connection: keep-alive\r\n"
4680 "Authorization: NTLM "
4681 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4683 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4684 // (the credentials for the origin server). The second request continues
4685 // on the same connection.
4686 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4687 "Host: 172.22.68.17\r\n"
4688 "Connection: keep-alive\r\n"
4689 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4690 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4691 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4692 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4693 "ahlhx5I=\r\n\r\n"),
4696 MockRead data_reads2
[] = {
4697 // The origin server responds with a Type 2 message.
4698 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4699 MockRead("WWW-Authenticate: NTLM "
4700 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4701 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4702 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4703 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4704 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4705 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4707 MockRead("Content-Length: 42\r\n"),
4708 MockRead("Content-Type: text/html\r\n\r\n"),
4709 MockRead("You are not authorized to view this page\r\n"),
4711 // Lastly we get the desired content.
4712 MockRead("HTTP/1.1 200 OK\r\n"),
4713 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4714 MockRead("Content-Length: 13\r\n\r\n"),
4715 MockRead("Please Login\r\n"),
4716 MockRead(SYNCHRONOUS
, OK
),
4719 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4720 data_writes1
, arraysize(data_writes1
));
4721 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4722 data_writes2
, arraysize(data_writes2
));
4723 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4724 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4726 TestCompletionCallback callback1
;
4728 scoped_ptr
<HttpTransaction
> trans(
4729 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4731 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4734 rv
= callback1
.WaitForResult();
4737 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4739 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4740 ASSERT_FALSE(response
== NULL
);
4741 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4743 TestCompletionCallback callback2
;
4745 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4746 callback2
.callback());
4747 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4749 rv
= callback2
.WaitForResult();
4752 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4754 response
= trans
->GetResponseInfo();
4755 ASSERT_TRUE(response
!= NULL
);
4756 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4758 TestCompletionCallback callback3
;
4760 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4761 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4763 rv
= callback3
.WaitForResult();
4766 response
= trans
->GetResponseInfo();
4767 ASSERT_TRUE(response
!= NULL
);
4768 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4769 EXPECT_EQ(13, response
->headers
->GetContentLength());
4772 // Enter a wrong password, and then the correct one.
4773 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4774 HttpRequestInfo request
;
4775 request
.method
= "GET";
4776 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4777 request
.load_flags
= 0;
4779 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4781 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4783 MockWrite data_writes1
[] = {
4784 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4785 "Host: 172.22.68.17\r\n"
4786 "Connection: keep-alive\r\n\r\n"),
4789 MockRead data_reads1
[] = {
4790 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4791 // Negotiate and NTLM are often requested together. However, we only want
4792 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4793 // the header that requests Negotiate for this test.
4794 MockRead("WWW-Authenticate: NTLM\r\n"),
4795 MockRead("Connection: close\r\n"),
4796 MockRead("Content-Length: 42\r\n"),
4797 MockRead("Content-Type: text/html\r\n\r\n"),
4798 // Missing content -- won't matter, as connection will be reset.
4799 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4802 MockWrite data_writes2
[] = {
4803 // After restarting with a null identity, this is the
4804 // request we should be issuing -- the final header line contains a Type
4806 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4807 "Host: 172.22.68.17\r\n"
4808 "Connection: keep-alive\r\n"
4809 "Authorization: NTLM "
4810 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4812 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4813 // (the credentials for the origin server). The second request continues
4814 // on the same connection.
4815 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4816 "Host: 172.22.68.17\r\n"
4817 "Connection: keep-alive\r\n"
4818 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4819 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4820 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4821 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4822 "4Ww7b7E=\r\n\r\n"),
4825 MockRead data_reads2
[] = {
4826 // The origin server responds with a Type 2 message.
4827 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4828 MockRead("WWW-Authenticate: NTLM "
4829 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4830 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4831 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4832 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4833 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4834 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4836 MockRead("Content-Length: 42\r\n"),
4837 MockRead("Content-Type: text/html\r\n\r\n"),
4838 MockRead("You are not authorized to view this page\r\n"),
4841 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4842 MockRead("WWW-Authenticate: NTLM\r\n"),
4843 MockRead("Connection: close\r\n"),
4844 MockRead("Content-Length: 42\r\n"),
4845 MockRead("Content-Type: text/html\r\n\r\n"),
4846 // Missing content -- won't matter, as connection will be reset.
4847 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4850 MockWrite data_writes3
[] = {
4851 // After restarting with a null identity, this is the
4852 // request we should be issuing -- the final header line contains a Type
4854 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4855 "Host: 172.22.68.17\r\n"
4856 "Connection: keep-alive\r\n"
4857 "Authorization: NTLM "
4858 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4860 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4861 // (the credentials for the origin server). The second request continues
4862 // on the same connection.
4863 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4864 "Host: 172.22.68.17\r\n"
4865 "Connection: keep-alive\r\n"
4866 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4867 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4868 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4869 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4870 "+4MUm7c=\r\n\r\n"),
4873 MockRead data_reads3
[] = {
4874 // The origin server responds with a Type 2 message.
4875 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4876 MockRead("WWW-Authenticate: NTLM "
4877 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4878 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4879 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4880 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4881 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4882 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4884 MockRead("Content-Length: 42\r\n"),
4885 MockRead("Content-Type: text/html\r\n\r\n"),
4886 MockRead("You are not authorized to view this page\r\n"),
4888 // Lastly we get the desired content.
4889 MockRead("HTTP/1.1 200 OK\r\n"),
4890 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4891 MockRead("Content-Length: 13\r\n\r\n"),
4892 MockRead("Please Login\r\n"),
4893 MockRead(SYNCHRONOUS
, OK
),
4896 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4897 data_writes1
, arraysize(data_writes1
));
4898 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4899 data_writes2
, arraysize(data_writes2
));
4900 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4901 data_writes3
, arraysize(data_writes3
));
4902 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4903 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4904 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4906 TestCompletionCallback callback1
;
4908 scoped_ptr
<HttpTransaction
> trans(
4909 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4911 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4914 rv
= callback1
.WaitForResult();
4917 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4919 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4920 ASSERT_TRUE(response
!= NULL
);
4921 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4923 TestCompletionCallback callback2
;
4925 // Enter the wrong password.
4926 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4927 callback2
.callback());
4928 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4930 rv
= callback2
.WaitForResult();
4933 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4934 TestCompletionCallback callback3
;
4935 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4937 rv
= callback3
.WaitForResult();
4939 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4941 response
= trans
->GetResponseInfo();
4942 ASSERT_FALSE(response
== NULL
);
4943 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4945 TestCompletionCallback callback4
;
4947 // Now enter the right password.
4948 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4949 callback4
.callback());
4950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4952 rv
= callback4
.WaitForResult();
4955 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4957 TestCompletionCallback callback5
;
4959 // One more roundtrip
4960 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4961 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4963 rv
= callback5
.WaitForResult();
4966 response
= trans
->GetResponseInfo();
4967 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4968 EXPECT_EQ(13, response
->headers
->GetContentLength());
4970 #endif // NTLM_PORTABLE
4972 // Test reading a server response which has only headers, and no body.
4973 // After some maximum number of bytes is consumed, the transaction should
4974 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4975 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4976 HttpRequestInfo request
;
4977 request
.method
= "GET";
4978 request
.url
= GURL("http://www.example.org/");
4979 request
.load_flags
= 0;
4981 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4982 scoped_ptr
<HttpTransaction
> trans(
4983 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4985 // Respond with 300 kb of headers (we should fail after 256 kb).
4986 std::string large_headers_string
;
4987 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4989 MockRead data_reads
[] = {
4990 MockRead("HTTP/1.0 200 OK\r\n"),
4991 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4992 MockRead("\r\nBODY"),
4993 MockRead(SYNCHRONOUS
, OK
),
4995 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4996 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4998 TestCompletionCallback callback
;
5000 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5001 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5003 rv
= callback
.WaitForResult();
5004 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5007 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5008 // establish tunnel.
5009 // http://code.google.com/p/chromium/issues/detail?id=3772
5010 TEST_P(HttpNetworkTransactionTest
,
5011 DontRecycleTransportSocketForSSLTunnel
) {
5012 HttpRequestInfo request
;
5013 request
.method
= "GET";
5014 request
.url
= GURL("https://www.example.org/");
5015 request
.load_flags
= 0;
5017 // Configure against proxy server "myproxy:70".
5018 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5020 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5022 scoped_ptr
<HttpTransaction
> trans(
5023 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5025 // Since we have proxy, should try to establish tunnel.
5026 MockWrite data_writes1
[] = {
5028 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5029 "Host: www.example.org\r\n"
5030 "Proxy-Connection: keep-alive\r\n\r\n"),
5033 // The proxy responds to the connect with a 404, using a persistent
5034 // connection. Usually a proxy would return 501 (not implemented),
5035 // or 200 (tunnel established).
5036 MockRead data_reads1
[] = {
5037 MockRead("HTTP/1.1 404 Not Found\r\n"),
5038 MockRead("Content-Length: 10\r\n\r\n"),
5039 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5042 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5043 data_writes1
, arraysize(data_writes1
));
5044 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5046 TestCompletionCallback callback1
;
5048 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5049 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5051 rv
= callback1
.WaitForResult();
5052 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5054 // Empty the current queue. This is necessary because idle sockets are
5055 // added to the connection pool asynchronously with a PostTask.
5056 base::MessageLoop::current()->RunUntilIdle();
5058 // We now check to make sure the TCPClientSocket was not added back to
5060 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5062 base::MessageLoop::current()->RunUntilIdle();
5063 // Make sure that the socket didn't get recycled after calling the destructor.
5064 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5067 // Make sure that we recycle a socket after reading all of the response body.
5068 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5069 HttpRequestInfo request
;
5070 request
.method
= "GET";
5071 request
.url
= GURL("http://www.example.org/");
5072 request
.load_flags
= 0;
5074 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5076 scoped_ptr
<HttpTransaction
> trans(
5077 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5079 MockRead data_reads
[] = {
5080 // A part of the response body is received with the response headers.
5081 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5082 // The rest of the response body is received in two parts.
5085 MockRead("junk"), // Should not be read!!
5086 MockRead(SYNCHRONOUS
, OK
),
5089 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5090 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5092 TestCompletionCallback callback
;
5094 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5095 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5097 rv
= callback
.WaitForResult();
5100 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5101 ASSERT_TRUE(response
!= NULL
);
5103 EXPECT_TRUE(response
->headers
.get() != NULL
);
5104 std::string status_line
= response
->headers
->GetStatusLine();
5105 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5107 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5109 std::string response_data
;
5110 rv
= ReadTransaction(trans
.get(), &response_data
);
5112 EXPECT_EQ("hello world", response_data
);
5114 // Empty the current queue. This is necessary because idle sockets are
5115 // added to the connection pool asynchronously with a PostTask.
5116 base::MessageLoop::current()->RunUntilIdle();
5118 // We now check to make sure the socket was added back to the pool.
5119 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5122 // Make sure that we recycle a SSL socket after reading all of the response
5124 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5125 HttpRequestInfo request
;
5126 request
.method
= "GET";
5127 request
.url
= GURL("https://www.example.org/");
5128 request
.load_flags
= 0;
5130 MockWrite data_writes
[] = {
5132 "GET / HTTP/1.1\r\n"
5133 "Host: www.example.org\r\n"
5134 "Connection: keep-alive\r\n\r\n"),
5137 MockRead data_reads
[] = {
5138 MockRead("HTTP/1.1 200 OK\r\n"),
5139 MockRead("Content-Length: 11\r\n\r\n"),
5140 MockRead("hello world"),
5141 MockRead(SYNCHRONOUS
, OK
),
5144 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5145 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5147 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5148 data_writes
, arraysize(data_writes
));
5149 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5151 TestCompletionCallback callback
;
5153 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5154 scoped_ptr
<HttpTransaction
> trans(
5155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5157 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5159 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5160 EXPECT_EQ(OK
, callback
.WaitForResult());
5162 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5163 ASSERT_TRUE(response
!= NULL
);
5164 ASSERT_TRUE(response
->headers
.get() != NULL
);
5165 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5167 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5169 std::string response_data
;
5170 rv
= ReadTransaction(trans
.get(), &response_data
);
5172 EXPECT_EQ("hello world", response_data
);
5174 // Empty the current queue. This is necessary because idle sockets are
5175 // added to the connection pool asynchronously with a PostTask.
5176 base::MessageLoop::current()->RunUntilIdle();
5178 // We now check to make sure the socket was added back to the pool.
5179 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5182 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5183 // from the pool and make sure that we recover okay.
5184 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5185 HttpRequestInfo request
;
5186 request
.method
= "GET";
5187 request
.url
= GURL("https://www.example.org/");
5188 request
.load_flags
= 0;
5190 MockWrite data_writes
[] = {
5192 "GET / HTTP/1.1\r\n"
5193 "Host: www.example.org\r\n"
5194 "Connection: keep-alive\r\n\r\n"),
5196 "GET / HTTP/1.1\r\n"
5197 "Host: www.example.org\r\n"
5198 "Connection: keep-alive\r\n\r\n"),
5201 MockRead data_reads
[] = {
5202 MockRead("HTTP/1.1 200 OK\r\n"),
5203 MockRead("Content-Length: 11\r\n\r\n"),
5204 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5205 MockRead("hello world"),
5206 MockRead(ASYNC
, 0, 0) // EOF
5209 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5210 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5211 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5212 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5214 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5215 data_writes
, arraysize(data_writes
));
5216 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5217 data_writes
, arraysize(data_writes
));
5218 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5219 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5221 TestCompletionCallback callback
;
5223 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5224 scoped_ptr
<HttpTransaction
> trans(
5225 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5227 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5229 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5230 EXPECT_EQ(OK
, callback
.WaitForResult());
5232 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5233 ASSERT_TRUE(response
!= NULL
);
5234 ASSERT_TRUE(response
->headers
.get() != NULL
);
5235 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5237 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5239 std::string response_data
;
5240 rv
= ReadTransaction(trans
.get(), &response_data
);
5242 EXPECT_EQ("hello world", response_data
);
5244 // Empty the current queue. This is necessary because idle sockets are
5245 // added to the connection pool asynchronously with a PostTask.
5246 base::MessageLoop::current()->RunUntilIdle();
5248 // We now check to make sure the socket was added back to the pool.
5249 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5251 // Now start the second transaction, which should reuse the previous socket.
5253 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5255 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5257 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5258 EXPECT_EQ(OK
, callback
.WaitForResult());
5260 response
= trans
->GetResponseInfo();
5261 ASSERT_TRUE(response
!= NULL
);
5262 ASSERT_TRUE(response
->headers
.get() != NULL
);
5263 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5265 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5267 rv
= ReadTransaction(trans
.get(), &response_data
);
5269 EXPECT_EQ("hello world", response_data
);
5271 // Empty the current queue. This is necessary because idle sockets are
5272 // added to the connection pool asynchronously with a PostTask.
5273 base::MessageLoop::current()->RunUntilIdle();
5275 // We now check to make sure the socket was added back to the pool.
5276 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5279 // Make sure that we recycle a socket after a zero-length response.
5280 // http://crbug.com/9880
5281 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5282 HttpRequestInfo request
;
5283 request
.method
= "GET";
5285 "http://www.example.org/csi?v=3&s=web&action=&"
5286 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5287 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5288 "rt=prt.2642,ol.2649,xjs.2951");
5289 request
.load_flags
= 0;
5291 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5293 scoped_ptr
<HttpTransaction
> trans(
5294 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5296 MockRead data_reads
[] = {
5297 MockRead("HTTP/1.1 204 No Content\r\n"
5298 "Content-Length: 0\r\n"
5299 "Content-Type: text/html\r\n\r\n"),
5300 MockRead("junk"), // Should not be read!!
5301 MockRead(SYNCHRONOUS
, OK
),
5304 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5305 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5307 TestCompletionCallback callback
;
5309 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5310 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5312 rv
= callback
.WaitForResult();
5315 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5316 ASSERT_TRUE(response
!= NULL
);
5318 EXPECT_TRUE(response
->headers
.get() != NULL
);
5319 std::string status_line
= response
->headers
->GetStatusLine();
5320 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5322 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5324 std::string response_data
;
5325 rv
= ReadTransaction(trans
.get(), &response_data
);
5327 EXPECT_EQ("", response_data
);
5329 // Empty the current queue. This is necessary because idle sockets are
5330 // added to the connection pool asynchronously with a PostTask.
5331 base::MessageLoop::current()->RunUntilIdle();
5333 // We now check to make sure the socket was added back to the pool.
5334 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5337 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5338 ScopedVector
<UploadElementReader
> element_readers
;
5339 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5340 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5342 HttpRequestInfo request
[2];
5343 // Transaction 1: a GET request that succeeds. The socket is recycled
5345 request
[0].method
= "GET";
5346 request
[0].url
= GURL("http://www.google.com/");
5347 request
[0].load_flags
= 0;
5348 // Transaction 2: a POST request. Reuses the socket kept alive from
5349 // transaction 1. The first attempts fails when writing the POST data.
5350 // This causes the transaction to retry with a new socket. The second
5351 // attempt succeeds.
5352 request
[1].method
= "POST";
5353 request
[1].url
= GURL("http://www.google.com/login.cgi");
5354 request
[1].upload_data_stream
= &upload_data_stream
;
5355 request
[1].load_flags
= 0;
5357 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5359 // The first socket is used for transaction 1 and the first attempt of
5362 // The response of transaction 1.
5363 MockRead data_reads1
[] = {
5364 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5365 MockRead("hello world"),
5366 MockRead(SYNCHRONOUS
, OK
),
5368 // The mock write results of transaction 1 and the first attempt of
5370 MockWrite data_writes1
[] = {
5371 MockWrite(SYNCHRONOUS
, 64), // GET
5372 MockWrite(SYNCHRONOUS
, 93), // POST
5373 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5375 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5376 data_writes1
, arraysize(data_writes1
));
5378 // The second socket is used for the second attempt of transaction 2.
5380 // The response of transaction 2.
5381 MockRead data_reads2
[] = {
5382 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5383 MockRead("welcome"),
5384 MockRead(SYNCHRONOUS
, OK
),
5386 // The mock write results of the second attempt of transaction 2.
5387 MockWrite data_writes2
[] = {
5388 MockWrite(SYNCHRONOUS
, 93), // POST
5389 MockWrite(SYNCHRONOUS
, 3), // POST data
5391 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5392 data_writes2
, arraysize(data_writes2
));
5394 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5395 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5397 const char* const kExpectedResponseData
[] = {
5398 "hello world", "welcome"
5401 for (int i
= 0; i
< 2; ++i
) {
5402 scoped_ptr
<HttpTransaction
> trans(
5403 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5405 TestCompletionCallback callback
;
5407 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5408 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5410 rv
= callback
.WaitForResult();
5413 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5414 ASSERT_TRUE(response
!= NULL
);
5416 EXPECT_TRUE(response
->headers
.get() != NULL
);
5417 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5419 std::string response_data
;
5420 rv
= ReadTransaction(trans
.get(), &response_data
);
5422 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5426 // Test the request-challenge-retry sequence for basic auth when there is
5427 // an identity in the URL. The request should be sent as normal, but when
5428 // it fails the identity from the URL is used to answer the challenge.
5429 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5430 HttpRequestInfo request
;
5431 request
.method
= "GET";
5432 request
.url
= GURL("http://foo:b@r@www.example.org/");
5433 request
.load_flags
= LOAD_NORMAL
;
5435 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5436 scoped_ptr
<HttpTransaction
> trans(
5437 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5439 // The password contains an escaped character -- for this test to pass it
5440 // will need to be unescaped by HttpNetworkTransaction.
5441 EXPECT_EQ("b%40r", request
.url
.password());
5443 MockWrite data_writes1
[] = {
5445 "GET / HTTP/1.1\r\n"
5446 "Host: www.example.org\r\n"
5447 "Connection: keep-alive\r\n\r\n"),
5450 MockRead data_reads1
[] = {
5451 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5452 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5453 MockRead("Content-Length: 10\r\n\r\n"),
5454 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5457 // After the challenge above, the transaction will be restarted using the
5458 // identity from the url (foo, b@r) to answer the challenge.
5459 MockWrite data_writes2
[] = {
5461 "GET / HTTP/1.1\r\n"
5462 "Host: www.example.org\r\n"
5463 "Connection: keep-alive\r\n"
5464 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5467 MockRead data_reads2
[] = {
5468 MockRead("HTTP/1.0 200 OK\r\n"),
5469 MockRead("Content-Length: 100\r\n\r\n"),
5470 MockRead(SYNCHRONOUS
, OK
),
5473 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5474 data_writes1
, arraysize(data_writes1
));
5475 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5476 data_writes2
, arraysize(data_writes2
));
5477 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5478 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5480 TestCompletionCallback callback1
;
5481 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5482 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5483 rv
= callback1
.WaitForResult();
5485 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5487 TestCompletionCallback callback2
;
5488 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5489 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5490 rv
= callback2
.WaitForResult();
5492 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5494 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5495 ASSERT_TRUE(response
!= NULL
);
5497 // There is no challenge info, since the identity in URL worked.
5498 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5500 EXPECT_EQ(100, response
->headers
->GetContentLength());
5502 // Empty the current queue.
5503 base::MessageLoop::current()->RunUntilIdle();
5506 // Test the request-challenge-retry sequence for basic auth when there is an
5507 // incorrect identity in the URL. The identity from the URL should be used only
5509 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5510 HttpRequestInfo request
;
5511 request
.method
= "GET";
5512 // Note: the URL has a username:password in it. The password "baz" is
5513 // wrong (should be "bar").
5514 request
.url
= GURL("http://foo:baz@www.example.org/");
5516 request
.load_flags
= LOAD_NORMAL
;
5518 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5519 scoped_ptr
<HttpTransaction
> trans(
5520 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5522 MockWrite data_writes1
[] = {
5524 "GET / HTTP/1.1\r\n"
5525 "Host: www.example.org\r\n"
5526 "Connection: keep-alive\r\n\r\n"),
5529 MockRead data_reads1
[] = {
5530 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5531 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5532 MockRead("Content-Length: 10\r\n\r\n"),
5533 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5536 // After the challenge above, the transaction will be restarted using the
5537 // identity from the url (foo, baz) to answer the challenge.
5538 MockWrite data_writes2
[] = {
5540 "GET / HTTP/1.1\r\n"
5541 "Host: www.example.org\r\n"
5542 "Connection: keep-alive\r\n"
5543 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5546 MockRead data_reads2
[] = {
5547 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5548 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5549 MockRead("Content-Length: 10\r\n\r\n"),
5550 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5553 // After the challenge above, the transaction will be restarted using the
5554 // identity supplied by the user (foo, bar) to answer the challenge.
5555 MockWrite data_writes3
[] = {
5557 "GET / HTTP/1.1\r\n"
5558 "Host: www.example.org\r\n"
5559 "Connection: keep-alive\r\n"
5560 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5563 MockRead data_reads3
[] = {
5564 MockRead("HTTP/1.0 200 OK\r\n"),
5565 MockRead("Content-Length: 100\r\n\r\n"),
5566 MockRead(SYNCHRONOUS
, OK
),
5569 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5570 data_writes1
, arraysize(data_writes1
));
5571 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5572 data_writes2
, arraysize(data_writes2
));
5573 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5574 data_writes3
, arraysize(data_writes3
));
5575 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5576 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5577 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5579 TestCompletionCallback callback1
;
5581 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5584 rv
= callback1
.WaitForResult();
5587 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5588 TestCompletionCallback callback2
;
5589 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5590 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5591 rv
= callback2
.WaitForResult();
5593 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5595 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5596 ASSERT_TRUE(response
!= NULL
);
5597 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5599 TestCompletionCallback callback3
;
5600 rv
= trans
->RestartWithAuth(
5601 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5602 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5603 rv
= callback3
.WaitForResult();
5605 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5607 response
= trans
->GetResponseInfo();
5608 ASSERT_TRUE(response
!= NULL
);
5610 // There is no challenge info, since the identity worked.
5611 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5613 EXPECT_EQ(100, response
->headers
->GetContentLength());
5615 // Empty the current queue.
5616 base::MessageLoop::current()->RunUntilIdle();
5620 // Test the request-challenge-retry sequence for basic auth when there is a
5621 // correct identity in the URL, but its use is being suppressed. The identity
5622 // from the URL should never be used.
5623 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5624 HttpRequestInfo request
;
5625 request
.method
= "GET";
5626 request
.url
= GURL("http://foo:bar@www.example.org/");
5627 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5629 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5630 scoped_ptr
<HttpTransaction
> trans(
5631 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5633 MockWrite data_writes1
[] = {
5635 "GET / HTTP/1.1\r\n"
5636 "Host: www.example.org\r\n"
5637 "Connection: keep-alive\r\n\r\n"),
5640 MockRead data_reads1
[] = {
5641 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5643 MockRead("Content-Length: 10\r\n\r\n"),
5644 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5647 // After the challenge above, the transaction will be restarted using the
5648 // identity supplied by the user, not the one in the URL, to answer the
5650 MockWrite data_writes3
[] = {
5652 "GET / HTTP/1.1\r\n"
5653 "Host: www.example.org\r\n"
5654 "Connection: keep-alive\r\n"
5655 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5658 MockRead data_reads3
[] = {
5659 MockRead("HTTP/1.0 200 OK\r\n"),
5660 MockRead("Content-Length: 100\r\n\r\n"),
5661 MockRead(SYNCHRONOUS
, OK
),
5664 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5665 data_writes1
, arraysize(data_writes1
));
5666 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5667 data_writes3
, arraysize(data_writes3
));
5668 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5669 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5671 TestCompletionCallback callback1
;
5672 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5673 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5674 rv
= callback1
.WaitForResult();
5676 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5678 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5679 ASSERT_TRUE(response
!= NULL
);
5680 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5682 TestCompletionCallback callback3
;
5683 rv
= trans
->RestartWithAuth(
5684 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5685 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5686 rv
= callback3
.WaitForResult();
5688 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5690 response
= trans
->GetResponseInfo();
5691 ASSERT_TRUE(response
!= NULL
);
5693 // There is no challenge info, since the identity worked.
5694 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5695 EXPECT_EQ(100, response
->headers
->GetContentLength());
5697 // Empty the current queue.
5698 base::MessageLoop::current()->RunUntilIdle();
5701 // Test that previously tried username/passwords for a realm get re-used.
5702 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5703 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5705 // Transaction 1: authenticate (foo, bar) on MyRealm1
5707 HttpRequestInfo request
;
5708 request
.method
= "GET";
5709 request
.url
= GURL("http://www.example.org/x/y/z");
5710 request
.load_flags
= 0;
5712 scoped_ptr
<HttpTransaction
> trans(
5713 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5715 MockWrite data_writes1
[] = {
5717 "GET /x/y/z HTTP/1.1\r\n"
5718 "Host: www.example.org\r\n"
5719 "Connection: keep-alive\r\n\r\n"),
5722 MockRead data_reads1
[] = {
5723 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5724 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5725 MockRead("Content-Length: 10000\r\n\r\n"),
5726 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5729 // Resend with authorization (username=foo, password=bar)
5730 MockWrite data_writes2
[] = {
5732 "GET /x/y/z HTTP/1.1\r\n"
5733 "Host: www.example.org\r\n"
5734 "Connection: keep-alive\r\n"
5735 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5738 // Sever accepts the authorization.
5739 MockRead data_reads2
[] = {
5740 MockRead("HTTP/1.0 200 OK\r\n"),
5741 MockRead("Content-Length: 100\r\n\r\n"),
5742 MockRead(SYNCHRONOUS
, OK
),
5745 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5746 data_writes1
, arraysize(data_writes1
));
5747 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5748 data_writes2
, arraysize(data_writes2
));
5749 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5750 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5752 TestCompletionCallback callback1
;
5754 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5755 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5757 rv
= callback1
.WaitForResult();
5760 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5761 ASSERT_TRUE(response
!= NULL
);
5762 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5764 TestCompletionCallback callback2
;
5766 rv
= trans
->RestartWithAuth(
5767 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5768 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5770 rv
= callback2
.WaitForResult();
5773 response
= trans
->GetResponseInfo();
5774 ASSERT_TRUE(response
!= NULL
);
5775 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5776 EXPECT_EQ(100, response
->headers
->GetContentLength());
5779 // ------------------------------------------------------------------------
5781 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5783 HttpRequestInfo request
;
5784 request
.method
= "GET";
5785 // Note that Transaction 1 was at /x/y/z, so this is in the same
5786 // protection space as MyRealm1.
5787 request
.url
= GURL("http://www.example.org/x/y/a/b");
5788 request
.load_flags
= 0;
5790 scoped_ptr
<HttpTransaction
> trans(
5791 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5793 MockWrite data_writes1
[] = {
5795 "GET /x/y/a/b HTTP/1.1\r\n"
5796 "Host: www.example.org\r\n"
5797 "Connection: keep-alive\r\n"
5798 // Send preemptive authorization for MyRealm1
5799 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5802 // The server didn't like the preemptive authorization, and
5803 // challenges us for a different realm (MyRealm2).
5804 MockRead data_reads1
[] = {
5805 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5806 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5807 MockRead("Content-Length: 10000\r\n\r\n"),
5808 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5811 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5812 MockWrite data_writes2
[] = {
5814 "GET /x/y/a/b HTTP/1.1\r\n"
5815 "Host: www.example.org\r\n"
5816 "Connection: keep-alive\r\n"
5817 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5820 // Sever accepts the authorization.
5821 MockRead data_reads2
[] = {
5822 MockRead("HTTP/1.0 200 OK\r\n"),
5823 MockRead("Content-Length: 100\r\n\r\n"),
5824 MockRead(SYNCHRONOUS
, OK
),
5827 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5828 data_writes1
, arraysize(data_writes1
));
5829 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5830 data_writes2
, arraysize(data_writes2
));
5831 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5832 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5834 TestCompletionCallback callback1
;
5836 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5837 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5839 rv
= callback1
.WaitForResult();
5842 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5843 ASSERT_TRUE(response
!= NULL
);
5844 ASSERT_TRUE(response
->auth_challenge
.get());
5845 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5846 EXPECT_EQ("www.example.org:80",
5847 response
->auth_challenge
->challenger
.ToString());
5848 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5849 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5851 TestCompletionCallback callback2
;
5853 rv
= trans
->RestartWithAuth(
5854 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5855 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5857 rv
= callback2
.WaitForResult();
5860 response
= trans
->GetResponseInfo();
5861 ASSERT_TRUE(response
!= NULL
);
5862 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5863 EXPECT_EQ(100, response
->headers
->GetContentLength());
5866 // ------------------------------------------------------------------------
5868 // Transaction 3: Resend a request in MyRealm's protection space --
5869 // succeed with preemptive authorization.
5871 HttpRequestInfo request
;
5872 request
.method
= "GET";
5873 request
.url
= GURL("http://www.example.org/x/y/z2");
5874 request
.load_flags
= 0;
5876 scoped_ptr
<HttpTransaction
> trans(
5877 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5879 MockWrite data_writes1
[] = {
5881 "GET /x/y/z2 HTTP/1.1\r\n"
5882 "Host: www.example.org\r\n"
5883 "Connection: keep-alive\r\n"
5884 // The authorization for MyRealm1 gets sent preemptively
5885 // (since the url is in the same protection space)
5886 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5889 // Sever accepts the preemptive authorization
5890 MockRead data_reads1
[] = {
5891 MockRead("HTTP/1.0 200 OK\r\n"),
5892 MockRead("Content-Length: 100\r\n\r\n"),
5893 MockRead(SYNCHRONOUS
, OK
),
5896 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5897 data_writes1
, arraysize(data_writes1
));
5898 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5900 TestCompletionCallback callback1
;
5902 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5903 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5905 rv
= callback1
.WaitForResult();
5908 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5909 ASSERT_TRUE(response
!= NULL
);
5911 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5912 EXPECT_EQ(100, response
->headers
->GetContentLength());
5915 // ------------------------------------------------------------------------
5917 // Transaction 4: request another URL in MyRealm (however the
5918 // url is not known to belong to the protection space, so no pre-auth).
5920 HttpRequestInfo request
;
5921 request
.method
= "GET";
5922 request
.url
= GURL("http://www.example.org/x/1");
5923 request
.load_flags
= 0;
5925 scoped_ptr
<HttpTransaction
> trans(
5926 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5928 MockWrite data_writes1
[] = {
5930 "GET /x/1 HTTP/1.1\r\n"
5931 "Host: www.example.org\r\n"
5932 "Connection: keep-alive\r\n\r\n"),
5935 MockRead data_reads1
[] = {
5936 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5937 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5938 MockRead("Content-Length: 10000\r\n\r\n"),
5939 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5942 // Resend with authorization from MyRealm's cache.
5943 MockWrite data_writes2
[] = {
5945 "GET /x/1 HTTP/1.1\r\n"
5946 "Host: www.example.org\r\n"
5947 "Connection: keep-alive\r\n"
5948 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5951 // Sever accepts the authorization.
5952 MockRead data_reads2
[] = {
5953 MockRead("HTTP/1.0 200 OK\r\n"),
5954 MockRead("Content-Length: 100\r\n\r\n"),
5955 MockRead(SYNCHRONOUS
, OK
),
5958 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5959 data_writes1
, arraysize(data_writes1
));
5960 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5961 data_writes2
, arraysize(data_writes2
));
5962 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5963 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5965 TestCompletionCallback callback1
;
5967 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5968 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5970 rv
= callback1
.WaitForResult();
5973 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5974 TestCompletionCallback callback2
;
5975 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5977 rv
= callback2
.WaitForResult();
5979 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5981 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5982 ASSERT_TRUE(response
!= NULL
);
5983 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5984 EXPECT_EQ(100, response
->headers
->GetContentLength());
5987 // ------------------------------------------------------------------------
5989 // Transaction 5: request a URL in MyRealm, but the server rejects the
5990 // cached identity. Should invalidate and re-prompt.
5992 HttpRequestInfo request
;
5993 request
.method
= "GET";
5994 request
.url
= GURL("http://www.example.org/p/q/t");
5995 request
.load_flags
= 0;
5997 scoped_ptr
<HttpTransaction
> trans(
5998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6000 MockWrite data_writes1
[] = {
6002 "GET /p/q/t HTTP/1.1\r\n"
6003 "Host: www.example.org\r\n"
6004 "Connection: keep-alive\r\n\r\n"),
6007 MockRead data_reads1
[] = {
6008 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6009 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6010 MockRead("Content-Length: 10000\r\n\r\n"),
6011 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6014 // Resend with authorization from cache for MyRealm.
6015 MockWrite data_writes2
[] = {
6017 "GET /p/q/t HTTP/1.1\r\n"
6018 "Host: www.example.org\r\n"
6019 "Connection: keep-alive\r\n"
6020 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6023 // Sever rejects the authorization.
6024 MockRead data_reads2
[] = {
6025 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6026 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6027 MockRead("Content-Length: 10000\r\n\r\n"),
6028 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6031 // At this point we should prompt for new credentials for MyRealm.
6032 // Restart with username=foo3, password=foo4.
6033 MockWrite data_writes3
[] = {
6035 "GET /p/q/t HTTP/1.1\r\n"
6036 "Host: www.example.org\r\n"
6037 "Connection: keep-alive\r\n"
6038 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6041 // Sever accepts the authorization.
6042 MockRead data_reads3
[] = {
6043 MockRead("HTTP/1.0 200 OK\r\n"),
6044 MockRead("Content-Length: 100\r\n\r\n"),
6045 MockRead(SYNCHRONOUS
, OK
),
6048 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6049 data_writes1
, arraysize(data_writes1
));
6050 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6051 data_writes2
, arraysize(data_writes2
));
6052 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6053 data_writes3
, arraysize(data_writes3
));
6054 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6055 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6056 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6058 TestCompletionCallback callback1
;
6060 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6061 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6063 rv
= callback1
.WaitForResult();
6066 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6067 TestCompletionCallback callback2
;
6068 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6070 rv
= callback2
.WaitForResult();
6072 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6074 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6075 ASSERT_TRUE(response
!= NULL
);
6076 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6078 TestCompletionCallback callback3
;
6080 rv
= trans
->RestartWithAuth(
6081 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6082 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6084 rv
= callback3
.WaitForResult();
6087 response
= trans
->GetResponseInfo();
6088 ASSERT_TRUE(response
!= NULL
);
6089 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6090 EXPECT_EQ(100, response
->headers
->GetContentLength());
6094 // Tests that nonce count increments when multiple auth attempts
6095 // are started with the same nonce.
6096 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6097 HttpAuthHandlerDigest::Factory
* digest_factory
=
6098 new HttpAuthHandlerDigest::Factory();
6099 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6100 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6101 digest_factory
->set_nonce_generator(nonce_generator
);
6102 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6103 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6105 // Transaction 1: authenticate (foo, bar) on MyRealm1
6107 HttpRequestInfo request
;
6108 request
.method
= "GET";
6109 request
.url
= GURL("http://www.example.org/x/y/z");
6110 request
.load_flags
= 0;
6112 scoped_ptr
<HttpTransaction
> trans(
6113 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6115 MockWrite data_writes1
[] = {
6117 "GET /x/y/z HTTP/1.1\r\n"
6118 "Host: www.example.org\r\n"
6119 "Connection: keep-alive\r\n\r\n"),
6122 MockRead data_reads1
[] = {
6123 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6124 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6125 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6126 MockRead(SYNCHRONOUS
, OK
),
6129 // Resend with authorization (username=foo, password=bar)
6130 MockWrite data_writes2
[] = {
6132 "GET /x/y/z HTTP/1.1\r\n"
6133 "Host: www.example.org\r\n"
6134 "Connection: keep-alive\r\n"
6135 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6136 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6137 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6138 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6141 // Sever accepts the authorization.
6142 MockRead data_reads2
[] = {
6143 MockRead("HTTP/1.0 200 OK\r\n"),
6144 MockRead(SYNCHRONOUS
, OK
),
6147 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6148 data_writes1
, arraysize(data_writes1
));
6149 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6150 data_writes2
, arraysize(data_writes2
));
6151 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6152 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6154 TestCompletionCallback callback1
;
6156 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6159 rv
= callback1
.WaitForResult();
6162 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6163 ASSERT_TRUE(response
!= NULL
);
6164 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6166 TestCompletionCallback callback2
;
6168 rv
= trans
->RestartWithAuth(
6169 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6170 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6172 rv
= callback2
.WaitForResult();
6175 response
= trans
->GetResponseInfo();
6176 ASSERT_TRUE(response
!= NULL
);
6177 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6180 // ------------------------------------------------------------------------
6182 // Transaction 2: Request another resource in digestive's protection space.
6183 // This will preemptively add an Authorization header which should have an
6184 // "nc" value of 2 (as compared to 1 in the first use.
6186 HttpRequestInfo request
;
6187 request
.method
= "GET";
6188 // Note that Transaction 1 was at /x/y/z, so this is in the same
6189 // protection space as digest.
6190 request
.url
= GURL("http://www.example.org/x/y/a/b");
6191 request
.load_flags
= 0;
6193 scoped_ptr
<HttpTransaction
> trans(
6194 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6196 MockWrite data_writes1
[] = {
6198 "GET /x/y/a/b HTTP/1.1\r\n"
6199 "Host: www.example.org\r\n"
6200 "Connection: keep-alive\r\n"
6201 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6202 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6203 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6204 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6207 // Sever accepts the authorization.
6208 MockRead data_reads1
[] = {
6209 MockRead("HTTP/1.0 200 OK\r\n"),
6210 MockRead("Content-Length: 100\r\n\r\n"),
6211 MockRead(SYNCHRONOUS
, OK
),
6214 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6215 data_writes1
, arraysize(data_writes1
));
6216 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6218 TestCompletionCallback callback1
;
6220 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6221 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6223 rv
= callback1
.WaitForResult();
6226 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6227 ASSERT_TRUE(response
!= NULL
);
6228 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6232 // Test the ResetStateForRestart() private method.
6233 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6234 // Create a transaction (the dependencies aren't important).
6235 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6236 scoped_ptr
<HttpNetworkTransaction
> trans(
6237 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6239 // Setup some state (which we expect ResetStateForRestart() will clear).
6240 trans
->read_buf_
= new IOBuffer(15);
6241 trans
->read_buf_len_
= 15;
6242 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6244 // Setup state in response_
6245 HttpResponseInfo
* response
= &trans
->response_
;
6246 response
->auth_challenge
= new AuthChallengeInfo();
6247 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6248 response
->response_time
= base::Time::Now();
6249 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6251 { // Setup state for response_.vary_data
6252 HttpRequestInfo request
;
6253 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6254 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6255 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6256 request
.extra_headers
.SetHeader("Foo", "1");
6257 request
.extra_headers
.SetHeader("bar", "23");
6258 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6261 // Cause the above state to be reset.
6262 trans
->ResetStateForRestart();
6264 // Verify that the state that needed to be reset, has been reset.
6265 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6266 EXPECT_EQ(0, trans
->read_buf_len_
);
6267 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6268 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6269 EXPECT_TRUE(response
->headers
.get() == NULL
);
6270 EXPECT_FALSE(response
->was_cached
);
6271 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6272 EXPECT_FALSE(response
->vary_data
.is_valid());
6275 // Test HTTPS connections to a site with a bad certificate
6276 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6277 HttpRequestInfo request
;
6278 request
.method
= "GET";
6279 request
.url
= GURL("https://www.example.org/");
6280 request
.load_flags
= 0;
6282 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6283 scoped_ptr
<HttpTransaction
> trans(
6284 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6286 MockWrite data_writes
[] = {
6288 "GET / HTTP/1.1\r\n"
6289 "Host: www.example.org\r\n"
6290 "Connection: keep-alive\r\n\r\n"),
6293 MockRead data_reads
[] = {
6294 MockRead("HTTP/1.0 200 OK\r\n"),
6295 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6296 MockRead("Content-Length: 100\r\n\r\n"),
6297 MockRead(SYNCHRONOUS
, OK
),
6300 StaticSocketDataProvider ssl_bad_certificate
;
6301 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6302 data_writes
, arraysize(data_writes
));
6303 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6304 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6306 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6307 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6308 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6309 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6311 TestCompletionCallback callback
;
6313 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6314 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6316 rv
= callback
.WaitForResult();
6317 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6319 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6320 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6322 rv
= callback
.WaitForResult();
6325 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6327 ASSERT_TRUE(response
!= NULL
);
6328 EXPECT_EQ(100, response
->headers
->GetContentLength());
6331 // Test HTTPS connections to a site with a bad certificate, going through a
6333 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6334 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6336 HttpRequestInfo request
;
6337 request
.method
= "GET";
6338 request
.url
= GURL("https://www.example.org/");
6339 request
.load_flags
= 0;
6341 MockWrite proxy_writes
[] = {
6343 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6344 "Host: www.example.org\r\n"
6345 "Proxy-Connection: keep-alive\r\n\r\n"),
6348 MockRead proxy_reads
[] = {
6349 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6350 MockRead(SYNCHRONOUS
, OK
)
6353 MockWrite data_writes
[] = {
6355 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6356 "Host: www.example.org\r\n"
6357 "Proxy-Connection: keep-alive\r\n\r\n"),
6359 "GET / HTTP/1.1\r\n"
6360 "Host: www.example.org\r\n"
6361 "Connection: keep-alive\r\n\r\n"),
6364 MockRead data_reads
[] = {
6365 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6366 MockRead("HTTP/1.0 200 OK\r\n"),
6367 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6368 MockRead("Content-Length: 100\r\n\r\n"),
6369 MockRead(SYNCHRONOUS
, OK
),
6372 StaticSocketDataProvider
ssl_bad_certificate(
6373 proxy_reads
, arraysize(proxy_reads
),
6374 proxy_writes
, arraysize(proxy_writes
));
6375 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6376 data_writes
, arraysize(data_writes
));
6377 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6378 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6380 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6381 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6382 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6383 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6385 TestCompletionCallback callback
;
6387 for (int i
= 0; i
< 2; i
++) {
6388 session_deps_
.socket_factory
->ResetNextMockIndexes();
6390 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6391 scoped_ptr
<HttpTransaction
> trans(
6392 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6394 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6395 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6397 rv
= callback
.WaitForResult();
6398 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6400 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6401 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6403 rv
= callback
.WaitForResult();
6406 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6408 ASSERT_TRUE(response
!= NULL
);
6409 EXPECT_EQ(100, response
->headers
->GetContentLength());
6414 // Test HTTPS connections to a site, going through an HTTPS proxy
6415 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6416 session_deps_
.proxy_service
.reset(
6417 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6419 session_deps_
.net_log
= &net_log
;
6421 HttpRequestInfo request
;
6422 request
.method
= "GET";
6423 request
.url
= GURL("https://www.example.org/");
6424 request
.load_flags
= 0;
6426 MockWrite data_writes
[] = {
6428 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6429 "Host: www.example.org\r\n"
6430 "Proxy-Connection: keep-alive\r\n\r\n"),
6432 "GET / HTTP/1.1\r\n"
6433 "Host: www.example.org\r\n"
6434 "Connection: keep-alive\r\n\r\n"),
6437 MockRead data_reads
[] = {
6438 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6439 MockRead("HTTP/1.1 200 OK\r\n"),
6440 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6441 MockRead("Content-Length: 100\r\n\r\n"),
6442 MockRead(SYNCHRONOUS
, OK
),
6445 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6446 data_writes
, arraysize(data_writes
));
6447 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6448 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6450 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6451 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6452 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6454 TestCompletionCallback callback
;
6456 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6457 scoped_ptr
<HttpTransaction
> trans(
6458 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6460 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6461 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6463 rv
= callback
.WaitForResult();
6465 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6467 ASSERT_TRUE(response
!= NULL
);
6469 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6470 EXPECT_EQ(200, response
->headers
->response_code());
6471 EXPECT_EQ(100, response
->headers
->GetContentLength());
6472 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6474 LoadTimingInfo load_timing_info
;
6475 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6476 TestLoadTimingNotReusedWithPac(load_timing_info
,
6477 CONNECT_TIMING_HAS_SSL_TIMES
);
6480 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6481 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6482 session_deps_
.proxy_service
.reset(
6483 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6485 session_deps_
.net_log
= &net_log
;
6487 HttpRequestInfo request
;
6488 request
.method
= "GET";
6489 request
.url
= GURL("https://www.example.org/");
6490 request
.load_flags
= 0;
6492 MockWrite data_writes
[] = {
6494 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6495 "Host: www.example.org\r\n"
6496 "Proxy-Connection: keep-alive\r\n\r\n"),
6499 MockRead data_reads
[] = {
6500 MockRead("HTTP/1.1 302 Redirect\r\n"),
6501 MockRead("Location: http://login.example.com/\r\n"),
6502 MockRead("Content-Length: 0\r\n\r\n"),
6503 MockRead(SYNCHRONOUS
, OK
),
6506 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6507 data_writes
, arraysize(data_writes
));
6508 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6510 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6511 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6513 TestCompletionCallback callback
;
6515 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6516 scoped_ptr
<HttpTransaction
> trans(
6517 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6519 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6520 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6522 rv
= callback
.WaitForResult();
6524 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6526 ASSERT_TRUE(response
!= NULL
);
6528 EXPECT_EQ(302, response
->headers
->response_code());
6530 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6531 EXPECT_EQ("http://login.example.com/", url
);
6533 // In the case of redirects from proxies, HttpNetworkTransaction returns
6534 // timing for the proxy connection instead of the connection to the host,
6535 // and no send / receive times.
6536 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6537 LoadTimingInfo load_timing_info
;
6538 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6540 EXPECT_FALSE(load_timing_info
.socket_reused
);
6541 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6543 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6544 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6545 load_timing_info
.proxy_resolve_end
);
6546 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6547 load_timing_info
.connect_timing
.connect_start
);
6548 ExpectConnectTimingHasTimes(
6549 load_timing_info
.connect_timing
,
6550 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6552 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6553 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6554 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6557 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6558 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6559 session_deps_
.proxy_service
.reset(
6560 ProxyService::CreateFixed("https://proxy:70"));
6562 HttpRequestInfo request
;
6563 request
.method
= "GET";
6564 request
.url
= GURL("https://www.example.org/");
6565 request
.load_flags
= 0;
6567 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6568 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6569 scoped_ptr
<SpdyFrame
> goaway(
6570 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6571 MockWrite data_writes
[] = {
6572 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6573 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6576 static const char* const kExtraHeaders
[] = {
6578 "http://login.example.com/",
6580 scoped_ptr
<SpdyFrame
> resp(
6581 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6582 arraysize(kExtraHeaders
)/2, 1));
6583 MockRead data_reads
[] = {
6584 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6587 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6588 arraysize(data_writes
));
6589 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6590 proxy_ssl
.SetNextProto(GetParam());
6592 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6593 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6595 TestCompletionCallback callback
;
6597 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6598 scoped_ptr
<HttpTransaction
> trans(
6599 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6601 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6602 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6604 rv
= callback
.WaitForResult();
6606 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6608 ASSERT_TRUE(response
!= NULL
);
6610 EXPECT_EQ(302, response
->headers
->response_code());
6612 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6613 EXPECT_EQ("http://login.example.com/", url
);
6616 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6617 TEST_P(HttpNetworkTransactionTest
,
6618 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6619 session_deps_
.proxy_service
.reset(
6620 ProxyService::CreateFixed("https://proxy:70"));
6622 HttpRequestInfo request
;
6623 request
.method
= "GET";
6624 request
.url
= GURL("https://www.example.org/");
6625 request
.load_flags
= 0;
6627 MockWrite data_writes
[] = {
6629 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6630 "Host: www.example.org\r\n"
6631 "Proxy-Connection: keep-alive\r\n\r\n"),
6634 MockRead data_reads
[] = {
6635 MockRead("HTTP/1.1 404 Not Found\r\n"),
6636 MockRead("Content-Length: 23\r\n\r\n"),
6637 MockRead("The host does not exist"),
6638 MockRead(SYNCHRONOUS
, OK
),
6641 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6642 data_writes
, arraysize(data_writes
));
6643 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6645 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6646 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6648 TestCompletionCallback callback
;
6650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6651 scoped_ptr
<HttpTransaction
> trans(
6652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6654 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6655 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6657 rv
= callback
.WaitForResult();
6658 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6660 // TODO(ttuttle): Anything else to check here?
6663 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6664 TEST_P(HttpNetworkTransactionTest
,
6665 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6666 session_deps_
.proxy_service
.reset(
6667 ProxyService::CreateFixed("https://proxy:70"));
6669 HttpRequestInfo request
;
6670 request
.method
= "GET";
6671 request
.url
= GURL("https://www.example.org/");
6672 request
.load_flags
= 0;
6674 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6675 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6676 scoped_ptr
<SpdyFrame
> rst(
6677 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6678 MockWrite data_writes
[] = {
6679 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6682 static const char* const kExtraHeaders
[] = {
6684 "http://login.example.com/",
6686 scoped_ptr
<SpdyFrame
> resp(
6687 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6688 arraysize(kExtraHeaders
)/2, 1));
6689 scoped_ptr
<SpdyFrame
> body(
6690 spdy_util_
.ConstructSpdyBodyFrame(
6691 1, "The host does not exist", 23, true));
6692 MockRead data_reads
[] = {
6693 CreateMockRead(*resp
.get(), 1),
6694 CreateMockRead(*body
.get(), 2),
6695 MockRead(ASYNC
, 0, 4), // EOF
6698 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6699 arraysize(data_writes
));
6700 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6701 proxy_ssl
.SetNextProto(GetParam());
6703 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6704 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6706 TestCompletionCallback callback
;
6708 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6709 scoped_ptr
<HttpTransaction
> trans(
6710 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6712 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6713 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6715 rv
= callback
.WaitForResult();
6716 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6718 // TODO(ttuttle): Anything else to check here?
6721 // Test the request-challenge-retry sequence for basic auth, through
6722 // a SPDY proxy over a single SPDY session.
6723 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6724 HttpRequestInfo request
;
6725 request
.method
= "GET";
6726 request
.url
= GURL("https://www.example.org/");
6727 // when the no authentication data flag is set.
6728 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6730 // Configure against https proxy server "myproxy:70".
6731 session_deps_
.proxy_service
.reset(
6732 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6733 BoundTestNetLog log
;
6734 session_deps_
.net_log
= log
.bound().net_log();
6735 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6737 // Since we have proxy, should try to establish tunnel.
6738 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6739 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6740 scoped_ptr
<SpdyFrame
> rst(
6741 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6743 // After calling trans->RestartWithAuth(), this is the request we should
6744 // be issuing -- the final header line contains the credentials.
6745 const char* const kAuthCredentials
[] = {
6746 "proxy-authorization", "Basic Zm9vOmJhcg==",
6748 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6749 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6750 HostPortPair("www.example.org", 443)));
6751 // fetch https://www.example.org/ via HTTP
6753 "GET / HTTP/1.1\r\n"
6754 "Host: www.example.org\r\n"
6755 "Connection: keep-alive\r\n\r\n";
6756 scoped_ptr
<SpdyFrame
> wrapped_get(
6757 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6759 MockWrite spdy_writes
[] = {
6760 CreateMockWrite(*req
, 0, ASYNC
),
6761 CreateMockWrite(*rst
, 2, ASYNC
),
6762 CreateMockWrite(*connect2
, 3),
6763 CreateMockWrite(*wrapped_get
, 5),
6766 // The proxy responds to the connect with a 407, using a persistent
6768 const char kAuthStatus
[] = "407";
6769 const char* const kAuthChallenge
[] = {
6770 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6772 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6773 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6775 scoped_ptr
<SpdyFrame
> conn_resp(
6776 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6777 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6778 "Content-Length: 5\r\n\r\n";
6780 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6781 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6782 scoped_ptr
<SpdyFrame
> wrapped_body(
6783 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6784 MockRead spdy_reads
[] = {
6785 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6786 CreateMockRead(*conn_resp
, 4, ASYNC
),
6787 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6788 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6789 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6792 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6793 arraysize(spdy_writes
));
6794 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6795 // Negotiate SPDY to the proxy
6796 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6797 proxy
.SetNextProto(GetParam());
6798 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6799 // Vanilla SSL to the server
6800 SSLSocketDataProvider
server(ASYNC
, OK
);
6801 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6803 TestCompletionCallback callback1
;
6805 scoped_ptr
<HttpTransaction
> trans(
6806 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6808 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6809 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6811 rv
= callback1
.WaitForResult();
6813 TestNetLogEntry::List entries
;
6814 log
.GetEntries(&entries
);
6815 size_t pos
= ExpectLogContainsSomewhere(
6816 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6817 NetLog::PHASE_NONE
);
6818 ExpectLogContainsSomewhere(
6820 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6821 NetLog::PHASE_NONE
);
6823 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6824 ASSERT_TRUE(response
!= NULL
);
6825 ASSERT_FALSE(response
->headers
.get() == NULL
);
6826 EXPECT_EQ(407, response
->headers
->response_code());
6827 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6828 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6829 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6831 TestCompletionCallback callback2
;
6833 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6834 callback2
.callback());
6835 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6837 rv
= callback2
.WaitForResult();
6840 response
= trans
->GetResponseInfo();
6841 ASSERT_TRUE(response
!= NULL
);
6843 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6844 EXPECT_EQ(200, response
->headers
->response_code());
6845 EXPECT_EQ(5, response
->headers
->GetContentLength());
6846 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6848 // The password prompt info should not be set.
6849 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6851 LoadTimingInfo load_timing_info
;
6852 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6853 TestLoadTimingNotReusedWithPac(load_timing_info
,
6854 CONNECT_TIMING_HAS_SSL_TIMES
);
6857 session
->CloseAllConnections();
6860 // Test that an explicitly trusted SPDY proxy can push a resource from an
6861 // origin that is different from that of its associated resource.
6862 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6863 HttpRequestInfo request
;
6864 HttpRequestInfo push_request
;
6866 request
.method
= "GET";
6867 request
.url
= GURL("http://www.example.org/");
6868 push_request
.method
= "GET";
6869 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6871 // Configure against https proxy server "myproxy:70".
6872 session_deps_
.proxy_service
.reset(
6873 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6874 BoundTestNetLog log
;
6875 session_deps_
.net_log
= log
.bound().net_log();
6877 // Enable cross-origin push.
6878 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6880 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6882 scoped_ptr
<SpdyFrame
> stream1_syn(
6883 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6885 MockWrite spdy_writes
[] = {
6886 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6889 scoped_ptr
<SpdyFrame
>
6890 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6892 scoped_ptr
<SpdyFrame
>
6893 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6895 scoped_ptr
<SpdyFrame
>
6896 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6900 "http://www.another-origin.com/foo.dat"));
6901 const char kPushedData
[] = "pushed";
6902 scoped_ptr
<SpdyFrame
> stream2_body(
6903 spdy_util_
.ConstructSpdyBodyFrame(
6904 2, kPushedData
, strlen(kPushedData
), true));
6906 MockRead spdy_reads
[] = {
6907 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6908 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6909 CreateMockRead(*stream1_body
, 3, ASYNC
),
6910 CreateMockRead(*stream2_body
, 4, ASYNC
),
6911 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
6914 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6915 arraysize(spdy_writes
));
6916 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6917 // Negotiate SPDY to the proxy
6918 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6919 proxy
.SetNextProto(GetParam());
6920 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6922 scoped_ptr
<HttpTransaction
> trans(
6923 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6924 TestCompletionCallback callback
;
6925 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6928 rv
= callback
.WaitForResult();
6930 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6932 scoped_ptr
<HttpTransaction
> push_trans(
6933 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6934 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6935 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6937 rv
= callback
.WaitForResult();
6939 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6941 ASSERT_TRUE(response
!= NULL
);
6942 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6944 EXPECT_EQ(200, response
->headers
->response_code());
6945 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6947 std::string response_data
;
6948 rv
= ReadTransaction(trans
.get(), &response_data
);
6950 EXPECT_EQ("hello!", response_data
);
6952 LoadTimingInfo load_timing_info
;
6953 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6954 TestLoadTimingNotReusedWithPac(load_timing_info
,
6955 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6957 // Verify the pushed stream.
6958 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6959 EXPECT_EQ(200, push_response
->headers
->response_code());
6961 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6963 EXPECT_EQ("pushed", response_data
);
6965 LoadTimingInfo push_load_timing_info
;
6966 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6967 TestLoadTimingReusedWithPac(push_load_timing_info
);
6968 // The transactions should share a socket ID, despite being for different
6970 EXPECT_EQ(load_timing_info
.socket_log_id
,
6971 push_load_timing_info
.socket_log_id
);
6975 session
->CloseAllConnections();
6978 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6979 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6980 HttpRequestInfo request
;
6982 request
.method
= "GET";
6983 request
.url
= GURL("http://www.example.org/");
6985 // Configure against https proxy server "myproxy:70".
6986 session_deps_
.proxy_service
.reset(
6987 ProxyService::CreateFixed("https://myproxy:70"));
6988 BoundTestNetLog log
;
6989 session_deps_
.net_log
= log
.bound().net_log();
6991 // Enable cross-origin push.
6992 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6994 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6996 scoped_ptr
<SpdyFrame
> stream1_syn(
6997 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6999 scoped_ptr
<SpdyFrame
> push_rst(
7000 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7002 MockWrite spdy_writes
[] = {
7003 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
7006 scoped_ptr
<SpdyFrame
>
7007 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7009 scoped_ptr
<SpdyFrame
>
7010 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7012 scoped_ptr
<SpdyFrame
>
7013 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7017 "https://www.another-origin.com/foo.dat"));
7019 MockRead spdy_reads
[] = {
7020 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7021 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7022 CreateMockRead(*stream1_body
, 4, ASYNC
),
7023 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7026 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7027 arraysize(spdy_writes
));
7028 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7029 // Negotiate SPDY to the proxy
7030 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7031 proxy
.SetNextProto(GetParam());
7032 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7034 scoped_ptr
<HttpTransaction
> trans(
7035 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7036 TestCompletionCallback callback
;
7037 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7038 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7040 rv
= callback
.WaitForResult();
7042 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7044 ASSERT_TRUE(response
!= NULL
);
7045 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7047 EXPECT_EQ(200, response
->headers
->response_code());
7048 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7050 std::string response_data
;
7051 rv
= ReadTransaction(trans
.get(), &response_data
);
7053 EXPECT_EQ("hello!", response_data
);
7056 session
->CloseAllConnections();
7059 // Test HTTPS connections to a site with a bad certificate, going through an
7061 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7062 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7063 "https://proxy:70"));
7065 HttpRequestInfo request
;
7066 request
.method
= "GET";
7067 request
.url
= GURL("https://www.example.org/");
7068 request
.load_flags
= 0;
7070 // Attempt to fetch the URL from a server with a bad cert
7071 MockWrite bad_cert_writes
[] = {
7073 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7074 "Host: www.example.org\r\n"
7075 "Proxy-Connection: keep-alive\r\n\r\n"),
7078 MockRead bad_cert_reads
[] = {
7079 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7080 MockRead(SYNCHRONOUS
, OK
)
7083 // Attempt to fetch the URL with a good cert
7084 MockWrite good_data_writes
[] = {
7086 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7087 "Host: www.example.org\r\n"
7088 "Proxy-Connection: keep-alive\r\n\r\n"),
7090 "GET / HTTP/1.1\r\n"
7091 "Host: www.example.org\r\n"
7092 "Connection: keep-alive\r\n\r\n"),
7095 MockRead good_cert_reads
[] = {
7096 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7097 MockRead("HTTP/1.0 200 OK\r\n"),
7098 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7099 MockRead("Content-Length: 100\r\n\r\n"),
7100 MockRead(SYNCHRONOUS
, OK
),
7103 StaticSocketDataProvider
ssl_bad_certificate(
7104 bad_cert_reads
, arraysize(bad_cert_reads
),
7105 bad_cert_writes
, arraysize(bad_cert_writes
));
7106 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7107 good_data_writes
, arraysize(good_data_writes
));
7108 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7109 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7111 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7112 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7113 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7114 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7116 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7117 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7118 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7119 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7121 TestCompletionCallback callback
;
7123 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7124 scoped_ptr
<HttpTransaction
> trans(
7125 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7127 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7128 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7130 rv
= callback
.WaitForResult();
7131 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7133 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7134 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7136 rv
= callback
.WaitForResult();
7139 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7141 ASSERT_TRUE(response
!= NULL
);
7142 EXPECT_EQ(100, response
->headers
->GetContentLength());
7145 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7146 HttpRequestInfo request
;
7147 request
.method
= "GET";
7148 request
.url
= GURL("http://www.example.org/");
7149 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7150 "Chromium Ultra Awesome X Edition");
7152 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7153 scoped_ptr
<HttpTransaction
> trans(
7154 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7156 MockWrite data_writes
[] = {
7158 "GET / HTTP/1.1\r\n"
7159 "Host: www.example.org\r\n"
7160 "Connection: keep-alive\r\n"
7161 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7164 // Lastly, the server responds with the actual content.
7165 MockRead data_reads
[] = {
7166 MockRead("HTTP/1.0 200 OK\r\n"),
7167 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7168 MockRead("Content-Length: 100\r\n\r\n"),
7169 MockRead(SYNCHRONOUS
, OK
),
7172 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7173 data_writes
, arraysize(data_writes
));
7174 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7176 TestCompletionCallback callback
;
7178 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7179 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7181 rv
= callback
.WaitForResult();
7185 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7186 HttpRequestInfo request
;
7187 request
.method
= "GET";
7188 request
.url
= GURL("https://www.example.org/");
7189 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7190 "Chromium Ultra Awesome X Edition");
7192 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7193 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7194 scoped_ptr
<HttpTransaction
> trans(
7195 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7197 MockWrite data_writes
[] = {
7199 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7200 "Host: www.example.org\r\n"
7201 "Proxy-Connection: keep-alive\r\n"
7202 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7204 MockRead data_reads
[] = {
7205 // Return an error, so the transaction stops here (this test isn't
7206 // interested in the rest).
7207 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7208 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7209 MockRead("Proxy-Connection: close\r\n\r\n"),
7212 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7213 data_writes
, arraysize(data_writes
));
7214 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7216 TestCompletionCallback callback
;
7218 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7219 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7221 rv
= callback
.WaitForResult();
7225 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7226 HttpRequestInfo request
;
7227 request
.method
= "GET";
7228 request
.url
= GURL("http://www.example.org/");
7229 request
.load_flags
= 0;
7230 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7231 "http://the.previous.site.com/");
7233 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7234 scoped_ptr
<HttpTransaction
> trans(
7235 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7237 MockWrite data_writes
[] = {
7239 "GET / HTTP/1.1\r\n"
7240 "Host: www.example.org\r\n"
7241 "Connection: keep-alive\r\n"
7242 "Referer: http://the.previous.site.com/\r\n\r\n"),
7245 // Lastly, the server responds with the actual content.
7246 MockRead data_reads
[] = {
7247 MockRead("HTTP/1.0 200 OK\r\n"),
7248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7249 MockRead("Content-Length: 100\r\n\r\n"),
7250 MockRead(SYNCHRONOUS
, OK
),
7253 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7254 data_writes
, arraysize(data_writes
));
7255 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7257 TestCompletionCallback callback
;
7259 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7260 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7262 rv
= callback
.WaitForResult();
7266 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7267 HttpRequestInfo request
;
7268 request
.method
= "POST";
7269 request
.url
= GURL("http://www.example.org/");
7271 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7272 scoped_ptr
<HttpTransaction
> trans(
7273 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7275 MockWrite data_writes
[] = {
7277 "POST / HTTP/1.1\r\n"
7278 "Host: www.example.org\r\n"
7279 "Connection: keep-alive\r\n"
7280 "Content-Length: 0\r\n\r\n"),
7283 // Lastly, the server responds with the actual content.
7284 MockRead data_reads
[] = {
7285 MockRead("HTTP/1.0 200 OK\r\n"),
7286 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7287 MockRead("Content-Length: 100\r\n\r\n"),
7288 MockRead(SYNCHRONOUS
, OK
),
7291 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7292 data_writes
, arraysize(data_writes
));
7293 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7295 TestCompletionCallback callback
;
7297 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7298 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7300 rv
= callback
.WaitForResult();
7304 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7305 HttpRequestInfo request
;
7306 request
.method
= "PUT";
7307 request
.url
= GURL("http://www.example.org/");
7309 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7310 scoped_ptr
<HttpTransaction
> trans(
7311 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7313 MockWrite data_writes
[] = {
7315 "PUT / HTTP/1.1\r\n"
7316 "Host: www.example.org\r\n"
7317 "Connection: keep-alive\r\n"
7318 "Content-Length: 0\r\n\r\n"),
7321 // Lastly, the server responds with the actual content.
7322 MockRead data_reads
[] = {
7323 MockRead("HTTP/1.0 200 OK\r\n"),
7324 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7325 MockRead("Content-Length: 100\r\n\r\n"),
7326 MockRead(SYNCHRONOUS
, OK
),
7329 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7330 data_writes
, arraysize(data_writes
));
7331 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7333 TestCompletionCallback callback
;
7335 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7336 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7338 rv
= callback
.WaitForResult();
7342 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7343 HttpRequestInfo request
;
7344 request
.method
= "HEAD";
7345 request
.url
= GURL("http://www.example.org/");
7347 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7348 scoped_ptr
<HttpTransaction
> trans(
7349 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7351 MockWrite data_writes
[] = {
7353 "HEAD / HTTP/1.1\r\n"
7354 "Host: www.example.org\r\n"
7355 "Connection: keep-alive\r\n"
7356 "Content-Length: 0\r\n\r\n"),
7359 // Lastly, the server responds with the actual content.
7360 MockRead data_reads
[] = {
7361 MockRead("HTTP/1.0 200 OK\r\n"),
7362 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7363 MockRead("Content-Length: 100\r\n\r\n"),
7364 MockRead(SYNCHRONOUS
, OK
),
7367 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7368 data_writes
, arraysize(data_writes
));
7369 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7371 TestCompletionCallback callback
;
7373 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7374 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7376 rv
= callback
.WaitForResult();
7380 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7381 HttpRequestInfo request
;
7382 request
.method
= "GET";
7383 request
.url
= GURL("http://www.example.org/");
7384 request
.load_flags
= LOAD_BYPASS_CACHE
;
7386 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7387 scoped_ptr
<HttpTransaction
> trans(
7388 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7390 MockWrite data_writes
[] = {
7392 "GET / HTTP/1.1\r\n"
7393 "Host: www.example.org\r\n"
7394 "Connection: keep-alive\r\n"
7395 "Pragma: no-cache\r\n"
7396 "Cache-Control: no-cache\r\n\r\n"),
7399 // Lastly, the server responds with the actual content.
7400 MockRead data_reads
[] = {
7401 MockRead("HTTP/1.0 200 OK\r\n"),
7402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7403 MockRead("Content-Length: 100\r\n\r\n"),
7404 MockRead(SYNCHRONOUS
, OK
),
7407 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7408 data_writes
, arraysize(data_writes
));
7409 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7411 TestCompletionCallback callback
;
7413 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7414 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7416 rv
= callback
.WaitForResult();
7420 TEST_P(HttpNetworkTransactionTest
,
7421 BuildRequest_CacheControlValidateCache
) {
7422 HttpRequestInfo request
;
7423 request
.method
= "GET";
7424 request
.url
= GURL("http://www.example.org/");
7425 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7427 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7428 scoped_ptr
<HttpTransaction
> trans(
7429 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7431 MockWrite data_writes
[] = {
7433 "GET / HTTP/1.1\r\n"
7434 "Host: www.example.org\r\n"
7435 "Connection: keep-alive\r\n"
7436 "Cache-Control: max-age=0\r\n\r\n"),
7439 // Lastly, the server responds with the actual content.
7440 MockRead data_reads
[] = {
7441 MockRead("HTTP/1.0 200 OK\r\n"),
7442 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7443 MockRead("Content-Length: 100\r\n\r\n"),
7444 MockRead(SYNCHRONOUS
, OK
),
7447 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7448 data_writes
, arraysize(data_writes
));
7449 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7451 TestCompletionCallback callback
;
7453 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7456 rv
= callback
.WaitForResult();
7460 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7461 HttpRequestInfo request
;
7462 request
.method
= "GET";
7463 request
.url
= GURL("http://www.example.org/");
7464 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7466 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7467 scoped_ptr
<HttpTransaction
> trans(
7468 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7470 MockWrite data_writes
[] = {
7472 "GET / HTTP/1.1\r\n"
7473 "Host: www.example.org\r\n"
7474 "Connection: keep-alive\r\n"
7475 "FooHeader: Bar\r\n\r\n"),
7478 // Lastly, the server responds with the actual content.
7479 MockRead data_reads
[] = {
7480 MockRead("HTTP/1.0 200 OK\r\n"),
7481 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7482 MockRead("Content-Length: 100\r\n\r\n"),
7483 MockRead(SYNCHRONOUS
, OK
),
7486 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7487 data_writes
, arraysize(data_writes
));
7488 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7490 TestCompletionCallback callback
;
7492 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7493 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7495 rv
= callback
.WaitForResult();
7499 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7500 HttpRequestInfo request
;
7501 request
.method
= "GET";
7502 request
.url
= GURL("http://www.example.org/");
7503 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7504 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7505 request
.extra_headers
.SetHeader("FoO", "bar");
7507 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7508 scoped_ptr
<HttpTransaction
> trans(
7509 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7511 MockWrite data_writes
[] = {
7513 "GET / HTTP/1.1\r\n"
7514 "Host: www.example.org\r\n"
7515 "Connection: keep-alive\r\n"
7516 "referer: www.foo.com\r\n"
7518 "FoO: bar\r\n\r\n"),
7521 // Lastly, the server responds with the actual content.
7522 MockRead data_reads
[] = {
7523 MockRead("HTTP/1.0 200 OK\r\n"),
7524 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7525 MockRead("Content-Length: 100\r\n\r\n"),
7526 MockRead(SYNCHRONOUS
, OK
),
7529 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7530 data_writes
, arraysize(data_writes
));
7531 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7533 TestCompletionCallback callback
;
7535 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7536 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7538 rv
= callback
.WaitForResult();
7542 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7543 HttpRequestInfo request
;
7544 request
.method
= "GET";
7545 request
.url
= GURL("http://www.example.org/");
7546 request
.load_flags
= 0;
7548 session_deps_
.proxy_service
.reset(
7549 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7551 session_deps_
.net_log
= &net_log
;
7553 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7554 scoped_ptr
<HttpTransaction
> trans(
7555 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7557 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7558 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7560 MockWrite data_writes
[] = {
7561 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7563 "GET / HTTP/1.1\r\n"
7564 "Host: www.example.org\r\n"
7565 "Connection: keep-alive\r\n\r\n")};
7567 MockRead data_reads
[] = {
7568 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7569 MockRead("HTTP/1.0 200 OK\r\n"),
7570 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7571 MockRead("Payload"),
7572 MockRead(SYNCHRONOUS
, OK
)
7575 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7576 data_writes
, arraysize(data_writes
));
7577 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7579 TestCompletionCallback callback
;
7581 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7584 rv
= callback
.WaitForResult();
7587 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7588 ASSERT_TRUE(response
!= NULL
);
7590 LoadTimingInfo load_timing_info
;
7591 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7592 TestLoadTimingNotReusedWithPac(load_timing_info
,
7593 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7595 std::string response_text
;
7596 rv
= ReadTransaction(trans
.get(), &response_text
);
7598 EXPECT_EQ("Payload", response_text
);
7601 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7602 HttpRequestInfo request
;
7603 request
.method
= "GET";
7604 request
.url
= GURL("https://www.example.org/");
7605 request
.load_flags
= 0;
7607 session_deps_
.proxy_service
.reset(
7608 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7610 session_deps_
.net_log
= &net_log
;
7612 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7613 scoped_ptr
<HttpTransaction
> trans(
7614 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7616 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7617 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7619 MockWrite data_writes
[] = {
7620 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7621 arraysize(write_buffer
)),
7623 "GET / HTTP/1.1\r\n"
7624 "Host: www.example.org\r\n"
7625 "Connection: keep-alive\r\n\r\n")};
7627 MockRead data_reads
[] = {
7628 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7629 arraysize(read_buffer
)),
7630 MockRead("HTTP/1.0 200 OK\r\n"),
7631 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7632 MockRead("Payload"),
7633 MockRead(SYNCHRONOUS
, OK
)
7636 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7637 data_writes
, arraysize(data_writes
));
7638 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7640 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7641 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7643 TestCompletionCallback callback
;
7645 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7646 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7648 rv
= callback
.WaitForResult();
7651 LoadTimingInfo load_timing_info
;
7652 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7653 TestLoadTimingNotReusedWithPac(load_timing_info
,
7654 CONNECT_TIMING_HAS_SSL_TIMES
);
7656 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7657 ASSERT_TRUE(response
!= NULL
);
7659 std::string response_text
;
7660 rv
= ReadTransaction(trans
.get(), &response_text
);
7662 EXPECT_EQ("Payload", response_text
);
7665 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7666 HttpRequestInfo request
;
7667 request
.method
= "GET";
7668 request
.url
= GURL("http://www.example.org/");
7669 request
.load_flags
= 0;
7671 session_deps_
.proxy_service
.reset(
7672 ProxyService::CreateFixed("socks4://myproxy:1080"));
7674 session_deps_
.net_log
= &net_log
;
7676 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7677 scoped_ptr
<HttpTransaction
> trans(
7678 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7680 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7681 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7683 MockWrite data_writes
[] = {
7684 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7686 "GET / HTTP/1.1\r\n"
7687 "Host: www.example.org\r\n"
7688 "Connection: keep-alive\r\n\r\n")};
7690 MockRead data_reads
[] = {
7691 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7692 MockRead("HTTP/1.0 200 OK\r\n"),
7693 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7694 MockRead("Payload"),
7695 MockRead(SYNCHRONOUS
, OK
)
7698 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7699 data_writes
, arraysize(data_writes
));
7700 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7702 TestCompletionCallback callback
;
7704 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7705 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7707 rv
= callback
.WaitForResult();
7710 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7711 ASSERT_TRUE(response
!= NULL
);
7713 LoadTimingInfo load_timing_info
;
7714 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7715 TestLoadTimingNotReused(load_timing_info
,
7716 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7718 std::string response_text
;
7719 rv
= ReadTransaction(trans
.get(), &response_text
);
7721 EXPECT_EQ("Payload", response_text
);
7724 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7725 HttpRequestInfo request
;
7726 request
.method
= "GET";
7727 request
.url
= GURL("http://www.example.org/");
7728 request
.load_flags
= 0;
7730 session_deps_
.proxy_service
.reset(
7731 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7733 session_deps_
.net_log
= &net_log
;
7735 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7736 scoped_ptr
<HttpTransaction
> trans(
7737 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7739 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7740 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7741 const char kSOCKS5OkRequest
[] = {
7743 0x01, // Command (CONNECT)
7745 0x03, // Address type (DOMAINNAME).
7746 0x0F, // Length of domain (15)
7747 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7748 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7750 const char kSOCKS5OkResponse
[] =
7751 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7753 MockWrite data_writes
[] = {
7754 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7755 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7757 "GET / HTTP/1.1\r\n"
7758 "Host: www.example.org\r\n"
7759 "Connection: keep-alive\r\n\r\n")};
7761 MockRead data_reads
[] = {
7762 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7763 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7764 MockRead("HTTP/1.0 200 OK\r\n"),
7765 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7766 MockRead("Payload"),
7767 MockRead(SYNCHRONOUS
, OK
)
7770 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7771 data_writes
, arraysize(data_writes
));
7772 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7774 TestCompletionCallback callback
;
7776 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7779 rv
= callback
.WaitForResult();
7782 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7783 ASSERT_TRUE(response
!= NULL
);
7785 LoadTimingInfo load_timing_info
;
7786 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7787 TestLoadTimingNotReusedWithPac(load_timing_info
,
7788 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7790 std::string response_text
;
7791 rv
= ReadTransaction(trans
.get(), &response_text
);
7793 EXPECT_EQ("Payload", response_text
);
7796 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7797 HttpRequestInfo request
;
7798 request
.method
= "GET";
7799 request
.url
= GURL("https://www.example.org/");
7800 request
.load_flags
= 0;
7802 session_deps_
.proxy_service
.reset(
7803 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7805 session_deps_
.net_log
= &net_log
;
7807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7808 scoped_ptr
<HttpTransaction
> trans(
7809 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7811 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7812 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7813 const unsigned char kSOCKS5OkRequest
[] = {
7815 0x01, // Command (CONNECT)
7817 0x03, // Address type (DOMAINNAME).
7818 0x0F, // Length of domain (15)
7819 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7820 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7823 const char kSOCKS5OkResponse
[] =
7824 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7826 MockWrite data_writes
[] = {
7827 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7828 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7829 arraysize(kSOCKS5OkRequest
)),
7831 "GET / HTTP/1.1\r\n"
7832 "Host: www.example.org\r\n"
7833 "Connection: keep-alive\r\n\r\n")};
7835 MockRead data_reads
[] = {
7836 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7837 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7838 MockRead("HTTP/1.0 200 OK\r\n"),
7839 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7840 MockRead("Payload"),
7841 MockRead(SYNCHRONOUS
, OK
)
7844 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7845 data_writes
, arraysize(data_writes
));
7846 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7848 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7849 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7851 TestCompletionCallback callback
;
7853 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7856 rv
= callback
.WaitForResult();
7859 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7860 ASSERT_TRUE(response
!= NULL
);
7862 LoadTimingInfo load_timing_info
;
7863 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7864 TestLoadTimingNotReusedWithPac(load_timing_info
,
7865 CONNECT_TIMING_HAS_SSL_TIMES
);
7867 std::string response_text
;
7868 rv
= ReadTransaction(trans
.get(), &response_text
);
7870 EXPECT_EQ("Payload", response_text
);
7875 // Tests that for connection endpoints the group names are correctly set.
7877 struct GroupNameTest
{
7878 std::string proxy_server
;
7880 std::string expected_group_name
;
7884 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7885 NextProto next_proto
,
7886 SpdySessionDependencies
* session_deps_
) {
7887 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7889 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7890 session
->http_server_properties();
7891 AlternativeService
alternative_service(
7892 AlternateProtocolFromNextProto(next_proto
), "", 443);
7893 http_server_properties
->SetAlternativeService(
7894 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0);
7899 int GroupNameTransactionHelper(
7900 const std::string
& url
,
7901 const scoped_refptr
<HttpNetworkSession
>& session
) {
7902 HttpRequestInfo request
;
7903 request
.method
= "GET";
7904 request
.url
= GURL(url
);
7905 request
.load_flags
= 0;
7907 scoped_ptr
<HttpTransaction
> trans(
7908 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7910 TestCompletionCallback callback
;
7912 // We do not complete this request, the dtor will clean the transaction up.
7913 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7918 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7919 const GroupNameTest tests
[] = {
7922 "http://www.example.org/direct",
7923 "www.example.org:80",
7928 "http://[2001:1418:13:1::25]/direct",
7929 "[2001:1418:13:1::25]:80",
7936 "https://www.example.org/direct_ssl",
7937 "ssl/www.example.org:443",
7942 "https://[2001:1418:13:1::25]/direct",
7943 "ssl/[2001:1418:13:1::25]:443",
7948 "http://host.with.alternate/direct",
7949 "ssl/host.with.alternate:443",
7954 session_deps_
.use_alternate_protocols
= true;
7956 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7957 session_deps_
.proxy_service
.reset(
7958 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7959 scoped_refptr
<HttpNetworkSession
> session(
7960 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7962 HttpNetworkSessionPeer
peer(session
);
7963 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7964 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7965 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7966 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7967 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7968 new MockClientSocketPoolManager
);
7969 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7970 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7971 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7973 EXPECT_EQ(ERR_IO_PENDING
,
7974 GroupNameTransactionHelper(tests
[i
].url
, session
));
7976 EXPECT_EQ(tests
[i
].expected_group_name
,
7977 ssl_conn_pool
->last_group_name_received());
7979 EXPECT_EQ(tests
[i
].expected_group_name
,
7980 transport_conn_pool
->last_group_name_received());
7985 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7986 const GroupNameTest tests
[] = {
7989 "http://www.example.org/http_proxy_normal",
7990 "www.example.org:80",
7997 "https://www.example.org/http_connect_ssl",
7998 "ssl/www.example.org:443",
8004 "http://host.with.alternate/direct",
8005 "ssl/host.with.alternate:443",
8011 "ftp://ftp.google.com/http_proxy_normal",
8012 "ftp/ftp.google.com:21",
8017 session_deps_
.use_alternate_protocols
= true;
8019 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8020 session_deps_
.proxy_service
.reset(
8021 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8022 scoped_refptr
<HttpNetworkSession
> session(
8023 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8025 HttpNetworkSessionPeer
peer(session
);
8027 HostPortPair
proxy_host("http_proxy", 80);
8028 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8029 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8030 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8031 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8033 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8034 new MockClientSocketPoolManager
);
8035 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8036 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8037 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8039 EXPECT_EQ(ERR_IO_PENDING
,
8040 GroupNameTransactionHelper(tests
[i
].url
, session
));
8042 EXPECT_EQ(tests
[i
].expected_group_name
,
8043 ssl_conn_pool
->last_group_name_received());
8045 EXPECT_EQ(tests
[i
].expected_group_name
,
8046 http_proxy_pool
->last_group_name_received());
8050 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8051 const GroupNameTest tests
[] = {
8053 "socks4://socks_proxy:1080",
8054 "http://www.example.org/socks4_direct",
8055 "socks4/www.example.org:80",
8059 "socks5://socks_proxy:1080",
8060 "http://www.example.org/socks5_direct",
8061 "socks5/www.example.org:80",
8067 "socks4://socks_proxy:1080",
8068 "https://www.example.org/socks4_ssl",
8069 "socks4/ssl/www.example.org:443",
8073 "socks5://socks_proxy:1080",
8074 "https://www.example.org/socks5_ssl",
8075 "socks5/ssl/www.example.org:443",
8080 "socks4://socks_proxy:1080",
8081 "http://host.with.alternate/direct",
8082 "socks4/ssl/host.with.alternate:443",
8087 session_deps_
.use_alternate_protocols
= true;
8089 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8090 session_deps_
.proxy_service
.reset(
8091 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8092 scoped_refptr
<HttpNetworkSession
> session(
8093 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8095 HttpNetworkSessionPeer
peer(session
);
8097 HostPortPair
proxy_host("socks_proxy", 1080);
8098 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8099 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8100 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8101 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8103 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8104 new MockClientSocketPoolManager
);
8105 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8106 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8107 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8109 scoped_ptr
<HttpTransaction
> trans(
8110 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8112 EXPECT_EQ(ERR_IO_PENDING
,
8113 GroupNameTransactionHelper(tests
[i
].url
, session
));
8115 EXPECT_EQ(tests
[i
].expected_group_name
,
8116 ssl_conn_pool
->last_group_name_received());
8118 EXPECT_EQ(tests
[i
].expected_group_name
,
8119 socks_conn_pool
->last_group_name_received());
8123 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8124 HttpRequestInfo request
;
8125 request
.method
= "GET";
8126 request
.url
= GURL("http://www.example.org/");
8128 session_deps_
.proxy_service
.reset(
8129 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8131 // This simulates failure resolving all hostnames; that means we will fail
8132 // connecting to both proxies (myproxy:70 and foobar:80).
8133 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8135 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8136 scoped_ptr
<HttpTransaction
> trans(
8137 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8139 TestCompletionCallback callback
;
8141 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8142 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8144 rv
= callback
.WaitForResult();
8145 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8148 // Base test to make sure that when the load flags for a request specify to
8149 // bypass the cache, the DNS cache is not used.
8150 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8152 // Issue a request, asking to bypass the cache(s).
8153 HttpRequestInfo request
;
8154 request
.method
= "GET";
8155 request
.load_flags
= load_flags
;
8156 request
.url
= GURL("http://www.example.org/");
8158 // Select a host resolver that does caching.
8159 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8161 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8162 scoped_ptr
<HttpTransaction
> trans(
8163 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8165 // Warm up the host cache so it has an entry for "www.example.org".
8166 AddressList addrlist
;
8167 TestCompletionCallback callback
;
8168 int rv
= session_deps_
.host_resolver
->Resolve(
8169 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8170 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8171 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8172 rv
= callback
.WaitForResult();
8175 // Verify that it was added to host cache, by doing a subsequent async lookup
8176 // and confirming it completes synchronously.
8177 rv
= session_deps_
.host_resolver
->Resolve(
8178 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8179 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8182 // Inject a failure the next time that "www.example.org" is resolved. This way
8183 // we can tell if the next lookup hit the cache, or the "network".
8184 // (cache --> success, "network" --> failure).
8185 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8187 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8188 // first read -- this won't be reached as the host resolution will fail first.
8189 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8190 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8191 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8194 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8195 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8196 rv
= callback
.WaitForResult();
8198 // If we bypassed the cache, we would have gotten a failure while resolving
8199 // "www.example.org".
8200 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8203 // There are multiple load flags that should trigger the host cache bypass.
8204 // Test each in isolation:
8205 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8206 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8209 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8210 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8213 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8214 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8217 // Make sure we can handle an error when writing the request.
8218 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8219 HttpRequestInfo request
;
8220 request
.method
= "GET";
8221 request
.url
= GURL("http://www.foo.com/");
8222 request
.load_flags
= 0;
8224 MockWrite write_failure
[] = {
8225 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8227 StaticSocketDataProvider
data(NULL
, 0,
8228 write_failure
, arraysize(write_failure
));
8229 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8230 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8232 TestCompletionCallback callback
;
8234 scoped_ptr
<HttpTransaction
> trans(
8235 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8237 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8238 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8240 rv
= callback
.WaitForResult();
8241 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8244 // Check that a connection closed after the start of the headers finishes ok.
8245 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8246 HttpRequestInfo request
;
8247 request
.method
= "GET";
8248 request
.url
= GURL("http://www.foo.com/");
8249 request
.load_flags
= 0;
8251 MockRead data_reads
[] = {
8252 MockRead("HTTP/1."),
8253 MockRead(SYNCHRONOUS
, OK
),
8256 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8257 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8258 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8260 TestCompletionCallback callback
;
8262 scoped_ptr
<HttpTransaction
> trans(
8263 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8265 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8266 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8268 rv
= callback
.WaitForResult();
8271 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8272 ASSERT_TRUE(response
!= NULL
);
8274 EXPECT_TRUE(response
->headers
.get() != NULL
);
8275 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8277 std::string response_data
;
8278 rv
= ReadTransaction(trans
.get(), &response_data
);
8280 EXPECT_EQ("", response_data
);
8283 // Make sure that a dropped connection while draining the body for auth
8284 // restart does the right thing.
8285 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8286 HttpRequestInfo request
;
8287 request
.method
= "GET";
8288 request
.url
= GURL("http://www.example.org/");
8289 request
.load_flags
= 0;
8291 MockWrite data_writes1
[] = {
8293 "GET / HTTP/1.1\r\n"
8294 "Host: www.example.org\r\n"
8295 "Connection: keep-alive\r\n\r\n"),
8298 MockRead data_reads1
[] = {
8299 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8300 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8302 MockRead("Content-Length: 14\r\n\r\n"),
8304 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8307 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8308 data_writes1
, arraysize(data_writes1
));
8309 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8311 // After calling trans->RestartWithAuth(), this is the request we should
8312 // be issuing -- the final header line contains the credentials.
8313 MockWrite data_writes2
[] = {
8315 "GET / HTTP/1.1\r\n"
8316 "Host: www.example.org\r\n"
8317 "Connection: keep-alive\r\n"
8318 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8321 // Lastly, the server responds with the actual content.
8322 MockRead data_reads2
[] = {
8323 MockRead("HTTP/1.1 200 OK\r\n"),
8324 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8325 MockRead("Content-Length: 100\r\n\r\n"),
8326 MockRead(SYNCHRONOUS
, OK
),
8329 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8330 data_writes2
, arraysize(data_writes2
));
8331 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8332 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8334 TestCompletionCallback callback1
;
8336 scoped_ptr
<HttpTransaction
> trans(
8337 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8339 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8340 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8342 rv
= callback1
.WaitForResult();
8345 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8346 ASSERT_TRUE(response
!= NULL
);
8347 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8349 TestCompletionCallback callback2
;
8351 rv
= trans
->RestartWithAuth(
8352 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8353 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8355 rv
= callback2
.WaitForResult();
8358 response
= trans
->GetResponseInfo();
8359 ASSERT_TRUE(response
!= NULL
);
8360 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8361 EXPECT_EQ(100, response
->headers
->GetContentLength());
8364 // Test HTTPS connections going through a proxy that sends extra data.
8365 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8366 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8368 HttpRequestInfo request
;
8369 request
.method
= "GET";
8370 request
.url
= GURL("https://www.example.org/");
8371 request
.load_flags
= 0;
8373 MockRead proxy_reads
[] = {
8374 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8375 MockRead(SYNCHRONOUS
, OK
)
8378 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8379 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8381 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8382 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8384 TestCompletionCallback callback
;
8386 session_deps_
.socket_factory
->ResetNextMockIndexes();
8388 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8389 scoped_ptr
<HttpTransaction
> trans(
8390 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8392 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8393 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8395 rv
= callback
.WaitForResult();
8396 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8399 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8400 HttpRequestInfo request
;
8401 request
.method
= "GET";
8402 request
.url
= GURL("http://www.example.org/");
8403 request
.load_flags
= 0;
8405 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8406 scoped_ptr
<HttpTransaction
> trans(
8407 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8409 MockRead data_reads
[] = {
8410 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8411 MockRead(SYNCHRONOUS
, OK
),
8414 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8415 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8417 TestCompletionCallback callback
;
8419 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8420 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8422 EXPECT_EQ(OK
, callback
.WaitForResult());
8424 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8425 ASSERT_TRUE(response
!= NULL
);
8427 EXPECT_TRUE(response
->headers
.get() != NULL
);
8428 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8430 std::string response_data
;
8431 rv
= ReadTransaction(trans
.get(), &response_data
);
8432 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8435 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8436 base::FilePath temp_file_path
;
8437 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8438 const uint64 kFakeSize
= 100000; // file is actually blank
8439 UploadFileElementReader::ScopedOverridingContentLengthForTests
8440 overriding_content_length(kFakeSize
);
8442 ScopedVector
<UploadElementReader
> element_readers
;
8443 element_readers
.push_back(
8444 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8449 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8451 HttpRequestInfo request
;
8452 request
.method
= "POST";
8453 request
.url
= GURL("http://www.example.org/upload");
8454 request
.upload_data_stream
= &upload_data_stream
;
8455 request
.load_flags
= 0;
8457 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8458 scoped_ptr
<HttpTransaction
> trans(
8459 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8461 MockRead data_reads
[] = {
8462 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8463 MockRead("hello world"),
8464 MockRead(SYNCHRONOUS
, OK
),
8466 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8467 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8469 TestCompletionCallback callback
;
8471 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8472 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8474 rv
= callback
.WaitForResult();
8477 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8478 ASSERT_TRUE(response
!= NULL
);
8480 EXPECT_TRUE(response
->headers
.get() != NULL
);
8481 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8483 std::string response_data
;
8484 rv
= ReadTransaction(trans
.get(), &response_data
);
8486 EXPECT_EQ("hello world", response_data
);
8488 base::DeleteFile(temp_file_path
, false);
8491 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8492 base::FilePath temp_file
;
8493 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8494 std::string
temp_file_content("Unreadable file.");
8495 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8496 temp_file_content
.length()));
8497 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8499 ScopedVector
<UploadElementReader
> element_readers
;
8500 element_readers
.push_back(
8501 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8506 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8508 HttpRequestInfo request
;
8509 request
.method
= "POST";
8510 request
.url
= GURL("http://www.example.org/upload");
8511 request
.upload_data_stream
= &upload_data_stream
;
8512 request
.load_flags
= 0;
8514 // If we try to upload an unreadable file, the transaction should fail.
8515 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8516 scoped_ptr
<HttpTransaction
> trans(
8517 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8519 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8520 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8522 TestCompletionCallback callback
;
8524 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8525 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8527 rv
= callback
.WaitForResult();
8528 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8530 base::DeleteFile(temp_file
, false);
8533 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8534 class FakeUploadElementReader
: public UploadElementReader
{
8536 FakeUploadElementReader() {}
8537 ~FakeUploadElementReader() override
{}
8539 const CompletionCallback
& callback() const { return callback_
; }
8541 // UploadElementReader overrides:
8542 int Init(const CompletionCallback
& callback
) override
{
8543 callback_
= callback
;
8544 return ERR_IO_PENDING
;
8546 uint64
GetContentLength() const override
{ return 0; }
8547 uint64
BytesRemaining() const override
{ return 0; }
8548 int Read(IOBuffer
* buf
,
8550 const CompletionCallback
& callback
) override
{
8555 CompletionCallback callback_
;
8558 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8559 ScopedVector
<UploadElementReader
> element_readers
;
8560 element_readers
.push_back(fake_reader
);
8561 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8563 HttpRequestInfo request
;
8564 request
.method
= "POST";
8565 request
.url
= GURL("http://www.example.org/upload");
8566 request
.upload_data_stream
= &upload_data_stream
;
8567 request
.load_flags
= 0;
8569 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8570 scoped_ptr
<HttpTransaction
> trans(
8571 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8573 StaticSocketDataProvider data
;
8574 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8576 TestCompletionCallback callback
;
8577 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8578 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8579 base::MessageLoop::current()->RunUntilIdle();
8581 // Transaction is pending on request body initialization.
8582 ASSERT_FALSE(fake_reader
->callback().is_null());
8584 // Return Init()'s result after the transaction gets destroyed.
8586 fake_reader
->callback().Run(OK
); // Should not crash.
8589 // Tests that changes to Auth realms are treated like auth rejections.
8590 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8592 HttpRequestInfo request
;
8593 request
.method
= "GET";
8594 request
.url
= GURL("http://www.example.org/");
8595 request
.load_flags
= 0;
8597 // First transaction will request a resource and receive a Basic challenge
8598 // with realm="first_realm".
8599 MockWrite data_writes1
[] = {
8601 "GET / HTTP/1.1\r\n"
8602 "Host: www.example.org\r\n"
8603 "Connection: keep-alive\r\n"
8606 MockRead data_reads1
[] = {
8607 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8608 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8612 // After calling trans->RestartWithAuth(), provide an Authentication header
8613 // for first_realm. The server will reject and provide a challenge with
8615 MockWrite data_writes2
[] = {
8617 "GET / HTTP/1.1\r\n"
8618 "Host: www.example.org\r\n"
8619 "Connection: keep-alive\r\n"
8620 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8623 MockRead data_reads2
[] = {
8624 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8625 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8629 // This again fails, and goes back to first_realm. Make sure that the
8630 // entry is removed from cache.
8631 MockWrite data_writes3
[] = {
8633 "GET / HTTP/1.1\r\n"
8634 "Host: www.example.org\r\n"
8635 "Connection: keep-alive\r\n"
8636 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8639 MockRead data_reads3
[] = {
8640 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8641 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8645 // Try one last time (with the correct password) and get the resource.
8646 MockWrite data_writes4
[] = {
8648 "GET / HTTP/1.1\r\n"
8649 "Host: www.example.org\r\n"
8650 "Connection: keep-alive\r\n"
8651 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8654 MockRead data_reads4
[] = {
8655 MockRead("HTTP/1.1 200 OK\r\n"
8656 "Content-Type: text/html; charset=iso-8859-1\r\n"
8657 "Content-Length: 5\r\n"
8662 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8663 data_writes1
, arraysize(data_writes1
));
8664 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8665 data_writes2
, arraysize(data_writes2
));
8666 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8667 data_writes3
, arraysize(data_writes3
));
8668 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8669 data_writes4
, arraysize(data_writes4
));
8670 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8671 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8672 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8673 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8675 TestCompletionCallback callback1
;
8677 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8678 scoped_ptr
<HttpTransaction
> trans(
8679 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8681 // Issue the first request with Authorize headers. There should be a
8682 // password prompt for first_realm waiting to be filled in after the
8683 // transaction completes.
8684 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8685 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8686 rv
= callback1
.WaitForResult();
8688 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8689 ASSERT_TRUE(response
!= NULL
);
8690 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8691 ASSERT_FALSE(challenge
== NULL
);
8692 EXPECT_FALSE(challenge
->is_proxy
);
8693 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8694 EXPECT_EQ("first_realm", challenge
->realm
);
8695 EXPECT_EQ("basic", challenge
->scheme
);
8697 // Issue the second request with an incorrect password. There should be a
8698 // password prompt for second_realm waiting to be filled in after the
8699 // transaction completes.
8700 TestCompletionCallback callback2
;
8701 rv
= trans
->RestartWithAuth(
8702 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8703 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8704 rv
= callback2
.WaitForResult();
8706 response
= trans
->GetResponseInfo();
8707 ASSERT_TRUE(response
!= NULL
);
8708 challenge
= response
->auth_challenge
.get();
8709 ASSERT_FALSE(challenge
== NULL
);
8710 EXPECT_FALSE(challenge
->is_proxy
);
8711 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8712 EXPECT_EQ("second_realm", challenge
->realm
);
8713 EXPECT_EQ("basic", challenge
->scheme
);
8715 // Issue the third request with another incorrect password. There should be
8716 // a password prompt for first_realm waiting to be filled in. If the password
8717 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8718 // first_realm was not correctly removed.
8719 TestCompletionCallback callback3
;
8720 rv
= trans
->RestartWithAuth(
8721 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8723 rv
= callback3
.WaitForResult();
8725 response
= trans
->GetResponseInfo();
8726 ASSERT_TRUE(response
!= NULL
);
8727 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 fourth request with the correct password and username.
8735 TestCompletionCallback callback4
;
8736 rv
= trans
->RestartWithAuth(
8737 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8738 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8739 rv
= callback4
.WaitForResult();
8741 response
= trans
->GetResponseInfo();
8742 ASSERT_TRUE(response
!= NULL
);
8743 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8746 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8747 session_deps_
.next_protos
= SpdyNextProtos();
8748 session_deps_
.use_alternate_protocols
= true;
8750 std::string alternate_protocol_http_header
=
8751 GetAlternateProtocolHttpHeader();
8753 MockRead data_reads
[] = {
8754 MockRead("HTTP/1.1 200 OK\r\n"),
8755 MockRead(alternate_protocol_http_header
.c_str()),
8756 MockRead("hello world"),
8757 MockRead(SYNCHRONOUS
, OK
),
8760 HttpRequestInfo request
;
8761 request
.method
= "GET";
8762 request
.url
= GURL("http://www.example.org/");
8763 request
.load_flags
= 0;
8765 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8767 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8769 TestCompletionCallback callback
;
8771 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8772 scoped_ptr
<HttpTransaction
> trans(
8773 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8775 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8778 HostPortPair
http_host_port_pair("www.example.org", 80);
8779 HttpServerProperties
& http_server_properties
=
8780 *session
->http_server_properties();
8781 AlternativeService alternative_service
=
8782 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8783 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8785 EXPECT_EQ(OK
, callback
.WaitForResult());
8787 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8788 ASSERT_TRUE(response
!= NULL
);
8789 ASSERT_TRUE(response
->headers
.get() != NULL
);
8790 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8791 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8792 EXPECT_FALSE(response
->was_npn_negotiated
);
8794 std::string response_data
;
8795 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8796 EXPECT_EQ("hello world", response_data
);
8798 alternative_service
=
8799 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8800 EXPECT_EQ(443, alternative_service
.port
);
8801 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8802 alternative_service
.protocol
);
8805 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8806 session_deps_
.next_protos
= SpdyNextProtos();
8807 session_deps_
.use_alternate_protocols
= true;
8809 MockRead data_reads
[] = {
8810 MockRead("HTTP/1.1 200 OK\r\n"),
8811 MockRead("Alternate-Protocol: \r\n\r\n"),
8812 MockRead("hello world"),
8813 MockRead(SYNCHRONOUS
, OK
),
8816 HttpRequestInfo request
;
8817 request
.method
= "GET";
8818 request
.url
= GURL("http://www.example.org/");
8819 request
.load_flags
= 0;
8821 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8823 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8825 TestCompletionCallback callback
;
8827 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8829 HostPortPair
http_host_port_pair("www.example.org", 80);
8830 HttpServerProperties
& http_server_properties
=
8831 *session
->http_server_properties();
8832 AlternativeService
alternative_service(QUIC
, "", 80);
8833 http_server_properties
.SetAlternativeService(http_host_port_pair
,
8834 alternative_service
, 1.0);
8836 alternative_service
=
8837 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8838 EXPECT_EQ(alternative_service
.protocol
, QUIC
);
8840 scoped_ptr
<HttpTransaction
> trans(
8841 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8843 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8844 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8846 EXPECT_EQ(OK
, callback
.WaitForResult());
8848 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8849 ASSERT_TRUE(response
!= NULL
);
8850 ASSERT_TRUE(response
->headers
.get() != NULL
);
8851 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8852 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8853 EXPECT_FALSE(response
->was_npn_negotiated
);
8855 std::string response_data
;
8856 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8857 EXPECT_EQ("hello world", response_data
);
8859 alternative_service
=
8860 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8861 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8864 TEST_P(HttpNetworkTransactionTest
,
8865 MarkBrokenAlternateProtocolAndFallback
) {
8866 session_deps_
.use_alternate_protocols
= true;
8868 HttpRequestInfo request
;
8869 request
.method
= "GET";
8870 request
.url
= GURL("http://www.example.org/");
8871 request
.load_flags
= 0;
8873 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8874 StaticSocketDataProvider first_data
;
8875 first_data
.set_connect_data(mock_connect
);
8876 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8878 MockRead data_reads
[] = {
8879 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8880 MockRead("hello world"),
8881 MockRead(ASYNC
, OK
),
8883 StaticSocketDataProvider
second_data(
8884 data_reads
, arraysize(data_reads
), NULL
, 0);
8885 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8887 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8889 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8890 session
->http_server_properties();
8891 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
8892 // Port must be < 1024, or the header will be ignored (since initial port was
8893 // port 80 (another restricted port).
8894 AlternativeService
alternative_service(
8895 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8896 666); /* port is ignored by MockConnect anyway */
8897 http_server_properties
->SetAlternativeService(host_port_pair
,
8898 alternative_service
, 1.0);
8900 scoped_ptr
<HttpTransaction
> trans(
8901 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8902 TestCompletionCallback callback
;
8904 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8905 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8906 EXPECT_EQ(OK
, callback
.WaitForResult());
8908 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8909 ASSERT_TRUE(response
!= NULL
);
8910 ASSERT_TRUE(response
->headers
.get() != NULL
);
8911 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8913 std::string response_data
;
8914 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8915 EXPECT_EQ("hello world", response_data
);
8917 alternative_service
=
8918 http_server_properties
->GetAlternativeService(host_port_pair
);
8919 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL
, alternative_service
.protocol
);
8921 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
8924 TEST_P(HttpNetworkTransactionTest
,
8925 AlternateProtocolPortRestrictedBlocked
) {
8926 // Ensure that we're not allowed to redirect traffic via an alternate
8927 // protocol to an unrestricted (port >= 1024) when the original traffic was
8928 // on a restricted port (port < 1024). Ensure that we can redirect in all
8930 session_deps_
.use_alternate_protocols
= true;
8932 HttpRequestInfo restricted_port_request
;
8933 restricted_port_request
.method
= "GET";
8934 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8935 restricted_port_request
.load_flags
= 0;
8937 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8938 StaticSocketDataProvider first_data
;
8939 first_data
.set_connect_data(mock_connect
);
8940 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8942 MockRead data_reads
[] = {
8943 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8944 MockRead("hello world"),
8945 MockRead(ASYNC
, OK
),
8947 StaticSocketDataProvider
second_data(
8948 data_reads
, arraysize(data_reads
), NULL
, 0);
8949 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8951 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8953 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8954 session
->http_server_properties();
8955 const int kUnrestrictedAlternatePort
= 1024;
8956 AlternativeService
alternative_service(
8957 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8958 kUnrestrictedAlternatePort
);
8959 http_server_properties
->SetAlternativeService(
8960 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8963 scoped_ptr
<HttpTransaction
> trans(
8964 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8965 TestCompletionCallback callback
;
8967 int rv
= trans
->Start(
8968 &restricted_port_request
,
8969 callback
.callback(), BoundNetLog());
8970 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8971 // Invalid change to unrestricted port should fail.
8972 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8975 TEST_P(HttpNetworkTransactionTest
,
8976 AlternateProtocolPortRestrictedPermitted
) {
8977 // Ensure that we're allowed to redirect traffic via an alternate
8978 // protocol to an unrestricted (port >= 1024) when the original traffic was
8979 // on a restricted port (port < 1024) if we set
8980 // enable_user_alternate_protocol_ports.
8982 session_deps_
.use_alternate_protocols
= true;
8983 session_deps_
.enable_user_alternate_protocol_ports
= true;
8985 HttpRequestInfo restricted_port_request
;
8986 restricted_port_request
.method
= "GET";
8987 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8988 restricted_port_request
.load_flags
= 0;
8990 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8991 StaticSocketDataProvider first_data
;
8992 first_data
.set_connect_data(mock_connect
);
8993 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8995 MockRead data_reads
[] = {
8996 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8997 MockRead("hello world"),
8998 MockRead(ASYNC
, OK
),
9000 StaticSocketDataProvider
second_data(
9001 data_reads
, arraysize(data_reads
), NULL
, 0);
9002 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9004 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9006 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9007 session
->http_server_properties();
9008 const int kUnrestrictedAlternatePort
= 1024;
9009 AlternativeService
alternative_service(
9010 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9011 kUnrestrictedAlternatePort
);
9012 http_server_properties
->SetAlternativeService(
9013 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9016 scoped_ptr
<HttpTransaction
> trans(
9017 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9018 TestCompletionCallback callback
;
9020 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9021 &restricted_port_request
,
9022 callback
.callback(), BoundNetLog()));
9023 // Change to unrestricted port should succeed.
9024 EXPECT_EQ(OK
, callback
.WaitForResult());
9027 TEST_P(HttpNetworkTransactionTest
,
9028 AlternateProtocolPortRestrictedAllowed
) {
9029 // Ensure that we're not allowed to redirect traffic via an alternate
9030 // protocol to an unrestricted (port >= 1024) when the original traffic was
9031 // on a restricted port (port < 1024). Ensure that we can redirect in all
9033 session_deps_
.use_alternate_protocols
= true;
9035 HttpRequestInfo restricted_port_request
;
9036 restricted_port_request
.method
= "GET";
9037 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9038 restricted_port_request
.load_flags
= 0;
9040 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9041 StaticSocketDataProvider first_data
;
9042 first_data
.set_connect_data(mock_connect
);
9043 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9045 MockRead data_reads
[] = {
9046 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9047 MockRead("hello world"),
9048 MockRead(ASYNC
, OK
),
9050 StaticSocketDataProvider
second_data(
9051 data_reads
, arraysize(data_reads
), NULL
, 0);
9052 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9054 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9056 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9057 session
->http_server_properties();
9058 const int kRestrictedAlternatePort
= 80;
9059 AlternativeService
alternative_service(
9060 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9061 kRestrictedAlternatePort
);
9062 http_server_properties
->SetAlternativeService(
9063 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9066 scoped_ptr
<HttpTransaction
> trans(
9067 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9068 TestCompletionCallback callback
;
9070 int rv
= trans
->Start(
9071 &restricted_port_request
,
9072 callback
.callback(), BoundNetLog());
9073 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9074 // Valid change to restricted port should pass.
9075 EXPECT_EQ(OK
, callback
.WaitForResult());
9078 TEST_P(HttpNetworkTransactionTest
,
9079 AlternateProtocolPortUnrestrictedAllowed1
) {
9080 // Ensure that we're not allowed to redirect traffic via an alternate
9081 // protocol to an unrestricted (port >= 1024) when the original traffic was
9082 // on a restricted port (port < 1024). Ensure that we can redirect in all
9084 session_deps_
.use_alternate_protocols
= true;
9086 HttpRequestInfo unrestricted_port_request
;
9087 unrestricted_port_request
.method
= "GET";
9088 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9089 unrestricted_port_request
.load_flags
= 0;
9091 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9092 StaticSocketDataProvider first_data
;
9093 first_data
.set_connect_data(mock_connect
);
9094 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9096 MockRead data_reads
[] = {
9097 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9098 MockRead("hello world"),
9099 MockRead(ASYNC
, OK
),
9101 StaticSocketDataProvider
second_data(
9102 data_reads
, arraysize(data_reads
), NULL
, 0);
9103 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9105 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9107 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9108 session
->http_server_properties();
9109 const int kRestrictedAlternatePort
= 80;
9110 AlternativeService
alternative_service(
9111 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9112 kRestrictedAlternatePort
);
9113 http_server_properties
->SetAlternativeService(
9114 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9117 scoped_ptr
<HttpTransaction
> trans(
9118 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9119 TestCompletionCallback callback
;
9121 int rv
= trans
->Start(
9122 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9123 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9124 // Valid change to restricted port should pass.
9125 EXPECT_EQ(OK
, callback
.WaitForResult());
9128 TEST_P(HttpNetworkTransactionTest
,
9129 AlternateProtocolPortUnrestrictedAllowed2
) {
9130 // Ensure that we're not allowed to redirect traffic via an alternate
9131 // protocol to an unrestricted (port >= 1024) when the original traffic was
9132 // on a restricted port (port < 1024). Ensure that we can redirect in all
9134 session_deps_
.use_alternate_protocols
= true;
9136 HttpRequestInfo unrestricted_port_request
;
9137 unrestricted_port_request
.method
= "GET";
9138 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9139 unrestricted_port_request
.load_flags
= 0;
9141 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9142 StaticSocketDataProvider first_data
;
9143 first_data
.set_connect_data(mock_connect
);
9144 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9146 MockRead data_reads
[] = {
9147 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9148 MockRead("hello world"),
9149 MockRead(ASYNC
, OK
),
9151 StaticSocketDataProvider
second_data(
9152 data_reads
, arraysize(data_reads
), NULL
, 0);
9153 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9155 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9157 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9158 session
->http_server_properties();
9159 const int kUnrestrictedAlternatePort
= 1024;
9160 AlternativeService
alternative_service(
9161 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9162 kUnrestrictedAlternatePort
);
9163 http_server_properties
->SetAlternativeService(
9164 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9167 scoped_ptr
<HttpTransaction
> trans(
9168 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9169 TestCompletionCallback callback
;
9171 int rv
= trans
->Start(
9172 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9173 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9174 // Valid change to an unrestricted port should pass.
9175 EXPECT_EQ(OK
, callback
.WaitForResult());
9178 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9179 // Ensure that we're not allowed to redirect traffic via an alternate
9180 // protocol to an unsafe port, and that we resume the second
9181 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9182 session_deps_
.use_alternate_protocols
= true;
9184 HttpRequestInfo request
;
9185 request
.method
= "GET";
9186 request
.url
= GURL("http://www.example.org/");
9187 request
.load_flags
= 0;
9189 // The alternate protocol request will error out before we attempt to connect,
9190 // so only the standard HTTP request will try to connect.
9191 MockRead data_reads
[] = {
9192 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9193 MockRead("hello world"),
9194 MockRead(ASYNC
, OK
),
9196 StaticSocketDataProvider
data(
9197 data_reads
, arraysize(data_reads
), NULL
, 0);
9198 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9202 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9203 session
->http_server_properties();
9204 const int kUnsafePort
= 7;
9205 AlternativeService
alternative_service(
9206 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9208 http_server_properties
->SetAlternativeService(
9209 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0);
9211 scoped_ptr
<HttpTransaction
> trans(
9212 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9213 TestCompletionCallback callback
;
9215 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9216 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9217 // The HTTP request should succeed.
9218 EXPECT_EQ(OK
, callback
.WaitForResult());
9220 // Disable alternate protocol before the asserts.
9221 // HttpStreamFactory::set_use_alternate_protocols(false);
9223 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9224 ASSERT_TRUE(response
!= NULL
);
9225 ASSERT_TRUE(response
->headers
.get() != NULL
);
9226 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9228 std::string response_data
;
9229 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9230 EXPECT_EQ("hello world", response_data
);
9233 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9234 session_deps_
.use_alternate_protocols
= true;
9235 session_deps_
.next_protos
= SpdyNextProtos();
9237 HttpRequestInfo request
;
9238 request
.method
= "GET";
9239 request
.url
= GURL("http://www.example.org/");
9240 request
.load_flags
= 0;
9242 std::string alternate_protocol_http_header
=
9243 GetAlternateProtocolHttpHeader();
9245 MockRead data_reads
[] = {
9246 MockRead("HTTP/1.1 200 OK\r\n"),
9247 MockRead(alternate_protocol_http_header
.c_str()),
9248 MockRead("hello world"),
9249 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9253 StaticSocketDataProvider
first_transaction(
9254 data_reads
, arraysize(data_reads
), NULL
, 0);
9255 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9257 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9258 ssl
.SetNextProto(GetParam());
9259 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9260 ASSERT_TRUE(ssl
.cert
.get());
9261 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9263 scoped_ptr
<SpdyFrame
> req(
9264 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9265 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9267 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9268 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9269 MockRead spdy_reads
[] = {
9270 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9273 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9274 arraysize(spdy_writes
));
9275 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9277 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9278 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9280 hanging_non_alternate_protocol_socket
.set_connect_data(
9281 never_finishing_connect
);
9282 session_deps_
.socket_factory
->AddSocketDataProvider(
9283 &hanging_non_alternate_protocol_socket
);
9285 TestCompletionCallback callback
;
9287 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9288 scoped_ptr
<HttpTransaction
> trans(
9289 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9291 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9292 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9293 EXPECT_EQ(OK
, callback
.WaitForResult());
9295 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9296 ASSERT_TRUE(response
!= NULL
);
9297 ASSERT_TRUE(response
->headers
.get() != NULL
);
9298 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9300 std::string response_data
;
9301 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9302 EXPECT_EQ("hello world", response_data
);
9304 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9306 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9307 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9308 EXPECT_EQ(OK
, callback
.WaitForResult());
9310 response
= trans
->GetResponseInfo();
9311 ASSERT_TRUE(response
!= NULL
);
9312 ASSERT_TRUE(response
->headers
.get() != NULL
);
9313 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9314 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9315 EXPECT_TRUE(response
->was_npn_negotiated
);
9317 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9318 EXPECT_EQ("hello!", response_data
);
9321 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9322 session_deps_
.use_alternate_protocols
= true;
9323 session_deps_
.next_protos
= SpdyNextProtos();
9325 HttpRequestInfo request
;
9326 request
.method
= "GET";
9327 request
.url
= GURL("http://www.example.org/");
9328 request
.load_flags
= 0;
9330 std::string alternate_protocol_http_header
=
9331 GetAlternateProtocolHttpHeader();
9333 MockRead data_reads
[] = {
9334 MockRead("HTTP/1.1 200 OK\r\n"),
9335 MockRead(alternate_protocol_http_header
.c_str()),
9336 MockRead("hello world"),
9337 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9338 MockRead(ASYNC
, OK
),
9341 StaticSocketDataProvider
first_transaction(
9342 data_reads
, arraysize(data_reads
), NULL
, 0);
9343 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9344 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9346 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9347 StaticSocketDataProvider
hanging_socket(
9349 hanging_socket
.set_connect_data(never_finishing_connect
);
9350 // Socket 2 and 3 are the hanging Alternate-Protocol and
9351 // non-Alternate-Protocol jobs from the 2nd transaction.
9352 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9353 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9355 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9356 ssl
.SetNextProto(GetParam());
9357 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9358 ASSERT_TRUE(ssl
.cert
.get());
9359 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9361 scoped_ptr
<SpdyFrame
> req1(
9362 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9363 scoped_ptr
<SpdyFrame
> req2(
9364 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9365 MockWrite spdy_writes
[] = {
9366 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9368 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9369 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9370 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9371 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9372 MockRead spdy_reads
[] = {
9373 CreateMockRead(*resp1
, 2),
9374 CreateMockRead(*data1
, 3),
9375 CreateMockRead(*resp2
, 4),
9376 CreateMockRead(*data2
, 5),
9377 MockRead(ASYNC
, 0, 6),
9380 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9381 arraysize(spdy_writes
));
9382 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9383 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9385 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9386 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9388 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9389 TestCompletionCallback callback1
;
9390 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9392 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9393 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9394 EXPECT_EQ(OK
, callback1
.WaitForResult());
9396 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9397 ASSERT_TRUE(response
!= NULL
);
9398 ASSERT_TRUE(response
->headers
.get() != NULL
);
9399 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9401 std::string response_data
;
9402 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9403 EXPECT_EQ("hello world", response_data
);
9405 TestCompletionCallback callback2
;
9406 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9407 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9408 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9410 TestCompletionCallback callback3
;
9411 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9412 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9413 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9415 EXPECT_EQ(OK
, callback2
.WaitForResult());
9416 EXPECT_EQ(OK
, callback3
.WaitForResult());
9418 response
= trans2
.GetResponseInfo();
9419 ASSERT_TRUE(response
!= NULL
);
9420 ASSERT_TRUE(response
->headers
.get() != NULL
);
9421 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9422 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9423 EXPECT_TRUE(response
->was_npn_negotiated
);
9424 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9425 EXPECT_EQ("hello!", response_data
);
9427 response
= trans3
.GetResponseInfo();
9428 ASSERT_TRUE(response
!= NULL
);
9429 ASSERT_TRUE(response
->headers
.get() != NULL
);
9430 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9431 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9432 EXPECT_TRUE(response
->was_npn_negotiated
);
9433 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9434 EXPECT_EQ("hello!", response_data
);
9437 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9438 session_deps_
.use_alternate_protocols
= true;
9439 session_deps_
.next_protos
= SpdyNextProtos();
9441 HttpRequestInfo request
;
9442 request
.method
= "GET";
9443 request
.url
= GURL("http://www.example.org/");
9444 request
.load_flags
= 0;
9446 std::string alternate_protocol_http_header
=
9447 GetAlternateProtocolHttpHeader();
9449 MockRead data_reads
[] = {
9450 MockRead("HTTP/1.1 200 OK\r\n"),
9451 MockRead(alternate_protocol_http_header
.c_str()),
9452 MockRead("hello world"),
9453 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9454 MockRead(ASYNC
, OK
),
9457 StaticSocketDataProvider
first_transaction(
9458 data_reads
, arraysize(data_reads
), NULL
, 0);
9459 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9461 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9462 ssl
.SetNextProto(GetParam());
9463 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9465 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9466 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9468 hanging_alternate_protocol_socket
.set_connect_data(
9469 never_finishing_connect
);
9470 session_deps_
.socket_factory
->AddSocketDataProvider(
9471 &hanging_alternate_protocol_socket
);
9473 // 2nd request is just a copy of the first one, over HTTP again.
9474 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9476 TestCompletionCallback callback
;
9478 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9479 scoped_ptr
<HttpTransaction
> trans(
9480 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9482 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9483 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9484 EXPECT_EQ(OK
, callback
.WaitForResult());
9486 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9487 ASSERT_TRUE(response
!= NULL
);
9488 ASSERT_TRUE(response
->headers
.get() != NULL
);
9489 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9491 std::string response_data
;
9492 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9493 EXPECT_EQ("hello world", response_data
);
9495 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9497 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9498 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9499 EXPECT_EQ(OK
, callback
.WaitForResult());
9501 response
= trans
->GetResponseInfo();
9502 ASSERT_TRUE(response
!= NULL
);
9503 ASSERT_TRUE(response
->headers
.get() != NULL
);
9504 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9505 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9506 EXPECT_FALSE(response
->was_npn_negotiated
);
9508 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9509 EXPECT_EQ("hello world", response_data
);
9512 class CapturingProxyResolver
: public ProxyResolver
{
9514 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9515 ~CapturingProxyResolver() override
{}
9517 int GetProxyForURL(const GURL
& url
,
9519 const CompletionCallback
& callback
,
9520 RequestHandle
* request
,
9521 const BoundNetLog
& net_log
) override
{
9522 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9523 HostPortPair("myproxy", 80));
9524 results
->UseProxyServer(proxy_server
);
9525 resolved_
.push_back(url
);
9529 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9531 LoadState
GetLoadState(RequestHandle request
) const override
{
9533 return LOAD_STATE_IDLE
;
9536 void CancelSetPacScript() override
{ NOTREACHED(); }
9538 int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9539 const CompletionCallback
& /*callback*/) override
{
9543 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9546 std::vector
<GURL
> resolved_
;
9548 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9551 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9553 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9554 : ProxyResolverFactory(false), resolver_(resolver
) {}
9556 int CreateProxyResolver(
9557 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9558 scoped_ptr
<ProxyResolver
>* resolver
,
9559 const net::CompletionCallback
& callback
,
9560 scoped_ptr
<Request
>* request
) override
{
9561 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9566 ProxyResolver
* resolver_
;
9569 TEST_P(HttpNetworkTransactionTest
,
9570 UseAlternateProtocolForTunneledNpnSpdy
) {
9571 session_deps_
.use_alternate_protocols
= true;
9572 session_deps_
.next_protos
= SpdyNextProtos();
9574 ProxyConfig proxy_config
;
9575 proxy_config
.set_auto_detect(true);
9576 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9578 CapturingProxyResolver capturing_proxy_resolver
;
9579 session_deps_
.proxy_service
.reset(new ProxyService(
9580 new ProxyConfigServiceFixed(proxy_config
),
9582 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9585 session_deps_
.net_log
= &net_log
;
9587 HttpRequestInfo request
;
9588 request
.method
= "GET";
9589 request
.url
= GURL("http://www.example.org/");
9590 request
.load_flags
= 0;
9592 std::string alternate_protocol_http_header
=
9593 GetAlternateProtocolHttpHeader();
9595 MockRead data_reads
[] = {
9596 MockRead("HTTP/1.1 200 OK\r\n"),
9597 MockRead(alternate_protocol_http_header
.c_str()),
9598 MockRead("hello world"),
9599 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9600 MockRead(ASYNC
, OK
),
9603 StaticSocketDataProvider
first_transaction(
9604 data_reads
, arraysize(data_reads
), NULL
, 0);
9605 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9607 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9608 ssl
.SetNextProto(GetParam());
9609 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9610 ASSERT_TRUE(ssl
.cert
.get());
9611 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9613 scoped_ptr
<SpdyFrame
> req(
9614 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9615 MockWrite spdy_writes
[] = {
9617 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9618 "Host: www.example.org\r\n"
9619 "Proxy-Connection: keep-alive\r\n\r\n"),
9620 CreateMockWrite(*req
, 2),
9623 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9625 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9626 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9627 MockRead spdy_reads
[] = {
9628 MockRead(ASYNC
, 1, kCONNECTResponse
),
9629 CreateMockRead(*resp
.get(), 3),
9630 CreateMockRead(*data
.get(), 4),
9631 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
9634 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9635 arraysize(spdy_writes
));
9636 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9638 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9639 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9641 hanging_non_alternate_protocol_socket
.set_connect_data(
9642 never_finishing_connect
);
9643 session_deps_
.socket_factory
->AddSocketDataProvider(
9644 &hanging_non_alternate_protocol_socket
);
9646 TestCompletionCallback callback
;
9648 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9649 scoped_ptr
<HttpTransaction
> trans(
9650 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9652 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9653 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9654 EXPECT_EQ(OK
, callback
.WaitForResult());
9656 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9657 ASSERT_TRUE(response
!= NULL
);
9658 ASSERT_TRUE(response
->headers
.get() != NULL
);
9659 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9660 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9661 EXPECT_FALSE(response
->was_npn_negotiated
);
9663 std::string response_data
;
9664 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9665 EXPECT_EQ("hello world", response_data
);
9667 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9669 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9670 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9671 EXPECT_EQ(OK
, callback
.WaitForResult());
9673 response
= trans
->GetResponseInfo();
9674 ASSERT_TRUE(response
!= NULL
);
9675 ASSERT_TRUE(response
->headers
.get() != NULL
);
9676 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9677 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9678 EXPECT_TRUE(response
->was_npn_negotiated
);
9680 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9681 EXPECT_EQ("hello!", response_data
);
9682 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9683 EXPECT_EQ("http://www.example.org/",
9684 capturing_proxy_resolver
.resolved()[0].spec());
9685 EXPECT_EQ("https://www.example.org/",
9686 capturing_proxy_resolver
.resolved()[1].spec());
9688 LoadTimingInfo load_timing_info
;
9689 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9690 TestLoadTimingNotReusedWithPac(load_timing_info
,
9691 CONNECT_TIMING_HAS_SSL_TIMES
);
9694 TEST_P(HttpNetworkTransactionTest
,
9695 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9696 session_deps_
.use_alternate_protocols
= true;
9697 session_deps_
.next_protos
= SpdyNextProtos();
9699 HttpRequestInfo request
;
9700 request
.method
= "GET";
9701 request
.url
= GURL("http://www.example.org/");
9702 request
.load_flags
= 0;
9704 std::string alternate_protocol_http_header
=
9705 GetAlternateProtocolHttpHeader();
9707 MockRead data_reads
[] = {
9708 MockRead("HTTP/1.1 200 OK\r\n"),
9709 MockRead(alternate_protocol_http_header
.c_str()),
9710 MockRead("hello world"),
9711 MockRead(ASYNC
, OK
),
9714 StaticSocketDataProvider
first_transaction(
9715 data_reads
, arraysize(data_reads
), NULL
, 0);
9716 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9718 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9719 ssl
.SetNextProto(GetParam());
9720 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9721 ASSERT_TRUE(ssl
.cert
.get());
9722 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9724 scoped_ptr
<SpdyFrame
> req(
9725 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9726 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9728 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9729 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9730 MockRead spdy_reads
[] = {
9731 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9734 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9735 arraysize(spdy_writes
));
9736 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9738 TestCompletionCallback callback
;
9740 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9742 scoped_ptr
<HttpTransaction
> trans(
9743 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9745 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9746 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9747 EXPECT_EQ(OK
, callback
.WaitForResult());
9749 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9750 ASSERT_TRUE(response
!= NULL
);
9751 ASSERT_TRUE(response
->headers
.get() != NULL
);
9752 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9754 std::string response_data
;
9755 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9756 EXPECT_EQ("hello world", response_data
);
9758 // Set up an initial SpdySession in the pool to reuse.
9759 HostPortPair
host_port_pair("www.example.org", 443);
9760 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9761 PRIVACY_MODE_DISABLED
);
9762 base::WeakPtr
<SpdySession
> spdy_session
=
9763 CreateSecureSpdySession(session
, key
, BoundNetLog());
9765 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9767 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9768 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9769 EXPECT_EQ(OK
, callback
.WaitForResult());
9771 response
= trans
->GetResponseInfo();
9772 ASSERT_TRUE(response
!= NULL
);
9773 ASSERT_TRUE(response
->headers
.get() != NULL
);
9774 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9775 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9776 EXPECT_TRUE(response
->was_npn_negotiated
);
9778 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9779 EXPECT_EQ("hello!", response_data
);
9782 // GenerateAuthToken is a mighty big test.
9783 // It tests all permutation of GenerateAuthToken behavior:
9784 // - Synchronous and Asynchronous completion.
9785 // - OK or error on completion.
9786 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9787 // - HTTP or HTTPS backend (to include proxy tunneling).
9788 // - Non-authenticating and authenticating backend.
9790 // In all, there are 44 reasonable permuations (for example, if there are
9791 // problems generating an auth token for an authenticating proxy, we don't
9792 // need to test all permutations of the backend server).
9794 // The test proceeds by going over each of the configuration cases, and
9795 // potentially running up to three rounds in each of the tests. The TestConfig
9796 // specifies both the configuration for the test as well as the expectations
9798 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9799 static const char kServer
[] = "http://www.example.com";
9800 static const char kSecureServer
[] = "https://www.example.com";
9801 static const char kProxy
[] = "myproxy:70";
9802 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9810 const MockWrite
kGet(
9811 "GET / HTTP/1.1\r\n"
9812 "Host: www.example.com\r\n"
9813 "Connection: keep-alive\r\n\r\n");
9814 const MockWrite
kGetProxy(
9815 "GET http://www.example.com/ HTTP/1.1\r\n"
9816 "Host: www.example.com\r\n"
9817 "Proxy-Connection: keep-alive\r\n\r\n");
9818 const MockWrite
kGetAuth(
9819 "GET / HTTP/1.1\r\n"
9820 "Host: www.example.com\r\n"
9821 "Connection: keep-alive\r\n"
9822 "Authorization: auth_token\r\n\r\n");
9823 const MockWrite
kGetProxyAuth(
9824 "GET http://www.example.com/ HTTP/1.1\r\n"
9825 "Host: www.example.com\r\n"
9826 "Proxy-Connection: keep-alive\r\n"
9827 "Proxy-Authorization: auth_token\r\n\r\n");
9828 const MockWrite
kGetAuthThroughProxy(
9829 "GET http://www.example.com/ HTTP/1.1\r\n"
9830 "Host: www.example.com\r\n"
9831 "Proxy-Connection: keep-alive\r\n"
9832 "Authorization: auth_token\r\n\r\n");
9833 const MockWrite
kGetAuthWithProxyAuth(
9834 "GET http://www.example.com/ HTTP/1.1\r\n"
9835 "Host: www.example.com\r\n"
9836 "Proxy-Connection: keep-alive\r\n"
9837 "Proxy-Authorization: auth_token\r\n"
9838 "Authorization: auth_token\r\n\r\n");
9839 const MockWrite
kConnect(
9840 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9841 "Host: www.example.com\r\n"
9842 "Proxy-Connection: keep-alive\r\n\r\n");
9843 const MockWrite
kConnectProxyAuth(
9844 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9845 "Host: www.example.com\r\n"
9846 "Proxy-Connection: keep-alive\r\n"
9847 "Proxy-Authorization: auth_token\r\n\r\n");
9849 const MockRead
kSuccess(
9850 "HTTP/1.1 200 OK\r\n"
9851 "Content-Type: text/html; charset=iso-8859-1\r\n"
9852 "Content-Length: 3\r\n\r\n"
9854 const MockRead
kFailure(
9855 "Should not be called.");
9856 const MockRead
kServerChallenge(
9857 "HTTP/1.1 401 Unauthorized\r\n"
9858 "WWW-Authenticate: Mock realm=server\r\n"
9859 "Content-Type: text/html; charset=iso-8859-1\r\n"
9860 "Content-Length: 14\r\n\r\n"
9861 "Unauthorized\r\n");
9862 const MockRead
kProxyChallenge(
9863 "HTTP/1.1 407 Unauthorized\r\n"
9864 "Proxy-Authenticate: Mock realm=proxy\r\n"
9865 "Proxy-Connection: close\r\n"
9866 "Content-Type: text/html; charset=iso-8859-1\r\n"
9867 "Content-Length: 14\r\n\r\n"
9868 "Unauthorized\r\n");
9869 const MockRead
kProxyConnected(
9870 "HTTP/1.1 200 Connection Established\r\n\r\n");
9872 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9873 // no constructors, but the C++ compiler on Windows warns about
9874 // unspecified data in compound literals. So, moved to using constructors,
9875 // and TestRound's created with the default constructor should not be used.
9878 : expected_rv(ERR_UNEXPECTED
),
9882 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9883 int expected_rv_arg
)
9886 expected_rv(expected_rv_arg
),
9890 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9891 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9892 const MockRead
* extra_read_arg
)
9895 expected_rv(expected_rv_arg
),
9896 extra_write(extra_write_arg
),
9897 extra_read(extra_read_arg
) {
9902 const MockWrite
* extra_write
;
9903 const MockRead
* extra_read
;
9906 static const int kNoSSL
= 500;
9909 const char* const proxy_url
;
9910 AuthTiming proxy_auth_timing
;
9912 const char* const server_url
;
9913 AuthTiming server_auth_timing
;
9915 int num_auth_rounds
;
9916 int first_ssl_round
;
9917 TestRound rounds
[3];
9918 } test_configs
[] = {
9919 // Non-authenticating HTTP server with a direct connection.
9920 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9921 { TestRound(kGet
, kSuccess
, OK
)}},
9922 // Authenticating HTTP server with a direct connection.
9923 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9924 { TestRound(kGet
, kServerChallenge
, OK
),
9925 TestRound(kGetAuth
, kSuccess
, OK
)}},
9926 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9927 { TestRound(kGet
, kServerChallenge
, OK
),
9928 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9929 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9930 { TestRound(kGet
, kServerChallenge
, OK
),
9931 TestRound(kGetAuth
, kSuccess
, OK
)}},
9932 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9933 { TestRound(kGet
, kServerChallenge
, OK
),
9934 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9935 // Non-authenticating HTTP server through a non-authenticating proxy.
9936 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9937 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9938 // Authenticating HTTP server through a non-authenticating proxy.
9939 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9940 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9941 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9942 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9943 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9944 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9945 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9946 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9947 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9948 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9949 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9950 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9951 // Non-authenticating HTTP server through an authenticating proxy.
9952 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9953 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9954 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9955 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9956 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9957 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9958 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9959 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9960 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9961 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9962 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9963 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9964 // Authenticating HTTP server through an authenticating proxy.
9965 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9966 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9967 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9968 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9969 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9970 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9971 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9972 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9973 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9974 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9975 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9976 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9977 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9978 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9979 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9980 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9981 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9982 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9983 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9984 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9985 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9986 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9987 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9988 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9989 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9990 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9991 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9992 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9993 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9994 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9995 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9996 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9997 // Non-authenticating HTTPS server with a direct connection.
9998 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
9999 { TestRound(kGet
, kSuccess
, OK
)}},
10000 // Authenticating HTTPS server with a direct connection.
10001 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10002 { TestRound(kGet
, kServerChallenge
, OK
),
10003 TestRound(kGetAuth
, kSuccess
, OK
)}},
10004 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10005 { TestRound(kGet
, kServerChallenge
, OK
),
10006 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10007 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10008 { TestRound(kGet
, kServerChallenge
, OK
),
10009 TestRound(kGetAuth
, kSuccess
, OK
)}},
10010 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10011 { TestRound(kGet
, kServerChallenge
, OK
),
10012 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10013 // Non-authenticating HTTPS server with a non-authenticating proxy.
10014 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10015 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10016 // Authenticating HTTPS server through a non-authenticating proxy.
10017 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10018 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10019 TestRound(kGetAuth
, kSuccess
, OK
)}},
10020 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10021 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10022 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10023 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10024 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10025 TestRound(kGetAuth
, kSuccess
, OK
)}},
10026 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10027 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10028 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10029 // Non-Authenticating HTTPS server through an authenticating proxy.
10030 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10031 { TestRound(kConnect
, kProxyChallenge
, OK
),
10032 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10033 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10034 { TestRound(kConnect
, kProxyChallenge
, OK
),
10035 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10036 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10037 { TestRound(kConnect
, kProxyChallenge
, OK
),
10038 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10039 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10040 { TestRound(kConnect
, kProxyChallenge
, OK
),
10041 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10042 // Authenticating HTTPS server through an authenticating proxy.
10043 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10044 { TestRound(kConnect
, kProxyChallenge
, OK
),
10045 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10046 &kGet
, &kServerChallenge
),
10047 TestRound(kGetAuth
, kSuccess
, OK
)}},
10048 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10049 { TestRound(kConnect
, kProxyChallenge
, OK
),
10050 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10051 &kGet
, &kServerChallenge
),
10052 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10053 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10054 { TestRound(kConnect
, kProxyChallenge
, OK
),
10055 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10056 &kGet
, &kServerChallenge
),
10057 TestRound(kGetAuth
, kSuccess
, OK
)}},
10058 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10059 { TestRound(kConnect
, kProxyChallenge
, OK
),
10060 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10061 &kGet
, &kServerChallenge
),
10062 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10063 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10064 { TestRound(kConnect
, kProxyChallenge
, OK
),
10065 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10066 &kGet
, &kServerChallenge
),
10067 TestRound(kGetAuth
, kSuccess
, OK
)}},
10068 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10069 { TestRound(kConnect
, kProxyChallenge
, OK
),
10070 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10071 &kGet
, &kServerChallenge
),
10072 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10073 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10074 { TestRound(kConnect
, kProxyChallenge
, OK
),
10075 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10076 &kGet
, &kServerChallenge
),
10077 TestRound(kGetAuth
, kSuccess
, OK
)}},
10078 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10079 { TestRound(kConnect
, kProxyChallenge
, OK
),
10080 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10081 &kGet
, &kServerChallenge
),
10082 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10085 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10086 HttpAuthHandlerMock::Factory
* auth_factory(
10087 new HttpAuthHandlerMock::Factory());
10088 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10089 const TestConfig
& test_config
= test_configs
[i
];
10091 // Set up authentication handlers as necessary.
10092 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10093 for (int n
= 0; n
< 2; n
++) {
10094 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10095 std::string auth_challenge
= "Mock realm=proxy";
10096 GURL
origin(test_config
.proxy_url
);
10097 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10098 auth_challenge
.end());
10099 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10100 origin
, BoundNetLog());
10101 auth_handler
->SetGenerateExpectation(
10102 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10103 test_config
.proxy_auth_rv
);
10104 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10107 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10108 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10109 std::string auth_challenge
= "Mock realm=server";
10110 GURL
origin(test_config
.server_url
);
10111 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10112 auth_challenge
.end());
10113 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10114 origin
, BoundNetLog());
10115 auth_handler
->SetGenerateExpectation(
10116 test_config
.server_auth_timing
== AUTH_ASYNC
,
10117 test_config
.server_auth_rv
);
10118 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10120 if (test_config
.proxy_url
) {
10121 session_deps_
.proxy_service
.reset(
10122 ProxyService::CreateFixed(test_config
.proxy_url
));
10124 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10127 HttpRequestInfo request
;
10128 request
.method
= "GET";
10129 request
.url
= GURL(test_config
.server_url
);
10130 request
.load_flags
= 0;
10132 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10133 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10135 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10137 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10138 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10139 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10140 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10142 // Set up expected reads and writes.
10143 mock_reads
.back().push_back(read_write_round
.read
);
10144 mock_writes
.back().push_back(read_write_round
.write
);
10146 // kProxyChallenge uses Proxy-Connection: close which means that the
10147 // socket is closed and a new one will be created for the next request.
10148 if (read_write_round
.read
.data
== kProxyChallenge
.data
&&
10149 read_write_round
.write
.data
!= kConnect
.data
) {
10150 mock_reads
.push_back(std::vector
<MockRead
>());
10151 mock_writes
.push_back(std::vector
<MockWrite
>());
10154 if (read_write_round
.extra_read
) {
10155 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10157 if (read_write_round
.extra_write
) {
10158 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10161 // Add an SSL sequence if necessary.
10162 if (round
>= test_config
.first_ssl_round
)
10163 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10164 &ssl_socket_data_provider
);
10167 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10168 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10169 data_providers
.push_back(new StaticSocketDataProvider(
10170 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10171 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10172 session_deps_
.socket_factory
->AddSocketDataProvider(
10173 data_providers
.back());
10176 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10177 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10178 // Start or restart the transaction.
10179 TestCompletionCallback callback
;
10182 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10184 rv
= trans
.RestartWithAuth(
10185 AuthCredentials(kFoo
, kBar
), callback
.callback());
10187 if (rv
== ERR_IO_PENDING
)
10188 rv
= callback
.WaitForResult();
10190 // Compare results with expected data.
10191 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10192 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10193 if (read_write_round
.expected_rv
!= OK
) {
10194 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10197 if (round
+ 1 < test_config
.num_auth_rounds
) {
10198 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10200 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10206 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10207 // Do multi-round authentication and make sure it works correctly.
10208 HttpAuthHandlerMock::Factory
* auth_factory(
10209 new HttpAuthHandlerMock::Factory());
10210 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10211 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10212 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10213 session_deps_
.host_resolver
->set_synchronous_mode(true);
10215 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10216 auth_handler
->set_connection_based(true);
10217 std::string auth_challenge
= "Mock realm=server";
10218 GURL
origin("http://www.example.com");
10219 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10220 auth_challenge
.end());
10221 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10222 origin
, BoundNetLog());
10223 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10226 const HttpResponseInfo
* response
= NULL
;
10227 HttpRequestInfo request
;
10228 request
.method
= "GET";
10229 request
.url
= origin
;
10230 request
.load_flags
= 0;
10232 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10234 // Use a TCP Socket Pool with only one connection per group. This is used
10235 // to validate that the TCP socket is not released to the pool between
10236 // each round of multi-round authentication.
10237 HttpNetworkSessionPeer
session_peer(session
);
10238 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10239 50, // Max sockets for pool
10240 1, // Max sockets per group
10241 session_deps_
.host_resolver
.get(),
10242 session_deps_
.socket_factory
.get(),
10243 session_deps_
.net_log
);
10244 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10245 new MockClientSocketPoolManager
);
10246 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10247 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10249 scoped_ptr
<HttpTransaction
> trans(
10250 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10251 TestCompletionCallback callback
;
10253 const MockWrite
kGet(
10254 "GET / HTTP/1.1\r\n"
10255 "Host: www.example.com\r\n"
10256 "Connection: keep-alive\r\n\r\n");
10257 const MockWrite
kGetAuth(
10258 "GET / HTTP/1.1\r\n"
10259 "Host: www.example.com\r\n"
10260 "Connection: keep-alive\r\n"
10261 "Authorization: auth_token\r\n\r\n");
10263 const MockRead
kServerChallenge(
10264 "HTTP/1.1 401 Unauthorized\r\n"
10265 "WWW-Authenticate: Mock realm=server\r\n"
10266 "Content-Type: text/html; charset=iso-8859-1\r\n"
10267 "Content-Length: 14\r\n\r\n"
10268 "Unauthorized\r\n");
10269 const MockRead
kSuccess(
10270 "HTTP/1.1 200 OK\r\n"
10271 "Content-Type: text/html; charset=iso-8859-1\r\n"
10272 "Content-Length: 3\r\n\r\n"
10275 MockWrite writes
[] = {
10284 // Competing request
10287 MockRead reads
[] = {
10296 // Competing response
10299 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10300 writes
, arraysize(writes
));
10301 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10303 const char kSocketGroup
[] = "www.example.com:80";
10305 // First round of authentication.
10306 auth_handler
->SetGenerateExpectation(false, OK
);
10307 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10308 if (rv
== ERR_IO_PENDING
)
10309 rv
= callback
.WaitForResult();
10311 response
= trans
->GetResponseInfo();
10312 ASSERT_TRUE(response
!= NULL
);
10313 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10314 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10316 // In between rounds, another request comes in for the same domain.
10317 // It should not be able to grab the TCP socket that trans has already
10319 scoped_ptr
<HttpTransaction
> trans_compete(
10320 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10321 TestCompletionCallback callback_compete
;
10322 rv
= trans_compete
->Start(
10323 &request
, callback_compete
.callback(), BoundNetLog());
10324 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10325 // callback_compete.WaitForResult at this point would stall forever,
10326 // since the HttpNetworkTransaction does not release the request back to
10327 // the pool until after authentication completes.
10329 // Second round of authentication.
10330 auth_handler
->SetGenerateExpectation(false, OK
);
10331 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10332 if (rv
== ERR_IO_PENDING
)
10333 rv
= callback
.WaitForResult();
10335 response
= trans
->GetResponseInfo();
10336 ASSERT_TRUE(response
!= NULL
);
10337 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10338 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10340 // Third round of authentication.
10341 auth_handler
->SetGenerateExpectation(false, OK
);
10342 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10343 if (rv
== ERR_IO_PENDING
)
10344 rv
= callback
.WaitForResult();
10346 response
= trans
->GetResponseInfo();
10347 ASSERT_TRUE(response
!= NULL
);
10348 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10349 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10351 // Fourth round of authentication, which completes successfully.
10352 auth_handler
->SetGenerateExpectation(false, OK
);
10353 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10354 if (rv
== ERR_IO_PENDING
)
10355 rv
= callback
.WaitForResult();
10357 response
= trans
->GetResponseInfo();
10358 ASSERT_TRUE(response
!= NULL
);
10359 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10360 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10362 // Read the body since the fourth round was successful. This will also
10363 // release the socket back to the pool.
10364 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10365 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10366 if (rv
== ERR_IO_PENDING
)
10367 rv
= callback
.WaitForResult();
10369 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10371 // There are still 0 idle sockets, since the trans_compete transaction
10372 // will be handed it immediately after trans releases it to the group.
10373 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10375 // The competing request can now finish. Wait for the headers and then
10377 rv
= callback_compete
.WaitForResult();
10379 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10380 if (rv
== ERR_IO_PENDING
)
10381 rv
= callback
.WaitForResult();
10383 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10386 // Finally, the socket is released to the group.
10387 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10390 // This tests the case that a request is issued via http instead of spdy after
10391 // npn is negotiated.
10392 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10393 session_deps_
.use_alternate_protocols
= true;
10394 NextProtoVector next_protos
;
10395 next_protos
.push_back(kProtoHTTP11
);
10396 session_deps_
.next_protos
= next_protos
;
10398 HttpRequestInfo request
;
10399 request
.method
= "GET";
10400 request
.url
= GURL("https://www.example.org/");
10401 request
.load_flags
= 0;
10403 MockWrite data_writes
[] = {
10405 "GET / HTTP/1.1\r\n"
10406 "Host: www.example.org\r\n"
10407 "Connection: keep-alive\r\n\r\n"),
10410 std::string alternate_protocol_http_header
=
10411 GetAlternateProtocolHttpHeader();
10413 MockRead data_reads
[] = {
10414 MockRead("HTTP/1.1 200 OK\r\n"),
10415 MockRead(alternate_protocol_http_header
.c_str()),
10416 MockRead("hello world"),
10417 MockRead(SYNCHRONOUS
, OK
),
10420 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10421 ssl
.SetNextProto(kProtoHTTP11
);
10423 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10425 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10426 data_writes
, arraysize(data_writes
));
10427 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10429 TestCompletionCallback callback
;
10431 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10432 scoped_ptr
<HttpTransaction
> trans(
10433 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10435 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10437 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10438 EXPECT_EQ(OK
, callback
.WaitForResult());
10440 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10441 ASSERT_TRUE(response
!= NULL
);
10442 ASSERT_TRUE(response
->headers
.get() != NULL
);
10443 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10445 std::string response_data
;
10446 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10447 EXPECT_EQ("hello world", response_data
);
10449 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10450 EXPECT_TRUE(response
->was_npn_negotiated
);
10453 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10454 // Simulate the SSL handshake completing with an NPN negotiation
10455 // followed by an immediate server closing of the socket.
10456 // Fix crash: http://crbug.com/46369
10457 session_deps_
.use_alternate_protocols
= true;
10458 session_deps_
.next_protos
= SpdyNextProtos();
10460 HttpRequestInfo request
;
10461 request
.method
= "GET";
10462 request
.url
= GURL("https://www.example.org/");
10463 request
.load_flags
= 0;
10465 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10466 ssl
.SetNextProto(GetParam());
10467 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10469 scoped_ptr
<SpdyFrame
> req(
10470 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10471 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10473 MockRead spdy_reads
[] = {
10474 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10477 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10478 arraysize(spdy_writes
));
10479 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10481 TestCompletionCallback callback
;
10483 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10484 scoped_ptr
<HttpTransaction
> trans(
10485 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10487 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10488 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10489 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10492 // A subclass of HttpAuthHandlerMock that records the request URL when
10493 // it gets it. This is needed since the auth handler may get destroyed
10494 // before we get a chance to query it.
10495 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10497 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10499 ~UrlRecordingHttpAuthHandlerMock() override
{}
10502 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10503 const HttpRequestInfo
* request
,
10504 const CompletionCallback
& callback
,
10505 std::string
* auth_token
) override
{
10506 *url_
= request
->url
;
10507 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10508 credentials
, request
, callback
, auth_token
);
10515 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10516 // This test ensures that the URL passed into the proxy is upgraded
10517 // to https when doing an Alternate Protocol upgrade.
10518 session_deps_
.use_alternate_protocols
= true;
10519 session_deps_
.next_protos
= SpdyNextProtos();
10521 session_deps_
.proxy_service
.reset(
10522 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10523 TestNetLog net_log
;
10524 session_deps_
.net_log
= &net_log
;
10527 HttpAuthHandlerMock::Factory
* auth_factory
=
10528 new HttpAuthHandlerMock::Factory();
10529 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10530 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10531 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10532 auth_factory
->set_do_init_from_challenge(true);
10533 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10536 HttpRequestInfo request
;
10537 request
.method
= "GET";
10538 request
.url
= GURL("http://www.example.org");
10539 request
.load_flags
= 0;
10541 // First round goes unauthenticated through the proxy.
10542 MockWrite data_writes_1
[] = {
10544 "GET http://www.example.org/ HTTP/1.1\r\n"
10545 "Host: www.example.org\r\n"
10546 "Proxy-Connection: keep-alive\r\n"
10549 MockRead data_reads_1
[] = {
10550 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10551 MockRead("HTTP/1.1 200 OK\r\n"),
10552 MockRead("Alternate-Protocol: 443:"),
10553 MockRead(GetAlternateProtocolFromParam()),
10555 MockRead("Proxy-Connection: close\r\n"),
10558 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10559 data_writes_1
, arraysize(data_writes_1
));
10561 // Second round tries to tunnel to www.example.org due to the
10562 // Alternate-Protocol announcement in the first round. It fails due
10563 // to a proxy authentication challenge.
10564 // After the failure, a tunnel is established to www.example.org using
10565 // Proxy-Authorization headers. There is then a SPDY request round.
10567 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10568 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10569 // does a Disconnect and Connect on the same socket, rather than trying
10570 // to obtain a new one.
10572 // NOTE: Originally, the proxy response to the second CONNECT request
10573 // simply returned another 407 so the unit test could skip the SSL connection
10574 // establishment and SPDY framing issues. Alas, the
10575 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10576 // complicated to set up expectations for than the SPDY session.
10578 scoped_ptr
<SpdyFrame
> req(
10579 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10580 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10581 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10583 MockWrite data_writes_2
[] = {
10584 // First connection attempt without Proxy-Authorization.
10585 MockWrite(ASYNC
, 0,
10586 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10587 "Host: www.example.org\r\n"
10588 "Proxy-Connection: keep-alive\r\n"
10591 // Second connection attempt with Proxy-Authorization.
10592 MockWrite(ASYNC
, 2,
10593 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10594 "Host: www.example.org\r\n"
10595 "Proxy-Connection: keep-alive\r\n"
10596 "Proxy-Authorization: auth_token\r\n"
10600 CreateMockWrite(*req
, 4),
10602 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10603 "Proxy-Authenticate: Mock\r\n"
10604 "Proxy-Connection: close\r\n"
10606 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10607 MockRead data_reads_2
[] = {
10608 // First connection attempt fails
10609 MockRead(ASYNC
, kRejectConnectResponse
,
10610 arraysize(kRejectConnectResponse
) - 1, 1),
10612 // Second connection attempt passes
10613 MockRead(ASYNC
, kAcceptConnectResponse
,
10614 arraysize(kAcceptConnectResponse
) - 1, 3),
10617 CreateMockRead(*resp
.get(), 5),
10618 CreateMockRead(*data
.get(), 6),
10619 MockRead(ASYNC
, 0, 0, 7),
10621 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10622 data_writes_2
, arraysize(data_writes_2
));
10624 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10625 ssl
.SetNextProto(GetParam());
10626 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10627 ASSERT_TRUE(ssl
.cert
.get());
10629 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10630 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10632 hanging_non_alternate_protocol_socket
.set_connect_data(
10633 never_finishing_connect
);
10635 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10636 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10637 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10638 session_deps_
.socket_factory
->AddSocketDataProvider(
10639 &hanging_non_alternate_protocol_socket
);
10640 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10642 // First round should work and provide the Alternate-Protocol state.
10643 TestCompletionCallback callback_1
;
10644 scoped_ptr
<HttpTransaction
> trans_1(
10645 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10646 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10647 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10648 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10650 // Second round should attempt a tunnel connect and get an auth challenge.
10651 TestCompletionCallback callback_2
;
10652 scoped_ptr
<HttpTransaction
> trans_2(
10653 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10654 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10655 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10656 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10657 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10658 ASSERT_TRUE(response
!= NULL
);
10659 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10661 // Restart with auth. Tunnel should work and response received.
10662 TestCompletionCallback callback_3
;
10663 rv
= trans_2
->RestartWithAuth(
10664 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10665 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10666 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10668 // After all that work, these two lines (or actually, just the scheme) are
10669 // what this test is all about. Make sure it happens correctly.
10670 EXPECT_EQ("https", request_url
.scheme());
10671 EXPECT_EQ("www.example.org", request_url
.host());
10673 LoadTimingInfo load_timing_info
;
10674 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10675 TestLoadTimingNotReusedWithPac(load_timing_info
,
10676 CONNECT_TIMING_HAS_SSL_TIMES
);
10679 // Test that if we cancel the transaction as the connection is completing, that
10680 // everything tears down correctly.
10681 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10682 // Setup everything about the connection to complete synchronously, so that
10683 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10684 // for is the callback from the HttpStreamRequest.
10685 // Then cancel the transaction.
10686 // Verify that we don't crash.
10687 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10688 MockRead data_reads
[] = {
10689 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10690 MockRead(SYNCHRONOUS
, "hello world"),
10691 MockRead(SYNCHRONOUS
, OK
),
10694 HttpRequestInfo request
;
10695 request
.method
= "GET";
10696 request
.url
= GURL("http://www.example.org/");
10697 request
.load_flags
= 0;
10699 session_deps_
.host_resolver
->set_synchronous_mode(true);
10700 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10701 scoped_ptr
<HttpTransaction
> trans(
10702 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10704 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10705 data
.set_connect_data(mock_connect
);
10706 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10708 TestCompletionCallback callback
;
10710 BoundTestNetLog log
;
10711 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10713 trans
.reset(); // Cancel the transaction here.
10715 base::MessageLoop::current()->RunUntilIdle();
10718 // Test that if a transaction is cancelled after receiving the headers, the
10719 // stream is drained properly and added back to the socket pool. The main
10720 // purpose of this test is to make sure that an HttpStreamParser can be read
10721 // from after the HttpNetworkTransaction and the objects it owns have been
10723 // See http://crbug.com/368418
10724 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10725 MockRead data_reads
[] = {
10726 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10727 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10728 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10729 MockRead(ASYNC
, "1"),
10730 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10731 // HttpNetworkTransaction has been deleted.
10732 MockRead(ASYNC
, "2"),
10733 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10735 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10736 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10738 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10741 HttpRequestInfo request
;
10742 request
.method
= "GET";
10743 request
.url
= GURL("http://www.example.org/");
10744 request
.load_flags
= 0;
10746 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10747 TestCompletionCallback callback
;
10749 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10750 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10751 callback
.WaitForResult();
10753 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10754 ASSERT_TRUE(response
!= NULL
);
10755 EXPECT_TRUE(response
->headers
.get() != NULL
);
10756 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10758 // The transaction and HttpRequestInfo are deleted.
10761 // Let the HttpResponseBodyDrainer drain the socket.
10762 base::MessageLoop::current()->RunUntilIdle();
10764 // Socket should now be idle, waiting to be reused.
10765 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10768 // Test a basic GET request through a proxy.
10769 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10770 session_deps_
.proxy_service
.reset(
10771 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10772 BoundTestNetLog log
;
10773 session_deps_
.net_log
= log
.bound().net_log();
10774 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10776 HttpRequestInfo request
;
10777 request
.method
= "GET";
10778 request
.url
= GURL("http://www.example.org/");
10780 MockWrite data_writes1
[] = {
10782 "GET http://www.example.org/ HTTP/1.1\r\n"
10783 "Host: www.example.org\r\n"
10784 "Proxy-Connection: keep-alive\r\n\r\n"),
10787 MockRead data_reads1
[] = {
10788 MockRead("HTTP/1.1 200 OK\r\n"),
10789 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10790 MockRead("Content-Length: 100\r\n\r\n"),
10791 MockRead(SYNCHRONOUS
, OK
),
10794 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10795 data_writes1
, arraysize(data_writes1
));
10796 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10798 TestCompletionCallback callback1
;
10800 scoped_ptr
<HttpTransaction
> trans(
10801 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10802 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10803 trans
->SetBeforeProxyHeadersSentCallback(
10804 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10805 base::Unretained(&proxy_headers_handler
)));
10807 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10808 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10810 rv
= callback1
.WaitForResult();
10813 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10814 ASSERT_TRUE(response
!= NULL
);
10816 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10817 EXPECT_EQ(200, response
->headers
->response_code());
10818 EXPECT_EQ(100, response
->headers
->GetContentLength());
10819 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10821 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10822 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10823 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10824 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10826 LoadTimingInfo load_timing_info
;
10827 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10828 TestLoadTimingNotReusedWithPac(load_timing_info
,
10829 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10832 // Test a basic HTTPS GET request through a proxy.
10833 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10834 session_deps_
.proxy_service
.reset(
10835 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10836 BoundTestNetLog log
;
10837 session_deps_
.net_log
= log
.bound().net_log();
10838 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10840 HttpRequestInfo request
;
10841 request
.method
= "GET";
10842 request
.url
= GURL("https://www.example.org/");
10844 // Since we have proxy, should try to establish tunnel.
10845 MockWrite data_writes1
[] = {
10847 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10848 "Host: www.example.org\r\n"
10849 "Proxy-Connection: keep-alive\r\n\r\n"),
10852 "GET / HTTP/1.1\r\n"
10853 "Host: www.example.org\r\n"
10854 "Connection: keep-alive\r\n\r\n"),
10857 MockRead data_reads1
[] = {
10858 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10860 MockRead("HTTP/1.1 200 OK\r\n"),
10861 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10862 MockRead("Content-Length: 100\r\n\r\n"),
10863 MockRead(SYNCHRONOUS
, OK
),
10866 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10867 data_writes1
, arraysize(data_writes1
));
10868 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10869 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10870 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10872 TestCompletionCallback callback1
;
10874 scoped_ptr
<HttpTransaction
> trans(
10875 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10877 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10880 rv
= callback1
.WaitForResult();
10882 TestNetLogEntry::List entries
;
10883 log
.GetEntries(&entries
);
10884 size_t pos
= ExpectLogContainsSomewhere(
10885 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10886 NetLog::PHASE_NONE
);
10887 ExpectLogContainsSomewhere(
10889 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10890 NetLog::PHASE_NONE
);
10892 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10893 ASSERT_TRUE(response
!= NULL
);
10895 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10896 EXPECT_EQ(200, response
->headers
->response_code());
10897 EXPECT_EQ(100, response
->headers
->GetContentLength());
10898 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10899 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10901 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10903 LoadTimingInfo load_timing_info
;
10904 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10905 TestLoadTimingNotReusedWithPac(load_timing_info
,
10906 CONNECT_TIMING_HAS_SSL_TIMES
);
10909 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10910 // while establishing the tunnel.
10911 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10912 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10913 BoundTestNetLog log
;
10914 session_deps_
.net_log
= log
.bound().net_log();
10915 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10917 HttpRequestInfo request
;
10918 request
.method
= "GET";
10919 request
.url
= GURL("https://www.example.org/");
10921 // Since we have proxy, should try to establish tunnel.
10922 MockWrite data_writes1
[] = {
10924 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10925 "Host: www.example.org\r\n"
10926 "Proxy-Connection: keep-alive\r\n\r\n"),
10929 "GET / HTTP/1.1\r\n"
10930 "Host: www.example.org\r\n"
10931 "Connection: keep-alive\r\n\r\n"),
10934 MockRead data_reads1
[] = {
10935 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10936 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10937 MockRead(ASYNC
, 0, 0), // EOF
10940 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10941 data_writes1
, arraysize(data_writes1
));
10942 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10943 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10944 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10946 TestCompletionCallback callback1
;
10948 scoped_ptr
<HttpTransaction
> trans(
10949 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10951 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10952 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10954 rv
= callback1
.WaitForResult();
10955 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10956 TestNetLogEntry::List entries
;
10957 log
.GetEntries(&entries
);
10958 size_t pos
= ExpectLogContainsSomewhere(
10959 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10960 NetLog::PHASE_NONE
);
10961 ExpectLogContainsSomewhere(
10963 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10964 NetLog::PHASE_NONE
);
10967 // Test for crbug.com/55424.
10968 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10969 scoped_ptr
<SpdyFrame
> req(
10970 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
10971 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
10973 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10974 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10975 MockRead spdy_reads
[] = {
10976 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
10979 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10980 arraysize(spdy_writes
));
10981 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10983 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10984 ssl
.SetNextProto(GetParam());
10985 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10987 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10989 // Set up an initial SpdySession in the pool to reuse.
10990 HostPortPair
host_port_pair("www.example.org", 443);
10991 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10992 PRIVACY_MODE_DISABLED
);
10993 base::WeakPtr
<SpdySession
> spdy_session
=
10994 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10996 HttpRequestInfo request
;
10997 request
.method
= "GET";
10998 request
.url
= GURL("https://www.example.org/");
10999 request
.load_flags
= 0;
11001 // This is the important line that marks this as a preconnect.
11002 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11004 scoped_ptr
<HttpTransaction
> trans(
11005 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11007 TestCompletionCallback callback
;
11008 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11009 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11010 EXPECT_EQ(OK
, callback
.WaitForResult());
11013 // Given a net error, cause that error to be returned from the first Write()
11014 // call and verify that the HttpTransaction fails with that error.
11015 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11016 int error
, IoMode mode
) {
11017 HttpRequestInfo request_info
;
11018 request_info
.url
= GURL("https://www.example.com/");
11019 request_info
.method
= "GET";
11020 request_info
.load_flags
= LOAD_NORMAL
;
11022 SSLSocketDataProvider
ssl_data(mode
, OK
);
11023 MockWrite data_writes
[] = {
11024 MockWrite(mode
, error
),
11026 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11027 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11028 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11030 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11031 scoped_ptr
<HttpTransaction
> trans(
11032 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11034 TestCompletionCallback callback
;
11035 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11036 if (rv
== ERR_IO_PENDING
)
11037 rv
= callback
.WaitForResult();
11038 ASSERT_EQ(error
, rv
);
11041 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11042 // Just check a grab bag of cert errors.
11043 static const int kErrors
[] = {
11044 ERR_CERT_COMMON_NAME_INVALID
,
11045 ERR_CERT_AUTHORITY_INVALID
,
11046 ERR_CERT_DATE_INVALID
,
11048 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11049 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11050 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11054 // Ensure that a client certificate is removed from the SSL client auth
11056 // 1) No proxy is involved.
11057 // 2) TLS False Start is disabled.
11058 // 3) The initial TLS handshake requests a client certificate.
11059 // 4) The client supplies an invalid/unacceptable certificate.
11060 TEST_P(HttpNetworkTransactionTest
,
11061 ClientAuthCertCache_Direct_NoFalseStart
) {
11062 HttpRequestInfo request_info
;
11063 request_info
.url
= GURL("https://www.example.com/");
11064 request_info
.method
= "GET";
11065 request_info
.load_flags
= LOAD_NORMAL
;
11067 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11068 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11070 // [ssl_]data1 contains the data for the first SSL handshake. When a
11071 // CertificateRequest is received for the first time, the handshake will
11072 // be aborted to allow the caller to provide a certificate.
11073 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11074 ssl_data1
.cert_request_info
= cert_request
.get();
11075 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11076 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11077 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11079 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11080 // False Start is not being used, the result of the SSL handshake will be
11081 // returned as part of the SSLClientSocket::Connect() call. This test
11082 // matches the result of a server sending a handshake_failure alert,
11083 // rather than a Finished message, because it requires a client
11084 // certificate and none was supplied.
11085 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11086 ssl_data2
.cert_request_info
= cert_request
.get();
11087 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11088 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11089 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11091 // [ssl_]data3 contains the data for the third SSL handshake. When a
11092 // connection to a server fails during an SSL handshake,
11093 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11094 // connection was attempted with TLSv1.2. This is transparent to the caller
11095 // of the HttpNetworkTransaction. Because this test failure is due to
11096 // requiring a client certificate, this fallback handshake should also
11098 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11099 ssl_data3
.cert_request_info
= cert_request
.get();
11100 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11101 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11102 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11104 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11105 // connection to a server fails during an SSL handshake,
11106 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11107 // connection was attempted with TLSv1.1. This is transparent to the caller
11108 // of the HttpNetworkTransaction. Because this test failure is due to
11109 // requiring a client certificate, this fallback handshake should also
11111 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11112 ssl_data4
.cert_request_info
= cert_request
.get();
11113 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11114 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11115 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11117 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11118 scoped_ptr
<HttpTransaction
> trans(
11119 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11121 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11122 TestCompletionCallback callback
;
11123 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11124 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11126 // Complete the SSL handshake, which should abort due to requiring a
11127 // client certificate.
11128 rv
= callback
.WaitForResult();
11129 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11131 // Indicate that no certificate should be supplied. From the perspective
11132 // of SSLClientCertCache, NULL is just as meaningful as a real
11133 // certificate, so this is the same as supply a
11134 // legitimate-but-unacceptable certificate.
11135 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11136 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11138 // Ensure the certificate was added to the client auth cache before
11139 // allowing the connection to continue restarting.
11140 scoped_refptr
<X509Certificate
> client_cert
;
11141 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11142 HostPortPair("www.example.com", 443), &client_cert
));
11143 ASSERT_EQ(NULL
, client_cert
.get());
11145 // Restart the handshake. This will consume ssl_data2, which fails, and
11146 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11147 // The result code is checked against what ssl_data4 should return.
11148 rv
= callback
.WaitForResult();
11149 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11151 // Ensure that the client certificate is removed from the cache on a
11152 // handshake failure.
11153 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11154 HostPortPair("www.example.com", 443), &client_cert
));
11157 // Ensure that a client certificate is removed from the SSL client auth
11159 // 1) No proxy is involved.
11160 // 2) TLS False Start is enabled.
11161 // 3) The initial TLS handshake requests a client certificate.
11162 // 4) The client supplies an invalid/unacceptable certificate.
11163 TEST_P(HttpNetworkTransactionTest
,
11164 ClientAuthCertCache_Direct_FalseStart
) {
11165 HttpRequestInfo request_info
;
11166 request_info
.url
= GURL("https://www.example.com/");
11167 request_info
.method
= "GET";
11168 request_info
.load_flags
= LOAD_NORMAL
;
11170 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11171 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11173 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11174 // return successfully after reading up to the peer's Certificate message.
11175 // This is to allow the caller to call SSLClientSocket::Write(), which can
11176 // enqueue application data to be sent in the same packet as the
11177 // ChangeCipherSpec and Finished messages.
11178 // The actual handshake will be finished when SSLClientSocket::Read() is
11179 // called, which expects to process the peer's ChangeCipherSpec and
11180 // Finished messages. If there was an error negotiating with the peer,
11181 // such as due to the peer requiring a client certificate when none was
11182 // supplied, the alert sent by the peer won't be processed until Read() is
11185 // Like the non-False Start case, when a client certificate is requested by
11186 // the peer, the handshake is aborted during the Connect() call.
11187 // [ssl_]data1 represents the initial SSL handshake with the peer.
11188 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11189 ssl_data1
.cert_request_info
= cert_request
.get();
11190 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11191 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11192 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11194 // When a client certificate is supplied, Connect() will not be aborted
11195 // when the peer requests the certificate. Instead, the handshake will
11196 // artificially succeed, allowing the caller to write the HTTP request to
11197 // the socket. The handshake messages are not processed until Read() is
11198 // called, which then detects that the handshake was aborted, due to the
11199 // peer sending a handshake_failure because it requires a client
11201 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11202 ssl_data2
.cert_request_info
= cert_request
.get();
11203 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11204 MockRead data2_reads
[] = {
11205 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11207 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11208 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11210 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11211 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11212 // TLSv1. It has the same behaviour as [ssl_]data2.
11213 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11214 ssl_data3
.cert_request_info
= cert_request
.get();
11215 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11216 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11217 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11219 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11220 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11221 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11222 ssl_data4
.cert_request_info
= cert_request
.get();
11223 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11224 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11225 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11227 // Need one more if TLSv1.2 is enabled.
11228 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11229 ssl_data5
.cert_request_info
= cert_request
.get();
11230 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11231 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11232 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11234 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11235 scoped_ptr
<HttpTransaction
> trans(
11236 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11238 // Begin the initial SSL handshake.
11239 TestCompletionCallback callback
;
11240 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11241 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11243 // Complete the SSL handshake, which should abort due to requiring a
11244 // client certificate.
11245 rv
= callback
.WaitForResult();
11246 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11248 // Indicate that no certificate should be supplied. From the perspective
11249 // of SSLClientCertCache, NULL is just as meaningful as a real
11250 // certificate, so this is the same as supply a
11251 // legitimate-but-unacceptable certificate.
11252 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11253 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11255 // Ensure the certificate was added to the client auth cache before
11256 // allowing the connection to continue restarting.
11257 scoped_refptr
<X509Certificate
> client_cert
;
11258 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11259 HostPortPair("www.example.com", 443), &client_cert
));
11260 ASSERT_EQ(NULL
, client_cert
.get());
11262 // Restart the handshake. This will consume ssl_data2, which fails, and
11263 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11264 // The result code is checked against what ssl_data4 should return.
11265 rv
= callback
.WaitForResult();
11266 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11268 // Ensure that the client certificate is removed from the cache on a
11269 // handshake failure.
11270 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11271 HostPortPair("www.example.com", 443), &client_cert
));
11274 // Ensure that a client certificate is removed from the SSL client auth
11276 // 1) An HTTPS proxy is involved.
11277 // 3) The HTTPS proxy requests a client certificate.
11278 // 4) The client supplies an invalid/unacceptable certificate for the
11280 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11281 // then for connecting to an HTTP endpoint.
11282 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11283 session_deps_
.proxy_service
.reset(
11284 ProxyService::CreateFixed("https://proxy:70"));
11285 BoundTestNetLog log
;
11286 session_deps_
.net_log
= log
.bound().net_log();
11288 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11289 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11291 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11292 // [ssl_]data[1-3]. Rather than represending the endpoint
11293 // (www.example.com:443), they represent failures with the HTTPS proxy
11295 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11296 ssl_data1
.cert_request_info
= cert_request
.get();
11297 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11298 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11299 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11301 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11302 ssl_data2
.cert_request_info
= cert_request
.get();
11303 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11304 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11305 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11307 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11309 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11310 ssl_data3
.cert_request_info
= cert_request
.get();
11311 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11312 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11313 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11316 HttpRequestInfo requests
[2];
11317 requests
[0].url
= GURL("https://www.example.com/");
11318 requests
[0].method
= "GET";
11319 requests
[0].load_flags
= LOAD_NORMAL
;
11321 requests
[1].url
= GURL("http://www.example.com/");
11322 requests
[1].method
= "GET";
11323 requests
[1].load_flags
= LOAD_NORMAL
;
11325 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11326 session_deps_
.socket_factory
->ResetNextMockIndexes();
11327 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11328 scoped_ptr
<HttpNetworkTransaction
> trans(
11329 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11331 // Begin the SSL handshake with the proxy.
11332 TestCompletionCallback callback
;
11333 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11334 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11336 // Complete the SSL handshake, which should abort due to requiring a
11337 // client certificate.
11338 rv
= callback
.WaitForResult();
11339 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11341 // Indicate that no certificate should be supplied. From the perspective
11342 // of SSLClientCertCache, NULL is just as meaningful as a real
11343 // certificate, so this is the same as supply a
11344 // legitimate-but-unacceptable certificate.
11345 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11346 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11348 // Ensure the certificate was added to the client auth cache before
11349 // allowing the connection to continue restarting.
11350 scoped_refptr
<X509Certificate
> client_cert
;
11351 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11352 HostPortPair("proxy", 70), &client_cert
));
11353 ASSERT_EQ(NULL
, client_cert
.get());
11354 // Ensure the certificate was NOT cached for the endpoint. This only
11355 // applies to HTTPS requests, but is fine to check for HTTP requests.
11356 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11357 HostPortPair("www.example.com", 443), &client_cert
));
11359 // Restart the handshake. This will consume ssl_data2, which fails, and
11360 // then consume ssl_data3, which should also fail. The result code is
11361 // checked against what ssl_data3 should return.
11362 rv
= callback
.WaitForResult();
11363 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11365 // Now that the new handshake has failed, ensure that the client
11366 // certificate was removed from the client auth cache.
11367 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11368 HostPortPair("proxy", 70), &client_cert
));
11369 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11370 HostPortPair("www.example.com", 443), &client_cert
));
11374 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11375 // TEST_P is a macro that expands directly to code that stringizes the
11376 // arguments. As a result, macros passed as parameters (such as prefix
11377 // or test_case_name) will not be expanded by the preprocessor. To
11378 // work around this, indirect the macro for TEST_P, so that the
11379 // pre-processor will expand macros such as MAYBE_test_name before
11380 // instantiating the test.
11381 #define WRAPPED_TEST_P(test_case_name, test_name) \
11382 TEST_P(test_case_name, test_name)
11384 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11385 #if defined(OS_WIN)
11386 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11388 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11390 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
11391 session_deps_
.use_alternate_protocols
= true;
11392 session_deps_
.next_protos
= SpdyNextProtos();
11394 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11395 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11396 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11397 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11398 pool_peer
.DisableDomainAuthenticationVerification();
11400 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11401 ssl
.SetNextProto(GetParam());
11402 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11404 scoped_ptr
<SpdyFrame
> host1_req(
11405 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11406 scoped_ptr
<SpdyFrame
> host2_req(
11407 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11408 MockWrite spdy_writes
[] = {
11409 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11411 scoped_ptr
<SpdyFrame
> host1_resp(
11412 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11413 scoped_ptr
<SpdyFrame
> host1_resp_body(
11414 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11415 scoped_ptr
<SpdyFrame
> host2_resp(
11416 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11417 scoped_ptr
<SpdyFrame
> host2_resp_body(
11418 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11419 MockRead spdy_reads
[] = {
11420 CreateMockRead(*host1_resp
, 1),
11421 CreateMockRead(*host1_resp_body
, 2),
11422 CreateMockRead(*host2_resp
, 4),
11423 CreateMockRead(*host2_resp_body
, 5),
11424 MockRead(ASYNC
, 0, 6),
11427 IPAddressNumber ip
;
11428 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11429 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11430 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11431 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11432 spdy_writes
, arraysize(spdy_writes
));
11433 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11435 TestCompletionCallback callback
;
11436 HttpRequestInfo request1
;
11437 request1
.method
= "GET";
11438 request1
.url
= GURL("https://www.example.org/");
11439 request1
.load_flags
= 0;
11440 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11442 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11443 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11444 EXPECT_EQ(OK
, callback
.WaitForResult());
11446 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11447 ASSERT_TRUE(response
!= NULL
);
11448 ASSERT_TRUE(response
->headers
.get() != NULL
);
11449 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11451 std::string response_data
;
11452 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11453 EXPECT_EQ("hello!", response_data
);
11455 // Preload www.gmail.com into HostCache.
11456 HostPortPair
host_port("www.gmail.com", 443);
11457 HostResolver::RequestInfo
resolve_info(host_port
);
11458 AddressList ignored
;
11459 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11462 callback
.callback(),
11465 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11466 rv
= callback
.WaitForResult();
11469 HttpRequestInfo request2
;
11470 request2
.method
= "GET";
11471 request2
.url
= GURL("https://www.gmail.com/");
11472 request2
.load_flags
= 0;
11473 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11475 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11476 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11477 EXPECT_EQ(OK
, callback
.WaitForResult());
11479 response
= trans2
.GetResponseInfo();
11480 ASSERT_TRUE(response
!= NULL
);
11481 ASSERT_TRUE(response
->headers
.get() != NULL
);
11482 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11483 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11484 EXPECT_TRUE(response
->was_npn_negotiated
);
11485 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11486 EXPECT_EQ("hello!", response_data
);
11488 #undef MAYBE_UseIPConnectionPooling
11490 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11491 session_deps_
.use_alternate_protocols
= true;
11492 session_deps_
.next_protos
= SpdyNextProtos();
11494 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11495 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11496 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11497 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11498 pool_peer
.DisableDomainAuthenticationVerification();
11500 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11501 ssl
.SetNextProto(GetParam());
11502 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11504 scoped_ptr
<SpdyFrame
> host1_req(
11505 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11506 scoped_ptr
<SpdyFrame
> host2_req(
11507 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11508 MockWrite spdy_writes
[] = {
11509 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11511 scoped_ptr
<SpdyFrame
> host1_resp(
11512 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11513 scoped_ptr
<SpdyFrame
> host1_resp_body(
11514 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11515 scoped_ptr
<SpdyFrame
> host2_resp(
11516 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11517 scoped_ptr
<SpdyFrame
> host2_resp_body(
11518 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11519 MockRead spdy_reads
[] = {
11520 CreateMockRead(*host1_resp
, 1),
11521 CreateMockRead(*host1_resp_body
, 2),
11522 CreateMockRead(*host2_resp
, 4),
11523 CreateMockRead(*host2_resp_body
, 5),
11524 MockRead(ASYNC
, 0, 6),
11527 IPAddressNumber ip
;
11528 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11529 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11530 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11531 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11532 spdy_writes
, arraysize(spdy_writes
));
11533 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11535 TestCompletionCallback callback
;
11536 HttpRequestInfo request1
;
11537 request1
.method
= "GET";
11538 request1
.url
= GURL("https://www.example.org/");
11539 request1
.load_flags
= 0;
11540 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11542 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11543 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11544 EXPECT_EQ(OK
, callback
.WaitForResult());
11546 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11547 ASSERT_TRUE(response
!= NULL
);
11548 ASSERT_TRUE(response
->headers
.get() != NULL
);
11549 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11551 std::string response_data
;
11552 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11553 EXPECT_EQ("hello!", response_data
);
11555 HttpRequestInfo request2
;
11556 request2
.method
= "GET";
11557 request2
.url
= GURL("https://www.gmail.com/");
11558 request2
.load_flags
= 0;
11559 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11561 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11562 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11563 EXPECT_EQ(OK
, callback
.WaitForResult());
11565 response
= trans2
.GetResponseInfo();
11566 ASSERT_TRUE(response
!= NULL
);
11567 ASSERT_TRUE(response
->headers
.get() != NULL
);
11568 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11569 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11570 EXPECT_TRUE(response
->was_npn_negotiated
);
11571 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11572 EXPECT_EQ("hello!", response_data
);
11575 class OneTimeCachingHostResolver
: public HostResolver
{
11577 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11578 : host_port_(host_port
) {}
11579 ~OneTimeCachingHostResolver() override
{}
11581 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11583 // HostResolver methods:
11584 int Resolve(const RequestInfo
& info
,
11585 RequestPriority priority
,
11586 AddressList
* addresses
,
11587 const CompletionCallback
& callback
,
11588 RequestHandle
* out_req
,
11589 const BoundNetLog
& net_log
) override
{
11590 return host_resolver_
.Resolve(
11591 info
, priority
, addresses
, callback
, out_req
, net_log
);
11594 int ResolveFromCache(const RequestInfo
& info
,
11595 AddressList
* addresses
,
11596 const BoundNetLog
& net_log
) override
{
11597 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11598 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11599 host_resolver_
.GetHostCache()->clear();
11603 void CancelRequest(RequestHandle req
) override
{
11604 host_resolver_
.CancelRequest(req
);
11607 MockCachingHostResolver
* GetMockHostResolver() {
11608 return &host_resolver_
;
11612 MockCachingHostResolver host_resolver_
;
11613 const HostPortPair host_port_
;
11616 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11617 #if defined(OS_WIN)
11618 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11619 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11621 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11622 UseIPConnectionPoolingWithHostCacheExpiration
11624 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11625 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11626 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11627 // prefix doesn't work with parametrized tests).
11628 #if defined(OS_WIN)
11631 session_deps_
.use_alternate_protocols
= true;
11632 session_deps_
.next_protos
= SpdyNextProtos();
11634 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11635 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11636 HttpNetworkSession::Params params
=
11637 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11638 params
.host_resolver
= &host_resolver
;
11639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11640 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11641 pool_peer
.DisableDomainAuthenticationVerification();
11643 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11644 ssl
.SetNextProto(GetParam());
11645 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11647 scoped_ptr
<SpdyFrame
> host1_req(
11648 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11649 scoped_ptr
<SpdyFrame
> host2_req(
11650 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11651 MockWrite spdy_writes
[] = {
11652 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11654 scoped_ptr
<SpdyFrame
> host1_resp(
11655 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11656 scoped_ptr
<SpdyFrame
> host1_resp_body(
11657 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11658 scoped_ptr
<SpdyFrame
> host2_resp(
11659 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11660 scoped_ptr
<SpdyFrame
> host2_resp_body(
11661 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11662 MockRead spdy_reads
[] = {
11663 CreateMockRead(*host1_resp
, 1),
11664 CreateMockRead(*host1_resp_body
, 2),
11665 CreateMockRead(*host2_resp
, 4),
11666 CreateMockRead(*host2_resp_body
, 5),
11667 MockRead(ASYNC
, 0, 6),
11670 IPAddressNumber ip
;
11671 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11672 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11673 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11674 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11675 spdy_writes
, arraysize(spdy_writes
));
11676 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11678 TestCompletionCallback callback
;
11679 HttpRequestInfo request1
;
11680 request1
.method
= "GET";
11681 request1
.url
= GURL("https://www.example.org/");
11682 request1
.load_flags
= 0;
11683 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11685 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11687 EXPECT_EQ(OK
, callback
.WaitForResult());
11689 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11690 ASSERT_TRUE(response
!= NULL
);
11691 ASSERT_TRUE(response
->headers
.get() != NULL
);
11692 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11694 std::string response_data
;
11695 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11696 EXPECT_EQ("hello!", response_data
);
11698 // Preload cache entries into HostCache.
11699 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11700 AddressList ignored
;
11701 rv
= host_resolver
.Resolve(resolve_info
,
11704 callback
.callback(),
11707 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11708 rv
= callback
.WaitForResult();
11711 HttpRequestInfo request2
;
11712 request2
.method
= "GET";
11713 request2
.url
= GURL("https://www.gmail.com/");
11714 request2
.load_flags
= 0;
11715 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11717 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11718 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11719 EXPECT_EQ(OK
, callback
.WaitForResult());
11721 response
= trans2
.GetResponseInfo();
11722 ASSERT_TRUE(response
!= NULL
);
11723 ASSERT_TRUE(response
->headers
.get() != NULL
);
11724 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11725 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11726 EXPECT_TRUE(response
->was_npn_negotiated
);
11727 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11728 EXPECT_EQ("hello!", response_data
);
11731 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11733 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11734 const std::string https_url
= "https://www.example.org:8080/";
11735 const std::string http_url
= "http://www.example.org:8080/";
11737 // SPDY GET for HTTPS URL
11738 scoped_ptr
<SpdyFrame
> req1(
11739 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11741 MockWrite writes1
[] = {
11742 CreateMockWrite(*req1
, 0),
11745 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11746 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11747 MockRead reads1
[] = {
11748 CreateMockRead(*resp1
, 1),
11749 CreateMockRead(*body1
, 2),
11750 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11753 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
11754 arraysize(writes1
));
11755 MockConnect
connect_data1(ASYNC
, OK
);
11756 data1
.set_connect_data(connect_data1
);
11758 // HTTP GET for the HTTP URL
11759 MockWrite writes2
[] = {
11760 MockWrite(ASYNC
, 0,
11761 "GET / HTTP/1.1\r\n"
11762 "Host: www.example.org:8080\r\n"
11763 "Connection: keep-alive\r\n\r\n"),
11766 MockRead reads2
[] = {
11767 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11768 MockRead(ASYNC
, 2, "hello"),
11769 MockRead(ASYNC
, OK
, 3),
11772 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
11773 arraysize(writes2
));
11775 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11776 ssl
.SetNextProto(GetParam());
11777 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11778 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11779 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11781 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11783 // Start the first transaction to set up the SpdySession
11784 HttpRequestInfo request1
;
11785 request1
.method
= "GET";
11786 request1
.url
= GURL(https_url
);
11787 request1
.load_flags
= 0;
11788 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11789 TestCompletionCallback callback1
;
11790 EXPECT_EQ(ERR_IO_PENDING
,
11791 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11792 base::MessageLoop::current()->RunUntilIdle();
11794 EXPECT_EQ(OK
, callback1
.WaitForResult());
11795 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11797 // Now, start the HTTP request
11798 HttpRequestInfo request2
;
11799 request2
.method
= "GET";
11800 request2
.url
= GURL(http_url
);
11801 request2
.load_flags
= 0;
11802 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11803 TestCompletionCallback callback2
;
11804 EXPECT_EQ(ERR_IO_PENDING
,
11805 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11806 base::MessageLoop::current()->RunUntilIdle();
11808 EXPECT_EQ(OK
, callback2
.WaitForResult());
11809 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11812 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
11814 void Run(bool pooling
, bool valid
) {
11815 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
11817 HostPortPair
alternative("www.example.org", 443);
11819 base::FilePath certs_dir
= GetTestCertsDirectory();
11820 scoped_refptr
<X509Certificate
> cert(
11821 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
11822 ASSERT_TRUE(cert
.get());
11823 bool common_name_fallback_used
;
11825 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
11827 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
11828 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11829 ssl
.SetNextProto(GetParam());
11831 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11833 // If pooling, then start a request to alternative first to create a
11835 std::string url0
= "https://www.example.org:443";
11836 // Second request to origin, which has an alternative service, and could
11837 // open a connection to the alternative host or pool to the existing one.
11838 std::string
url1("https://");
11839 url1
.append(origin
.host());
11840 url1
.append(":443");
11842 scoped_ptr
<SpdyFrame
> req0
;
11843 scoped_ptr
<SpdyFrame
> req1
;
11844 scoped_ptr
<SpdyFrame
> resp0
;
11845 scoped_ptr
<SpdyFrame
> body0
;
11846 scoped_ptr
<SpdyFrame
> resp1
;
11847 scoped_ptr
<SpdyFrame
> body1
;
11848 std::vector
<MockWrite
> writes
;
11849 std::vector
<MockRead
> reads
;
11852 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
11853 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
11855 writes
.push_back(CreateMockWrite(*req0
, 0));
11856 writes
.push_back(CreateMockWrite(*req1
, 3));
11858 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11859 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11860 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11861 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11863 reads
.push_back(CreateMockRead(*resp0
, 1));
11864 reads
.push_back(CreateMockRead(*body0
, 2));
11865 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
11866 reads
.push_back(CreateMockRead(*resp1
, 5));
11867 reads
.push_back(CreateMockRead(*body1
, 6));
11868 reads
.push_back(MockRead(ASYNC
, OK
, 7));
11870 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
11872 writes
.push_back(CreateMockWrite(*req1
, 0));
11874 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11875 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11877 reads
.push_back(CreateMockRead(*resp1
, 1));
11878 reads
.push_back(CreateMockRead(*body1
, 2));
11879 reads
.push_back(MockRead(ASYNC
, OK
, 3));
11882 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
11883 vector_as_array(&writes
), writes
.size());
11884 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11886 // Connection to the origin fails.
11887 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11888 StaticSocketDataProvider data_refused
;
11889 data_refused
.set_connect_data(mock_connect
);
11890 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
11892 session_deps_
.use_alternate_protocols
= true;
11893 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11894 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
11895 session
->http_server_properties();
11896 AlternativeService
alternative_service(
11897 AlternateProtocolFromNextProto(GetParam()), alternative
);
11898 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
11901 // First request to alternative.
11903 scoped_ptr
<HttpTransaction
> trans0(
11904 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11905 HttpRequestInfo request0
;
11906 request0
.method
= "GET";
11907 request0
.url
= GURL(url0
);
11908 request0
.load_flags
= 0;
11909 TestCompletionCallback callback0
;
11911 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
11912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11913 rv
= callback0
.WaitForResult();
11917 // Second request to origin.
11918 scoped_ptr
<HttpTransaction
> trans1(
11919 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11920 HttpRequestInfo request1
;
11921 request1
.method
= "GET";
11922 request1
.url
= GURL(url1
);
11923 request1
.load_flags
= 0;
11924 TestCompletionCallback callback1
;
11926 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
11927 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11928 base::MessageLoop::current()->RunUntilIdle();
11929 if (data
.IsReadPaused()) {
11930 data
.CompleteRead();
11932 rv
= callback1
.WaitForResult();
11937 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11939 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
11945 INSTANTIATE_TEST_CASE_P(NextProto
,
11946 AltSvcCertificateVerificationTest
,
11947 testing::Values(kProtoSPDY31
,
11951 // The alternative service host must exhibit a certificate that is valid for the
11952 // origin host. Test that this is enforced when pooling to an existing
11954 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
11958 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
11962 // The alternative service host must exhibit a certificate that is valid for the
11963 // origin host. Test that this is enforced when opening a new connection.
11964 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
11968 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
11972 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
11973 // with the alternative server. That connection should not be used.
11974 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
11975 HostPortPair
origin("origin.example.org", 443);
11976 HostPortPair
alternative("alternative.example.org", 443);
11978 // Negotiate HTTP/1.1 with alternative.example.org.
11979 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11980 ssl
.SetNextProto(kProtoHTTP11
);
11981 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11983 // No data should be read from the alternative, because HTTP/1.1 is
11985 StaticSocketDataProvider data
;
11986 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11988 // This test documents that an alternate Job should not be used if HTTP/1.1 is
11989 // negotiated. In order to test this, a failed connection to the origin is
11990 // mocked. This way the request relies on the alternate Job.
11991 StaticSocketDataProvider data_refused
;
11992 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
11993 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
11995 // Set up alternative service for origin.
11996 session_deps_
.use_alternate_protocols
= true;
11997 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11998 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
11999 session
->http_server_properties();
12000 AlternativeService
alternative_service(
12001 AlternateProtocolFromNextProto(GetParam()), alternative
);
12002 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12005 scoped_ptr
<HttpTransaction
> trans(
12006 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12007 HttpRequestInfo request
;
12008 request
.method
= "GET";
12009 request
.url
= GURL("https://origin.example.org:443");
12010 request
.load_flags
= 0;
12011 TestCompletionCallback callback
;
12013 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12014 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12015 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12016 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
12019 // A request to a server with an alternative service fires two Jobs: one to the
12020 // origin, and an alternate one to the alternative server. If the former
12021 // succeeds, the request should succeed, even if the latter fails because
12022 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12023 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
12024 HostPortPair
origin("origin.example.org", 443);
12025 HostPortPair
alternative("alternative.example.org", 443);
12027 // Negotiate HTTP/1.1 with alternative.
12028 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
12029 alternative_ssl
.SetNextProto(kProtoHTTP11
);
12030 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
12032 // No data should be read from the alternative, because HTTP/1.1 is
12034 StaticSocketDataProvider data
;
12035 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12037 // Negotiate HTTP/1.1 with origin.
12038 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
12039 origin_ssl
.SetNextProto(kProtoHTTP11
);
12040 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
12042 MockWrite http_writes
[] = {
12044 "GET / HTTP/1.1\r\n"
12045 "Host: origin.example.org\r\n"
12046 "Connection: keep-alive\r\n\r\n"),
12048 "GET /second HTTP/1.1\r\n"
12049 "Host: origin.example.org\r\n"
12050 "Connection: keep-alive\r\n\r\n"),
12053 MockRead http_reads
[] = {
12054 MockRead("HTTP/1.1 200 OK\r\n"),
12055 MockRead("Content-Type: text/html\r\n"),
12056 MockRead("Content-Length: 6\r\n\r\n"),
12057 MockRead("foobar"),
12058 MockRead("HTTP/1.1 200 OK\r\n"),
12059 MockRead("Content-Type: text/html\r\n"),
12060 MockRead("Content-Length: 7\r\n\r\n"),
12061 MockRead("another"),
12063 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12064 http_writes
, arraysize(http_writes
));
12065 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12067 // Set up alternative service for origin.
12068 session_deps_
.use_alternate_protocols
= true;
12069 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12070 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12071 session
->http_server_properties();
12072 AlternativeService
alternative_service(
12073 AlternateProtocolFromNextProto(GetParam()), alternative
);
12074 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12077 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12078 HttpRequestInfo request1
;
12079 request1
.method
= "GET";
12080 request1
.url
= GURL("https://origin.example.org:443");
12081 request1
.load_flags
= 0;
12082 TestCompletionCallback callback1
;
12084 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12085 rv
= callback1
.GetResult(rv
);
12088 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12089 ASSERT_TRUE(response1
!= nullptr);
12090 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12091 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12093 std::string response_data1
;
12094 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12095 EXPECT_EQ("foobar", response_data1
);
12097 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12098 // for alternative service.
12100 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12102 // Since |alternative_service| is broken, a second transaction to origin
12103 // should not start an alternate Job. It should pool to existing connection
12105 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12106 HttpRequestInfo request2
;
12107 request2
.method
= "GET";
12108 request2
.url
= GURL("https://origin.example.org:443/second");
12109 request2
.load_flags
= 0;
12110 TestCompletionCallback callback2
;
12112 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12113 rv
= callback2
.GetResult(rv
);
12116 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12117 ASSERT_TRUE(response2
!= nullptr);
12118 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12119 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12121 std::string response_data2
;
12122 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12123 EXPECT_EQ("another", response_data2
);
12126 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12127 // HTTP/1.1 socket open to the alternative server. That socket should not be
12129 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12130 HostPortPair
origin("origin.example.org", 443);
12131 HostPortPair
alternative("alternative.example.org", 443);
12132 std::string origin_url
= "https://origin.example.org:443";
12133 std::string alternative_url
= "https://alternative.example.org:443";
12135 // Negotiate HTTP/1.1 with alternative.example.org.
12136 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12137 ssl
.SetNextProto(kProtoHTTP11
);
12138 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12140 // HTTP/1.1 data for |request1| and |request2|.
12141 MockWrite http_writes
[] = {
12143 "GET / HTTP/1.1\r\n"
12144 "Host: alternative.example.org\r\n"
12145 "Connection: keep-alive\r\n\r\n"),
12147 "GET / HTTP/1.1\r\n"
12148 "Host: alternative.example.org\r\n"
12149 "Connection: keep-alive\r\n\r\n"),
12152 MockRead http_reads
[] = {
12154 "HTTP/1.1 200 OK\r\n"
12155 "Content-Type: text/html; charset=iso-8859-1\r\n"
12156 "Content-Length: 40\r\n\r\n"
12157 "first HTTP/1.1 response from alternative"),
12159 "HTTP/1.1 200 OK\r\n"
12160 "Content-Type: text/html; charset=iso-8859-1\r\n"
12161 "Content-Length: 41\r\n\r\n"
12162 "second HTTP/1.1 response from alternative"),
12164 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12165 http_writes
, arraysize(http_writes
));
12166 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12168 // This test documents that an alternate Job should not pool to an already
12169 // existing HTTP/1.1 connection. In order to test this, a failed connection
12170 // to the origin is mocked. This way |request2| relies on the alternate Job.
12171 StaticSocketDataProvider data_refused
;
12172 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12173 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12175 // Set up alternative service for origin.
12176 session_deps_
.use_alternate_protocols
= true;
12177 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12178 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12179 session
->http_server_properties();
12180 AlternativeService
alternative_service(
12181 AlternateProtocolFromNextProto(GetParam()), alternative
);
12182 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12185 // First transaction to alternative to open an HTTP/1.1 socket.
12186 scoped_ptr
<HttpTransaction
> trans1(
12187 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12188 HttpRequestInfo request1
;
12189 request1
.method
= "GET";
12190 request1
.url
= GURL(alternative_url
);
12191 request1
.load_flags
= 0;
12192 TestCompletionCallback callback1
;
12194 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12195 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12196 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12197 ASSERT_TRUE(response1
);
12198 ASSERT_TRUE(response1
->headers
.get());
12199 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12200 EXPECT_TRUE(response1
->was_npn_negotiated
);
12201 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12202 std::string response_data1
;
12203 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12204 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12206 // Request for origin.example.org, which has an alternative service. This
12207 // will start two Jobs: the alternative looks for connections to pool to,
12208 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12209 // open other connections to alternative server. The Job to origin fails, so
12210 // this request fails.
12211 scoped_ptr
<HttpTransaction
> trans2(
12212 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12213 HttpRequestInfo request2
;
12214 request2
.method
= "GET";
12215 request2
.url
= GURL(origin_url
);
12216 request2
.load_flags
= 0;
12217 TestCompletionCallback callback2
;
12219 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12220 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12222 // Another transaction to alternative. This is to test that the HTTP/1.1
12223 // socket is still open and in the pool.
12224 scoped_ptr
<HttpTransaction
> trans3(
12225 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12226 HttpRequestInfo request3
;
12227 request3
.method
= "GET";
12228 request3
.url
= GURL(alternative_url
);
12229 request3
.load_flags
= 0;
12230 TestCompletionCallback callback3
;
12232 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12233 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12234 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12235 ASSERT_TRUE(response3
);
12236 ASSERT_TRUE(response3
->headers
.get());
12237 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12238 EXPECT_TRUE(response3
->was_npn_negotiated
);
12239 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12240 std::string response_data3
;
12241 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12242 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12245 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12246 const std::string https_url
= "https://www.example.org:8080/";
12247 const std::string http_url
= "http://www.example.org:8080/";
12249 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12250 const HostPortPair
host_port_pair("www.example.org", 8080);
12251 scoped_ptr
<SpdyFrame
> connect(
12252 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12253 scoped_ptr
<SpdyFrame
> req1(
12254 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12255 scoped_ptr
<SpdyFrame
> wrapped_req1(
12256 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12258 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12259 SpdyHeaderBlock req2_block
;
12260 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12261 req2_block
[spdy_util_
.GetPathKey()] = "/";
12262 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12263 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12264 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12265 scoped_ptr
<SpdyFrame
> req2(
12266 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12268 MockWrite writes1
[] = {
12269 CreateMockWrite(*connect
, 0),
12270 CreateMockWrite(*wrapped_req1
, 2),
12271 CreateMockWrite(*req2
, 5),
12274 scoped_ptr
<SpdyFrame
> conn_resp(
12275 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12276 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12277 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12278 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12279 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12280 scoped_ptr
<SpdyFrame
> wrapped_body1(
12281 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12282 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12283 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12284 MockRead reads1
[] = {
12285 CreateMockRead(*conn_resp
, 1),
12286 CreateMockRead(*wrapped_resp1
, 3),
12287 CreateMockRead(*wrapped_body1
, 4),
12288 CreateMockRead(*resp2
, 6),
12289 CreateMockRead(*body2
, 7),
12290 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12293 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12294 writes1
, arraysize(writes1
));
12295 MockConnect
connect_data1(ASYNC
, OK
);
12296 data1
.set_connect_data(connect_data1
);
12298 session_deps_
.proxy_service
.reset(
12299 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12301 session_deps_
.net_log
= &log
;
12302 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12303 ssl1
.SetNextProto(GetParam());
12304 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12305 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12306 ssl2
.SetNextProto(GetParam());
12307 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12308 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12310 scoped_refptr
<HttpNetworkSession
> session(
12311 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12313 // Start the first transaction to set up the SpdySession
12314 HttpRequestInfo request1
;
12315 request1
.method
= "GET";
12316 request1
.url
= GURL(https_url
);
12317 request1
.load_flags
= 0;
12318 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12319 TestCompletionCallback callback1
;
12320 EXPECT_EQ(ERR_IO_PENDING
,
12321 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12322 base::MessageLoop::current()->RunUntilIdle();
12325 EXPECT_EQ(OK
, callback1
.WaitForResult());
12326 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12328 LoadTimingInfo load_timing_info1
;
12329 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12330 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12331 CONNECT_TIMING_HAS_SSL_TIMES
);
12333 // Now, start the HTTP request
12334 HttpRequestInfo request2
;
12335 request2
.method
= "GET";
12336 request2
.url
= GURL(http_url
);
12337 request2
.load_flags
= 0;
12338 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12339 TestCompletionCallback callback2
;
12340 EXPECT_EQ(ERR_IO_PENDING
,
12341 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12342 base::MessageLoop::current()->RunUntilIdle();
12345 EXPECT_EQ(OK
, callback2
.WaitForResult());
12346 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12348 LoadTimingInfo load_timing_info2
;
12349 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12350 // The established SPDY sessions is considered reused by the HTTP request.
12351 TestLoadTimingReusedWithPac(load_timing_info2
);
12352 // HTTP requests over a SPDY session should have a different connection
12353 // socket_log_id than requests over a tunnel.
12354 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12357 // Test that in the case where we have a SPDY session to a SPDY proxy
12358 // that we do not pool other origins that resolve to the same IP when
12359 // the certificate does not match the new origin.
12360 // http://crbug.com/134690
12361 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12362 const std::string url1
= "http://www.example.org/";
12363 const std::string url2
= "https://news.example.org/";
12364 const std::string ip_addr
= "1.2.3.4";
12366 // SPDY GET for HTTP URL (through SPDY proxy)
12367 scoped_ptr
<SpdyHeaderBlock
> headers(
12368 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12369 scoped_ptr
<SpdyFrame
> req1(
12370 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12372 MockWrite writes1
[] = {
12373 CreateMockWrite(*req1
, 0),
12376 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12377 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12378 MockRead reads1
[] = {
12379 CreateMockRead(*resp1
, 1),
12380 CreateMockRead(*body1
, 2),
12381 MockRead(ASYNC
, OK
, 3) // EOF
12384 scoped_ptr
<DeterministicSocketData
> data1(
12385 new DeterministicSocketData(reads1
, arraysize(reads1
),
12386 writes1
, arraysize(writes1
)));
12387 IPAddressNumber ip
;
12388 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12389 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12390 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12391 data1
->set_connect_data(connect_data1
);
12393 // SPDY GET for HTTPS URL (direct)
12394 scoped_ptr
<SpdyFrame
> req2(
12395 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12397 MockWrite writes2
[] = {
12398 CreateMockWrite(*req2
, 0),
12401 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12402 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12403 MockRead reads2
[] = {
12404 CreateMockRead(*resp2
, 1),
12405 CreateMockRead(*body2
, 2),
12406 MockRead(ASYNC
, OK
, 3) // EOF
12409 scoped_ptr
<DeterministicSocketData
> data2(
12410 new DeterministicSocketData(reads2
, arraysize(reads2
),
12411 writes2
, arraysize(writes2
)));
12412 MockConnect
connect_data2(ASYNC
, OK
);
12413 data2
->set_connect_data(connect_data2
);
12415 // Set up a proxy config that sends HTTP requests to a proxy, and
12416 // all others direct.
12417 ProxyConfig proxy_config
;
12418 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12419 session_deps_
.proxy_service
.reset(new ProxyService(
12420 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12422 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12423 ssl1
.SetNextProto(GetParam());
12424 // Load a valid cert. Note, that this does not need to
12425 // be valid for proxy because the MockSSLClientSocket does
12426 // not actually verify it. But SpdySession will use this
12427 // to see if it is valid for the new origin
12428 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12429 ASSERT_TRUE(ssl1
.cert
.get());
12430 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12431 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12434 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12435 ssl2
.SetNextProto(GetParam());
12436 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12437 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12440 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12441 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12442 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12444 scoped_refptr
<HttpNetworkSession
> session(
12445 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12447 // Start the first transaction to set up the SpdySession
12448 HttpRequestInfo request1
;
12449 request1
.method
= "GET";
12450 request1
.url
= GURL(url1
);
12451 request1
.load_flags
= 0;
12452 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12453 TestCompletionCallback callback1
;
12454 ASSERT_EQ(ERR_IO_PENDING
,
12455 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12458 ASSERT_TRUE(callback1
.have_result());
12459 EXPECT_EQ(OK
, callback1
.WaitForResult());
12460 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12462 // Now, start the HTTP request
12463 HttpRequestInfo request2
;
12464 request2
.method
= "GET";
12465 request2
.url
= GURL(url2
);
12466 request2
.load_flags
= 0;
12467 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12468 TestCompletionCallback callback2
;
12469 EXPECT_EQ(ERR_IO_PENDING
,
12470 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12471 base::MessageLoop::current()->RunUntilIdle();
12474 ASSERT_TRUE(callback2
.have_result());
12475 EXPECT_EQ(OK
, callback2
.WaitForResult());
12476 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12479 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12480 // error) in SPDY session, removes the socket from pool and closes the SPDY
12481 // session. Verify that new url's from the same HttpNetworkSession (and a new
12482 // SpdySession) do work. http://crbug.com/224701
12483 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12484 const std::string https_url
= "https://www.example.org/";
12486 MockRead reads1
[] = {
12487 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12490 scoped_ptr
<DeterministicSocketData
> data1(
12491 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
12494 scoped_ptr
<SpdyFrame
> req2(
12495 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12496 MockWrite writes2
[] = {
12497 CreateMockWrite(*req2
, 0),
12500 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12501 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12502 MockRead reads2
[] = {
12503 CreateMockRead(*resp2
, 1),
12504 CreateMockRead(*body2
, 2),
12505 MockRead(ASYNC
, OK
, 3) // EOF
12508 scoped_ptr
<DeterministicSocketData
> data2(
12509 new DeterministicSocketData(reads2
, arraysize(reads2
),
12510 writes2
, arraysize(writes2
)));
12512 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12513 ssl1
.SetNextProto(GetParam());
12514 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12515 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12518 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12519 ssl2
.SetNextProto(GetParam());
12520 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12521 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12524 scoped_refptr
<HttpNetworkSession
> session(
12525 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12527 // Start the first transaction to set up the SpdySession and verify that
12528 // connection was closed.
12529 HttpRequestInfo request1
;
12530 request1
.method
= "GET";
12531 request1
.url
= GURL(https_url
);
12532 request1
.load_flags
= 0;
12533 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12534 TestCompletionCallback callback1
;
12535 EXPECT_EQ(ERR_IO_PENDING
,
12536 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12537 base::MessageLoop::current()->RunUntilIdle();
12538 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12540 // Now, start the second request and make sure it succeeds.
12541 HttpRequestInfo request2
;
12542 request2
.method
= "GET";
12543 request2
.url
= GURL(https_url
);
12544 request2
.load_flags
= 0;
12545 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12546 TestCompletionCallback callback2
;
12547 EXPECT_EQ(ERR_IO_PENDING
,
12548 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12549 base::MessageLoop::current()->RunUntilIdle();
12552 ASSERT_TRUE(callback2
.have_result());
12553 EXPECT_EQ(OK
, callback2
.WaitForResult());
12554 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12557 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12558 session_deps_
.next_protos
= SpdyNextProtos();
12559 ClientSocketPoolManager::set_max_sockets_per_group(
12560 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12561 ClientSocketPoolManager::set_max_sockets_per_pool(
12562 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12564 // Use two different hosts with different IPs so they don't get pooled.
12565 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12566 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12567 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12569 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12570 ssl1
.SetNextProto(GetParam());
12571 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12572 ssl2
.SetNextProto(GetParam());
12573 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12574 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12576 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12577 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12578 MockWrite spdy1_writes
[] = {
12579 CreateMockWrite(*host1_req
, 0),
12581 scoped_ptr
<SpdyFrame
> host1_resp(
12582 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12583 scoped_ptr
<SpdyFrame
> host1_resp_body(
12584 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12585 MockRead spdy1_reads
[] = {
12586 CreateMockRead(*host1_resp
, 1),
12587 CreateMockRead(*host1_resp_body
, 2),
12588 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12591 scoped_ptr
<SequencedSocketData
> spdy1_data(
12592 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12593 arraysize(spdy1_writes
)));
12594 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12596 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12597 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12598 MockWrite spdy2_writes
[] = {
12599 CreateMockWrite(*host2_req
, 0),
12601 scoped_ptr
<SpdyFrame
> host2_resp(
12602 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12603 scoped_ptr
<SpdyFrame
> host2_resp_body(
12604 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12605 MockRead spdy2_reads
[] = {
12606 CreateMockRead(*host2_resp
, 1),
12607 CreateMockRead(*host2_resp_body
, 2),
12608 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12611 scoped_ptr
<SequencedSocketData
> spdy2_data(
12612 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12613 arraysize(spdy2_writes
)));
12614 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12616 MockWrite http_write
[] = {
12617 MockWrite("GET / HTTP/1.1\r\n"
12618 "Host: www.a.com\r\n"
12619 "Connection: keep-alive\r\n\r\n"),
12622 MockRead http_read
[] = {
12623 MockRead("HTTP/1.1 200 OK\r\n"),
12624 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12625 MockRead("Content-Length: 6\r\n\r\n"),
12626 MockRead("hello!"),
12628 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12629 http_write
, arraysize(http_write
));
12630 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12632 HostPortPair
host_port_pair_a("www.a.com", 443);
12633 SpdySessionKey
spdy_session_key_a(
12634 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12636 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12638 TestCompletionCallback callback
;
12639 HttpRequestInfo request1
;
12640 request1
.method
= "GET";
12641 request1
.url
= GURL("https://www.a.com/");
12642 request1
.load_flags
= 0;
12643 scoped_ptr
<HttpNetworkTransaction
> trans(
12644 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12646 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12647 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12648 EXPECT_EQ(OK
, callback
.WaitForResult());
12650 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12651 ASSERT_TRUE(response
!= NULL
);
12652 ASSERT_TRUE(response
->headers
.get() != NULL
);
12653 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12654 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12655 EXPECT_TRUE(response
->was_npn_negotiated
);
12657 std::string response_data
;
12658 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12659 EXPECT_EQ("hello!", response_data
);
12662 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12664 HostPortPair
host_port_pair_b("www.b.com", 443);
12665 SpdySessionKey
spdy_session_key_b(
12666 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12668 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12669 HttpRequestInfo request2
;
12670 request2
.method
= "GET";
12671 request2
.url
= GURL("https://www.b.com/");
12672 request2
.load_flags
= 0;
12673 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12675 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12676 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12677 EXPECT_EQ(OK
, callback
.WaitForResult());
12679 response
= trans
->GetResponseInfo();
12680 ASSERT_TRUE(response
!= NULL
);
12681 ASSERT_TRUE(response
->headers
.get() != NULL
);
12682 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12683 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12684 EXPECT_TRUE(response
->was_npn_negotiated
);
12685 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12686 EXPECT_EQ("hello!", response_data
);
12688 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12690 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12692 HostPortPair
host_port_pair_a1("www.a.com", 80);
12693 SpdySessionKey
spdy_session_key_a1(
12694 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12696 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12697 HttpRequestInfo request3
;
12698 request3
.method
= "GET";
12699 request3
.url
= GURL("http://www.a.com/");
12700 request3
.load_flags
= 0;
12701 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12703 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12705 EXPECT_EQ(OK
, callback
.WaitForResult());
12707 response
= trans
->GetResponseInfo();
12708 ASSERT_TRUE(response
!= NULL
);
12709 ASSERT_TRUE(response
->headers
.get() != NULL
);
12710 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12711 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12712 EXPECT_FALSE(response
->was_npn_negotiated
);
12713 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12714 EXPECT_EQ("hello!", response_data
);
12716 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12718 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12721 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12722 HttpRequestInfo request
;
12723 request
.method
= "GET";
12724 request
.url
= GURL("http://www.example.org/");
12725 request
.load_flags
= 0;
12727 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12728 scoped_ptr
<HttpTransaction
> trans(
12729 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12731 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12732 StaticSocketDataProvider data
;
12733 data
.set_connect_data(mock_connect
);
12734 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12736 TestCompletionCallback callback
;
12738 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12739 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12741 rv
= callback
.WaitForResult();
12742 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12744 // We don't care whether this succeeds or fails, but it shouldn't crash.
12745 HttpRequestHeaders request_headers
;
12746 trans
->GetFullRequestHeaders(&request_headers
);
12748 ConnectionAttempts attempts
;
12749 trans
->GetConnectionAttempts(&attempts
);
12750 ASSERT_EQ(1u, attempts
.size());
12751 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12754 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12755 HttpRequestInfo request
;
12756 request
.method
= "GET";
12757 request
.url
= GURL("http://www.example.org/");
12758 request
.load_flags
= 0;
12760 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12761 scoped_ptr
<HttpTransaction
> trans(
12762 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12764 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12765 StaticSocketDataProvider data
;
12766 data
.set_connect_data(mock_connect
);
12767 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12769 TestCompletionCallback callback
;
12771 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12772 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12774 rv
= callback
.WaitForResult();
12775 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12777 // We don't care whether this succeeds or fails, but it shouldn't crash.
12778 HttpRequestHeaders request_headers
;
12779 trans
->GetFullRequestHeaders(&request_headers
);
12781 ConnectionAttempts attempts
;
12782 trans
->GetConnectionAttempts(&attempts
);
12783 ASSERT_EQ(1u, attempts
.size());
12784 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12787 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12788 HttpRequestInfo request
;
12789 request
.method
= "GET";
12790 request
.url
= GURL("http://www.example.org/");
12791 request
.load_flags
= 0;
12793 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12794 scoped_ptr
<HttpTransaction
> trans(
12795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12797 MockWrite data_writes
[] = {
12798 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12800 MockRead data_reads
[] = {
12801 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12804 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12805 data_writes
, arraysize(data_writes
));
12806 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12808 TestCompletionCallback callback
;
12810 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12811 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12813 rv
= callback
.WaitForResult();
12814 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12816 HttpRequestHeaders request_headers
;
12817 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12818 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12821 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12822 HttpRequestInfo request
;
12823 request
.method
= "GET";
12824 request
.url
= GURL("http://www.example.org/");
12825 request
.load_flags
= 0;
12827 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12828 scoped_ptr
<HttpTransaction
> trans(
12829 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12831 MockWrite data_writes
[] = {
12832 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12834 MockRead data_reads
[] = {
12835 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12838 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12839 data_writes
, arraysize(data_writes
));
12840 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12842 TestCompletionCallback callback
;
12844 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12845 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12847 rv
= callback
.WaitForResult();
12848 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12850 HttpRequestHeaders request_headers
;
12851 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12852 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12855 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12856 HttpRequestInfo request
;
12857 request
.method
= "GET";
12858 request
.url
= GURL("http://www.example.org/");
12859 request
.load_flags
= 0;
12861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12862 scoped_ptr
<HttpTransaction
> trans(
12863 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12865 MockWrite data_writes
[] = {
12867 "GET / HTTP/1.1\r\n"
12868 "Host: www.example.org\r\n"
12869 "Connection: keep-alive\r\n\r\n"),
12871 MockRead data_reads
[] = {
12872 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12875 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12876 data_writes
, arraysize(data_writes
));
12877 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12879 TestCompletionCallback callback
;
12881 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12882 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12884 rv
= callback
.WaitForResult();
12885 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12887 HttpRequestHeaders request_headers
;
12888 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12889 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12892 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12893 HttpRequestInfo request
;
12894 request
.method
= "GET";
12895 request
.url
= GURL("http://www.example.org/");
12896 request
.load_flags
= 0;
12898 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12899 scoped_ptr
<HttpTransaction
> trans(
12900 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12902 MockWrite data_writes
[] = {
12904 "GET / HTTP/1.1\r\n"
12905 "Host: www.example.org\r\n"
12906 "Connection: keep-alive\r\n\r\n"),
12908 MockRead data_reads
[] = {
12909 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12912 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12913 data_writes
, arraysize(data_writes
));
12914 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12916 TestCompletionCallback callback
;
12918 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12919 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12921 rv
= callback
.WaitForResult();
12922 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12924 HttpRequestHeaders request_headers
;
12925 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12926 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12929 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12930 HttpRequestInfo request
;
12931 request
.method
= "GET";
12932 request
.url
= GURL("http://www.example.org/");
12933 request
.load_flags
= 0;
12934 request
.extra_headers
.SetHeader("X-Foo", "bar");
12936 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12937 scoped_ptr
<HttpTransaction
> trans(
12938 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12940 MockWrite data_writes
[] = {
12942 "GET / HTTP/1.1\r\n"
12943 "Host: www.example.org\r\n"
12944 "Connection: keep-alive\r\n"
12945 "X-Foo: bar\r\n\r\n"),
12947 MockRead data_reads
[] = {
12948 MockRead("HTTP/1.1 200 OK\r\n"
12949 "Content-Length: 5\r\n\r\n"
12951 MockRead(ASYNC
, ERR_UNEXPECTED
),
12954 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12955 data_writes
, arraysize(data_writes
));
12956 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12958 TestCompletionCallback callback
;
12960 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12961 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12963 rv
= callback
.WaitForResult();
12966 HttpRequestHeaders request_headers
;
12967 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12969 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12970 EXPECT_EQ("bar", foo
);
12975 // Fake HttpStream that simply records calls to SetPriority().
12976 class FakeStream
: public HttpStream
,
12977 public base::SupportsWeakPtr
<FakeStream
> {
12979 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12980 ~FakeStream() override
{}
12982 RequestPriority
priority() const { return priority_
; }
12984 int InitializeStream(const HttpRequestInfo
* request_info
,
12985 RequestPriority priority
,
12986 const BoundNetLog
& net_log
,
12987 const CompletionCallback
& callback
) override
{
12988 return ERR_IO_PENDING
;
12991 int SendRequest(const HttpRequestHeaders
& request_headers
,
12992 HttpResponseInfo
* response
,
12993 const CompletionCallback
& callback
) override
{
12995 return ERR_UNEXPECTED
;
12998 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13000 return ERR_UNEXPECTED
;
13003 int ReadResponseBody(IOBuffer
* buf
,
13005 const CompletionCallback
& callback
) override
{
13007 return ERR_UNEXPECTED
;
13010 void Close(bool not_reusable
) override
{}
13012 bool IsResponseBodyComplete() const override
{
13017 bool CanFindEndOfResponse() const override
{ return false; }
13019 bool IsConnectionReused() const override
{
13024 void SetConnectionReused() override
{ ADD_FAILURE(); }
13026 bool IsConnectionReusable() const override
{
13031 int64
GetTotalReceivedBytes() const override
{
13036 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13041 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
13043 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13047 bool IsSpdyHttpStream() const override
{
13052 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
13054 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13056 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
13058 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
13061 RequestPriority priority_
;
13063 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
13066 // Fake HttpStreamRequest that simply records calls to SetPriority()
13067 // and vends FakeStreams with its current priority.
13068 class FakeStreamRequest
: public HttpStreamRequest
,
13069 public base::SupportsWeakPtr
<FakeStreamRequest
> {
13071 FakeStreamRequest(RequestPriority priority
,
13072 HttpStreamRequest::Delegate
* delegate
)
13073 : priority_(priority
),
13074 delegate_(delegate
),
13075 websocket_stream_create_helper_(NULL
) {}
13077 FakeStreamRequest(RequestPriority priority
,
13078 HttpStreamRequest::Delegate
* delegate
,
13079 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13080 : priority_(priority
),
13081 delegate_(delegate
),
13082 websocket_stream_create_helper_(create_helper
) {}
13084 ~FakeStreamRequest() override
{}
13086 RequestPriority
priority() const { return priority_
; }
13088 const WebSocketHandshakeStreamBase::CreateHelper
*
13089 websocket_stream_create_helper() const {
13090 return websocket_stream_create_helper_
;
13093 // Create a new FakeStream and pass it to the request's
13094 // delegate. Returns a weak pointer to the FakeStream.
13095 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13096 FakeStream
* fake_stream
= new FakeStream(priority_
);
13097 // Do this before calling OnStreamReady() as OnStreamReady() may
13098 // immediately delete |fake_stream|.
13099 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13100 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13101 return weak_stream
;
13104 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13106 return ERR_UNEXPECTED
;
13109 LoadState
GetLoadState() const override
{
13111 return LoadState();
13114 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13116 bool was_npn_negotiated() const override
{ return false; }
13118 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13120 bool using_spdy() const override
{ return false; }
13122 const ConnectionAttempts
& connection_attempts() const override
{
13123 static ConnectionAttempts no_attempts
;
13124 return no_attempts
;
13128 RequestPriority priority_
;
13129 HttpStreamRequest::Delegate
* const delegate_
;
13130 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13132 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13135 // Fake HttpStreamFactory that vends FakeStreamRequests.
13136 class FakeStreamFactory
: public HttpStreamFactory
{
13138 FakeStreamFactory() {}
13139 ~FakeStreamFactory() override
{}
13141 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13142 // RequestStream() (which may be NULL if it was destroyed already).
13143 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13144 return last_stream_request_
;
13147 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13148 RequestPriority priority
,
13149 const SSLConfig
& server_ssl_config
,
13150 const SSLConfig
& proxy_ssl_config
,
13151 HttpStreamRequest::Delegate
* delegate
,
13152 const BoundNetLog
& net_log
) override
{
13153 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13154 last_stream_request_
= fake_request
->AsWeakPtr();
13155 return fake_request
;
13158 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13159 const HttpRequestInfo
& info
,
13160 RequestPriority priority
,
13161 const SSLConfig
& server_ssl_config
,
13162 const SSLConfig
& proxy_ssl_config
,
13163 HttpStreamRequest::Delegate
* delegate
,
13164 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13165 const BoundNetLog
& net_log
) override
{
13166 FakeStreamRequest
* fake_request
=
13167 new FakeStreamRequest(priority
, delegate
, create_helper
);
13168 last_stream_request_
= fake_request
->AsWeakPtr();
13169 return fake_request
;
13172 void PreconnectStreams(int num_streams
,
13173 const HttpRequestInfo
& info
,
13174 RequestPriority priority
,
13175 const SSLConfig
& server_ssl_config
,
13176 const SSLConfig
& proxy_ssl_config
) override
{
13180 const HostMappingRules
* GetHostMappingRules() const override
{
13186 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13188 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13191 // TODO(ricea): Maybe unify this with the one in
13192 // url_request_http_job_unittest.cc ?
13193 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13195 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13197 : state_(connection
.release(), using_proxy
) {}
13199 // Fake implementation of HttpStreamBase methods.
13200 // This ends up being quite "real" because this object has to really send data
13201 // on the mock socket. It might be easier to use the real implementation, but
13202 // the fact that the WebSocket code is not compiled on iOS makes that
13204 int InitializeStream(const HttpRequestInfo
* request_info
,
13205 RequestPriority priority
,
13206 const BoundNetLog
& net_log
,
13207 const CompletionCallback
& callback
) override
{
13208 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13212 int SendRequest(const HttpRequestHeaders
& request_headers
,
13213 HttpResponseInfo
* response
,
13214 const CompletionCallback
& callback
) override
{
13215 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13216 response
, callback
);
13219 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13220 return parser()->ReadResponseHeaders(callback
);
13223 int ReadResponseBody(IOBuffer
* buf
,
13225 const CompletionCallback
& callback
) override
{
13227 return ERR_IO_PENDING
;
13230 void Close(bool not_reusable
) override
{
13232 parser()->Close(true);
13235 bool IsResponseBodyComplete() const override
{
13240 bool CanFindEndOfResponse() const override
{
13241 return parser()->CanFindEndOfResponse();
13244 bool IsConnectionReused() const override
{
13248 void SetConnectionReused() override
{ NOTREACHED(); }
13250 bool IsConnectionReusable() const override
{
13255 int64
GetTotalReceivedBytes() const override
{
13260 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13265 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13267 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13271 bool IsSpdyHttpStream() const override
{
13276 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13278 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13280 UploadProgress
GetUploadProgress() const override
{
13282 return UploadProgress();
13285 HttpStream
* RenewStreamForAuth() override
{
13290 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13291 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13293 return scoped_ptr
<WebSocketStream
>();
13297 HttpStreamParser
* parser() const { return state_
.parser(); }
13298 HttpBasicState state_
;
13300 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13303 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13305 class FakeWebSocketStreamCreateHelper
:
13306 public WebSocketHandshakeStreamBase::CreateHelper
{
13308 WebSocketHandshakeStreamBase
* CreateBasicStream(
13309 scoped_ptr
<ClientSocketHandle
> connection
,
13310 bool using_proxy
) override
{
13311 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13315 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13316 const base::WeakPtr
<SpdySession
>& session
,
13317 bool use_relative_url
) override
{
13322 ~FakeWebSocketStreamCreateHelper() override
{}
13324 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13326 return scoped_ptr
<WebSocketStream
>();
13332 // Make sure that HttpNetworkTransaction passes on its priority to its
13333 // stream request on start.
13334 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13335 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13336 HttpNetworkSessionPeer
peer(session
);
13337 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13338 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13340 HttpNetworkTransaction
trans(LOW
, session
.get());
13342 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13344 HttpRequestInfo request
;
13345 TestCompletionCallback callback
;
13346 EXPECT_EQ(ERR_IO_PENDING
,
13347 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13349 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13350 fake_factory
->last_stream_request();
13351 ASSERT_TRUE(fake_request
!= NULL
);
13352 EXPECT_EQ(LOW
, fake_request
->priority());
13355 // Make sure that HttpNetworkTransaction passes on its priority
13356 // updates to its stream request.
13357 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13358 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13359 HttpNetworkSessionPeer
peer(session
);
13360 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13361 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13363 HttpNetworkTransaction
trans(LOW
, session
.get());
13365 HttpRequestInfo request
;
13366 TestCompletionCallback callback
;
13367 EXPECT_EQ(ERR_IO_PENDING
,
13368 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13370 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13371 fake_factory
->last_stream_request();
13372 ASSERT_TRUE(fake_request
!= NULL
);
13373 EXPECT_EQ(LOW
, fake_request
->priority());
13375 trans
.SetPriority(LOWEST
);
13376 ASSERT_TRUE(fake_request
!= NULL
);
13377 EXPECT_EQ(LOWEST
, fake_request
->priority());
13380 // Make sure that HttpNetworkTransaction passes on its priority
13381 // updates to its stream.
13382 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13383 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13384 HttpNetworkSessionPeer
peer(session
);
13385 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13386 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13388 HttpNetworkTransaction
trans(LOW
, session
.get());
13390 HttpRequestInfo request
;
13391 TestCompletionCallback callback
;
13392 EXPECT_EQ(ERR_IO_PENDING
,
13393 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13395 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13396 fake_factory
->last_stream_request();
13397 ASSERT_TRUE(fake_request
!= NULL
);
13398 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13399 ASSERT_TRUE(fake_stream
!= NULL
);
13400 EXPECT_EQ(LOW
, fake_stream
->priority());
13402 trans
.SetPriority(LOWEST
);
13403 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13406 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13407 // The same logic needs to be tested for both ws: and wss: schemes, but this
13408 // test is already parameterised on NextProto, so it uses a loop to verify
13409 // that the different schemes work.
13410 std::string test_cases
[] = {"ws://www.example.org/",
13411 "wss://www.example.org/"};
13412 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13414 HttpNetworkSessionPeer
peer(session
);
13415 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13416 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13417 peer
.SetHttpStreamFactoryForWebSocket(
13418 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13420 HttpNetworkTransaction
trans(LOW
, session
.get());
13421 trans
.SetWebSocketHandshakeStreamCreateHelper(
13422 &websocket_stream_create_helper
);
13424 HttpRequestInfo request
;
13425 TestCompletionCallback callback
;
13426 request
.method
= "GET";
13427 request
.url
= GURL(test_cases
[i
]);
13429 EXPECT_EQ(ERR_IO_PENDING
,
13430 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13432 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13433 fake_factory
->last_stream_request();
13434 ASSERT_TRUE(fake_request
!= NULL
);
13435 EXPECT_EQ(&websocket_stream_create_helper
,
13436 fake_request
->websocket_stream_create_helper());
13440 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13441 // if the transport socket pool is stalled on the global socket limit.
13442 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13443 ClientSocketPoolManager::set_max_sockets_per_group(
13444 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13445 ClientSocketPoolManager::set_max_sockets_per_pool(
13446 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13448 // Set up SSL request.
13450 HttpRequestInfo ssl_request
;
13451 ssl_request
.method
= "GET";
13452 ssl_request
.url
= GURL("https://www.example.org/");
13454 MockWrite ssl_writes
[] = {
13456 "GET / HTTP/1.1\r\n"
13457 "Host: www.example.org\r\n"
13458 "Connection: keep-alive\r\n\r\n"),
13460 MockRead ssl_reads
[] = {
13461 MockRead("HTTP/1.1 200 OK\r\n"),
13462 MockRead("Content-Length: 11\r\n\r\n"),
13463 MockRead("hello world"),
13464 MockRead(SYNCHRONOUS
, OK
),
13466 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13467 ssl_writes
, arraysize(ssl_writes
));
13468 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13470 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13471 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13473 // Set up HTTP request.
13475 HttpRequestInfo http_request
;
13476 http_request
.method
= "GET";
13477 http_request
.url
= GURL("http://www.example.org/");
13479 MockWrite http_writes
[] = {
13481 "GET / HTTP/1.1\r\n"
13482 "Host: www.example.org\r\n"
13483 "Connection: keep-alive\r\n\r\n"),
13485 MockRead http_reads
[] = {
13486 MockRead("HTTP/1.1 200 OK\r\n"),
13487 MockRead("Content-Length: 7\r\n\r\n"),
13488 MockRead("falafel"),
13489 MockRead(SYNCHRONOUS
, OK
),
13491 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13492 http_writes
, arraysize(http_writes
));
13493 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13495 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13497 // Start the SSL request.
13498 TestCompletionCallback ssl_callback
;
13499 scoped_ptr
<HttpTransaction
> ssl_trans(
13500 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13501 ASSERT_EQ(ERR_IO_PENDING
,
13502 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13505 // Start the HTTP request. Pool should stall.
13506 TestCompletionCallback http_callback
;
13507 scoped_ptr
<HttpTransaction
> http_trans(
13508 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13509 ASSERT_EQ(ERR_IO_PENDING
,
13510 http_trans
->Start(&http_request
, http_callback
.callback(),
13512 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13514 // Wait for response from SSL request.
13515 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13516 std::string response_data
;
13517 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13518 EXPECT_EQ("hello world", response_data
);
13520 // The SSL socket should automatically be closed, so the HTTP request can
13522 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13523 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13525 // The HTTP request can now complete.
13526 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13527 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13528 EXPECT_EQ("falafel", response_data
);
13530 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13533 // Tests that when a SSL connection is established but there's no corresponding
13534 // request that needs it, the new socket is closed if the transport socket pool
13535 // is stalled on the global socket limit.
13536 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13537 ClientSocketPoolManager::set_max_sockets_per_group(
13538 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13539 ClientSocketPoolManager::set_max_sockets_per_pool(
13540 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13542 // Set up an ssl request.
13544 HttpRequestInfo ssl_request
;
13545 ssl_request
.method
= "GET";
13546 ssl_request
.url
= GURL("https://www.foopy.com/");
13548 // No data will be sent on the SSL socket.
13549 StaticSocketDataProvider ssl_data
;
13550 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13552 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13553 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13555 // Set up HTTP request.
13557 HttpRequestInfo http_request
;
13558 http_request
.method
= "GET";
13559 http_request
.url
= GURL("http://www.example.org/");
13561 MockWrite http_writes
[] = {
13563 "GET / HTTP/1.1\r\n"
13564 "Host: www.example.org\r\n"
13565 "Connection: keep-alive\r\n\r\n"),
13567 MockRead http_reads
[] = {
13568 MockRead("HTTP/1.1 200 OK\r\n"),
13569 MockRead("Content-Length: 7\r\n\r\n"),
13570 MockRead("falafel"),
13571 MockRead(SYNCHRONOUS
, OK
),
13573 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13574 http_writes
, arraysize(http_writes
));
13575 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13577 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13579 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13580 // cancelled when a normal transaction is cancelled.
13581 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13582 SSLConfig ssl_config
;
13583 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13584 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
13585 ssl_config
, ssl_config
);
13586 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13588 // Start the HTTP request. Pool should stall.
13589 TestCompletionCallback http_callback
;
13590 scoped_ptr
<HttpTransaction
> http_trans(
13591 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13592 ASSERT_EQ(ERR_IO_PENDING
,
13593 http_trans
->Start(&http_request
, http_callback
.callback(),
13595 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13597 // The SSL connection will automatically be closed once the connection is
13598 // established, to let the HTTP request start.
13599 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13600 std::string response_data
;
13601 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13602 EXPECT_EQ("falafel", response_data
);
13604 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13607 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13608 ScopedVector
<UploadElementReader
> element_readers
;
13609 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13610 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13612 HttpRequestInfo request
;
13613 request
.method
= "POST";
13614 request
.url
= GURL("http://www.foo.com/");
13615 request
.upload_data_stream
= &upload_data_stream
;
13616 request
.load_flags
= 0;
13618 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13619 scoped_ptr
<HttpTransaction
> trans(
13620 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13621 // Send headers successfully, but get an error while sending the body.
13622 MockWrite data_writes
[] = {
13623 MockWrite("POST / HTTP/1.1\r\n"
13624 "Host: www.foo.com\r\n"
13625 "Connection: keep-alive\r\n"
13626 "Content-Length: 3\r\n\r\n"),
13627 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13630 MockRead data_reads
[] = {
13631 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13632 MockRead("hello world"),
13633 MockRead(SYNCHRONOUS
, OK
),
13635 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13636 arraysize(data_writes
));
13637 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13639 TestCompletionCallback callback
;
13641 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13642 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13644 rv
= callback
.WaitForResult();
13647 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13648 ASSERT_TRUE(response
!= NULL
);
13650 EXPECT_TRUE(response
->headers
.get() != NULL
);
13651 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13653 std::string response_data
;
13654 rv
= ReadTransaction(trans
.get(), &response_data
);
13656 EXPECT_EQ("hello world", response_data
);
13659 // This test makes sure the retry logic doesn't trigger when reading an error
13660 // response from a server that rejected a POST with a CONNECTION_RESET.
13661 TEST_P(HttpNetworkTransactionTest
,
13662 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13663 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13664 MockWrite data_writes
[] = {
13665 MockWrite("GET / HTTP/1.1\r\n"
13666 "Host: www.foo.com\r\n"
13667 "Connection: keep-alive\r\n\r\n"),
13668 MockWrite("POST / HTTP/1.1\r\n"
13669 "Host: www.foo.com\r\n"
13670 "Connection: keep-alive\r\n"
13671 "Content-Length: 3\r\n\r\n"),
13672 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13675 MockRead data_reads
[] = {
13676 MockRead("HTTP/1.1 200 Peachy\r\n"
13677 "Content-Length: 14\r\n\r\n"),
13678 MockRead("first response"),
13679 MockRead("HTTP/1.1 400 Not OK\r\n"
13680 "Content-Length: 15\r\n\r\n"),
13681 MockRead("second response"),
13682 MockRead(SYNCHRONOUS
, OK
),
13684 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13685 arraysize(data_writes
));
13686 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13688 TestCompletionCallback callback
;
13689 HttpRequestInfo request1
;
13690 request1
.method
= "GET";
13691 request1
.url
= GURL("http://www.foo.com/");
13692 request1
.load_flags
= 0;
13694 scoped_ptr
<HttpTransaction
> trans1(
13695 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13696 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13697 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13699 rv
= callback
.WaitForResult();
13702 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13703 ASSERT_TRUE(response1
!= NULL
);
13705 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13706 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13708 std::string response_data1
;
13709 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13711 EXPECT_EQ("first response", response_data1
);
13712 // Delete the transaction to release the socket back into the socket pool.
13715 ScopedVector
<UploadElementReader
> element_readers
;
13716 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13717 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13719 HttpRequestInfo request2
;
13720 request2
.method
= "POST";
13721 request2
.url
= GURL("http://www.foo.com/");
13722 request2
.upload_data_stream
= &upload_data_stream
;
13723 request2
.load_flags
= 0;
13725 scoped_ptr
<HttpTransaction
> trans2(
13726 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13727 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13728 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13730 rv
= callback
.WaitForResult();
13733 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13734 ASSERT_TRUE(response2
!= NULL
);
13736 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13737 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13739 std::string response_data2
;
13740 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13742 EXPECT_EQ("second response", response_data2
);
13745 TEST_P(HttpNetworkTransactionTest
,
13746 PostReadsErrorResponseAfterResetPartialBodySent
) {
13747 ScopedVector
<UploadElementReader
> element_readers
;
13748 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13749 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13751 HttpRequestInfo request
;
13752 request
.method
= "POST";
13753 request
.url
= GURL("http://www.foo.com/");
13754 request
.upload_data_stream
= &upload_data_stream
;
13755 request
.load_flags
= 0;
13757 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13758 scoped_ptr
<HttpTransaction
> trans(
13759 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13760 // Send headers successfully, but get an error while sending the body.
13761 MockWrite data_writes
[] = {
13762 MockWrite("POST / HTTP/1.1\r\n"
13763 "Host: www.foo.com\r\n"
13764 "Connection: keep-alive\r\n"
13765 "Content-Length: 3\r\n\r\n"
13767 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13770 MockRead data_reads
[] = {
13771 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13772 MockRead("hello world"),
13773 MockRead(SYNCHRONOUS
, OK
),
13775 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13776 arraysize(data_writes
));
13777 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13779 TestCompletionCallback callback
;
13781 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13782 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13784 rv
= callback
.WaitForResult();
13787 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13788 ASSERT_TRUE(response
!= NULL
);
13790 EXPECT_TRUE(response
->headers
.get() != NULL
);
13791 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13793 std::string response_data
;
13794 rv
= ReadTransaction(trans
.get(), &response_data
);
13796 EXPECT_EQ("hello world", response_data
);
13799 // This tests the more common case than the previous test, where headers and
13800 // body are not merged into a single request.
13801 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13802 ScopedVector
<UploadElementReader
> element_readers
;
13803 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13804 ChunkedUploadDataStream
upload_data_stream(0);
13806 HttpRequestInfo request
;
13807 request
.method
= "POST";
13808 request
.url
= GURL("http://www.foo.com/");
13809 request
.upload_data_stream
= &upload_data_stream
;
13810 request
.load_flags
= 0;
13812 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13813 scoped_ptr
<HttpTransaction
> trans(
13814 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13815 // Send headers successfully, but get an error while sending the body.
13816 MockWrite data_writes
[] = {
13817 MockWrite("POST / HTTP/1.1\r\n"
13818 "Host: www.foo.com\r\n"
13819 "Connection: keep-alive\r\n"
13820 "Transfer-Encoding: chunked\r\n\r\n"),
13821 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13824 MockRead data_reads
[] = {
13825 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13826 MockRead("hello world"),
13827 MockRead(SYNCHRONOUS
, OK
),
13829 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13830 arraysize(data_writes
));
13831 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13833 TestCompletionCallback callback
;
13835 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13836 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13837 // Make sure the headers are sent before adding a chunk. This ensures that
13838 // they can't be merged with the body in a single send. Not currently
13839 // necessary since a chunked body is never merged with headers, but this makes
13840 // the test more future proof.
13841 base::RunLoop().RunUntilIdle();
13843 upload_data_stream
.AppendData("last chunk", 10, true);
13845 rv
= callback
.WaitForResult();
13848 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13849 ASSERT_TRUE(response
!= NULL
);
13851 EXPECT_TRUE(response
->headers
.get() != NULL
);
13852 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13854 std::string response_data
;
13855 rv
= ReadTransaction(trans
.get(), &response_data
);
13857 EXPECT_EQ("hello world", response_data
);
13860 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13861 ScopedVector
<UploadElementReader
> element_readers
;
13862 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13863 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13865 HttpRequestInfo request
;
13866 request
.method
= "POST";
13867 request
.url
= GURL("http://www.foo.com/");
13868 request
.upload_data_stream
= &upload_data_stream
;
13869 request
.load_flags
= 0;
13871 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13872 scoped_ptr
<HttpTransaction
> trans(
13873 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13875 MockWrite data_writes
[] = {
13876 MockWrite("POST / HTTP/1.1\r\n"
13877 "Host: www.foo.com\r\n"
13878 "Connection: keep-alive\r\n"
13879 "Content-Length: 3\r\n\r\n"),
13880 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13883 MockRead data_reads
[] = {
13884 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13885 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13886 MockRead("hello world"),
13887 MockRead(SYNCHRONOUS
, OK
),
13889 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13890 arraysize(data_writes
));
13891 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13893 TestCompletionCallback callback
;
13895 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13896 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13898 rv
= callback
.WaitForResult();
13901 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13902 ASSERT_TRUE(response
!= NULL
);
13904 EXPECT_TRUE(response
->headers
.get() != NULL
);
13905 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13907 std::string response_data
;
13908 rv
= ReadTransaction(trans
.get(), &response_data
);
13910 EXPECT_EQ("hello world", response_data
);
13913 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13914 ScopedVector
<UploadElementReader
> element_readers
;
13915 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13916 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13918 HttpRequestInfo request
;
13919 request
.method
= "POST";
13920 request
.url
= GURL("http://www.foo.com/");
13921 request
.upload_data_stream
= &upload_data_stream
;
13922 request
.load_flags
= 0;
13924 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13925 scoped_ptr
<HttpTransaction
> trans(
13926 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13927 // Send headers successfully, but get an error while sending the body.
13928 MockWrite data_writes
[] = {
13929 MockWrite("POST / HTTP/1.1\r\n"
13930 "Host: www.foo.com\r\n"
13931 "Connection: keep-alive\r\n"
13932 "Content-Length: 3\r\n\r\n"),
13933 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13936 MockRead data_reads
[] = {
13937 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13938 MockRead("hello world"),
13939 MockRead(SYNCHRONOUS
, OK
),
13941 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13942 arraysize(data_writes
));
13943 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13945 TestCompletionCallback callback
;
13947 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13948 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13950 rv
= callback
.WaitForResult();
13951 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13954 TEST_P(HttpNetworkTransactionTest
,
13955 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13956 ScopedVector
<UploadElementReader
> element_readers
;
13957 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13958 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13960 HttpRequestInfo request
;
13961 request
.method
= "POST";
13962 request
.url
= GURL("http://www.foo.com/");
13963 request
.upload_data_stream
= &upload_data_stream
;
13964 request
.load_flags
= 0;
13966 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13967 scoped_ptr
<HttpTransaction
> trans(
13968 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13969 // Send headers successfully, but get an error while sending the body.
13970 MockWrite data_writes
[] = {
13971 MockWrite("POST / HTTP/1.1\r\n"
13972 "Host: www.foo.com\r\n"
13973 "Connection: keep-alive\r\n"
13974 "Content-Length: 3\r\n\r\n"),
13975 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13978 MockRead data_reads
[] = {
13979 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13980 MockRead("HTTP/1.0 302 Redirect\r\n"),
13981 MockRead("Location: http://somewhere-else.com/\r\n"),
13982 MockRead("Content-Length: 0\r\n\r\n"),
13983 MockRead(SYNCHRONOUS
, OK
),
13985 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13986 arraysize(data_writes
));
13987 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13989 TestCompletionCallback callback
;
13991 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13992 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13994 rv
= callback
.WaitForResult();
13995 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13998 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13999 ScopedVector
<UploadElementReader
> element_readers
;
14000 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14001 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14003 HttpRequestInfo request
;
14004 request
.method
= "POST";
14005 request
.url
= GURL("http://www.foo.com/");
14006 request
.upload_data_stream
= &upload_data_stream
;
14007 request
.load_flags
= 0;
14009 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14010 scoped_ptr
<HttpTransaction
> trans(
14011 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14012 // Send headers successfully, but get an error while sending the body.
14013 MockWrite data_writes
[] = {
14014 MockWrite("POST / HTTP/1.1\r\n"
14015 "Host: www.foo.com\r\n"
14016 "Connection: keep-alive\r\n"
14017 "Content-Length: 3\r\n\r\n"),
14018 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14021 MockRead data_reads
[] = {
14022 MockRead("HTTP 0.9 rocks!"),
14023 MockRead(SYNCHRONOUS
, OK
),
14025 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14026 arraysize(data_writes
));
14027 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14029 TestCompletionCallback callback
;
14031 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14032 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14034 rv
= callback
.WaitForResult();
14035 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14038 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
14039 ScopedVector
<UploadElementReader
> element_readers
;
14040 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14041 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14043 HttpRequestInfo request
;
14044 request
.method
= "POST";
14045 request
.url
= GURL("http://www.foo.com/");
14046 request
.upload_data_stream
= &upload_data_stream
;
14047 request
.load_flags
= 0;
14049 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14050 scoped_ptr
<HttpTransaction
> trans(
14051 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14052 // Send headers successfully, but get an error while sending the body.
14053 MockWrite data_writes
[] = {
14054 MockWrite("POST / HTTP/1.1\r\n"
14055 "Host: www.foo.com\r\n"
14056 "Connection: keep-alive\r\n"
14057 "Content-Length: 3\r\n\r\n"),
14058 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14061 MockRead data_reads
[] = {
14062 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14063 MockRead(SYNCHRONOUS
, OK
),
14065 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14066 arraysize(data_writes
));
14067 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14069 TestCompletionCallback callback
;
14071 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14072 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14074 rv
= callback
.WaitForResult();
14075 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14078 // Verify that proxy headers are not sent to the destination server when
14079 // establishing a tunnel for a secure WebSocket connection.
14080 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14081 HttpRequestInfo request
;
14082 request
.method
= "GET";
14083 request
.url
= GURL("wss://www.example.org/");
14084 AddWebSocketHeaders(&request
.extra_headers
);
14086 // Configure against proxy server "myproxy:70".
14087 session_deps_
.proxy_service
.reset(
14088 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14090 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14092 // Since a proxy is configured, try to establish a tunnel.
14093 MockWrite data_writes
[] = {
14095 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14096 "Host: www.example.org\r\n"
14097 "Proxy-Connection: keep-alive\r\n\r\n"),
14099 // After calling trans->RestartWithAuth(), this is the request we should
14100 // be issuing -- the final header line contains the credentials.
14102 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14103 "Host: www.example.org\r\n"
14104 "Proxy-Connection: keep-alive\r\n"
14105 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14108 "GET / HTTP/1.1\r\n"
14109 "Host: www.example.org\r\n"
14110 "Connection: Upgrade\r\n"
14111 "Upgrade: websocket\r\n"
14112 "Origin: http://www.example.org\r\n"
14113 "Sec-WebSocket-Version: 13\r\n"
14114 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14117 // The proxy responds to the connect with a 407, using a persistent
14119 MockRead data_reads
[] = {
14121 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14122 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14123 MockRead("Proxy-Connection: close\r\n\r\n"),
14125 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14127 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14128 MockRead("Upgrade: websocket\r\n"),
14129 MockRead("Connection: Upgrade\r\n"),
14130 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14133 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14134 arraysize(data_writes
));
14135 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14136 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14137 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14139 scoped_ptr
<HttpTransaction
> trans(
14140 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14141 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14142 trans
->SetWebSocketHandshakeStreamCreateHelper(
14143 &websocket_stream_create_helper
);
14146 TestCompletionCallback callback
;
14148 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14149 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14151 rv
= callback
.WaitForResult();
14155 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14156 ASSERT_TRUE(response
);
14157 ASSERT_TRUE(response
->headers
.get());
14158 EXPECT_EQ(407, response
->headers
->response_code());
14161 TestCompletionCallback callback
;
14163 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14164 callback
.callback());
14165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14167 rv
= callback
.WaitForResult();
14171 response
= trans
->GetResponseInfo();
14172 ASSERT_TRUE(response
);
14173 ASSERT_TRUE(response
->headers
.get());
14175 EXPECT_EQ(101, response
->headers
->response_code());
14178 session
->CloseAllConnections();
14181 // Verify that proxy headers are not sent to the destination server when
14182 // establishing a tunnel for an insecure WebSocket connection.
14183 // This requires the authentication info to be injected into the auth cache
14184 // due to crbug.com/395064
14185 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14186 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14187 HttpRequestInfo request
;
14188 request
.method
= "GET";
14189 request
.url
= GURL("ws://www.example.org/");
14190 AddWebSocketHeaders(&request
.extra_headers
);
14192 // Configure against proxy server "myproxy:70".
14193 session_deps_
.proxy_service
.reset(
14194 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14196 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14198 MockWrite data_writes
[] = {
14199 // Try to establish a tunnel for the WebSocket connection, with
14200 // credentials. Because WebSockets have a separate set of socket pools,
14201 // they cannot and will not use the same TCP/IP connection as the
14202 // preflight HTTP request.
14204 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14205 "Host: www.example.org:80\r\n"
14206 "Proxy-Connection: keep-alive\r\n"
14207 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14210 "GET / HTTP/1.1\r\n"
14211 "Host: www.example.org\r\n"
14212 "Connection: Upgrade\r\n"
14213 "Upgrade: websocket\r\n"
14214 "Origin: http://www.example.org\r\n"
14215 "Sec-WebSocket-Version: 13\r\n"
14216 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14219 MockRead data_reads
[] = {
14220 // HTTP CONNECT with credentials.
14221 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14223 // WebSocket connection established inside tunnel.
14224 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14225 MockRead("Upgrade: websocket\r\n"),
14226 MockRead("Connection: Upgrade\r\n"),
14227 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14230 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14231 arraysize(data_writes
));
14232 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14234 session
->http_auth_cache()->Add(
14235 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14236 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14238 scoped_ptr
<HttpTransaction
> trans(
14239 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14240 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14241 trans
->SetWebSocketHandshakeStreamCreateHelper(
14242 &websocket_stream_create_helper
);
14244 TestCompletionCallback callback
;
14246 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14247 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14249 rv
= callback
.WaitForResult();
14252 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14253 ASSERT_TRUE(response
);
14254 ASSERT_TRUE(response
->headers
.get());
14256 EXPECT_EQ(101, response
->headers
->response_code());
14259 session
->CloseAllConnections();