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().GetCaptureMode().enabled());
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
);
1588 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1589 EXPECT_TRUE(response
== NULL
);
1592 // What do various browsers do when the server closes a non-keepalive
1593 // connection without sending any response header or body?
1596 // Safari 3.1.2 (Windows): error page
1597 // Firefox 3.0.1: blank page
1598 // Opera 9.52: after five attempts, blank page
1599 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1600 // Us: error page (EMPTY_RESPONSE)
1601 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1602 MockRead data_reads
[] = {
1603 MockRead(SYNCHRONOUS
, OK
), // EOF
1604 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1605 MockRead("hello world"),
1606 MockRead(SYNCHRONOUS
, OK
),
1608 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1609 arraysize(data_reads
));
1610 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1613 // Test that network access can be deferred and resumed.
1614 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1615 HttpRequestInfo request
;
1616 request
.method
= "GET";
1617 request
.url
= GURL("http://www.example.org/");
1618 request
.load_flags
= 0;
1620 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1621 scoped_ptr
<HttpTransaction
> trans(
1622 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1624 // Defer on OnBeforeNetworkStart.
1625 BeforeNetworkStartHandler
net_start_handler(true); // defer
1626 trans
->SetBeforeNetworkStartCallback(
1627 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1628 base::Unretained(&net_start_handler
)));
1630 MockRead data_reads
[] = {
1631 MockRead("HTTP/1.0 200 OK\r\n"),
1632 MockRead("Content-Length: 5\r\n\r\n"),
1634 MockRead(SYNCHRONOUS
, 0),
1636 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1637 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1639 TestCompletionCallback callback
;
1641 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1642 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1643 base::MessageLoop::current()->RunUntilIdle();
1645 // Should have deferred for network start.
1646 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1647 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1648 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1650 trans
->ResumeNetworkStart();
1651 rv
= callback
.WaitForResult();
1653 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1655 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1656 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1657 if (rv
== ERR_IO_PENDING
)
1658 rv
= callback
.WaitForResult();
1663 // Test that network use can be deferred and canceled.
1664 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1665 HttpRequestInfo request
;
1666 request
.method
= "GET";
1667 request
.url
= GURL("http://www.example.org/");
1668 request
.load_flags
= 0;
1670 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1671 scoped_ptr
<HttpTransaction
> trans(
1672 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1674 // Defer on OnBeforeNetworkStart.
1675 BeforeNetworkStartHandler
net_start_handler(true); // defer
1676 trans
->SetBeforeNetworkStartCallback(
1677 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1678 base::Unretained(&net_start_handler
)));
1680 TestCompletionCallback callback
;
1682 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1683 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1684 base::MessageLoop::current()->RunUntilIdle();
1686 // Should have deferred for network start.
1687 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1688 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1689 EXPECT_TRUE(trans
->GetResponseInfo() == NULL
);
1692 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1693 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1694 // destructor in such situations.
1695 // See http://crbug.com/154712 and http://crbug.com/156609.
1696 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1697 HttpRequestInfo request
;
1698 request
.method
= "GET";
1699 request
.url
= GURL("http://www.example.org/");
1700 request
.load_flags
= 0;
1702 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1703 scoped_ptr
<HttpTransaction
> trans(
1704 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1706 MockRead data_reads
[] = {
1707 MockRead("HTTP/1.0 200 OK\r\n"),
1708 MockRead("Connection: keep-alive\r\n"),
1709 MockRead("Content-Length: 100\r\n\r\n"),
1711 MockRead(SYNCHRONOUS
, 0),
1713 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1714 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1716 TestCompletionCallback callback
;
1718 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1719 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1721 rv
= callback
.WaitForResult();
1724 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1725 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1726 if (rv
== ERR_IO_PENDING
)
1727 rv
= callback
.WaitForResult();
1729 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1730 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1733 base::MessageLoop::current()->RunUntilIdle();
1734 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1737 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1738 HttpRequestInfo request
;
1739 request
.method
= "GET";
1740 request
.url
= GURL("http://www.example.org/");
1741 request
.load_flags
= 0;
1743 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1744 scoped_ptr
<HttpTransaction
> trans(
1745 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1747 MockRead data_reads
[] = {
1748 MockRead("HTTP/1.0 200 OK\r\n"),
1749 MockRead("Connection: keep-alive\r\n"),
1750 MockRead("Content-Length: 100\r\n\r\n"),
1751 MockRead(SYNCHRONOUS
, 0),
1753 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1754 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1756 TestCompletionCallback callback
;
1758 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1761 rv
= callback
.WaitForResult();
1764 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1765 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1766 if (rv
== ERR_IO_PENDING
)
1767 rv
= callback
.WaitForResult();
1768 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1771 base::MessageLoop::current()->RunUntilIdle();
1772 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1775 // Test that we correctly reuse a keep-alive connection after not explicitly
1776 // reading the body.
1777 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1778 HttpRequestInfo request
;
1779 request
.method
= "GET";
1780 request
.url
= GURL("http://www.foo.com/");
1781 request
.load_flags
= 0;
1784 session_deps_
.net_log
= &net_log
;
1785 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1787 // Note that because all these reads happen in the same
1788 // StaticSocketDataProvider, it shows that the same socket is being reused for
1789 // all transactions.
1790 MockRead data1_reads
[] = {
1791 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1792 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1793 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1794 MockRead("HTTP/1.1 302 Found\r\n"
1795 "Content-Length: 0\r\n\r\n"),
1796 MockRead("HTTP/1.1 302 Found\r\n"
1797 "Content-Length: 5\r\n\r\n"
1799 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1800 "Content-Length: 0\r\n\r\n"),
1801 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1802 "Content-Length: 5\r\n\r\n"
1804 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1807 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1808 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1810 MockRead data2_reads
[] = {
1811 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1813 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1814 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1816 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1817 std::string response_lines
[kNumUnreadBodies
];
1819 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1820 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1821 TestCompletionCallback callback
;
1823 scoped_ptr
<HttpTransaction
> trans(
1824 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1826 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1827 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1829 rv
= callback
.WaitForResult();
1832 LoadTimingInfo load_timing_info
;
1833 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1835 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1836 first_socket_log_id
= load_timing_info
.socket_log_id
;
1838 TestLoadTimingReused(load_timing_info
);
1839 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1842 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1843 ASSERT_TRUE(response
!= NULL
);
1845 ASSERT_TRUE(response
->headers
.get() != NULL
);
1846 response_lines
[i
] = response
->headers
->GetStatusLine();
1848 // We intentionally don't read the response bodies.
1851 const char* const kStatusLines
[] = {
1852 "HTTP/1.1 204 No Content",
1853 "HTTP/1.1 205 Reset Content",
1854 "HTTP/1.1 304 Not Modified",
1855 "HTTP/1.1 302 Found",
1856 "HTTP/1.1 302 Found",
1857 "HTTP/1.1 301 Moved Permanently",
1858 "HTTP/1.1 301 Moved Permanently",
1861 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1862 "forgot to update kStatusLines");
1864 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1865 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1867 TestCompletionCallback callback
;
1868 scoped_ptr
<HttpTransaction
> trans(
1869 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1870 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1871 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1872 rv
= callback
.WaitForResult();
1874 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1875 ASSERT_TRUE(response
!= NULL
);
1876 ASSERT_TRUE(response
->headers
.get() != NULL
);
1877 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1878 std::string response_data
;
1879 rv
= ReadTransaction(trans
.get(), &response_data
);
1881 EXPECT_EQ("hello", response_data
);
1884 // Test the request-challenge-retry sequence for basic auth.
1885 // (basic auth is the easiest to mock, because it has no randomness).
1886 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1887 HttpRequestInfo request
;
1888 request
.method
= "GET";
1889 request
.url
= GURL("http://www.example.org/");
1890 request
.load_flags
= 0;
1893 session_deps_
.net_log
= &log
;
1894 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1895 scoped_ptr
<HttpTransaction
> trans(
1896 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1898 MockWrite data_writes1
[] = {
1900 "GET / HTTP/1.1\r\n"
1901 "Host: www.example.org\r\n"
1902 "Connection: keep-alive\r\n\r\n"),
1905 MockRead data_reads1
[] = {
1906 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1907 // Give a couple authenticate options (only the middle one is actually
1909 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1910 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1911 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1912 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1913 // Large content-length -- won't matter, as connection will be reset.
1914 MockRead("Content-Length: 10000\r\n\r\n"),
1915 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1918 // After calling trans->RestartWithAuth(), this is the request we should
1919 // be issuing -- the final header line contains the credentials.
1920 MockWrite data_writes2
[] = {
1922 "GET / HTTP/1.1\r\n"
1923 "Host: www.example.org\r\n"
1924 "Connection: keep-alive\r\n"
1925 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1928 // Lastly, the server responds with the actual content.
1929 MockRead data_reads2
[] = {
1930 MockRead("HTTP/1.0 200 OK\r\n"),
1931 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1932 MockRead("Content-Length: 100\r\n\r\n"),
1933 MockRead(SYNCHRONOUS
, OK
),
1936 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1937 data_writes1
, arraysize(data_writes1
));
1938 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1939 data_writes2
, arraysize(data_writes2
));
1940 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1941 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1943 TestCompletionCallback callback1
;
1945 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1948 rv
= callback1
.WaitForResult();
1951 LoadTimingInfo load_timing_info1
;
1952 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1953 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1955 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1956 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1958 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1959 ASSERT_TRUE(response
!= NULL
);
1960 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1962 TestCompletionCallback callback2
;
1964 rv
= trans
->RestartWithAuth(
1965 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1966 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1968 rv
= callback2
.WaitForResult();
1971 LoadTimingInfo load_timing_info2
;
1972 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1973 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1974 // The load timing after restart should have a new socket ID, and times after
1975 // those of the first load timing.
1976 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1977 load_timing_info2
.connect_timing
.connect_start
);
1978 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1980 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1981 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1983 response
= trans
->GetResponseInfo();
1984 ASSERT_TRUE(response
!= NULL
);
1985 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1986 EXPECT_EQ(100, response
->headers
->GetContentLength());
1989 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1990 HttpRequestInfo request
;
1991 request
.method
= "GET";
1992 request
.url
= GURL("http://www.example.org/");
1993 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1995 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1996 scoped_ptr
<HttpTransaction
> trans(
1997 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1999 MockWrite data_writes
[] = {
2001 "GET / HTTP/1.1\r\n"
2002 "Host: www.example.org\r\n"
2003 "Connection: keep-alive\r\n\r\n"),
2006 MockRead data_reads
[] = {
2007 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2008 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2010 // Large content-length -- won't matter, as connection will be reset.
2011 MockRead("Content-Length: 10000\r\n\r\n"),
2012 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2015 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2016 data_writes
, arraysize(data_writes
));
2017 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2018 TestCompletionCallback callback
;
2020 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2021 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2023 rv
= callback
.WaitForResult();
2026 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2027 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2029 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2030 ASSERT_TRUE(response
!= NULL
);
2031 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2034 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2036 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2037 HttpRequestInfo request
;
2038 request
.method
= "GET";
2039 request
.url
= GURL("http://www.example.org/");
2040 request
.load_flags
= 0;
2043 session_deps_
.net_log
= &log
;
2044 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2046 MockWrite data_writes1
[] = {
2048 "GET / HTTP/1.1\r\n"
2049 "Host: www.example.org\r\n"
2050 "Connection: keep-alive\r\n\r\n"),
2052 // After calling trans->RestartWithAuth(), this is the request we should
2053 // be issuing -- the final header line contains the credentials.
2055 "GET / HTTP/1.1\r\n"
2056 "Host: www.example.org\r\n"
2057 "Connection: keep-alive\r\n"
2058 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2061 MockRead data_reads1
[] = {
2062 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2063 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2065 MockRead("Content-Length: 14\r\n\r\n"),
2066 MockRead("Unauthorized\r\n"),
2068 // Lastly, the server responds with the actual content.
2069 MockRead("HTTP/1.1 200 OK\r\n"),
2070 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2071 MockRead("Content-Length: 5\r\n\r\n"),
2075 // If there is a regression where we disconnect a Keep-Alive
2076 // connection during an auth roundtrip, we'll end up reading this.
2077 MockRead data_reads2
[] = {
2078 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2081 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2082 data_writes1
, arraysize(data_writes1
));
2083 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2085 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2086 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2088 TestCompletionCallback callback1
;
2090 scoped_ptr
<HttpTransaction
> trans(
2091 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2092 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2093 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2095 rv
= callback1
.WaitForResult();
2098 LoadTimingInfo load_timing_info1
;
2099 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2100 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2102 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2103 ASSERT_TRUE(response
!= NULL
);
2104 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2106 TestCompletionCallback callback2
;
2108 rv
= trans
->RestartWithAuth(
2109 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2110 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2112 rv
= callback2
.WaitForResult();
2115 LoadTimingInfo load_timing_info2
;
2116 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2117 TestLoadTimingReused(load_timing_info2
);
2118 // The load timing after restart should have the same socket ID, and times
2119 // those of the first load timing.
2120 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2121 load_timing_info2
.send_start
);
2122 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2124 response
= trans
->GetResponseInfo();
2125 ASSERT_TRUE(response
!= NULL
);
2126 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2127 EXPECT_EQ(5, response
->headers
->GetContentLength());
2129 std::string response_data
;
2130 rv
= ReadTransaction(trans
.get(), &response_data
);
2132 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2133 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2136 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2137 // connection and with no response body to drain.
2138 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2139 HttpRequestInfo request
;
2140 request
.method
= "GET";
2141 request
.url
= GURL("http://www.example.org/");
2142 request
.load_flags
= 0;
2144 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2146 MockWrite data_writes1
[] = {
2148 "GET / HTTP/1.1\r\n"
2149 "Host: www.example.org\r\n"
2150 "Connection: keep-alive\r\n\r\n"),
2152 // After calling trans->RestartWithAuth(), this is the request we should
2153 // be issuing -- the final header line contains the credentials.
2155 "GET / HTTP/1.1\r\n"
2156 "Host: www.example.org\r\n"
2157 "Connection: keep-alive\r\n"
2158 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2161 MockRead data_reads1
[] = {
2162 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2163 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2164 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2166 // Lastly, the server responds with the actual content.
2167 MockRead("HTTP/1.1 200 OK\r\n"),
2168 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2169 MockRead("Content-Length: 5\r\n\r\n"),
2173 // An incorrect reconnect would cause this to be read.
2174 MockRead data_reads2
[] = {
2175 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2178 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2179 data_writes1
, arraysize(data_writes1
));
2180 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2182 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2183 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2185 TestCompletionCallback callback1
;
2187 scoped_ptr
<HttpTransaction
> trans(
2188 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2189 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2190 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2192 rv
= callback1
.WaitForResult();
2195 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2196 ASSERT_TRUE(response
!= NULL
);
2197 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2199 TestCompletionCallback callback2
;
2201 rv
= trans
->RestartWithAuth(
2202 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2203 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2205 rv
= callback2
.WaitForResult();
2208 response
= trans
->GetResponseInfo();
2209 ASSERT_TRUE(response
!= NULL
);
2210 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2211 EXPECT_EQ(5, response
->headers
->GetContentLength());
2214 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2215 // connection and with a large response body to drain.
2216 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2217 HttpRequestInfo request
;
2218 request
.method
= "GET";
2219 request
.url
= GURL("http://www.example.org/");
2220 request
.load_flags
= 0;
2222 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2224 MockWrite data_writes1
[] = {
2226 "GET / HTTP/1.1\r\n"
2227 "Host: www.example.org\r\n"
2228 "Connection: keep-alive\r\n\r\n"),
2230 // After calling trans->RestartWithAuth(), this is the request we should
2231 // be issuing -- the final header line contains the credentials.
2233 "GET / HTTP/1.1\r\n"
2234 "Host: www.example.org\r\n"
2235 "Connection: keep-alive\r\n"
2236 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2239 // Respond with 5 kb of response body.
2240 std::string
large_body_string("Unauthorized");
2241 large_body_string
.append(5 * 1024, ' ');
2242 large_body_string
.append("\r\n");
2244 MockRead data_reads1
[] = {
2245 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2246 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2247 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2248 // 5134 = 12 + 5 * 1024 + 2
2249 MockRead("Content-Length: 5134\r\n\r\n"),
2250 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2252 // Lastly, the server responds with the actual content.
2253 MockRead("HTTP/1.1 200 OK\r\n"),
2254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2255 MockRead("Content-Length: 5\r\n\r\n"),
2259 // An incorrect reconnect would cause this to be read.
2260 MockRead data_reads2
[] = {
2261 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2264 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2265 data_writes1
, arraysize(data_writes1
));
2266 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2268 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2269 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2271 TestCompletionCallback callback1
;
2273 scoped_ptr
<HttpTransaction
> trans(
2274 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2275 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2276 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2278 rv
= callback1
.WaitForResult();
2281 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2282 ASSERT_TRUE(response
!= NULL
);
2283 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2285 TestCompletionCallback callback2
;
2287 rv
= trans
->RestartWithAuth(
2288 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2289 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2291 rv
= callback2
.WaitForResult();
2294 response
= trans
->GetResponseInfo();
2295 ASSERT_TRUE(response
!= NULL
);
2296 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2297 EXPECT_EQ(5, response
->headers
->GetContentLength());
2300 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2301 // connection, but the server gets impatient and closes the connection.
2302 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2303 HttpRequestInfo request
;
2304 request
.method
= "GET";
2305 request
.url
= GURL("http://www.example.org/");
2306 request
.load_flags
= 0;
2308 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2310 MockWrite data_writes1
[] = {
2312 "GET / HTTP/1.1\r\n"
2313 "Host: www.example.org\r\n"
2314 "Connection: keep-alive\r\n\r\n"),
2315 // This simulates the seemingly successful write to a closed connection
2316 // if the bug is not fixed.
2318 "GET / HTTP/1.1\r\n"
2319 "Host: www.example.org\r\n"
2320 "Connection: keep-alive\r\n"
2321 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2324 MockRead data_reads1
[] = {
2325 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2326 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2327 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2328 MockRead("Content-Length: 14\r\n\r\n"),
2329 // Tell MockTCPClientSocket to simulate the server closing the connection.
2330 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2331 MockRead("Unauthorized\r\n"),
2332 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2335 // After calling trans->RestartWithAuth(), this is the request we should
2336 // be issuing -- the final header line contains the credentials.
2337 MockWrite data_writes2
[] = {
2339 "GET / HTTP/1.1\r\n"
2340 "Host: www.example.org\r\n"
2341 "Connection: keep-alive\r\n"
2342 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2345 // Lastly, the server responds with the actual content.
2346 MockRead data_reads2
[] = {
2347 MockRead("HTTP/1.1 200 OK\r\n"),
2348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2349 MockRead("Content-Length: 5\r\n\r\n"),
2353 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2354 data_writes1
, arraysize(data_writes1
));
2355 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2356 data_writes2
, arraysize(data_writes2
));
2357 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2358 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2360 TestCompletionCallback callback1
;
2362 scoped_ptr
<HttpTransaction
> trans(
2363 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2364 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2365 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2367 rv
= callback1
.WaitForResult();
2370 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2371 ASSERT_TRUE(response
!= NULL
);
2372 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2374 TestCompletionCallback callback2
;
2376 rv
= trans
->RestartWithAuth(
2377 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2378 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2380 rv
= callback2
.WaitForResult();
2383 response
= trans
->GetResponseInfo();
2384 ASSERT_TRUE(response
!= NULL
);
2385 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2386 EXPECT_EQ(5, response
->headers
->GetContentLength());
2389 // Test the request-challenge-retry sequence for basic auth, over a connection
2390 // that requires a restart when setting up an SSL tunnel.
2391 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2392 HttpRequestInfo request
;
2393 request
.method
= "GET";
2394 request
.url
= GURL("https://www.example.org/");
2395 // when the no authentication data flag is set.
2396 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2398 // Configure against proxy server "myproxy:70".
2399 session_deps_
.proxy_service
.reset(
2400 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2401 BoundTestNetLog log
;
2402 session_deps_
.net_log
= log
.bound().net_log();
2403 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2405 // Since we have proxy, should try to establish tunnel.
2406 MockWrite data_writes1
[] = {
2408 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2409 "Host: www.example.org\r\n"
2410 "Proxy-Connection: keep-alive\r\n\r\n"),
2412 // After calling trans->RestartWithAuth(), this is the request we should
2413 // be issuing -- the final header line contains the credentials.
2415 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2416 "Host: www.example.org\r\n"
2417 "Proxy-Connection: keep-alive\r\n"
2418 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2421 "GET / HTTP/1.1\r\n"
2422 "Host: www.example.org\r\n"
2423 "Connection: keep-alive\r\n\r\n"),
2426 // The proxy responds to the connect with a 407, using a persistent
2428 MockRead data_reads1
[] = {
2430 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2431 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2433 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2435 MockRead("HTTP/1.1 200 OK\r\n"),
2436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2437 MockRead("Content-Length: 5\r\n\r\n"),
2438 MockRead(SYNCHRONOUS
, "hello"),
2441 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2442 data_writes1
, arraysize(data_writes1
));
2443 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2444 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2445 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2447 TestCompletionCallback callback1
;
2449 scoped_ptr
<HttpTransaction
> trans(
2450 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2452 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2453 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2455 rv
= callback1
.WaitForResult();
2457 TestNetLogEntry::List entries
;
2458 log
.GetEntries(&entries
);
2459 size_t pos
= ExpectLogContainsSomewhere(
2460 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2461 NetLog::PHASE_NONE
);
2462 ExpectLogContainsSomewhere(
2463 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2464 NetLog::PHASE_NONE
);
2466 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2467 ASSERT_TRUE(response
!= NULL
);
2468 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2469 ASSERT_FALSE(response
->headers
.get() == NULL
);
2470 EXPECT_EQ(407, response
->headers
->response_code());
2471 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2472 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2474 LoadTimingInfo load_timing_info
;
2475 // CONNECT requests and responses are handled at the connect job level, so
2476 // the transaction does not yet have a connection.
2477 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2479 TestCompletionCallback callback2
;
2482 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2483 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2485 rv
= callback2
.WaitForResult();
2488 response
= trans
->GetResponseInfo();
2489 ASSERT_TRUE(response
!= NULL
);
2491 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2492 EXPECT_EQ(200, response
->headers
->response_code());
2493 EXPECT_EQ(5, response
->headers
->GetContentLength());
2494 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2496 // The password prompt info should not be set.
2497 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2499 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2500 TestLoadTimingNotReusedWithPac(load_timing_info
,
2501 CONNECT_TIMING_HAS_SSL_TIMES
);
2504 session
->CloseAllConnections();
2507 // Test the request-challenge-retry sequence for basic auth, over a connection
2508 // that requires a restart when setting up an SSL tunnel.
2509 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2510 HttpRequestInfo request
;
2511 request
.method
= "GET";
2512 request
.url
= GURL("https://www.example.org/");
2513 // when the no authentication data flag is set.
2514 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2516 // Configure against proxy server "myproxy:70".
2517 session_deps_
.proxy_service
.reset(
2518 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2519 BoundTestNetLog log
;
2520 session_deps_
.net_log
= log
.bound().net_log();
2521 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2523 // Since we have proxy, should try to establish tunnel.
2524 MockWrite data_writes1
[] = {
2526 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2527 "Host: www.example.org\r\n"
2528 "Proxy-Connection: keep-alive\r\n\r\n"),
2530 // After calling trans->RestartWithAuth(), this is the request we should
2531 // be issuing -- the final header line contains the credentials.
2533 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2534 "Host: www.example.org\r\n"
2535 "Proxy-Connection: keep-alive\r\n"
2536 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2539 "GET / HTTP/1.1\r\n"
2540 "Host: www.example.org\r\n"
2541 "Connection: keep-alive\r\n\r\n"),
2544 // The proxy responds to the connect with a 407, using a persistent
2546 MockRead data_reads1
[] = {
2548 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2549 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2550 MockRead("Proxy-Connection: close\r\n\r\n"),
2552 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2554 MockRead("HTTP/1.1 200 OK\r\n"),
2555 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2556 MockRead("Content-Length: 5\r\n\r\n"),
2557 MockRead(SYNCHRONOUS
, "hello"),
2560 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2561 data_writes1
, arraysize(data_writes1
));
2562 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2563 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2564 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2566 TestCompletionCallback callback1
;
2568 scoped_ptr
<HttpTransaction
> trans(
2569 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2571 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2572 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2574 rv
= callback1
.WaitForResult();
2576 TestNetLogEntry::List entries
;
2577 log
.GetEntries(&entries
);
2578 size_t pos
= ExpectLogContainsSomewhere(
2579 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2580 NetLog::PHASE_NONE
);
2581 ExpectLogContainsSomewhere(
2583 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2584 NetLog::PHASE_NONE
);
2586 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2587 ASSERT_TRUE(response
!= NULL
);
2588 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2589 ASSERT_FALSE(response
->headers
.get() == NULL
);
2590 EXPECT_EQ(407, response
->headers
->response_code());
2591 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2592 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2594 LoadTimingInfo load_timing_info
;
2595 // CONNECT requests and responses are handled at the connect job level, so
2596 // the transaction does not yet have a connection.
2597 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2599 TestCompletionCallback callback2
;
2601 rv
= trans
->RestartWithAuth(
2602 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2603 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2605 rv
= callback2
.WaitForResult();
2608 response
= trans
->GetResponseInfo();
2609 ASSERT_TRUE(response
!= NULL
);
2611 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2612 EXPECT_EQ(200, response
->headers
->response_code());
2613 EXPECT_EQ(5, response
->headers
->GetContentLength());
2614 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2616 // The password prompt info should not be set.
2617 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2619 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2620 TestLoadTimingNotReusedWithPac(load_timing_info
,
2621 CONNECT_TIMING_HAS_SSL_TIMES
);
2624 session
->CloseAllConnections();
2627 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2628 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2629 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2630 HttpRequestInfo request
;
2631 request
.method
= "GET";
2632 request
.url
= GURL("https://www.example.org/");
2633 // Ensure that proxy authentication is attempted even
2634 // when the no authentication data flag is set.
2635 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2637 // Configure against proxy server "myproxy:70".
2638 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2639 BoundTestNetLog log
;
2640 session_deps_
.net_log
= log
.bound().net_log();
2641 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2643 scoped_ptr
<HttpTransaction
> trans(
2644 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2646 // Since we have proxy, should try to establish tunnel.
2647 MockWrite data_writes1
[] = {
2649 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2650 "Host: www.example.org\r\n"
2651 "Proxy-Connection: keep-alive\r\n\r\n"),
2653 // After calling trans->RestartWithAuth(), this is the request we should
2654 // be issuing -- the final header line contains the credentials.
2656 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2657 "Host: www.example.org\r\n"
2658 "Proxy-Connection: keep-alive\r\n"
2659 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2662 // The proxy responds to the connect with a 407, using a persistent
2663 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2664 MockRead data_reads1
[] = {
2666 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2667 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2668 MockRead("Proxy-Connection: keep-alive\r\n"),
2669 MockRead("Content-Length: 10\r\n\r\n"),
2670 MockRead("0123456789"),
2672 // Wrong credentials (wrong password).
2673 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2674 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2675 MockRead("Proxy-Connection: keep-alive\r\n"),
2676 MockRead("Content-Length: 10\r\n\r\n"),
2677 // No response body because the test stops reading here.
2678 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2681 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2682 data_writes1
, arraysize(data_writes1
));
2683 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2685 TestCompletionCallback callback1
;
2687 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2688 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2690 rv
= callback1
.WaitForResult();
2692 TestNetLogEntry::List entries
;
2693 log
.GetEntries(&entries
);
2694 size_t pos
= ExpectLogContainsSomewhere(
2695 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2696 NetLog::PHASE_NONE
);
2697 ExpectLogContainsSomewhere(
2698 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2699 NetLog::PHASE_NONE
);
2701 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2702 ASSERT_TRUE(response
);
2703 ASSERT_TRUE(response
->headers
);
2704 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2705 EXPECT_EQ(407, response
->headers
->response_code());
2706 EXPECT_EQ(10, response
->headers
->GetContentLength());
2707 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2708 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2710 TestCompletionCallback callback2
;
2712 // Wrong password (should be "bar").
2714 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2715 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2717 rv
= callback2
.WaitForResult();
2720 response
= trans
->GetResponseInfo();
2721 ASSERT_TRUE(response
);
2722 ASSERT_TRUE(response
->headers
);
2723 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2724 EXPECT_EQ(407, response
->headers
->response_code());
2725 EXPECT_EQ(10, response
->headers
->GetContentLength());
2726 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2727 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2729 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2731 session
->CloseAllConnections();
2734 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2735 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2736 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2737 HttpRequestInfo request
;
2738 request
.method
= "GET";
2739 request
.url
= GURL("https://www.example.org/");
2740 // Ensure that proxy authentication is attempted even
2741 // when the no authentication data flag is set.
2742 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2744 // Configure against proxy server "myproxy:70".
2745 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2746 BoundTestNetLog log
;
2747 session_deps_
.net_log
= log
.bound().net_log();
2748 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2750 scoped_ptr
<HttpTransaction
> trans(
2751 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2753 // Since we have proxy, should try to establish tunnel.
2754 MockWrite data_writes1
[] = {
2756 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2757 "Host: www.example.org\r\n"
2758 "Proxy-Connection: keep-alive\r\n\r\n"),
2760 // After calling trans->RestartWithAuth(), this is the request we should
2761 // be issuing -- the final header line contains the credentials.
2763 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2764 "Host: www.example.org\r\n"
2765 "Proxy-Connection: keep-alive\r\n"
2766 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2769 // The proxy responds to the connect with a 407, using a persistent
2771 MockRead data_reads1
[] = {
2773 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2774 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2775 MockRead("Content-Length: 10\r\n\r\n"),
2776 MockRead("0123456789"),
2778 // Wrong credentials (wrong password).
2779 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2780 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2781 MockRead("Content-Length: 10\r\n\r\n"),
2782 // No response body because the test stops reading here.
2783 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2786 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2787 data_writes1
, arraysize(data_writes1
));
2788 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2790 TestCompletionCallback callback1
;
2792 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2793 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2795 rv
= callback1
.WaitForResult();
2797 TestNetLogEntry::List entries
;
2798 log
.GetEntries(&entries
);
2799 size_t pos
= ExpectLogContainsSomewhere(
2800 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2801 NetLog::PHASE_NONE
);
2802 ExpectLogContainsSomewhere(
2804 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2805 NetLog::PHASE_NONE
);
2807 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2808 ASSERT_TRUE(response
);
2809 ASSERT_TRUE(response
->headers
);
2810 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2811 EXPECT_EQ(407, response
->headers
->response_code());
2812 EXPECT_EQ(10, response
->headers
->GetContentLength());
2813 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2814 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2816 TestCompletionCallback callback2
;
2818 // Wrong password (should be "bar").
2819 rv
= trans
->RestartWithAuth(
2820 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2823 rv
= callback2
.WaitForResult();
2826 response
= trans
->GetResponseInfo();
2827 ASSERT_TRUE(response
);
2828 ASSERT_TRUE(response
->headers
);
2829 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2830 EXPECT_EQ(407, response
->headers
->response_code());
2831 EXPECT_EQ(10, response
->headers
->GetContentLength());
2832 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2833 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2835 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2837 session
->CloseAllConnections();
2840 // Test that we don't read the response body when we fail to establish a tunnel,
2841 // even if the user cancels the proxy's auth attempt.
2842 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2843 HttpRequestInfo request
;
2844 request
.method
= "GET";
2845 request
.url
= GURL("https://www.example.org/");
2846 request
.load_flags
= 0;
2848 // Configure against proxy server "myproxy:70".
2849 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2851 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2853 scoped_ptr
<HttpTransaction
> trans(
2854 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2856 // Since we have proxy, should try to establish tunnel.
2857 MockWrite data_writes
[] = {
2859 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2860 "Host: www.example.org\r\n"
2861 "Proxy-Connection: keep-alive\r\n\r\n"),
2864 // The proxy responds to the connect with a 407.
2865 MockRead data_reads
[] = {
2866 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2867 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2868 MockRead("Content-Length: 10\r\n\r\n"),
2869 MockRead("0123456789"), // Should not be reached.
2870 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2873 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2874 data_writes
, arraysize(data_writes
));
2875 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2877 TestCompletionCallback callback
;
2879 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2880 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2882 rv
= callback
.WaitForResult();
2885 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2886 ASSERT_TRUE(response
);
2887 ASSERT_TRUE(response
->headers
);
2888 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2889 EXPECT_EQ(407, response
->headers
->response_code());
2890 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2892 std::string response_data
;
2893 rv
= ReadTransaction(trans
.get(), &response_data
);
2894 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2896 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2897 session
->CloseAllConnections();
2900 // Test that we don't pass extraneous headers from the proxy's response to the
2901 // caller when the proxy responds to CONNECT with 407.
2902 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2903 HttpRequestInfo request
;
2904 request
.method
= "GET";
2905 request
.url
= GURL("https://www.example.org/");
2906 request
.load_flags
= 0;
2908 // Configure against proxy server "myproxy:70".
2909 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2911 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2913 scoped_ptr
<HttpTransaction
> trans(
2914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2916 // Since we have proxy, should try to establish tunnel.
2917 MockWrite data_writes
[] = {
2919 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2920 "Host: www.example.org\r\n"
2921 "Proxy-Connection: keep-alive\r\n\r\n"),
2924 // The proxy responds to the connect with a 407.
2925 MockRead data_reads
[] = {
2926 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2927 MockRead("X-Foo: bar\r\n"),
2928 MockRead("Set-Cookie: foo=bar\r\n"),
2929 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2930 MockRead("Content-Length: 10\r\n\r\n"),
2931 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2934 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2935 arraysize(data_writes
));
2936 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2938 TestCompletionCallback callback
;
2940 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2941 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2943 rv
= callback
.WaitForResult();
2946 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2947 ASSERT_TRUE(response
);
2948 ASSERT_TRUE(response
->headers
);
2949 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2950 EXPECT_EQ(407, response
->headers
->response_code());
2951 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2952 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2953 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2955 std::string response_data
;
2956 rv
= ReadTransaction(trans
.get(), &response_data
);
2957 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2959 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2960 session
->CloseAllConnections();
2963 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2964 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2965 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2966 HttpRequestInfo request
;
2967 request
.method
= "GET";
2968 request
.url
= GURL("http://www.example.org/");
2969 request
.load_flags
= 0;
2971 // We are using a DIRECT connection (i.e. no proxy) for this session.
2972 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2973 scoped_ptr
<HttpTransaction
> trans(
2974 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2976 MockWrite data_writes1
[] = {
2978 "GET / HTTP/1.1\r\n"
2979 "Host: www.example.org\r\n"
2980 "Connection: keep-alive\r\n\r\n"),
2983 MockRead data_reads1
[] = {
2984 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2985 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2986 // Large content-length -- won't matter, as connection will be reset.
2987 MockRead("Content-Length: 10000\r\n\r\n"),
2988 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2991 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2992 data_writes1
, arraysize(data_writes1
));
2993 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2995 TestCompletionCallback callback
;
2997 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2998 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3000 rv
= callback
.WaitForResult();
3001 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3004 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3005 // through a non-authenticating proxy. The request should fail with
3006 // ERR_UNEXPECTED_PROXY_AUTH.
3007 // Note that it is impossible to detect if an HTTP server returns a 407 through
3008 // a non-authenticating proxy - there is nothing to indicate whether the
3009 // response came from the proxy or the server, so it is treated as if the proxy
3010 // issued the challenge.
3011 TEST_P(HttpNetworkTransactionTest
,
3012 HttpsServerRequestsProxyAuthThroughProxy
) {
3013 HttpRequestInfo request
;
3014 request
.method
= "GET";
3015 request
.url
= GURL("https://www.example.org/");
3017 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3018 BoundTestNetLog log
;
3019 session_deps_
.net_log
= log
.bound().net_log();
3020 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3022 // Since we have proxy, should try to establish tunnel.
3023 MockWrite data_writes1
[] = {
3025 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3026 "Host: www.example.org\r\n"
3027 "Proxy-Connection: keep-alive\r\n\r\n"),
3030 "GET / HTTP/1.1\r\n"
3031 "Host: www.example.org\r\n"
3032 "Connection: keep-alive\r\n\r\n"),
3035 MockRead data_reads1
[] = {
3036 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3038 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3039 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3041 MockRead(SYNCHRONOUS
, OK
),
3044 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3045 data_writes1
, arraysize(data_writes1
));
3046 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3047 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3048 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3050 TestCompletionCallback callback1
;
3052 scoped_ptr
<HttpTransaction
> trans(
3053 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3055 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3056 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3058 rv
= callback1
.WaitForResult();
3059 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3060 TestNetLogEntry::List entries
;
3061 log
.GetEntries(&entries
);
3062 size_t pos
= ExpectLogContainsSomewhere(
3063 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3064 NetLog::PHASE_NONE
);
3065 ExpectLogContainsSomewhere(
3067 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3068 NetLog::PHASE_NONE
);
3071 // Test the load timing for HTTPS requests with an HTTP proxy.
3072 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3073 HttpRequestInfo request1
;
3074 request1
.method
= "GET";
3075 request1
.url
= GURL("https://www.example.org/1");
3077 HttpRequestInfo request2
;
3078 request2
.method
= "GET";
3079 request2
.url
= GURL("https://www.example.org/2");
3081 // Configure against proxy server "myproxy:70".
3082 session_deps_
.proxy_service
.reset(
3083 ProxyService::CreateFixed("PROXY myproxy:70"));
3084 BoundTestNetLog log
;
3085 session_deps_
.net_log
= log
.bound().net_log();
3086 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3088 // Since we have proxy, should try to establish tunnel.
3089 MockWrite data_writes1
[] = {
3091 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3092 "Host: www.example.org\r\n"
3093 "Proxy-Connection: keep-alive\r\n\r\n"),
3096 "GET /1 HTTP/1.1\r\n"
3097 "Host: www.example.org\r\n"
3098 "Connection: keep-alive\r\n\r\n"),
3101 "GET /2 HTTP/1.1\r\n"
3102 "Host: www.example.org\r\n"
3103 "Connection: keep-alive\r\n\r\n"),
3106 // The proxy responds to the connect with a 407, using a persistent
3108 MockRead data_reads1
[] = {
3109 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3111 MockRead("HTTP/1.1 200 OK\r\n"),
3112 MockRead("Content-Length: 1\r\n\r\n"),
3113 MockRead(SYNCHRONOUS
, "1"),
3115 MockRead("HTTP/1.1 200 OK\r\n"),
3116 MockRead("Content-Length: 2\r\n\r\n"),
3117 MockRead(SYNCHRONOUS
, "22"),
3120 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3121 data_writes1
, arraysize(data_writes1
));
3122 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3123 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3124 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3126 TestCompletionCallback callback1
;
3127 scoped_ptr
<HttpTransaction
> trans1(
3128 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3130 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3131 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3133 rv
= callback1
.WaitForResult();
3136 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3137 ASSERT_TRUE(response1
!= NULL
);
3138 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3139 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3141 LoadTimingInfo load_timing_info1
;
3142 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3143 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3147 TestCompletionCallback callback2
;
3148 scoped_ptr
<HttpTransaction
> trans2(
3149 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3151 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3152 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3154 rv
= callback2
.WaitForResult();
3157 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3158 ASSERT_TRUE(response2
!= NULL
);
3159 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3160 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3162 LoadTimingInfo load_timing_info2
;
3163 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3164 TestLoadTimingReused(load_timing_info2
);
3166 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3169 session
->CloseAllConnections();
3172 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3173 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3174 HttpRequestInfo request1
;
3175 request1
.method
= "GET";
3176 request1
.url
= GURL("https://www.example.org/1");
3178 HttpRequestInfo request2
;
3179 request2
.method
= "GET";
3180 request2
.url
= GURL("https://www.example.org/2");
3182 // Configure against proxy server "myproxy:70".
3183 session_deps_
.proxy_service
.reset(
3184 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3185 BoundTestNetLog log
;
3186 session_deps_
.net_log
= log
.bound().net_log();
3187 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3189 // Since we have proxy, should try to establish tunnel.
3190 MockWrite data_writes1
[] = {
3192 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3193 "Host: www.example.org\r\n"
3194 "Proxy-Connection: keep-alive\r\n\r\n"),
3197 "GET /1 HTTP/1.1\r\n"
3198 "Host: www.example.org\r\n"
3199 "Connection: keep-alive\r\n\r\n"),
3202 "GET /2 HTTP/1.1\r\n"
3203 "Host: www.example.org\r\n"
3204 "Connection: keep-alive\r\n\r\n"),
3207 // The proxy responds to the connect with a 407, using a persistent
3209 MockRead data_reads1
[] = {
3210 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3212 MockRead("HTTP/1.1 200 OK\r\n"),
3213 MockRead("Content-Length: 1\r\n\r\n"),
3214 MockRead(SYNCHRONOUS
, "1"),
3216 MockRead("HTTP/1.1 200 OK\r\n"),
3217 MockRead("Content-Length: 2\r\n\r\n"),
3218 MockRead(SYNCHRONOUS
, "22"),
3221 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3222 data_writes1
, arraysize(data_writes1
));
3223 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3224 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3225 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3227 TestCompletionCallback callback1
;
3228 scoped_ptr
<HttpTransaction
> trans1(
3229 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3231 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3232 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3234 rv
= callback1
.WaitForResult();
3237 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3238 ASSERT_TRUE(response1
!= NULL
);
3239 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3240 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3242 LoadTimingInfo load_timing_info1
;
3243 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3244 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3245 CONNECT_TIMING_HAS_SSL_TIMES
);
3249 TestCompletionCallback callback2
;
3250 scoped_ptr
<HttpTransaction
> trans2(
3251 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3253 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3256 rv
= callback2
.WaitForResult();
3259 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3260 ASSERT_TRUE(response2
!= NULL
);
3261 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3262 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3264 LoadTimingInfo load_timing_info2
;
3265 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3266 TestLoadTimingReusedWithPac(load_timing_info2
);
3268 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3271 session
->CloseAllConnections();
3274 // Test a simple get through an HTTPS Proxy.
3275 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3276 HttpRequestInfo request
;
3277 request
.method
= "GET";
3278 request
.url
= GURL("http://www.example.org/");
3280 // Configure against https proxy server "proxy:70".
3281 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3282 "https://proxy:70"));
3283 BoundTestNetLog log
;
3284 session_deps_
.net_log
= log
.bound().net_log();
3285 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3287 // Since we have proxy, should use full url
3288 MockWrite data_writes1
[] = {
3290 "GET http://www.example.org/ HTTP/1.1\r\n"
3291 "Host: www.example.org\r\n"
3292 "Proxy-Connection: keep-alive\r\n\r\n"),
3295 MockRead data_reads1
[] = {
3296 MockRead("HTTP/1.1 200 OK\r\n"),
3297 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3298 MockRead("Content-Length: 100\r\n\r\n"),
3299 MockRead(SYNCHRONOUS
, OK
),
3302 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3303 data_writes1
, arraysize(data_writes1
));
3304 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3305 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3306 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3308 TestCompletionCallback callback1
;
3310 scoped_ptr
<HttpTransaction
> trans(
3311 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3313 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3314 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3316 rv
= callback1
.WaitForResult();
3319 LoadTimingInfo load_timing_info
;
3320 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3321 TestLoadTimingNotReused(load_timing_info
,
3322 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3324 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3325 ASSERT_TRUE(response
!= NULL
);
3327 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3328 EXPECT_EQ(200, response
->headers
->response_code());
3329 EXPECT_EQ(100, response
->headers
->GetContentLength());
3330 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3332 // The password prompt info should not be set.
3333 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3336 // Test a SPDY get through an HTTPS Proxy.
3337 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3338 HttpRequestInfo request
;
3339 request
.method
= "GET";
3340 request
.url
= GURL("http://www.example.org/");
3341 request
.load_flags
= 0;
3343 // Configure against https proxy server "proxy:70".
3344 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3345 "https://proxy:70"));
3346 BoundTestNetLog log
;
3347 session_deps_
.net_log
= log
.bound().net_log();
3348 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3350 // fetch http://www.example.org/ via SPDY
3351 scoped_ptr
<SpdyFrame
> req(
3352 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3353 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3355 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3356 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3357 MockRead spdy_reads
[] = {
3358 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3361 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3362 arraysize(spdy_writes
));
3363 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3365 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3366 ssl
.SetNextProto(GetParam());
3367 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3369 TestCompletionCallback callback1
;
3371 scoped_ptr
<HttpTransaction
> trans(
3372 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3374 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3375 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3377 rv
= callback1
.WaitForResult();
3380 LoadTimingInfo load_timing_info
;
3381 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3382 TestLoadTimingNotReused(load_timing_info
,
3383 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3385 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3386 ASSERT_TRUE(response
!= NULL
);
3387 ASSERT_TRUE(response
->headers
.get() != NULL
);
3388 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3390 std::string response_data
;
3391 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3392 EXPECT_EQ(kUploadData
, response_data
);
3395 // Verifies that a session which races and wins against the owning transaction
3396 // (completing prior to host resolution), doesn't fail the transaction.
3397 // Regression test for crbug.com/334413.
3398 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3399 HttpRequestInfo request
;
3400 request
.method
= "GET";
3401 request
.url
= GURL("http://www.example.org/");
3402 request
.load_flags
= 0;
3404 // Configure SPDY proxy server "proxy:70".
3405 session_deps_
.proxy_service
.reset(
3406 ProxyService::CreateFixed("https://proxy:70"));
3407 BoundTestNetLog log
;
3408 session_deps_
.net_log
= log
.bound().net_log();
3409 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3411 // Fetch http://www.example.org/ through the SPDY proxy.
3412 scoped_ptr
<SpdyFrame
> req(
3413 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3414 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3416 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3417 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3418 MockRead spdy_reads
[] = {
3419 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3422 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3423 arraysize(spdy_writes
));
3424 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3426 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3427 ssl
.SetNextProto(GetParam());
3428 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3430 TestCompletionCallback callback1
;
3432 scoped_ptr
<HttpTransaction
> trans(
3433 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3435 // Stall the hostname resolution begun by the transaction.
3436 session_deps_
.host_resolver
->set_synchronous_mode(false);
3437 session_deps_
.host_resolver
->set_ondemand_mode(true);
3439 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3442 // Race a session to the proxy, which completes first.
3443 session_deps_
.host_resolver
->set_ondemand_mode(false);
3445 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3446 base::WeakPtr
<SpdySession
> spdy_session
=
3447 CreateSecureSpdySession(session
, key
, log
.bound());
3449 // Unstall the resolution begun by the transaction.
3450 session_deps_
.host_resolver
->set_ondemand_mode(true);
3451 session_deps_
.host_resolver
->ResolveAllPending();
3453 EXPECT_FALSE(callback1
.have_result());
3454 rv
= callback1
.WaitForResult();
3457 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3458 ASSERT_TRUE(response
!= NULL
);
3459 ASSERT_TRUE(response
->headers
.get() != NULL
);
3460 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3462 std::string response_data
;
3463 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3464 EXPECT_EQ(kUploadData
, response_data
);
3467 // Test a SPDY get through an HTTPS Proxy.
3468 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3469 HttpRequestInfo request
;
3470 request
.method
= "GET";
3471 request
.url
= GURL("http://www.example.org/");
3472 request
.load_flags
= 0;
3474 // Configure against https proxy server "myproxy:70".
3475 session_deps_
.proxy_service
.reset(
3476 ProxyService::CreateFixed("https://myproxy:70"));
3477 BoundTestNetLog log
;
3478 session_deps_
.net_log
= log
.bound().net_log();
3479 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3481 // The first request will be a bare GET, the second request will be a
3482 // GET with a Proxy-Authorization header.
3483 scoped_ptr
<SpdyFrame
> req_get(
3484 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3485 const char* const kExtraAuthorizationHeaders
[] = {
3486 "proxy-authorization", "Basic Zm9vOmJhcg=="
3488 scoped_ptr
<SpdyFrame
> req_get_authorization(
3489 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3490 arraysize(kExtraAuthorizationHeaders
) / 2,
3495 MockWrite spdy_writes
[] = {
3496 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3499 // The first response is a 407 proxy authentication challenge, and the second
3500 // response will be a 200 response since the second request includes a valid
3501 // Authorization header.
3502 const char* const kExtraAuthenticationHeaders
[] = {
3503 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3505 scoped_ptr
<SpdyFrame
> resp_authentication(
3506 spdy_util_
.ConstructSpdySynReplyError(
3507 "407 Proxy Authentication Required",
3508 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3510 scoped_ptr
<SpdyFrame
> body_authentication(
3511 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3512 scoped_ptr
<SpdyFrame
> resp_data(
3513 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3514 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3515 MockRead spdy_reads
[] = {
3516 CreateMockRead(*resp_authentication
, 1),
3517 CreateMockRead(*body_authentication
, 2),
3518 CreateMockRead(*resp_data
, 4),
3519 CreateMockRead(*body_data
, 5),
3520 MockRead(ASYNC
, 0, 6),
3523 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3524 arraysize(spdy_writes
));
3525 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3527 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3528 ssl
.SetNextProto(GetParam());
3529 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3531 TestCompletionCallback callback1
;
3533 scoped_ptr
<HttpTransaction
> trans(
3534 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3536 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3537 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3539 rv
= callback1
.WaitForResult();
3542 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3544 ASSERT_TRUE(response
!= NULL
);
3545 ASSERT_TRUE(response
->headers
.get() != NULL
);
3546 EXPECT_EQ(407, response
->headers
->response_code());
3547 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3548 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3550 TestCompletionCallback callback2
;
3552 rv
= trans
->RestartWithAuth(
3553 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3554 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3556 rv
= callback2
.WaitForResult();
3559 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3561 ASSERT_TRUE(response_restart
!= NULL
);
3562 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3563 EXPECT_EQ(200, response_restart
->headers
->response_code());
3564 // The password prompt info should not be set.
3565 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3568 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3569 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3570 HttpRequestInfo request
;
3571 request
.method
= "GET";
3572 request
.url
= GURL("https://www.example.org/");
3573 request
.load_flags
= 0;
3575 // Configure against https proxy server "proxy:70".
3576 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3577 "https://proxy:70"));
3578 BoundTestNetLog log
;
3579 session_deps_
.net_log
= log
.bound().net_log();
3580 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3582 scoped_ptr
<HttpTransaction
> trans(
3583 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3585 // CONNECT to www.example.org:443 via SPDY
3586 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3587 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3588 // fetch https://www.example.org/ via HTTP
3591 "GET / HTTP/1.1\r\n"
3592 "Host: www.example.org\r\n"
3593 "Connection: keep-alive\r\n\r\n";
3594 scoped_ptr
<SpdyFrame
> wrapped_get(
3595 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3596 scoped_ptr
<SpdyFrame
> conn_resp(
3597 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3598 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3599 "Content-Length: 10\r\n\r\n";
3600 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3601 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3602 scoped_ptr
<SpdyFrame
> wrapped_body(
3603 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3604 scoped_ptr
<SpdyFrame
> window_update(
3605 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3607 MockWrite spdy_writes
[] = {
3608 CreateMockWrite(*connect
, 0),
3609 CreateMockWrite(*wrapped_get
, 2),
3610 CreateMockWrite(*window_update
, 6),
3613 MockRead spdy_reads
[] = {
3614 CreateMockRead(*conn_resp
, 1, ASYNC
),
3615 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3616 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3617 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3618 MockRead(ASYNC
, 0, 7),
3621 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3622 arraysize(spdy_writes
));
3623 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3625 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3626 ssl
.SetNextProto(GetParam());
3627 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3628 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3629 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3631 TestCompletionCallback callback1
;
3633 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3634 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3636 rv
= callback1
.WaitForResult();
3639 LoadTimingInfo load_timing_info
;
3640 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3641 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3643 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3644 ASSERT_TRUE(response
!= NULL
);
3645 ASSERT_TRUE(response
->headers
.get() != NULL
);
3646 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3648 std::string response_data
;
3649 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3650 EXPECT_EQ("1234567890", response_data
);
3653 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3654 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3655 HttpRequestInfo request
;
3656 request
.method
= "GET";
3657 request
.url
= GURL("https://www.example.org/");
3658 request
.load_flags
= 0;
3660 // Configure against https proxy server "proxy:70".
3661 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3662 "https://proxy:70"));
3663 BoundTestNetLog log
;
3664 session_deps_
.net_log
= log
.bound().net_log();
3665 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3667 scoped_ptr
<HttpTransaction
> trans(
3668 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3670 // CONNECT to www.example.org:443 via SPDY
3671 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3672 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3673 // fetch https://www.example.org/ via SPDY
3674 const char kMyUrl
[] = "https://www.example.org/";
3675 scoped_ptr
<SpdyFrame
> get(
3676 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3677 scoped_ptr
<SpdyFrame
> wrapped_get(
3678 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3679 scoped_ptr
<SpdyFrame
> conn_resp(
3680 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3681 scoped_ptr
<SpdyFrame
> get_resp(
3682 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3683 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3684 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3685 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3686 scoped_ptr
<SpdyFrame
> wrapped_body(
3687 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3688 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3689 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3690 scoped_ptr
<SpdyFrame
> window_update_body(
3691 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3693 MockWrite spdy_writes
[] = {
3694 CreateMockWrite(*connect
, 1),
3695 CreateMockWrite(*wrapped_get
, 3),
3696 CreateMockWrite(*window_update_get_resp
, 5),
3697 CreateMockWrite(*window_update_body
, 7),
3700 MockRead spdy_reads
[] = {
3701 CreateMockRead(*conn_resp
, 2, ASYNC
),
3702 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3703 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3704 MockRead(ASYNC
, 0, 8),
3707 OrderedSocketData
spdy_data(
3708 spdy_reads
, arraysize(spdy_reads
),
3709 spdy_writes
, arraysize(spdy_writes
));
3710 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3712 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3713 ssl
.SetNextProto(GetParam());
3714 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3715 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3716 ssl2
.SetNextProto(GetParam());
3717 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3719 TestCompletionCallback callback1
;
3721 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3722 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3724 rv
= callback1
.WaitForResult();
3727 LoadTimingInfo load_timing_info
;
3728 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3729 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3731 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3732 ASSERT_TRUE(response
!= NULL
);
3733 ASSERT_TRUE(response
->headers
.get() != NULL
);
3734 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3736 std::string response_data
;
3737 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3738 EXPECT_EQ(kUploadData
, response_data
);
3741 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3742 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3743 HttpRequestInfo request
;
3744 request
.method
= "GET";
3745 request
.url
= GURL("https://www.example.org/");
3746 request
.load_flags
= 0;
3748 // Configure against https proxy server "proxy:70".
3749 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3750 "https://proxy:70"));
3751 BoundTestNetLog log
;
3752 session_deps_
.net_log
= log
.bound().net_log();
3753 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3755 scoped_ptr
<HttpTransaction
> trans(
3756 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3758 // CONNECT to www.example.org:443 via SPDY
3759 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3760 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3761 scoped_ptr
<SpdyFrame
> get(
3762 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3764 MockWrite spdy_writes
[] = {
3765 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3768 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3769 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3770 MockRead spdy_reads
[] = {
3771 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3774 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3775 arraysize(spdy_writes
));
3776 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3778 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3779 ssl
.SetNextProto(GetParam());
3780 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3781 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3782 ssl2
.SetNextProto(GetParam());
3783 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3785 TestCompletionCallback callback1
;
3787 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3788 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3790 rv
= callback1
.WaitForResult();
3791 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3793 // TODO(ttuttle): Anything else to check here?
3796 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3797 // HTTPS Proxy to different servers.
3798 TEST_P(HttpNetworkTransactionTest
,
3799 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3800 // Configure against https proxy server "proxy:70".
3801 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3802 "https://proxy:70"));
3803 BoundTestNetLog log
;
3804 session_deps_
.net_log
= log
.bound().net_log();
3805 scoped_refptr
<HttpNetworkSession
> session(
3806 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3808 HttpRequestInfo request1
;
3809 request1
.method
= "GET";
3810 request1
.url
= GURL("https://www.example.org/");
3811 request1
.load_flags
= 0;
3813 HttpRequestInfo request2
;
3814 request2
.method
= "GET";
3815 request2
.url
= GURL("https://mail.example.org/");
3816 request2
.load_flags
= 0;
3818 // CONNECT to www.example.org:443 via SPDY.
3819 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3820 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3821 scoped_ptr
<SpdyFrame
> conn_resp1(
3822 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3824 // Fetch https://www.example.org/ via HTTP.
3826 "GET / HTTP/1.1\r\n"
3827 "Host: www.example.org\r\n"
3828 "Connection: keep-alive\r\n\r\n";
3829 scoped_ptr
<SpdyFrame
> wrapped_get1(
3830 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3831 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3832 "Content-Length: 1\r\n\r\n";
3833 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3834 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3835 scoped_ptr
<SpdyFrame
> wrapped_body1(
3836 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3837 scoped_ptr
<SpdyFrame
> window_update(
3838 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3840 // CONNECT to mail.example.org:443 via SPDY.
3841 SpdyHeaderBlock connect2_block
;
3842 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3843 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3844 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3845 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3846 scoped_ptr
<SpdyFrame
> connect2(
3847 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3849 scoped_ptr
<SpdyFrame
> conn_resp2(
3850 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3852 // Fetch https://mail.example.org/ via HTTP.
3854 "GET / HTTP/1.1\r\n"
3855 "Host: mail.example.org\r\n"
3856 "Connection: keep-alive\r\n\r\n";
3857 scoped_ptr
<SpdyFrame
> wrapped_get2(
3858 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3859 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3860 "Content-Length: 2\r\n\r\n";
3861 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3862 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3863 scoped_ptr
<SpdyFrame
> wrapped_body2(
3864 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3866 MockWrite spdy_writes
[] = {
3867 CreateMockWrite(*connect1
, 0),
3868 CreateMockWrite(*wrapped_get1
, 2),
3869 CreateMockWrite(*connect2
, 5),
3870 CreateMockWrite(*wrapped_get2
, 7),
3873 MockRead spdy_reads
[] = {
3874 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3875 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3876 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3877 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3878 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3879 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3880 MockRead(ASYNC
, 0, 10),
3883 DeterministicSocketData
spdy_data(
3884 spdy_reads
, arraysize(spdy_reads
),
3885 spdy_writes
, arraysize(spdy_writes
));
3886 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3888 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3889 ssl
.SetNextProto(GetParam());
3890 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3891 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3892 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3893 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3894 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3896 TestCompletionCallback callback
;
3898 scoped_ptr
<HttpTransaction
> trans(
3899 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3900 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3901 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3902 // The first connect and request, each of their responses, and the body.
3903 spdy_data
.RunFor(5);
3905 rv
= callback
.WaitForResult();
3908 LoadTimingInfo load_timing_info
;
3909 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3910 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3912 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3913 ASSERT_TRUE(response
!= NULL
);
3914 ASSERT_TRUE(response
->headers
.get() != NULL
);
3915 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3917 std::string response_data
;
3918 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3919 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3921 scoped_ptr
<HttpTransaction
> trans2(
3922 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3923 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3926 // The second connect and request, each of their responses, and the body.
3927 spdy_data
.RunFor(5);
3928 rv
= callback
.WaitForResult();
3931 LoadTimingInfo load_timing_info2
;
3932 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3933 // Even though the SPDY connection is reused, a new tunnelled connection has
3934 // to be created, so the socket's load timing looks like a fresh connection.
3935 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3937 // The requests should have different IDs, since they each are using their own
3939 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3941 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3944 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3945 // HTTPS Proxy to the same server.
3946 TEST_P(HttpNetworkTransactionTest
,
3947 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3948 // Configure against https proxy server "proxy:70".
3949 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3950 "https://proxy:70"));
3951 BoundTestNetLog log
;
3952 session_deps_
.net_log
= log
.bound().net_log();
3953 scoped_refptr
<HttpNetworkSession
> session(
3954 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3956 HttpRequestInfo request1
;
3957 request1
.method
= "GET";
3958 request1
.url
= GURL("https://www.example.org/");
3959 request1
.load_flags
= 0;
3961 HttpRequestInfo request2
;
3962 request2
.method
= "GET";
3963 request2
.url
= GURL("https://www.example.org/2");
3964 request2
.load_flags
= 0;
3966 // CONNECT to www.example.org:443 via SPDY.
3967 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3968 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3969 scoped_ptr
<SpdyFrame
> conn_resp1(
3970 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3972 // Fetch https://www.example.org/ via HTTP.
3974 "GET / HTTP/1.1\r\n"
3975 "Host: www.example.org\r\n"
3976 "Connection: keep-alive\r\n\r\n";
3977 scoped_ptr
<SpdyFrame
> wrapped_get1(
3978 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3979 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3980 "Content-Length: 1\r\n\r\n";
3981 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3982 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3983 scoped_ptr
<SpdyFrame
> wrapped_body1(
3984 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3985 scoped_ptr
<SpdyFrame
> window_update(
3986 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3988 // Fetch https://www.example.org/2 via HTTP.
3990 "GET /2 HTTP/1.1\r\n"
3991 "Host: www.example.org\r\n"
3992 "Connection: keep-alive\r\n\r\n";
3993 scoped_ptr
<SpdyFrame
> wrapped_get2(
3994 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3995 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3996 "Content-Length: 2\r\n\r\n";
3997 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3998 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
3999 scoped_ptr
<SpdyFrame
> wrapped_body2(
4000 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4002 MockWrite spdy_writes
[] = {
4003 CreateMockWrite(*connect1
, 0),
4004 CreateMockWrite(*wrapped_get1
, 2),
4005 CreateMockWrite(*wrapped_get2
, 5),
4008 MockRead spdy_reads
[] = {
4009 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4010 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4011 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4012 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4013 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4014 MockRead(ASYNC
, 0, 8),
4017 DeterministicSocketData
spdy_data(
4018 spdy_reads
, arraysize(spdy_reads
),
4019 spdy_writes
, arraysize(spdy_writes
));
4020 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4022 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4023 ssl
.SetNextProto(GetParam());
4024 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4025 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4026 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4028 TestCompletionCallback callback
;
4030 scoped_ptr
<HttpTransaction
> trans(
4031 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4032 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4033 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4034 // The first connect and request, each of their responses, and the body.
4035 spdy_data
.RunFor(5);
4037 rv
= callback
.WaitForResult();
4040 LoadTimingInfo load_timing_info
;
4041 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4042 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4044 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4045 ASSERT_TRUE(response
!= NULL
);
4046 ASSERT_TRUE(response
->headers
.get() != NULL
);
4047 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4049 std::string response_data
;
4050 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4051 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4054 scoped_ptr
<HttpTransaction
> trans2(
4055 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4056 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4057 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4059 // The second request, response, and body. There should not be a second
4061 spdy_data
.RunFor(3);
4062 rv
= callback
.WaitForResult();
4065 LoadTimingInfo load_timing_info2
;
4066 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4067 TestLoadTimingReused(load_timing_info2
);
4069 // The requests should have the same ID.
4070 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4072 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4075 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4076 // Proxy to different servers.
4077 TEST_P(HttpNetworkTransactionTest
,
4078 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4079 // Configure against https proxy server "proxy:70".
4080 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4081 "https://proxy:70"));
4082 BoundTestNetLog log
;
4083 session_deps_
.net_log
= log
.bound().net_log();
4084 scoped_refptr
<HttpNetworkSession
> session(
4085 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
4087 HttpRequestInfo request1
;
4088 request1
.method
= "GET";
4089 request1
.url
= GURL("http://www.example.org/");
4090 request1
.load_flags
= 0;
4092 HttpRequestInfo request2
;
4093 request2
.method
= "GET";
4094 request2
.url
= GURL("http://mail.example.org/");
4095 request2
.load_flags
= 0;
4097 // http://www.example.org/
4098 scoped_ptr
<SpdyHeaderBlock
> headers(
4099 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4100 scoped_ptr
<SpdyFrame
> get1(
4101 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4102 scoped_ptr
<SpdyFrame
> get_resp1(
4103 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4104 scoped_ptr
<SpdyFrame
> body1(
4105 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4107 // http://mail.example.org/
4108 scoped_ptr
<SpdyHeaderBlock
> headers2(
4109 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4110 scoped_ptr
<SpdyFrame
> get2(
4111 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4112 scoped_ptr
<SpdyFrame
> get_resp2(
4113 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4114 scoped_ptr
<SpdyFrame
> body2(
4115 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4117 MockWrite spdy_writes
[] = {
4118 CreateMockWrite(*get1
, 0),
4119 CreateMockWrite(*get2
, 3),
4122 MockRead spdy_reads
[] = {
4123 CreateMockRead(*get_resp1
, 1, ASYNC
),
4124 CreateMockRead(*body1
, 2, ASYNC
),
4125 CreateMockRead(*get_resp2
, 4, ASYNC
),
4126 CreateMockRead(*body2
, 5, ASYNC
),
4127 MockRead(ASYNC
, 0, 6),
4130 DeterministicSocketData
spdy_data(
4131 spdy_reads
, arraysize(spdy_reads
),
4132 spdy_writes
, arraysize(spdy_writes
));
4133 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4135 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4136 ssl
.SetNextProto(GetParam());
4137 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4139 TestCompletionCallback callback
;
4141 scoped_ptr
<HttpTransaction
> trans(
4142 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4143 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4144 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4145 spdy_data
.RunFor(2);
4147 rv
= callback
.WaitForResult();
4150 LoadTimingInfo load_timing_info
;
4151 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4152 TestLoadTimingNotReused(load_timing_info
,
4153 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4155 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4156 ASSERT_TRUE(response
!= NULL
);
4157 ASSERT_TRUE(response
->headers
.get() != NULL
);
4158 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4160 std::string response_data
;
4161 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4162 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
4163 spdy_data
.RunFor(1);
4164 EXPECT_EQ(1, callback
.WaitForResult());
4165 // Delete the first request, so the second one can reuse the socket.
4168 scoped_ptr
<HttpTransaction
> trans2(
4169 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4170 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4171 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4173 spdy_data
.RunFor(2);
4174 rv
= callback
.WaitForResult();
4177 LoadTimingInfo load_timing_info2
;
4178 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4179 TestLoadTimingReused(load_timing_info2
);
4181 // The requests should have the same ID.
4182 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4184 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
4185 spdy_data
.RunFor(1);
4186 EXPECT_EQ(2, callback
.WaitForResult());
4189 // Test the challenge-response-retry sequence through an HTTPS Proxy
4190 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4191 HttpRequestInfo request
;
4192 request
.method
= "GET";
4193 request
.url
= GURL("http://www.example.org/");
4194 // when the no authentication data flag is set.
4195 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4197 // Configure against https proxy server "myproxy:70".
4198 session_deps_
.proxy_service
.reset(
4199 ProxyService::CreateFixed("https://myproxy:70"));
4200 BoundTestNetLog log
;
4201 session_deps_
.net_log
= log
.bound().net_log();
4202 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4204 // Since we have proxy, should use full url
4205 MockWrite data_writes1
[] = {
4207 "GET http://www.example.org/ HTTP/1.1\r\n"
4208 "Host: www.example.org\r\n"
4209 "Proxy-Connection: keep-alive\r\n\r\n"),
4211 // After calling trans->RestartWithAuth(), this is the request we should
4212 // be issuing -- the final header line contains the credentials.
4214 "GET http://www.example.org/ HTTP/1.1\r\n"
4215 "Host: www.example.org\r\n"
4216 "Proxy-Connection: keep-alive\r\n"
4217 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4220 // The proxy responds to the GET with a 407, using a persistent
4222 MockRead data_reads1
[] = {
4224 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4225 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4226 MockRead("Proxy-Connection: keep-alive\r\n"),
4227 MockRead("Content-Length: 0\r\n\r\n"),
4229 MockRead("HTTP/1.1 200 OK\r\n"),
4230 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4231 MockRead("Content-Length: 100\r\n\r\n"),
4232 MockRead(SYNCHRONOUS
, OK
),
4235 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4236 data_writes1
, arraysize(data_writes1
));
4237 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4238 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4239 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4241 TestCompletionCallback callback1
;
4243 scoped_ptr
<HttpTransaction
> trans(
4244 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4246 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4247 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4249 rv
= callback1
.WaitForResult();
4252 LoadTimingInfo load_timing_info
;
4253 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4254 TestLoadTimingNotReused(load_timing_info
,
4255 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4257 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4258 ASSERT_TRUE(response
!= NULL
);
4259 ASSERT_FALSE(response
->headers
.get() == NULL
);
4260 EXPECT_EQ(407, response
->headers
->response_code());
4261 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4262 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4264 TestCompletionCallback callback2
;
4266 rv
= trans
->RestartWithAuth(
4267 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4268 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4270 rv
= callback2
.WaitForResult();
4273 load_timing_info
= LoadTimingInfo();
4274 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4275 // Retrying with HTTP AUTH is considered to be reusing a socket.
4276 TestLoadTimingReused(load_timing_info
);
4278 response
= trans
->GetResponseInfo();
4279 ASSERT_TRUE(response
!= NULL
);
4281 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4282 EXPECT_EQ(200, response
->headers
->response_code());
4283 EXPECT_EQ(100, response
->headers
->GetContentLength());
4284 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4286 // The password prompt info should not be set.
4287 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4290 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4291 const MockRead
& status
, int expected_status
) {
4292 HttpRequestInfo request
;
4293 request
.method
= "GET";
4294 request
.url
= GURL("https://www.example.org/");
4295 request
.load_flags
= 0;
4297 // Configure against proxy server "myproxy:70".
4298 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4299 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4301 // Since we have proxy, should try to establish tunnel.
4302 MockWrite data_writes
[] = {
4304 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4305 "Host: www.example.org\r\n"
4306 "Proxy-Connection: keep-alive\r\n\r\n"),
4309 MockRead data_reads
[] = {
4311 MockRead("Content-Length: 10\r\n\r\n"),
4312 // No response body because the test stops reading here.
4313 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4316 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4317 data_writes
, arraysize(data_writes
));
4318 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4320 TestCompletionCallback callback
;
4322 scoped_ptr
<HttpTransaction
> trans(
4323 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4325 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4326 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4328 rv
= callback
.WaitForResult();
4329 EXPECT_EQ(expected_status
, rv
);
4332 void HttpNetworkTransactionTest::ConnectStatusHelper(
4333 const MockRead
& status
) {
4334 ConnectStatusHelperWithExpectedStatus(
4335 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4338 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4339 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4342 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4343 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4346 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4347 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4350 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4351 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4354 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4355 ConnectStatusHelper(
4356 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4359 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4360 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4363 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4364 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4367 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4368 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4371 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4372 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4375 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4376 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4379 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4380 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4383 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4384 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4387 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4388 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4391 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4392 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4395 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4396 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4399 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4400 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4403 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4404 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4407 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4408 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4411 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4412 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4415 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4416 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4419 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4420 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4423 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4424 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4427 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4428 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4431 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4432 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4435 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4436 ConnectStatusHelperWithExpectedStatus(
4437 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4438 ERR_PROXY_AUTH_UNSUPPORTED
);
4441 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4442 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4445 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4446 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4449 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4450 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4453 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4454 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4457 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4458 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4461 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4462 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4465 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4466 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4469 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4470 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4473 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4474 ConnectStatusHelper(
4475 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4478 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4479 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4482 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4483 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4486 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4487 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4490 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4491 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4494 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4495 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4498 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4499 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4502 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4503 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4506 // Test the flow when both the proxy server AND origin server require
4507 // authentication. Again, this uses basic auth for both since that is
4508 // the simplest to mock.
4509 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4510 HttpRequestInfo request
;
4511 request
.method
= "GET";
4512 request
.url
= GURL("http://www.example.org/");
4513 request
.load_flags
= 0;
4515 // Configure against proxy server "myproxy:70".
4516 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4517 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4519 scoped_ptr
<HttpTransaction
> trans(
4520 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4522 MockWrite data_writes1
[] = {
4524 "GET http://www.example.org/ HTTP/1.1\r\n"
4525 "Host: www.example.org\r\n"
4526 "Proxy-Connection: keep-alive\r\n\r\n"),
4529 MockRead data_reads1
[] = {
4530 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4531 // Give a couple authenticate options (only the middle one is actually
4533 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4534 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4535 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4536 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4537 // Large content-length -- won't matter, as connection will be reset.
4538 MockRead("Content-Length: 10000\r\n\r\n"),
4539 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4542 // After calling trans->RestartWithAuth() the first time, this is the
4543 // request we should be issuing -- the final header line contains the
4544 // proxy's credentials.
4545 MockWrite data_writes2
[] = {
4547 "GET http://www.example.org/ HTTP/1.1\r\n"
4548 "Host: www.example.org\r\n"
4549 "Proxy-Connection: keep-alive\r\n"
4550 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4553 // Now the proxy server lets the request pass through to origin server.
4554 // The origin server responds with a 401.
4555 MockRead data_reads2
[] = {
4556 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4557 // Note: We are using the same realm-name as the proxy server. This is
4558 // completely valid, as realms are unique across hosts.
4559 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4560 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4561 MockRead("Content-Length: 2000\r\n\r\n"),
4562 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4565 // After calling trans->RestartWithAuth() the second time, we should send
4566 // the credentials for both the proxy and origin server.
4567 MockWrite data_writes3
[] = {
4569 "GET http://www.example.org/ HTTP/1.1\r\n"
4570 "Host: www.example.org\r\n"
4571 "Proxy-Connection: keep-alive\r\n"
4572 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4573 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4576 // Lastly we get the desired content.
4577 MockRead data_reads3
[] = {
4578 MockRead("HTTP/1.0 200 OK\r\n"),
4579 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4580 MockRead("Content-Length: 100\r\n\r\n"),
4581 MockRead(SYNCHRONOUS
, OK
),
4584 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4585 data_writes1
, arraysize(data_writes1
));
4586 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4587 data_writes2
, arraysize(data_writes2
));
4588 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4589 data_writes3
, arraysize(data_writes3
));
4590 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4591 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4592 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4594 TestCompletionCallback callback1
;
4596 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4597 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4599 rv
= callback1
.WaitForResult();
4602 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4603 ASSERT_TRUE(response
!= NULL
);
4604 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4606 TestCompletionCallback callback2
;
4608 rv
= trans
->RestartWithAuth(
4609 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4610 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4612 rv
= callback2
.WaitForResult();
4615 response
= trans
->GetResponseInfo();
4616 ASSERT_TRUE(response
!= NULL
);
4617 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4619 TestCompletionCallback callback3
;
4621 rv
= trans
->RestartWithAuth(
4622 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4623 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4625 rv
= callback3
.WaitForResult();
4628 response
= trans
->GetResponseInfo();
4629 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4630 EXPECT_EQ(100, response
->headers
->GetContentLength());
4633 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4634 // can't hook into its internals to cause it to generate predictable NTLM
4635 // authorization headers.
4636 #if defined(NTLM_PORTABLE)
4637 // The NTLM authentication unit tests were generated by capturing the HTTP
4638 // requests and responses using Fiddler 2 and inspecting the generated random
4639 // bytes in the debugger.
4641 // Enter the correct password and authenticate successfully.
4642 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4643 HttpRequestInfo request
;
4644 request
.method
= "GET";
4645 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4647 // Ensure load is not disrupted by flags which suppress behaviour specific
4648 // to other auth schemes.
4649 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4651 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4653 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4655 MockWrite data_writes1
[] = {
4656 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4657 "Host: 172.22.68.17\r\n"
4658 "Connection: keep-alive\r\n\r\n"),
4661 MockRead data_reads1
[] = {
4662 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4663 // Negotiate and NTLM are often requested together. However, we only want
4664 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4665 // the header that requests Negotiate for this test.
4666 MockRead("WWW-Authenticate: NTLM\r\n"),
4667 MockRead("Connection: close\r\n"),
4668 MockRead("Content-Length: 42\r\n"),
4669 MockRead("Content-Type: text/html\r\n\r\n"),
4670 // Missing content -- won't matter, as connection will be reset.
4671 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4674 MockWrite data_writes2
[] = {
4675 // After restarting with a null identity, this is the
4676 // request we should be issuing -- the final header line contains a Type
4678 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4679 "Host: 172.22.68.17\r\n"
4680 "Connection: keep-alive\r\n"
4681 "Authorization: NTLM "
4682 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4684 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4685 // (the credentials for the origin server). The second request continues
4686 // on the same connection.
4687 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4688 "Host: 172.22.68.17\r\n"
4689 "Connection: keep-alive\r\n"
4690 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4691 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4692 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4693 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4694 "ahlhx5I=\r\n\r\n"),
4697 MockRead data_reads2
[] = {
4698 // The origin server responds with a Type 2 message.
4699 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4700 MockRead("WWW-Authenticate: NTLM "
4701 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4702 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4703 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4704 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4705 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4706 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4708 MockRead("Content-Length: 42\r\n"),
4709 MockRead("Content-Type: text/html\r\n\r\n"),
4710 MockRead("You are not authorized to view this page\r\n"),
4712 // Lastly we get the desired content.
4713 MockRead("HTTP/1.1 200 OK\r\n"),
4714 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4715 MockRead("Content-Length: 13\r\n\r\n"),
4716 MockRead("Please Login\r\n"),
4717 MockRead(SYNCHRONOUS
, OK
),
4720 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4721 data_writes1
, arraysize(data_writes1
));
4722 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4723 data_writes2
, arraysize(data_writes2
));
4724 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4725 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4727 TestCompletionCallback callback1
;
4729 scoped_ptr
<HttpTransaction
> trans(
4730 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4732 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4733 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4735 rv
= callback1
.WaitForResult();
4738 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4740 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4741 ASSERT_FALSE(response
== NULL
);
4742 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4744 TestCompletionCallback callback2
;
4746 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4747 callback2
.callback());
4748 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4750 rv
= callback2
.WaitForResult();
4753 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4755 response
= trans
->GetResponseInfo();
4756 ASSERT_TRUE(response
!= NULL
);
4757 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4759 TestCompletionCallback callback3
;
4761 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4762 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4764 rv
= callback3
.WaitForResult();
4767 response
= trans
->GetResponseInfo();
4768 ASSERT_TRUE(response
!= NULL
);
4769 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4770 EXPECT_EQ(13, response
->headers
->GetContentLength());
4773 // Enter a wrong password, and then the correct one.
4774 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4775 HttpRequestInfo request
;
4776 request
.method
= "GET";
4777 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4778 request
.load_flags
= 0;
4780 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4782 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4784 MockWrite data_writes1
[] = {
4785 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4786 "Host: 172.22.68.17\r\n"
4787 "Connection: keep-alive\r\n\r\n"),
4790 MockRead data_reads1
[] = {
4791 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4792 // Negotiate and NTLM are often requested together. However, we only want
4793 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4794 // the header that requests Negotiate for this test.
4795 MockRead("WWW-Authenticate: NTLM\r\n"),
4796 MockRead("Connection: close\r\n"),
4797 MockRead("Content-Length: 42\r\n"),
4798 MockRead("Content-Type: text/html\r\n\r\n"),
4799 // Missing content -- won't matter, as connection will be reset.
4800 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4803 MockWrite data_writes2
[] = {
4804 // After restarting with a null identity, this is the
4805 // request we should be issuing -- the final header line contains a Type
4807 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4808 "Host: 172.22.68.17\r\n"
4809 "Connection: keep-alive\r\n"
4810 "Authorization: NTLM "
4811 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4813 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4814 // (the credentials for the origin server). The second request continues
4815 // on the same connection.
4816 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4817 "Host: 172.22.68.17\r\n"
4818 "Connection: keep-alive\r\n"
4819 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4820 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4821 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4822 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4823 "4Ww7b7E=\r\n\r\n"),
4826 MockRead data_reads2
[] = {
4827 // The origin server responds with a Type 2 message.
4828 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4829 MockRead("WWW-Authenticate: NTLM "
4830 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4831 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4832 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4833 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4834 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4835 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4837 MockRead("Content-Length: 42\r\n"),
4838 MockRead("Content-Type: text/html\r\n\r\n"),
4839 MockRead("You are not authorized to view this page\r\n"),
4842 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4843 MockRead("WWW-Authenticate: NTLM\r\n"),
4844 MockRead("Connection: close\r\n"),
4845 MockRead("Content-Length: 42\r\n"),
4846 MockRead("Content-Type: text/html\r\n\r\n"),
4847 // Missing content -- won't matter, as connection will be reset.
4848 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4851 MockWrite data_writes3
[] = {
4852 // After restarting with a null identity, this is the
4853 // request we should be issuing -- the final header line contains a Type
4855 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4856 "Host: 172.22.68.17\r\n"
4857 "Connection: keep-alive\r\n"
4858 "Authorization: NTLM "
4859 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4861 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4862 // (the credentials for the origin server). The second request continues
4863 // on the same connection.
4864 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4865 "Host: 172.22.68.17\r\n"
4866 "Connection: keep-alive\r\n"
4867 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4868 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4869 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4870 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4871 "+4MUm7c=\r\n\r\n"),
4874 MockRead data_reads3
[] = {
4875 // The origin server responds with a Type 2 message.
4876 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4877 MockRead("WWW-Authenticate: NTLM "
4878 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4879 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4880 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4881 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4882 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4883 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4885 MockRead("Content-Length: 42\r\n"),
4886 MockRead("Content-Type: text/html\r\n\r\n"),
4887 MockRead("You are not authorized to view this page\r\n"),
4889 // Lastly we get the desired content.
4890 MockRead("HTTP/1.1 200 OK\r\n"),
4891 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4892 MockRead("Content-Length: 13\r\n\r\n"),
4893 MockRead("Please Login\r\n"),
4894 MockRead(SYNCHRONOUS
, OK
),
4897 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4898 data_writes1
, arraysize(data_writes1
));
4899 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4900 data_writes2
, arraysize(data_writes2
));
4901 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4902 data_writes3
, arraysize(data_writes3
));
4903 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4904 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4905 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4907 TestCompletionCallback callback1
;
4909 scoped_ptr
<HttpTransaction
> trans(
4910 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4912 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4913 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4915 rv
= callback1
.WaitForResult();
4918 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4920 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4921 ASSERT_TRUE(response
!= NULL
);
4922 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4924 TestCompletionCallback callback2
;
4926 // Enter the wrong password.
4927 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4928 callback2
.callback());
4929 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4931 rv
= callback2
.WaitForResult();
4934 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4935 TestCompletionCallback callback3
;
4936 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4937 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4938 rv
= callback3
.WaitForResult();
4940 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4942 response
= trans
->GetResponseInfo();
4943 ASSERT_FALSE(response
== NULL
);
4944 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4946 TestCompletionCallback callback4
;
4948 // Now enter the right password.
4949 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4950 callback4
.callback());
4951 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4953 rv
= callback4
.WaitForResult();
4956 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4958 TestCompletionCallback callback5
;
4960 // One more roundtrip
4961 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4962 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4964 rv
= callback5
.WaitForResult();
4967 response
= trans
->GetResponseInfo();
4968 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4969 EXPECT_EQ(13, response
->headers
->GetContentLength());
4971 #endif // NTLM_PORTABLE
4973 // Test reading a server response which has only headers, and no body.
4974 // After some maximum number of bytes is consumed, the transaction should
4975 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4976 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4977 HttpRequestInfo request
;
4978 request
.method
= "GET";
4979 request
.url
= GURL("http://www.example.org/");
4980 request
.load_flags
= 0;
4982 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4983 scoped_ptr
<HttpTransaction
> trans(
4984 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4986 // Respond with 300 kb of headers (we should fail after 256 kb).
4987 std::string large_headers_string
;
4988 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4990 MockRead data_reads
[] = {
4991 MockRead("HTTP/1.0 200 OK\r\n"),
4992 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4993 MockRead("\r\nBODY"),
4994 MockRead(SYNCHRONOUS
, OK
),
4996 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4997 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4999 TestCompletionCallback callback
;
5001 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5004 rv
= callback
.WaitForResult();
5005 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5007 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5008 EXPECT_TRUE(response
== NULL
);
5011 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5012 // establish tunnel.
5013 // http://code.google.com/p/chromium/issues/detail?id=3772
5014 TEST_P(HttpNetworkTransactionTest
,
5015 DontRecycleTransportSocketForSSLTunnel
) {
5016 HttpRequestInfo request
;
5017 request
.method
= "GET";
5018 request
.url
= GURL("https://www.example.org/");
5019 request
.load_flags
= 0;
5021 // Configure against proxy server "myproxy:70".
5022 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5024 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5026 scoped_ptr
<HttpTransaction
> trans(
5027 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5029 // Since we have proxy, should try to establish tunnel.
5030 MockWrite data_writes1
[] = {
5032 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5033 "Host: www.example.org\r\n"
5034 "Proxy-Connection: keep-alive\r\n\r\n"),
5037 // The proxy responds to the connect with a 404, using a persistent
5038 // connection. Usually a proxy would return 501 (not implemented),
5039 // or 200 (tunnel established).
5040 MockRead data_reads1
[] = {
5041 MockRead("HTTP/1.1 404 Not Found\r\n"),
5042 MockRead("Content-Length: 10\r\n\r\n"),
5043 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5046 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5047 data_writes1
, arraysize(data_writes1
));
5048 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5050 TestCompletionCallback callback1
;
5052 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5053 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5055 rv
= callback1
.WaitForResult();
5056 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5058 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5059 EXPECT_TRUE(response
== NULL
);
5061 // Empty the current queue. This is necessary because idle sockets are
5062 // added to the connection pool asynchronously with a PostTask.
5063 base::MessageLoop::current()->RunUntilIdle();
5065 // We now check to make sure the TCPClientSocket was not added back to
5067 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5069 base::MessageLoop::current()->RunUntilIdle();
5070 // Make sure that the socket didn't get recycled after calling the destructor.
5071 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5074 // Make sure that we recycle a socket after reading all of the response body.
5075 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5076 HttpRequestInfo request
;
5077 request
.method
= "GET";
5078 request
.url
= GURL("http://www.example.org/");
5079 request
.load_flags
= 0;
5081 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5083 scoped_ptr
<HttpTransaction
> trans(
5084 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5086 MockRead data_reads
[] = {
5087 // A part of the response body is received with the response headers.
5088 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5089 // The rest of the response body is received in two parts.
5092 MockRead("junk"), // Should not be read!!
5093 MockRead(SYNCHRONOUS
, OK
),
5096 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5097 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5099 TestCompletionCallback callback
;
5101 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5102 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5104 rv
= callback
.WaitForResult();
5107 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5108 ASSERT_TRUE(response
!= NULL
);
5110 EXPECT_TRUE(response
->headers
.get() != NULL
);
5111 std::string status_line
= response
->headers
->GetStatusLine();
5112 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5114 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5116 std::string response_data
;
5117 rv
= ReadTransaction(trans
.get(), &response_data
);
5119 EXPECT_EQ("hello world", response_data
);
5121 // Empty the current queue. This is necessary because idle sockets are
5122 // added to the connection pool asynchronously with a PostTask.
5123 base::MessageLoop::current()->RunUntilIdle();
5125 // We now check to make sure the socket was added back to the pool.
5126 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5129 // Make sure that we recycle a SSL socket after reading all of the response
5131 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5132 HttpRequestInfo request
;
5133 request
.method
= "GET";
5134 request
.url
= GURL("https://www.example.org/");
5135 request
.load_flags
= 0;
5137 MockWrite data_writes
[] = {
5139 "GET / HTTP/1.1\r\n"
5140 "Host: www.example.org\r\n"
5141 "Connection: keep-alive\r\n\r\n"),
5144 MockRead data_reads
[] = {
5145 MockRead("HTTP/1.1 200 OK\r\n"),
5146 MockRead("Content-Length: 11\r\n\r\n"),
5147 MockRead("hello world"),
5148 MockRead(SYNCHRONOUS
, OK
),
5151 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5152 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5154 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5155 data_writes
, arraysize(data_writes
));
5156 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5158 TestCompletionCallback callback
;
5160 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5161 scoped_ptr
<HttpTransaction
> trans(
5162 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5164 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5167 EXPECT_EQ(OK
, callback
.WaitForResult());
5169 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5170 ASSERT_TRUE(response
!= NULL
);
5171 ASSERT_TRUE(response
->headers
.get() != NULL
);
5172 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5174 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5176 std::string response_data
;
5177 rv
= ReadTransaction(trans
.get(), &response_data
);
5179 EXPECT_EQ("hello world", response_data
);
5181 // Empty the current queue. This is necessary because idle sockets are
5182 // added to the connection pool asynchronously with a PostTask.
5183 base::MessageLoop::current()->RunUntilIdle();
5185 // We now check to make sure the socket was added back to the pool.
5186 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5189 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5190 // from the pool and make sure that we recover okay.
5191 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5192 HttpRequestInfo request
;
5193 request
.method
= "GET";
5194 request
.url
= GURL("https://www.example.org/");
5195 request
.load_flags
= 0;
5197 MockWrite data_writes
[] = {
5199 "GET / HTTP/1.1\r\n"
5200 "Host: www.example.org\r\n"
5201 "Connection: keep-alive\r\n\r\n"),
5203 "GET / HTTP/1.1\r\n"
5204 "Host: www.example.org\r\n"
5205 "Connection: keep-alive\r\n\r\n"),
5208 MockRead data_reads
[] = {
5209 MockRead("HTTP/1.1 200 OK\r\n"),
5210 MockRead("Content-Length: 11\r\n\r\n"),
5211 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5212 MockRead("hello world"),
5213 MockRead(ASYNC
, 0, 0) // EOF
5216 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5217 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5218 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5219 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5221 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5222 data_writes
, arraysize(data_writes
));
5223 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5224 data_writes
, arraysize(data_writes
));
5225 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5226 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5228 TestCompletionCallback callback
;
5230 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5231 scoped_ptr
<HttpTransaction
> trans(
5232 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5234 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5236 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5237 EXPECT_EQ(OK
, callback
.WaitForResult());
5239 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5240 ASSERT_TRUE(response
!= NULL
);
5241 ASSERT_TRUE(response
->headers
.get() != NULL
);
5242 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5244 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5246 std::string response_data
;
5247 rv
= ReadTransaction(trans
.get(), &response_data
);
5249 EXPECT_EQ("hello world", response_data
);
5251 // Empty the current queue. This is necessary because idle sockets are
5252 // added to the connection pool asynchronously with a PostTask.
5253 base::MessageLoop::current()->RunUntilIdle();
5255 // We now check to make sure the socket was added back to the pool.
5256 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5258 // Now start the second transaction, which should reuse the previous socket.
5260 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5262 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5264 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5265 EXPECT_EQ(OK
, callback
.WaitForResult());
5267 response
= trans
->GetResponseInfo();
5268 ASSERT_TRUE(response
!= NULL
);
5269 ASSERT_TRUE(response
->headers
.get() != NULL
);
5270 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5272 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5274 rv
= ReadTransaction(trans
.get(), &response_data
);
5276 EXPECT_EQ("hello world", response_data
);
5278 // Empty the current queue. This is necessary because idle sockets are
5279 // added to the connection pool asynchronously with a PostTask.
5280 base::MessageLoop::current()->RunUntilIdle();
5282 // We now check to make sure the socket was added back to the pool.
5283 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5286 // Make sure that we recycle a socket after a zero-length response.
5287 // http://crbug.com/9880
5288 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5289 HttpRequestInfo request
;
5290 request
.method
= "GET";
5292 "http://www.example.org/csi?v=3&s=web&action=&"
5293 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5294 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5295 "rt=prt.2642,ol.2649,xjs.2951");
5296 request
.load_flags
= 0;
5298 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5300 scoped_ptr
<HttpTransaction
> trans(
5301 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5303 MockRead data_reads
[] = {
5304 MockRead("HTTP/1.1 204 No Content\r\n"
5305 "Content-Length: 0\r\n"
5306 "Content-Type: text/html\r\n\r\n"),
5307 MockRead("junk"), // Should not be read!!
5308 MockRead(SYNCHRONOUS
, OK
),
5311 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5312 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5314 TestCompletionCallback callback
;
5316 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5317 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5319 rv
= callback
.WaitForResult();
5322 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5323 ASSERT_TRUE(response
!= NULL
);
5325 EXPECT_TRUE(response
->headers
.get() != NULL
);
5326 std::string status_line
= response
->headers
->GetStatusLine();
5327 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5329 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5331 std::string response_data
;
5332 rv
= ReadTransaction(trans
.get(), &response_data
);
5334 EXPECT_EQ("", response_data
);
5336 // Empty the current queue. This is necessary because idle sockets are
5337 // added to the connection pool asynchronously with a PostTask.
5338 base::MessageLoop::current()->RunUntilIdle();
5340 // We now check to make sure the socket was added back to the pool.
5341 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5344 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5345 ScopedVector
<UploadElementReader
> element_readers
;
5346 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5347 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5349 HttpRequestInfo request
[2];
5350 // Transaction 1: a GET request that succeeds. The socket is recycled
5352 request
[0].method
= "GET";
5353 request
[0].url
= GURL("http://www.google.com/");
5354 request
[0].load_flags
= 0;
5355 // Transaction 2: a POST request. Reuses the socket kept alive from
5356 // transaction 1. The first attempts fails when writing the POST data.
5357 // This causes the transaction to retry with a new socket. The second
5358 // attempt succeeds.
5359 request
[1].method
= "POST";
5360 request
[1].url
= GURL("http://www.google.com/login.cgi");
5361 request
[1].upload_data_stream
= &upload_data_stream
;
5362 request
[1].load_flags
= 0;
5364 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5366 // The first socket is used for transaction 1 and the first attempt of
5369 // The response of transaction 1.
5370 MockRead data_reads1
[] = {
5371 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5372 MockRead("hello world"),
5373 MockRead(SYNCHRONOUS
, OK
),
5375 // The mock write results of transaction 1 and the first attempt of
5377 MockWrite data_writes1
[] = {
5378 MockWrite(SYNCHRONOUS
, 64), // GET
5379 MockWrite(SYNCHRONOUS
, 93), // POST
5380 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5382 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5383 data_writes1
, arraysize(data_writes1
));
5385 // The second socket is used for the second attempt of transaction 2.
5387 // The response of transaction 2.
5388 MockRead data_reads2
[] = {
5389 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5390 MockRead("welcome"),
5391 MockRead(SYNCHRONOUS
, OK
),
5393 // The mock write results of the second attempt of transaction 2.
5394 MockWrite data_writes2
[] = {
5395 MockWrite(SYNCHRONOUS
, 93), // POST
5396 MockWrite(SYNCHRONOUS
, 3), // POST data
5398 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5399 data_writes2
, arraysize(data_writes2
));
5401 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5402 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5404 const char* const kExpectedResponseData
[] = {
5405 "hello world", "welcome"
5408 for (int i
= 0; i
< 2; ++i
) {
5409 scoped_ptr
<HttpTransaction
> trans(
5410 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5412 TestCompletionCallback callback
;
5414 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5415 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5417 rv
= callback
.WaitForResult();
5420 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5421 ASSERT_TRUE(response
!= NULL
);
5423 EXPECT_TRUE(response
->headers
.get() != NULL
);
5424 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5426 std::string response_data
;
5427 rv
= ReadTransaction(trans
.get(), &response_data
);
5429 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5433 // Test the request-challenge-retry sequence for basic auth when there is
5434 // an identity in the URL. The request should be sent as normal, but when
5435 // it fails the identity from the URL is used to answer the challenge.
5436 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5437 HttpRequestInfo request
;
5438 request
.method
= "GET";
5439 request
.url
= GURL("http://foo:b@r@www.example.org/");
5440 request
.load_flags
= LOAD_NORMAL
;
5442 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5443 scoped_ptr
<HttpTransaction
> trans(
5444 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5446 // The password contains an escaped character -- for this test to pass it
5447 // will need to be unescaped by HttpNetworkTransaction.
5448 EXPECT_EQ("b%40r", request
.url
.password());
5450 MockWrite data_writes1
[] = {
5452 "GET / HTTP/1.1\r\n"
5453 "Host: www.example.org\r\n"
5454 "Connection: keep-alive\r\n\r\n"),
5457 MockRead data_reads1
[] = {
5458 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5459 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5460 MockRead("Content-Length: 10\r\n\r\n"),
5461 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5464 // After the challenge above, the transaction will be restarted using the
5465 // identity from the url (foo, b@r) to answer the challenge.
5466 MockWrite data_writes2
[] = {
5468 "GET / HTTP/1.1\r\n"
5469 "Host: www.example.org\r\n"
5470 "Connection: keep-alive\r\n"
5471 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5474 MockRead data_reads2
[] = {
5475 MockRead("HTTP/1.0 200 OK\r\n"),
5476 MockRead("Content-Length: 100\r\n\r\n"),
5477 MockRead(SYNCHRONOUS
, OK
),
5480 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5481 data_writes1
, arraysize(data_writes1
));
5482 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5483 data_writes2
, arraysize(data_writes2
));
5484 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5485 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5487 TestCompletionCallback callback1
;
5488 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5489 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5490 rv
= callback1
.WaitForResult();
5492 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5494 TestCompletionCallback callback2
;
5495 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5496 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5497 rv
= callback2
.WaitForResult();
5499 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5501 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5502 ASSERT_TRUE(response
!= NULL
);
5504 // There is no challenge info, since the identity in URL worked.
5505 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5507 EXPECT_EQ(100, response
->headers
->GetContentLength());
5509 // Empty the current queue.
5510 base::MessageLoop::current()->RunUntilIdle();
5513 // Test the request-challenge-retry sequence for basic auth when there is an
5514 // incorrect identity in the URL. The identity from the URL should be used only
5516 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5517 HttpRequestInfo request
;
5518 request
.method
= "GET";
5519 // Note: the URL has a username:password in it. The password "baz" is
5520 // wrong (should be "bar").
5521 request
.url
= GURL("http://foo:baz@www.example.org/");
5523 request
.load_flags
= LOAD_NORMAL
;
5525 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5526 scoped_ptr
<HttpTransaction
> trans(
5527 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5529 MockWrite data_writes1
[] = {
5531 "GET / HTTP/1.1\r\n"
5532 "Host: www.example.org\r\n"
5533 "Connection: keep-alive\r\n\r\n"),
5536 MockRead data_reads1
[] = {
5537 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5538 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5539 MockRead("Content-Length: 10\r\n\r\n"),
5540 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5543 // After the challenge above, the transaction will be restarted using the
5544 // identity from the url (foo, baz) to answer the challenge.
5545 MockWrite data_writes2
[] = {
5547 "GET / HTTP/1.1\r\n"
5548 "Host: www.example.org\r\n"
5549 "Connection: keep-alive\r\n"
5550 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5553 MockRead data_reads2
[] = {
5554 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5555 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5556 MockRead("Content-Length: 10\r\n\r\n"),
5557 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5560 // After the challenge above, the transaction will be restarted using the
5561 // identity supplied by the user (foo, bar) to answer the challenge.
5562 MockWrite data_writes3
[] = {
5564 "GET / HTTP/1.1\r\n"
5565 "Host: www.example.org\r\n"
5566 "Connection: keep-alive\r\n"
5567 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5570 MockRead data_reads3
[] = {
5571 MockRead("HTTP/1.0 200 OK\r\n"),
5572 MockRead("Content-Length: 100\r\n\r\n"),
5573 MockRead(SYNCHRONOUS
, OK
),
5576 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5577 data_writes1
, arraysize(data_writes1
));
5578 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5579 data_writes2
, arraysize(data_writes2
));
5580 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5581 data_writes3
, arraysize(data_writes3
));
5582 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5583 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5584 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5586 TestCompletionCallback callback1
;
5588 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5591 rv
= callback1
.WaitForResult();
5594 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5595 TestCompletionCallback callback2
;
5596 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5597 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5598 rv
= callback2
.WaitForResult();
5600 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5602 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5603 ASSERT_TRUE(response
!= NULL
);
5604 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5606 TestCompletionCallback callback3
;
5607 rv
= trans
->RestartWithAuth(
5608 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5609 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5610 rv
= callback3
.WaitForResult();
5612 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5614 response
= trans
->GetResponseInfo();
5615 ASSERT_TRUE(response
!= NULL
);
5617 // There is no challenge info, since the identity worked.
5618 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5620 EXPECT_EQ(100, response
->headers
->GetContentLength());
5622 // Empty the current queue.
5623 base::MessageLoop::current()->RunUntilIdle();
5627 // Test the request-challenge-retry sequence for basic auth when there is a
5628 // correct identity in the URL, but its use is being suppressed. The identity
5629 // from the URL should never be used.
5630 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5631 HttpRequestInfo request
;
5632 request
.method
= "GET";
5633 request
.url
= GURL("http://foo:bar@www.example.org/");
5634 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5636 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5637 scoped_ptr
<HttpTransaction
> trans(
5638 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5640 MockWrite data_writes1
[] = {
5642 "GET / HTTP/1.1\r\n"
5643 "Host: www.example.org\r\n"
5644 "Connection: keep-alive\r\n\r\n"),
5647 MockRead data_reads1
[] = {
5648 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5649 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5650 MockRead("Content-Length: 10\r\n\r\n"),
5651 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5654 // After the challenge above, the transaction will be restarted using the
5655 // identity supplied by the user, not the one in the URL, to answer the
5657 MockWrite data_writes3
[] = {
5659 "GET / HTTP/1.1\r\n"
5660 "Host: www.example.org\r\n"
5661 "Connection: keep-alive\r\n"
5662 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5665 MockRead data_reads3
[] = {
5666 MockRead("HTTP/1.0 200 OK\r\n"),
5667 MockRead("Content-Length: 100\r\n\r\n"),
5668 MockRead(SYNCHRONOUS
, OK
),
5671 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5672 data_writes1
, arraysize(data_writes1
));
5673 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5674 data_writes3
, arraysize(data_writes3
));
5675 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5676 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5678 TestCompletionCallback callback1
;
5679 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5681 rv
= callback1
.WaitForResult();
5683 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5685 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5686 ASSERT_TRUE(response
!= NULL
);
5687 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5689 TestCompletionCallback callback3
;
5690 rv
= trans
->RestartWithAuth(
5691 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5692 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5693 rv
= callback3
.WaitForResult();
5695 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5697 response
= trans
->GetResponseInfo();
5698 ASSERT_TRUE(response
!= NULL
);
5700 // There is no challenge info, since the identity worked.
5701 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5702 EXPECT_EQ(100, response
->headers
->GetContentLength());
5704 // Empty the current queue.
5705 base::MessageLoop::current()->RunUntilIdle();
5708 // Test that previously tried username/passwords for a realm get re-used.
5709 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5710 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5712 // Transaction 1: authenticate (foo, bar) on MyRealm1
5714 HttpRequestInfo request
;
5715 request
.method
= "GET";
5716 request
.url
= GURL("http://www.example.org/x/y/z");
5717 request
.load_flags
= 0;
5719 scoped_ptr
<HttpTransaction
> trans(
5720 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5722 MockWrite data_writes1
[] = {
5724 "GET /x/y/z HTTP/1.1\r\n"
5725 "Host: www.example.org\r\n"
5726 "Connection: keep-alive\r\n\r\n"),
5729 MockRead data_reads1
[] = {
5730 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5731 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5732 MockRead("Content-Length: 10000\r\n\r\n"),
5733 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5736 // Resend with authorization (username=foo, password=bar)
5737 MockWrite data_writes2
[] = {
5739 "GET /x/y/z HTTP/1.1\r\n"
5740 "Host: www.example.org\r\n"
5741 "Connection: keep-alive\r\n"
5742 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5745 // Sever accepts the authorization.
5746 MockRead data_reads2
[] = {
5747 MockRead("HTTP/1.0 200 OK\r\n"),
5748 MockRead("Content-Length: 100\r\n\r\n"),
5749 MockRead(SYNCHRONOUS
, OK
),
5752 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5753 data_writes1
, arraysize(data_writes1
));
5754 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5755 data_writes2
, arraysize(data_writes2
));
5756 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5757 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5759 TestCompletionCallback callback1
;
5761 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5762 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5764 rv
= callback1
.WaitForResult();
5767 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5768 ASSERT_TRUE(response
!= NULL
);
5769 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5771 TestCompletionCallback callback2
;
5773 rv
= trans
->RestartWithAuth(
5774 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5775 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5777 rv
= callback2
.WaitForResult();
5780 response
= trans
->GetResponseInfo();
5781 ASSERT_TRUE(response
!= NULL
);
5782 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5783 EXPECT_EQ(100, response
->headers
->GetContentLength());
5786 // ------------------------------------------------------------------------
5788 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5790 HttpRequestInfo request
;
5791 request
.method
= "GET";
5792 // Note that Transaction 1 was at /x/y/z, so this is in the same
5793 // protection space as MyRealm1.
5794 request
.url
= GURL("http://www.example.org/x/y/a/b");
5795 request
.load_flags
= 0;
5797 scoped_ptr
<HttpTransaction
> trans(
5798 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5800 MockWrite data_writes1
[] = {
5802 "GET /x/y/a/b HTTP/1.1\r\n"
5803 "Host: www.example.org\r\n"
5804 "Connection: keep-alive\r\n"
5805 // Send preemptive authorization for MyRealm1
5806 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5809 // The server didn't like the preemptive authorization, and
5810 // challenges us for a different realm (MyRealm2).
5811 MockRead data_reads1
[] = {
5812 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5813 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5814 MockRead("Content-Length: 10000\r\n\r\n"),
5815 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5818 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5819 MockWrite data_writes2
[] = {
5821 "GET /x/y/a/b HTTP/1.1\r\n"
5822 "Host: www.example.org\r\n"
5823 "Connection: keep-alive\r\n"
5824 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5827 // Sever accepts the authorization.
5828 MockRead data_reads2
[] = {
5829 MockRead("HTTP/1.0 200 OK\r\n"),
5830 MockRead("Content-Length: 100\r\n\r\n"),
5831 MockRead(SYNCHRONOUS
, OK
),
5834 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5835 data_writes1
, arraysize(data_writes1
));
5836 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5837 data_writes2
, arraysize(data_writes2
));
5838 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5839 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5841 TestCompletionCallback callback1
;
5843 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5844 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5846 rv
= callback1
.WaitForResult();
5849 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5850 ASSERT_TRUE(response
!= NULL
);
5851 ASSERT_TRUE(response
->auth_challenge
.get());
5852 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5853 EXPECT_EQ("www.example.org:80",
5854 response
->auth_challenge
->challenger
.ToString());
5855 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5856 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5858 TestCompletionCallback callback2
;
5860 rv
= trans
->RestartWithAuth(
5861 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5862 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5864 rv
= callback2
.WaitForResult();
5867 response
= trans
->GetResponseInfo();
5868 ASSERT_TRUE(response
!= NULL
);
5869 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5870 EXPECT_EQ(100, response
->headers
->GetContentLength());
5873 // ------------------------------------------------------------------------
5875 // Transaction 3: Resend a request in MyRealm's protection space --
5876 // succeed with preemptive authorization.
5878 HttpRequestInfo request
;
5879 request
.method
= "GET";
5880 request
.url
= GURL("http://www.example.org/x/y/z2");
5881 request
.load_flags
= 0;
5883 scoped_ptr
<HttpTransaction
> trans(
5884 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5886 MockWrite data_writes1
[] = {
5888 "GET /x/y/z2 HTTP/1.1\r\n"
5889 "Host: www.example.org\r\n"
5890 "Connection: keep-alive\r\n"
5891 // The authorization for MyRealm1 gets sent preemptively
5892 // (since the url is in the same protection space)
5893 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5896 // Sever accepts the preemptive authorization
5897 MockRead data_reads1
[] = {
5898 MockRead("HTTP/1.0 200 OK\r\n"),
5899 MockRead("Content-Length: 100\r\n\r\n"),
5900 MockRead(SYNCHRONOUS
, OK
),
5903 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5904 data_writes1
, arraysize(data_writes1
));
5905 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5907 TestCompletionCallback callback1
;
5909 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5910 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5912 rv
= callback1
.WaitForResult();
5915 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5916 ASSERT_TRUE(response
!= NULL
);
5918 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5919 EXPECT_EQ(100, response
->headers
->GetContentLength());
5922 // ------------------------------------------------------------------------
5924 // Transaction 4: request another URL in MyRealm (however the
5925 // url is not known to belong to the protection space, so no pre-auth).
5927 HttpRequestInfo request
;
5928 request
.method
= "GET";
5929 request
.url
= GURL("http://www.example.org/x/1");
5930 request
.load_flags
= 0;
5932 scoped_ptr
<HttpTransaction
> trans(
5933 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5935 MockWrite data_writes1
[] = {
5937 "GET /x/1 HTTP/1.1\r\n"
5938 "Host: www.example.org\r\n"
5939 "Connection: keep-alive\r\n\r\n"),
5942 MockRead data_reads1
[] = {
5943 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5944 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5945 MockRead("Content-Length: 10000\r\n\r\n"),
5946 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5949 // Resend with authorization from MyRealm's cache.
5950 MockWrite data_writes2
[] = {
5952 "GET /x/1 HTTP/1.1\r\n"
5953 "Host: www.example.org\r\n"
5954 "Connection: keep-alive\r\n"
5955 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5958 // Sever accepts the authorization.
5959 MockRead data_reads2
[] = {
5960 MockRead("HTTP/1.0 200 OK\r\n"),
5961 MockRead("Content-Length: 100\r\n\r\n"),
5962 MockRead(SYNCHRONOUS
, OK
),
5965 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5966 data_writes1
, arraysize(data_writes1
));
5967 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5968 data_writes2
, arraysize(data_writes2
));
5969 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5970 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5972 TestCompletionCallback callback1
;
5974 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5975 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5977 rv
= callback1
.WaitForResult();
5980 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5981 TestCompletionCallback callback2
;
5982 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5983 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5984 rv
= callback2
.WaitForResult();
5986 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5988 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5989 ASSERT_TRUE(response
!= NULL
);
5990 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5991 EXPECT_EQ(100, response
->headers
->GetContentLength());
5994 // ------------------------------------------------------------------------
5996 // Transaction 5: request a URL in MyRealm, but the server rejects the
5997 // cached identity. Should invalidate and re-prompt.
5999 HttpRequestInfo request
;
6000 request
.method
= "GET";
6001 request
.url
= GURL("http://www.example.org/p/q/t");
6002 request
.load_flags
= 0;
6004 scoped_ptr
<HttpTransaction
> trans(
6005 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6007 MockWrite data_writes1
[] = {
6009 "GET /p/q/t HTTP/1.1\r\n"
6010 "Host: www.example.org\r\n"
6011 "Connection: keep-alive\r\n\r\n"),
6014 MockRead data_reads1
[] = {
6015 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6016 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6017 MockRead("Content-Length: 10000\r\n\r\n"),
6018 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6021 // Resend with authorization from cache for MyRealm.
6022 MockWrite data_writes2
[] = {
6024 "GET /p/q/t HTTP/1.1\r\n"
6025 "Host: www.example.org\r\n"
6026 "Connection: keep-alive\r\n"
6027 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6030 // Sever rejects the authorization.
6031 MockRead data_reads2
[] = {
6032 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6033 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6034 MockRead("Content-Length: 10000\r\n\r\n"),
6035 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6038 // At this point we should prompt for new credentials for MyRealm.
6039 // Restart with username=foo3, password=foo4.
6040 MockWrite data_writes3
[] = {
6042 "GET /p/q/t HTTP/1.1\r\n"
6043 "Host: www.example.org\r\n"
6044 "Connection: keep-alive\r\n"
6045 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6048 // Sever accepts the authorization.
6049 MockRead data_reads3
[] = {
6050 MockRead("HTTP/1.0 200 OK\r\n"),
6051 MockRead("Content-Length: 100\r\n\r\n"),
6052 MockRead(SYNCHRONOUS
, OK
),
6055 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6056 data_writes1
, arraysize(data_writes1
));
6057 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6058 data_writes2
, arraysize(data_writes2
));
6059 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6060 data_writes3
, arraysize(data_writes3
));
6061 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6062 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6063 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6065 TestCompletionCallback callback1
;
6067 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6068 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6070 rv
= callback1
.WaitForResult();
6073 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6074 TestCompletionCallback callback2
;
6075 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6076 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6077 rv
= callback2
.WaitForResult();
6079 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6081 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6082 ASSERT_TRUE(response
!= NULL
);
6083 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6085 TestCompletionCallback callback3
;
6087 rv
= trans
->RestartWithAuth(
6088 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6089 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6091 rv
= callback3
.WaitForResult();
6094 response
= trans
->GetResponseInfo();
6095 ASSERT_TRUE(response
!= NULL
);
6096 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6097 EXPECT_EQ(100, response
->headers
->GetContentLength());
6101 // Tests that nonce count increments when multiple auth attempts
6102 // are started with the same nonce.
6103 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6104 HttpAuthHandlerDigest::Factory
* digest_factory
=
6105 new HttpAuthHandlerDigest::Factory();
6106 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6107 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6108 digest_factory
->set_nonce_generator(nonce_generator
);
6109 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6110 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6112 // Transaction 1: authenticate (foo, bar) on MyRealm1
6114 HttpRequestInfo request
;
6115 request
.method
= "GET";
6116 request
.url
= GURL("http://www.example.org/x/y/z");
6117 request
.load_flags
= 0;
6119 scoped_ptr
<HttpTransaction
> trans(
6120 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6122 MockWrite data_writes1
[] = {
6124 "GET /x/y/z HTTP/1.1\r\n"
6125 "Host: www.example.org\r\n"
6126 "Connection: keep-alive\r\n\r\n"),
6129 MockRead data_reads1
[] = {
6130 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6131 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6132 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6133 MockRead(SYNCHRONOUS
, OK
),
6136 // Resend with authorization (username=foo, password=bar)
6137 MockWrite data_writes2
[] = {
6139 "GET /x/y/z HTTP/1.1\r\n"
6140 "Host: www.example.org\r\n"
6141 "Connection: keep-alive\r\n"
6142 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6143 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6144 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6145 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6148 // Sever accepts the authorization.
6149 MockRead data_reads2
[] = {
6150 MockRead("HTTP/1.0 200 OK\r\n"),
6151 MockRead(SYNCHRONOUS
, OK
),
6154 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6155 data_writes1
, arraysize(data_writes1
));
6156 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6157 data_writes2
, arraysize(data_writes2
));
6158 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6159 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6161 TestCompletionCallback callback1
;
6163 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6164 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6166 rv
= callback1
.WaitForResult();
6169 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6170 ASSERT_TRUE(response
!= NULL
);
6171 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6173 TestCompletionCallback callback2
;
6175 rv
= trans
->RestartWithAuth(
6176 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6177 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6179 rv
= callback2
.WaitForResult();
6182 response
= trans
->GetResponseInfo();
6183 ASSERT_TRUE(response
!= NULL
);
6184 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6187 // ------------------------------------------------------------------------
6189 // Transaction 2: Request another resource in digestive's protection space.
6190 // This will preemptively add an Authorization header which should have an
6191 // "nc" value of 2 (as compared to 1 in the first use.
6193 HttpRequestInfo request
;
6194 request
.method
= "GET";
6195 // Note that Transaction 1 was at /x/y/z, so this is in the same
6196 // protection space as digest.
6197 request
.url
= GURL("http://www.example.org/x/y/a/b");
6198 request
.load_flags
= 0;
6200 scoped_ptr
<HttpTransaction
> trans(
6201 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6203 MockWrite data_writes1
[] = {
6205 "GET /x/y/a/b HTTP/1.1\r\n"
6206 "Host: www.example.org\r\n"
6207 "Connection: keep-alive\r\n"
6208 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6209 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6210 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6211 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6214 // Sever accepts the authorization.
6215 MockRead data_reads1
[] = {
6216 MockRead("HTTP/1.0 200 OK\r\n"),
6217 MockRead("Content-Length: 100\r\n\r\n"),
6218 MockRead(SYNCHRONOUS
, OK
),
6221 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6222 data_writes1
, arraysize(data_writes1
));
6223 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6225 TestCompletionCallback callback1
;
6227 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6228 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6230 rv
= callback1
.WaitForResult();
6233 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6234 ASSERT_TRUE(response
!= NULL
);
6235 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6239 // Test the ResetStateForRestart() private method.
6240 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6241 // Create a transaction (the dependencies aren't important).
6242 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6243 scoped_ptr
<HttpNetworkTransaction
> trans(
6244 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6246 // Setup some state (which we expect ResetStateForRestart() will clear).
6247 trans
->read_buf_
= new IOBuffer(15);
6248 trans
->read_buf_len_
= 15;
6249 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6251 // Setup state in response_
6252 HttpResponseInfo
* response
= &trans
->response_
;
6253 response
->auth_challenge
= new AuthChallengeInfo();
6254 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6255 response
->response_time
= base::Time::Now();
6256 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6258 { // Setup state for response_.vary_data
6259 HttpRequestInfo request
;
6260 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6261 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6262 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6263 request
.extra_headers
.SetHeader("Foo", "1");
6264 request
.extra_headers
.SetHeader("bar", "23");
6265 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6268 // Cause the above state to be reset.
6269 trans
->ResetStateForRestart();
6271 // Verify that the state that needed to be reset, has been reset.
6272 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6273 EXPECT_EQ(0, trans
->read_buf_len_
);
6274 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6275 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6276 EXPECT_TRUE(response
->headers
.get() == NULL
);
6277 EXPECT_FALSE(response
->was_cached
);
6278 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6279 EXPECT_FALSE(response
->vary_data
.is_valid());
6282 // Test HTTPS connections to a site with a bad certificate
6283 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6284 HttpRequestInfo request
;
6285 request
.method
= "GET";
6286 request
.url
= GURL("https://www.example.org/");
6287 request
.load_flags
= 0;
6289 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6290 scoped_ptr
<HttpTransaction
> trans(
6291 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6293 MockWrite data_writes
[] = {
6295 "GET / HTTP/1.1\r\n"
6296 "Host: www.example.org\r\n"
6297 "Connection: keep-alive\r\n\r\n"),
6300 MockRead data_reads
[] = {
6301 MockRead("HTTP/1.0 200 OK\r\n"),
6302 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6303 MockRead("Content-Length: 100\r\n\r\n"),
6304 MockRead(SYNCHRONOUS
, OK
),
6307 StaticSocketDataProvider ssl_bad_certificate
;
6308 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6309 data_writes
, arraysize(data_writes
));
6310 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6311 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6313 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6314 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6315 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6316 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6318 TestCompletionCallback callback
;
6320 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6321 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6323 rv
= callback
.WaitForResult();
6324 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6326 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6327 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6329 rv
= callback
.WaitForResult();
6332 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6334 ASSERT_TRUE(response
!= NULL
);
6335 EXPECT_EQ(100, response
->headers
->GetContentLength());
6338 // Test HTTPS connections to a site with a bad certificate, going through a
6340 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6341 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6343 HttpRequestInfo request
;
6344 request
.method
= "GET";
6345 request
.url
= GURL("https://www.example.org/");
6346 request
.load_flags
= 0;
6348 MockWrite proxy_writes
[] = {
6350 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6351 "Host: www.example.org\r\n"
6352 "Proxy-Connection: keep-alive\r\n\r\n"),
6355 MockRead proxy_reads
[] = {
6356 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6357 MockRead(SYNCHRONOUS
, OK
)
6360 MockWrite data_writes
[] = {
6362 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6363 "Host: www.example.org\r\n"
6364 "Proxy-Connection: keep-alive\r\n\r\n"),
6366 "GET / HTTP/1.1\r\n"
6367 "Host: www.example.org\r\n"
6368 "Connection: keep-alive\r\n\r\n"),
6371 MockRead data_reads
[] = {
6372 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6373 MockRead("HTTP/1.0 200 OK\r\n"),
6374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6375 MockRead("Content-Length: 100\r\n\r\n"),
6376 MockRead(SYNCHRONOUS
, OK
),
6379 StaticSocketDataProvider
ssl_bad_certificate(
6380 proxy_reads
, arraysize(proxy_reads
),
6381 proxy_writes
, arraysize(proxy_writes
));
6382 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6383 data_writes
, arraysize(data_writes
));
6384 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6385 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6387 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6388 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6389 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6390 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6392 TestCompletionCallback callback
;
6394 for (int i
= 0; i
< 2; i
++) {
6395 session_deps_
.socket_factory
->ResetNextMockIndexes();
6397 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6398 scoped_ptr
<HttpTransaction
> trans(
6399 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6401 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6402 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6404 rv
= callback
.WaitForResult();
6405 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6407 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6408 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6410 rv
= callback
.WaitForResult();
6413 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6415 ASSERT_TRUE(response
!= NULL
);
6416 EXPECT_EQ(100, response
->headers
->GetContentLength());
6421 // Test HTTPS connections to a site, going through an HTTPS proxy
6422 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6423 session_deps_
.proxy_service
.reset(
6424 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6426 session_deps_
.net_log
= &net_log
;
6428 HttpRequestInfo request
;
6429 request
.method
= "GET";
6430 request
.url
= GURL("https://www.example.org/");
6431 request
.load_flags
= 0;
6433 MockWrite data_writes
[] = {
6435 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6436 "Host: www.example.org\r\n"
6437 "Proxy-Connection: keep-alive\r\n\r\n"),
6439 "GET / HTTP/1.1\r\n"
6440 "Host: www.example.org\r\n"
6441 "Connection: keep-alive\r\n\r\n"),
6444 MockRead data_reads
[] = {
6445 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6446 MockRead("HTTP/1.1 200 OK\r\n"),
6447 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6448 MockRead("Content-Length: 100\r\n\r\n"),
6449 MockRead(SYNCHRONOUS
, OK
),
6452 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6453 data_writes
, arraysize(data_writes
));
6454 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6455 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6457 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6458 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6459 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6461 TestCompletionCallback callback
;
6463 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6464 scoped_ptr
<HttpTransaction
> trans(
6465 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6467 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6470 rv
= callback
.WaitForResult();
6472 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6474 ASSERT_TRUE(response
!= NULL
);
6476 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6477 EXPECT_EQ(200, response
->headers
->response_code());
6478 EXPECT_EQ(100, response
->headers
->GetContentLength());
6479 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6481 LoadTimingInfo load_timing_info
;
6482 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6483 TestLoadTimingNotReusedWithPac(load_timing_info
,
6484 CONNECT_TIMING_HAS_SSL_TIMES
);
6487 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6488 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6489 session_deps_
.proxy_service
.reset(
6490 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6492 session_deps_
.net_log
= &net_log
;
6494 HttpRequestInfo request
;
6495 request
.method
= "GET";
6496 request
.url
= GURL("https://www.example.org/");
6497 request
.load_flags
= 0;
6499 MockWrite data_writes
[] = {
6501 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6502 "Host: www.example.org\r\n"
6503 "Proxy-Connection: keep-alive\r\n\r\n"),
6506 MockRead data_reads
[] = {
6507 MockRead("HTTP/1.1 302 Redirect\r\n"),
6508 MockRead("Location: http://login.example.com/\r\n"),
6509 MockRead("Content-Length: 0\r\n\r\n"),
6510 MockRead(SYNCHRONOUS
, OK
),
6513 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6514 data_writes
, arraysize(data_writes
));
6515 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6517 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6518 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6520 TestCompletionCallback callback
;
6522 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6523 scoped_ptr
<HttpTransaction
> trans(
6524 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6526 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6527 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6529 rv
= callback
.WaitForResult();
6531 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6533 ASSERT_TRUE(response
!= NULL
);
6535 EXPECT_EQ(302, response
->headers
->response_code());
6537 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6538 EXPECT_EQ("http://login.example.com/", url
);
6540 // In the case of redirects from proxies, HttpNetworkTransaction returns
6541 // timing for the proxy connection instead of the connection to the host,
6542 // and no send / receive times.
6543 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6544 LoadTimingInfo load_timing_info
;
6545 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6547 EXPECT_FALSE(load_timing_info
.socket_reused
);
6548 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6550 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6551 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6552 load_timing_info
.proxy_resolve_end
);
6553 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6554 load_timing_info
.connect_timing
.connect_start
);
6555 ExpectConnectTimingHasTimes(
6556 load_timing_info
.connect_timing
,
6557 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6559 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6560 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6561 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6564 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6565 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6566 session_deps_
.proxy_service
.reset(
6567 ProxyService::CreateFixed("https://proxy:70"));
6569 HttpRequestInfo request
;
6570 request
.method
= "GET";
6571 request
.url
= GURL("https://www.example.org/");
6572 request
.load_flags
= 0;
6574 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6575 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6576 scoped_ptr
<SpdyFrame
> goaway(
6577 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6578 MockWrite data_writes
[] = {
6579 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6580 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6583 static const char* const kExtraHeaders
[] = {
6585 "http://login.example.com/",
6587 scoped_ptr
<SpdyFrame
> resp(
6588 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6589 arraysize(kExtraHeaders
)/2, 1));
6590 MockRead data_reads
[] = {
6591 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6594 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6595 arraysize(data_writes
));
6596 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6597 proxy_ssl
.SetNextProto(GetParam());
6599 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6600 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6602 TestCompletionCallback callback
;
6604 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6605 scoped_ptr
<HttpTransaction
> trans(
6606 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6608 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6609 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6611 rv
= callback
.WaitForResult();
6613 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6615 ASSERT_TRUE(response
!= NULL
);
6617 EXPECT_EQ(302, response
->headers
->response_code());
6619 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6620 EXPECT_EQ("http://login.example.com/", url
);
6623 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6624 TEST_P(HttpNetworkTransactionTest
,
6625 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6626 session_deps_
.proxy_service
.reset(
6627 ProxyService::CreateFixed("https://proxy:70"));
6629 HttpRequestInfo request
;
6630 request
.method
= "GET";
6631 request
.url
= GURL("https://www.example.org/");
6632 request
.load_flags
= 0;
6634 MockWrite data_writes
[] = {
6636 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6637 "Host: www.example.org\r\n"
6638 "Proxy-Connection: keep-alive\r\n\r\n"),
6641 MockRead data_reads
[] = {
6642 MockRead("HTTP/1.1 404 Not Found\r\n"),
6643 MockRead("Content-Length: 23\r\n\r\n"),
6644 MockRead("The host does not exist"),
6645 MockRead(SYNCHRONOUS
, OK
),
6648 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6649 data_writes
, arraysize(data_writes
));
6650 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6652 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6653 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6655 TestCompletionCallback callback
;
6657 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6658 scoped_ptr
<HttpTransaction
> trans(
6659 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6661 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6662 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6664 rv
= callback
.WaitForResult();
6665 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6667 // TODO(ttuttle): Anything else to check here?
6670 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6671 TEST_P(HttpNetworkTransactionTest
,
6672 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6673 session_deps_
.proxy_service
.reset(
6674 ProxyService::CreateFixed("https://proxy:70"));
6676 HttpRequestInfo request
;
6677 request
.method
= "GET";
6678 request
.url
= GURL("https://www.example.org/");
6679 request
.load_flags
= 0;
6681 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6682 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6683 scoped_ptr
<SpdyFrame
> rst(
6684 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6685 MockWrite data_writes
[] = {
6686 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6689 static const char* const kExtraHeaders
[] = {
6691 "http://login.example.com/",
6693 scoped_ptr
<SpdyFrame
> resp(
6694 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6695 arraysize(kExtraHeaders
)/2, 1));
6696 scoped_ptr
<SpdyFrame
> body(
6697 spdy_util_
.ConstructSpdyBodyFrame(
6698 1, "The host does not exist", 23, true));
6699 MockRead data_reads
[] = {
6700 CreateMockRead(*resp
.get(), 1),
6701 CreateMockRead(*body
.get(), 2),
6702 MockRead(ASYNC
, 0, 4), // EOF
6705 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6706 arraysize(data_writes
));
6707 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6708 proxy_ssl
.SetNextProto(GetParam());
6710 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6711 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6713 TestCompletionCallback callback
;
6715 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6716 scoped_ptr
<HttpTransaction
> trans(
6717 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6719 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6720 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6722 rv
= callback
.WaitForResult();
6723 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6725 // TODO(ttuttle): Anything else to check here?
6728 // Test the request-challenge-retry sequence for basic auth, through
6729 // a SPDY proxy over a single SPDY session.
6730 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6731 HttpRequestInfo request
;
6732 request
.method
= "GET";
6733 request
.url
= GURL("https://www.example.org/");
6734 // when the no authentication data flag is set.
6735 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6737 // Configure against https proxy server "myproxy:70".
6738 session_deps_
.proxy_service
.reset(
6739 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6740 BoundTestNetLog log
;
6741 session_deps_
.net_log
= log
.bound().net_log();
6742 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6744 // Since we have proxy, should try to establish tunnel.
6745 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6746 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6747 scoped_ptr
<SpdyFrame
> rst(
6748 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6750 // After calling trans->RestartWithAuth(), this is the request we should
6751 // be issuing -- the final header line contains the credentials.
6752 const char* const kAuthCredentials
[] = {
6753 "proxy-authorization", "Basic Zm9vOmJhcg==",
6755 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6756 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6757 HostPortPair("www.example.org", 443)));
6758 // fetch https://www.example.org/ via HTTP
6760 "GET / HTTP/1.1\r\n"
6761 "Host: www.example.org\r\n"
6762 "Connection: keep-alive\r\n\r\n";
6763 scoped_ptr
<SpdyFrame
> wrapped_get(
6764 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6766 MockWrite spdy_writes
[] = {
6767 CreateMockWrite(*req
, 0, ASYNC
),
6768 CreateMockWrite(*rst
, 2, ASYNC
),
6769 CreateMockWrite(*connect2
, 3),
6770 CreateMockWrite(*wrapped_get
, 5),
6773 // The proxy responds to the connect with a 407, using a persistent
6775 const char kAuthStatus
[] = "407";
6776 const char* const kAuthChallenge
[] = {
6777 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6779 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6780 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6782 scoped_ptr
<SpdyFrame
> conn_resp(
6783 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6784 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6785 "Content-Length: 5\r\n\r\n";
6787 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6788 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6789 scoped_ptr
<SpdyFrame
> wrapped_body(
6790 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6791 MockRead spdy_reads
[] = {
6792 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6793 CreateMockRead(*conn_resp
, 4, ASYNC
),
6794 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6795 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6796 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6799 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6800 arraysize(spdy_writes
));
6801 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6802 // Negotiate SPDY to the proxy
6803 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6804 proxy
.SetNextProto(GetParam());
6805 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6806 // Vanilla SSL to the server
6807 SSLSocketDataProvider
server(ASYNC
, OK
);
6808 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6810 TestCompletionCallback callback1
;
6812 scoped_ptr
<HttpTransaction
> trans(
6813 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6815 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6816 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6818 rv
= callback1
.WaitForResult();
6820 TestNetLogEntry::List entries
;
6821 log
.GetEntries(&entries
);
6822 size_t pos
= ExpectLogContainsSomewhere(
6823 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6824 NetLog::PHASE_NONE
);
6825 ExpectLogContainsSomewhere(
6827 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6828 NetLog::PHASE_NONE
);
6830 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6831 ASSERT_TRUE(response
!= NULL
);
6832 ASSERT_FALSE(response
->headers
.get() == NULL
);
6833 EXPECT_EQ(407, response
->headers
->response_code());
6834 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6835 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6836 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6838 TestCompletionCallback callback2
;
6840 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6841 callback2
.callback());
6842 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6844 rv
= callback2
.WaitForResult();
6847 response
= trans
->GetResponseInfo();
6848 ASSERT_TRUE(response
!= NULL
);
6850 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6851 EXPECT_EQ(200, response
->headers
->response_code());
6852 EXPECT_EQ(5, response
->headers
->GetContentLength());
6853 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6855 // The password prompt info should not be set.
6856 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6858 LoadTimingInfo load_timing_info
;
6859 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6860 TestLoadTimingNotReusedWithPac(load_timing_info
,
6861 CONNECT_TIMING_HAS_SSL_TIMES
);
6864 session
->CloseAllConnections();
6867 // Test that an explicitly trusted SPDY proxy can push a resource from an
6868 // origin that is different from that of its associated resource.
6869 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6870 HttpRequestInfo request
;
6871 HttpRequestInfo push_request
;
6873 request
.method
= "GET";
6874 request
.url
= GURL("http://www.example.org/");
6875 push_request
.method
= "GET";
6876 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6878 // Configure against https proxy server "myproxy:70".
6879 session_deps_
.proxy_service
.reset(
6880 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6881 BoundTestNetLog log
;
6882 session_deps_
.net_log
= log
.bound().net_log();
6884 // Enable cross-origin push.
6885 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6887 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6889 scoped_ptr
<SpdyFrame
> stream1_syn(
6890 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6892 MockWrite spdy_writes
[] = {
6893 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6896 scoped_ptr
<SpdyFrame
>
6897 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6899 scoped_ptr
<SpdyFrame
>
6900 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6902 scoped_ptr
<SpdyFrame
>
6903 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6907 "http://www.another-origin.com/foo.dat"));
6908 const char kPushedData
[] = "pushed";
6909 scoped_ptr
<SpdyFrame
> stream2_body(
6910 spdy_util_
.ConstructSpdyBodyFrame(
6911 2, kPushedData
, strlen(kPushedData
), true));
6913 MockRead spdy_reads
[] = {
6914 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6915 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6916 CreateMockRead(*stream1_body
, 3, ASYNC
),
6917 CreateMockRead(*stream2_body
, 4, ASYNC
),
6918 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
6921 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6922 arraysize(spdy_writes
));
6923 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6924 // Negotiate SPDY to the proxy
6925 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6926 proxy
.SetNextProto(GetParam());
6927 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6929 scoped_ptr
<HttpTransaction
> trans(
6930 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6931 TestCompletionCallback callback
;
6932 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6933 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6935 rv
= callback
.WaitForResult();
6937 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6939 scoped_ptr
<HttpTransaction
> push_trans(
6940 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6941 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6942 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6944 rv
= callback
.WaitForResult();
6946 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6948 ASSERT_TRUE(response
!= NULL
);
6949 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6951 EXPECT_EQ(200, response
->headers
->response_code());
6952 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6954 std::string response_data
;
6955 rv
= ReadTransaction(trans
.get(), &response_data
);
6957 EXPECT_EQ("hello!", response_data
);
6959 LoadTimingInfo load_timing_info
;
6960 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6961 TestLoadTimingNotReusedWithPac(load_timing_info
,
6962 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6964 // Verify the pushed stream.
6965 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6966 EXPECT_EQ(200, push_response
->headers
->response_code());
6968 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6970 EXPECT_EQ("pushed", response_data
);
6972 LoadTimingInfo push_load_timing_info
;
6973 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6974 TestLoadTimingReusedWithPac(push_load_timing_info
);
6975 // The transactions should share a socket ID, despite being for different
6977 EXPECT_EQ(load_timing_info
.socket_log_id
,
6978 push_load_timing_info
.socket_log_id
);
6982 session
->CloseAllConnections();
6985 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6986 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6987 HttpRequestInfo request
;
6989 request
.method
= "GET";
6990 request
.url
= GURL("http://www.example.org/");
6992 // Configure against https proxy server "myproxy:70".
6993 session_deps_
.proxy_service
.reset(
6994 ProxyService::CreateFixed("https://myproxy:70"));
6995 BoundTestNetLog log
;
6996 session_deps_
.net_log
= log
.bound().net_log();
6998 // Enable cross-origin push.
6999 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
7001 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7003 scoped_ptr
<SpdyFrame
> stream1_syn(
7004 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
7006 scoped_ptr
<SpdyFrame
> push_rst(
7007 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7009 MockWrite spdy_writes
[] = {
7010 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
7013 scoped_ptr
<SpdyFrame
>
7014 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7016 scoped_ptr
<SpdyFrame
>
7017 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7019 scoped_ptr
<SpdyFrame
>
7020 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7024 "https://www.another-origin.com/foo.dat"));
7026 MockRead spdy_reads
[] = {
7027 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7028 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7029 CreateMockRead(*stream1_body
, 4, ASYNC
),
7030 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7033 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7034 arraysize(spdy_writes
));
7035 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7036 // Negotiate SPDY to the proxy
7037 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7038 proxy
.SetNextProto(GetParam());
7039 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7041 scoped_ptr
<HttpTransaction
> trans(
7042 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7043 TestCompletionCallback callback
;
7044 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7045 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7047 rv
= callback
.WaitForResult();
7049 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7051 ASSERT_TRUE(response
!= NULL
);
7052 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7054 EXPECT_EQ(200, response
->headers
->response_code());
7055 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7057 std::string response_data
;
7058 rv
= ReadTransaction(trans
.get(), &response_data
);
7060 EXPECT_EQ("hello!", response_data
);
7063 session
->CloseAllConnections();
7066 // Test HTTPS connections to a site with a bad certificate, going through an
7068 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7069 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7070 "https://proxy:70"));
7072 HttpRequestInfo request
;
7073 request
.method
= "GET";
7074 request
.url
= GURL("https://www.example.org/");
7075 request
.load_flags
= 0;
7077 // Attempt to fetch the URL from a server with a bad cert
7078 MockWrite bad_cert_writes
[] = {
7080 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7081 "Host: www.example.org\r\n"
7082 "Proxy-Connection: keep-alive\r\n\r\n"),
7085 MockRead bad_cert_reads
[] = {
7086 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7087 MockRead(SYNCHRONOUS
, OK
)
7090 // Attempt to fetch the URL with a good cert
7091 MockWrite good_data_writes
[] = {
7093 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7094 "Host: www.example.org\r\n"
7095 "Proxy-Connection: keep-alive\r\n\r\n"),
7097 "GET / HTTP/1.1\r\n"
7098 "Host: www.example.org\r\n"
7099 "Connection: keep-alive\r\n\r\n"),
7102 MockRead good_cert_reads
[] = {
7103 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7104 MockRead("HTTP/1.0 200 OK\r\n"),
7105 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7106 MockRead("Content-Length: 100\r\n\r\n"),
7107 MockRead(SYNCHRONOUS
, OK
),
7110 StaticSocketDataProvider
ssl_bad_certificate(
7111 bad_cert_reads
, arraysize(bad_cert_reads
),
7112 bad_cert_writes
, arraysize(bad_cert_writes
));
7113 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7114 good_data_writes
, arraysize(good_data_writes
));
7115 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7116 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7118 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7119 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7120 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7121 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7123 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7124 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7125 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7126 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7128 TestCompletionCallback callback
;
7130 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7131 scoped_ptr
<HttpTransaction
> trans(
7132 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7134 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7137 rv
= callback
.WaitForResult();
7138 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7140 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7141 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7143 rv
= callback
.WaitForResult();
7146 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7148 ASSERT_TRUE(response
!= NULL
);
7149 EXPECT_EQ(100, response
->headers
->GetContentLength());
7152 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7153 HttpRequestInfo request
;
7154 request
.method
= "GET";
7155 request
.url
= GURL("http://www.example.org/");
7156 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7157 "Chromium Ultra Awesome X Edition");
7159 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7160 scoped_ptr
<HttpTransaction
> trans(
7161 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7163 MockWrite data_writes
[] = {
7165 "GET / HTTP/1.1\r\n"
7166 "Host: www.example.org\r\n"
7167 "Connection: keep-alive\r\n"
7168 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7171 // Lastly, the server responds with the actual content.
7172 MockRead data_reads
[] = {
7173 MockRead("HTTP/1.0 200 OK\r\n"),
7174 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7175 MockRead("Content-Length: 100\r\n\r\n"),
7176 MockRead(SYNCHRONOUS
, OK
),
7179 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7180 data_writes
, arraysize(data_writes
));
7181 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7183 TestCompletionCallback callback
;
7185 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7186 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7188 rv
= callback
.WaitForResult();
7192 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7193 HttpRequestInfo request
;
7194 request
.method
= "GET";
7195 request
.url
= GURL("https://www.example.org/");
7196 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7197 "Chromium Ultra Awesome X Edition");
7199 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7200 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7201 scoped_ptr
<HttpTransaction
> trans(
7202 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7204 MockWrite data_writes
[] = {
7206 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7207 "Host: www.example.org\r\n"
7208 "Proxy-Connection: keep-alive\r\n"
7209 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7211 MockRead data_reads
[] = {
7212 // Return an error, so the transaction stops here (this test isn't
7213 // interested in the rest).
7214 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7215 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7216 MockRead("Proxy-Connection: close\r\n\r\n"),
7219 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7220 data_writes
, arraysize(data_writes
));
7221 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7223 TestCompletionCallback callback
;
7225 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7226 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7228 rv
= callback
.WaitForResult();
7232 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7233 HttpRequestInfo request
;
7234 request
.method
= "GET";
7235 request
.url
= GURL("http://www.example.org/");
7236 request
.load_flags
= 0;
7237 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7238 "http://the.previous.site.com/");
7240 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7241 scoped_ptr
<HttpTransaction
> trans(
7242 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7244 MockWrite data_writes
[] = {
7246 "GET / HTTP/1.1\r\n"
7247 "Host: www.example.org\r\n"
7248 "Connection: keep-alive\r\n"
7249 "Referer: http://the.previous.site.com/\r\n\r\n"),
7252 // Lastly, the server responds with the actual content.
7253 MockRead data_reads
[] = {
7254 MockRead("HTTP/1.0 200 OK\r\n"),
7255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7256 MockRead("Content-Length: 100\r\n\r\n"),
7257 MockRead(SYNCHRONOUS
, OK
),
7260 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7261 data_writes
, arraysize(data_writes
));
7262 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7264 TestCompletionCallback callback
;
7266 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7267 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7269 rv
= callback
.WaitForResult();
7273 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7274 HttpRequestInfo request
;
7275 request
.method
= "POST";
7276 request
.url
= GURL("http://www.example.org/");
7278 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7279 scoped_ptr
<HttpTransaction
> trans(
7280 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7282 MockWrite data_writes
[] = {
7284 "POST / HTTP/1.1\r\n"
7285 "Host: www.example.org\r\n"
7286 "Connection: keep-alive\r\n"
7287 "Content-Length: 0\r\n\r\n"),
7290 // Lastly, the server responds with the actual content.
7291 MockRead data_reads
[] = {
7292 MockRead("HTTP/1.0 200 OK\r\n"),
7293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7294 MockRead("Content-Length: 100\r\n\r\n"),
7295 MockRead(SYNCHRONOUS
, OK
),
7298 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7299 data_writes
, arraysize(data_writes
));
7300 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7302 TestCompletionCallback callback
;
7304 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7307 rv
= callback
.WaitForResult();
7311 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7312 HttpRequestInfo request
;
7313 request
.method
= "PUT";
7314 request
.url
= GURL("http://www.example.org/");
7316 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7317 scoped_ptr
<HttpTransaction
> trans(
7318 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7320 MockWrite data_writes
[] = {
7322 "PUT / HTTP/1.1\r\n"
7323 "Host: www.example.org\r\n"
7324 "Connection: keep-alive\r\n"
7325 "Content-Length: 0\r\n\r\n"),
7328 // Lastly, the server responds with the actual content.
7329 MockRead data_reads
[] = {
7330 MockRead("HTTP/1.0 200 OK\r\n"),
7331 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7332 MockRead("Content-Length: 100\r\n\r\n"),
7333 MockRead(SYNCHRONOUS
, OK
),
7336 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7337 data_writes
, arraysize(data_writes
));
7338 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7340 TestCompletionCallback callback
;
7342 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7343 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7345 rv
= callback
.WaitForResult();
7349 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7350 HttpRequestInfo request
;
7351 request
.method
= "HEAD";
7352 request
.url
= GURL("http://www.example.org/");
7354 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7355 scoped_ptr
<HttpTransaction
> trans(
7356 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7358 MockWrite data_writes
[] = {
7360 "HEAD / HTTP/1.1\r\n"
7361 "Host: www.example.org\r\n"
7362 "Connection: keep-alive\r\n"
7363 "Content-Length: 0\r\n\r\n"),
7366 // Lastly, the server responds with the actual content.
7367 MockRead data_reads
[] = {
7368 MockRead("HTTP/1.0 200 OK\r\n"),
7369 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7370 MockRead("Content-Length: 100\r\n\r\n"),
7371 MockRead(SYNCHRONOUS
, OK
),
7374 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7375 data_writes
, arraysize(data_writes
));
7376 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7378 TestCompletionCallback callback
;
7380 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7381 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7383 rv
= callback
.WaitForResult();
7387 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7388 HttpRequestInfo request
;
7389 request
.method
= "GET";
7390 request
.url
= GURL("http://www.example.org/");
7391 request
.load_flags
= LOAD_BYPASS_CACHE
;
7393 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7394 scoped_ptr
<HttpTransaction
> trans(
7395 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7397 MockWrite data_writes
[] = {
7399 "GET / HTTP/1.1\r\n"
7400 "Host: www.example.org\r\n"
7401 "Connection: keep-alive\r\n"
7402 "Pragma: no-cache\r\n"
7403 "Cache-Control: no-cache\r\n\r\n"),
7406 // Lastly, the server responds with the actual content.
7407 MockRead data_reads
[] = {
7408 MockRead("HTTP/1.0 200 OK\r\n"),
7409 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7410 MockRead("Content-Length: 100\r\n\r\n"),
7411 MockRead(SYNCHRONOUS
, OK
),
7414 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7415 data_writes
, arraysize(data_writes
));
7416 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7418 TestCompletionCallback callback
;
7420 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7421 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7423 rv
= callback
.WaitForResult();
7427 TEST_P(HttpNetworkTransactionTest
,
7428 BuildRequest_CacheControlValidateCache
) {
7429 HttpRequestInfo request
;
7430 request
.method
= "GET";
7431 request
.url
= GURL("http://www.example.org/");
7432 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7434 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7435 scoped_ptr
<HttpTransaction
> trans(
7436 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7438 MockWrite data_writes
[] = {
7440 "GET / HTTP/1.1\r\n"
7441 "Host: www.example.org\r\n"
7442 "Connection: keep-alive\r\n"
7443 "Cache-Control: max-age=0\r\n\r\n"),
7446 // Lastly, the server responds with the actual content.
7447 MockRead data_reads
[] = {
7448 MockRead("HTTP/1.0 200 OK\r\n"),
7449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7450 MockRead("Content-Length: 100\r\n\r\n"),
7451 MockRead(SYNCHRONOUS
, OK
),
7454 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7455 data_writes
, arraysize(data_writes
));
7456 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7458 TestCompletionCallback callback
;
7460 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7461 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7463 rv
= callback
.WaitForResult();
7467 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7468 HttpRequestInfo request
;
7469 request
.method
= "GET";
7470 request
.url
= GURL("http://www.example.org/");
7471 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7473 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7474 scoped_ptr
<HttpTransaction
> trans(
7475 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7477 MockWrite data_writes
[] = {
7479 "GET / HTTP/1.1\r\n"
7480 "Host: www.example.org\r\n"
7481 "Connection: keep-alive\r\n"
7482 "FooHeader: Bar\r\n\r\n"),
7485 // Lastly, the server responds with the actual content.
7486 MockRead data_reads
[] = {
7487 MockRead("HTTP/1.0 200 OK\r\n"),
7488 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7489 MockRead("Content-Length: 100\r\n\r\n"),
7490 MockRead(SYNCHRONOUS
, OK
),
7493 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7494 data_writes
, arraysize(data_writes
));
7495 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7497 TestCompletionCallback callback
;
7499 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7500 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7502 rv
= callback
.WaitForResult();
7506 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7507 HttpRequestInfo request
;
7508 request
.method
= "GET";
7509 request
.url
= GURL("http://www.example.org/");
7510 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7511 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7512 request
.extra_headers
.SetHeader("FoO", "bar");
7514 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7515 scoped_ptr
<HttpTransaction
> trans(
7516 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7518 MockWrite data_writes
[] = {
7520 "GET / HTTP/1.1\r\n"
7521 "Host: www.example.org\r\n"
7522 "Connection: keep-alive\r\n"
7523 "referer: www.foo.com\r\n"
7525 "FoO: bar\r\n\r\n"),
7528 // Lastly, the server responds with the actual content.
7529 MockRead data_reads
[] = {
7530 MockRead("HTTP/1.0 200 OK\r\n"),
7531 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7532 MockRead("Content-Length: 100\r\n\r\n"),
7533 MockRead(SYNCHRONOUS
, OK
),
7536 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7537 data_writes
, arraysize(data_writes
));
7538 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7540 TestCompletionCallback callback
;
7542 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7543 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7545 rv
= callback
.WaitForResult();
7549 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7550 HttpRequestInfo request
;
7551 request
.method
= "GET";
7552 request
.url
= GURL("http://www.example.org/");
7553 request
.load_flags
= 0;
7555 session_deps_
.proxy_service
.reset(
7556 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7558 session_deps_
.net_log
= &net_log
;
7560 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7561 scoped_ptr
<HttpTransaction
> trans(
7562 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7564 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7565 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7567 MockWrite data_writes
[] = {
7568 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7570 "GET / HTTP/1.1\r\n"
7571 "Host: www.example.org\r\n"
7572 "Connection: keep-alive\r\n\r\n")};
7574 MockRead data_reads
[] = {
7575 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7576 MockRead("HTTP/1.0 200 OK\r\n"),
7577 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7578 MockRead("Payload"),
7579 MockRead(SYNCHRONOUS
, OK
)
7582 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7583 data_writes
, arraysize(data_writes
));
7584 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7586 TestCompletionCallback callback
;
7588 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7589 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7591 rv
= callback
.WaitForResult();
7594 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7595 ASSERT_TRUE(response
!= NULL
);
7597 LoadTimingInfo load_timing_info
;
7598 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7599 TestLoadTimingNotReusedWithPac(load_timing_info
,
7600 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7602 std::string response_text
;
7603 rv
= ReadTransaction(trans
.get(), &response_text
);
7605 EXPECT_EQ("Payload", response_text
);
7608 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7609 HttpRequestInfo request
;
7610 request
.method
= "GET";
7611 request
.url
= GURL("https://www.example.org/");
7612 request
.load_flags
= 0;
7614 session_deps_
.proxy_service
.reset(
7615 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7617 session_deps_
.net_log
= &net_log
;
7619 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7620 scoped_ptr
<HttpTransaction
> trans(
7621 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7623 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7624 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7626 MockWrite data_writes
[] = {
7627 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7628 arraysize(write_buffer
)),
7630 "GET / HTTP/1.1\r\n"
7631 "Host: www.example.org\r\n"
7632 "Connection: keep-alive\r\n\r\n")};
7634 MockRead data_reads
[] = {
7635 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7636 arraysize(read_buffer
)),
7637 MockRead("HTTP/1.0 200 OK\r\n"),
7638 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7639 MockRead("Payload"),
7640 MockRead(SYNCHRONOUS
, OK
)
7643 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7644 data_writes
, arraysize(data_writes
));
7645 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7647 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7648 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7650 TestCompletionCallback callback
;
7652 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7653 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7655 rv
= callback
.WaitForResult();
7658 LoadTimingInfo load_timing_info
;
7659 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7660 TestLoadTimingNotReusedWithPac(load_timing_info
,
7661 CONNECT_TIMING_HAS_SSL_TIMES
);
7663 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7664 ASSERT_TRUE(response
!= NULL
);
7666 std::string response_text
;
7667 rv
= ReadTransaction(trans
.get(), &response_text
);
7669 EXPECT_EQ("Payload", response_text
);
7672 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7673 HttpRequestInfo request
;
7674 request
.method
= "GET";
7675 request
.url
= GURL("http://www.example.org/");
7676 request
.load_flags
= 0;
7678 session_deps_
.proxy_service
.reset(
7679 ProxyService::CreateFixed("socks4://myproxy:1080"));
7681 session_deps_
.net_log
= &net_log
;
7683 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7684 scoped_ptr
<HttpTransaction
> trans(
7685 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7687 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7688 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7690 MockWrite data_writes
[] = {
7691 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7693 "GET / HTTP/1.1\r\n"
7694 "Host: www.example.org\r\n"
7695 "Connection: keep-alive\r\n\r\n")};
7697 MockRead data_reads
[] = {
7698 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7699 MockRead("HTTP/1.0 200 OK\r\n"),
7700 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7701 MockRead("Payload"),
7702 MockRead(SYNCHRONOUS
, OK
)
7705 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7706 data_writes
, arraysize(data_writes
));
7707 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7709 TestCompletionCallback callback
;
7711 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7714 rv
= callback
.WaitForResult();
7717 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7718 ASSERT_TRUE(response
!= NULL
);
7720 LoadTimingInfo load_timing_info
;
7721 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7722 TestLoadTimingNotReused(load_timing_info
,
7723 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7725 std::string response_text
;
7726 rv
= ReadTransaction(trans
.get(), &response_text
);
7728 EXPECT_EQ("Payload", response_text
);
7731 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7732 HttpRequestInfo request
;
7733 request
.method
= "GET";
7734 request
.url
= GURL("http://www.example.org/");
7735 request
.load_flags
= 0;
7737 session_deps_
.proxy_service
.reset(
7738 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7740 session_deps_
.net_log
= &net_log
;
7742 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7743 scoped_ptr
<HttpTransaction
> trans(
7744 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7746 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7747 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7748 const char kSOCKS5OkRequest
[] = {
7750 0x01, // Command (CONNECT)
7752 0x03, // Address type (DOMAINNAME).
7753 0x0F, // Length of domain (15)
7754 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7755 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7757 const char kSOCKS5OkResponse
[] =
7758 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7760 MockWrite data_writes
[] = {
7761 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7762 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7764 "GET / HTTP/1.1\r\n"
7765 "Host: www.example.org\r\n"
7766 "Connection: keep-alive\r\n\r\n")};
7768 MockRead data_reads
[] = {
7769 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7770 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7771 MockRead("HTTP/1.0 200 OK\r\n"),
7772 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7773 MockRead("Payload"),
7774 MockRead(SYNCHRONOUS
, OK
)
7777 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7778 data_writes
, arraysize(data_writes
));
7779 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7781 TestCompletionCallback callback
;
7783 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7784 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7786 rv
= callback
.WaitForResult();
7789 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7790 ASSERT_TRUE(response
!= NULL
);
7792 LoadTimingInfo load_timing_info
;
7793 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7794 TestLoadTimingNotReusedWithPac(load_timing_info
,
7795 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7797 std::string response_text
;
7798 rv
= ReadTransaction(trans
.get(), &response_text
);
7800 EXPECT_EQ("Payload", response_text
);
7803 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7804 HttpRequestInfo request
;
7805 request
.method
= "GET";
7806 request
.url
= GURL("https://www.example.org/");
7807 request
.load_flags
= 0;
7809 session_deps_
.proxy_service
.reset(
7810 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7812 session_deps_
.net_log
= &net_log
;
7814 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7815 scoped_ptr
<HttpTransaction
> trans(
7816 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7818 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7819 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7820 const unsigned char kSOCKS5OkRequest
[] = {
7822 0x01, // Command (CONNECT)
7824 0x03, // Address type (DOMAINNAME).
7825 0x0F, // Length of domain (15)
7826 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7827 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7830 const char kSOCKS5OkResponse
[] =
7831 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7833 MockWrite data_writes
[] = {
7834 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7835 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7836 arraysize(kSOCKS5OkRequest
)),
7838 "GET / HTTP/1.1\r\n"
7839 "Host: www.example.org\r\n"
7840 "Connection: keep-alive\r\n\r\n")};
7842 MockRead data_reads
[] = {
7843 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7844 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7845 MockRead("HTTP/1.0 200 OK\r\n"),
7846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7847 MockRead("Payload"),
7848 MockRead(SYNCHRONOUS
, OK
)
7851 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7852 data_writes
, arraysize(data_writes
));
7853 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7855 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7856 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7858 TestCompletionCallback callback
;
7860 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7861 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7863 rv
= callback
.WaitForResult();
7866 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7867 ASSERT_TRUE(response
!= NULL
);
7869 LoadTimingInfo load_timing_info
;
7870 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7871 TestLoadTimingNotReusedWithPac(load_timing_info
,
7872 CONNECT_TIMING_HAS_SSL_TIMES
);
7874 std::string response_text
;
7875 rv
= ReadTransaction(trans
.get(), &response_text
);
7877 EXPECT_EQ("Payload", response_text
);
7882 // Tests that for connection endpoints the group names are correctly set.
7884 struct GroupNameTest
{
7885 std::string proxy_server
;
7887 std::string expected_group_name
;
7891 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7892 NextProto next_proto
,
7893 SpdySessionDependencies
* session_deps_
) {
7894 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7896 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7897 session
->http_server_properties();
7898 AlternativeService
alternative_service(
7899 AlternateProtocolFromNextProto(next_proto
), "", 443);
7900 http_server_properties
->SetAlternativeService(
7901 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0);
7906 int GroupNameTransactionHelper(
7907 const std::string
& url
,
7908 const scoped_refptr
<HttpNetworkSession
>& session
) {
7909 HttpRequestInfo request
;
7910 request
.method
= "GET";
7911 request
.url
= GURL(url
);
7912 request
.load_flags
= 0;
7914 scoped_ptr
<HttpTransaction
> trans(
7915 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7917 TestCompletionCallback callback
;
7919 // We do not complete this request, the dtor will clean the transaction up.
7920 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7925 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7926 const GroupNameTest tests
[] = {
7929 "http://www.example.org/direct",
7930 "www.example.org:80",
7935 "http://[2001:1418:13:1::25]/direct",
7936 "[2001:1418:13:1::25]:80",
7943 "https://www.example.org/direct_ssl",
7944 "ssl/www.example.org:443",
7949 "https://[2001:1418:13:1::25]/direct",
7950 "ssl/[2001:1418:13:1::25]:443",
7955 "http://host.with.alternate/direct",
7956 "ssl/host.with.alternate:443",
7961 session_deps_
.use_alternate_protocols
= true;
7963 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7964 session_deps_
.proxy_service
.reset(
7965 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7966 scoped_refptr
<HttpNetworkSession
> session(
7967 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7969 HttpNetworkSessionPeer
peer(session
);
7970 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7971 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7972 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7973 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7974 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7975 new MockClientSocketPoolManager
);
7976 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7977 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7978 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7980 EXPECT_EQ(ERR_IO_PENDING
,
7981 GroupNameTransactionHelper(tests
[i
].url
, session
));
7983 EXPECT_EQ(tests
[i
].expected_group_name
,
7984 ssl_conn_pool
->last_group_name_received());
7986 EXPECT_EQ(tests
[i
].expected_group_name
,
7987 transport_conn_pool
->last_group_name_received());
7992 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7993 const GroupNameTest tests
[] = {
7996 "http://www.example.org/http_proxy_normal",
7997 "www.example.org:80",
8004 "https://www.example.org/http_connect_ssl",
8005 "ssl/www.example.org:443",
8011 "http://host.with.alternate/direct",
8012 "ssl/host.with.alternate:443",
8018 "ftp://ftp.google.com/http_proxy_normal",
8019 "ftp/ftp.google.com:21",
8024 session_deps_
.use_alternate_protocols
= true;
8026 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8027 session_deps_
.proxy_service
.reset(
8028 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8029 scoped_refptr
<HttpNetworkSession
> session(
8030 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8032 HttpNetworkSessionPeer
peer(session
);
8034 HostPortPair
proxy_host("http_proxy", 80);
8035 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8036 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8037 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8038 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8040 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8041 new MockClientSocketPoolManager
);
8042 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8043 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8044 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8046 EXPECT_EQ(ERR_IO_PENDING
,
8047 GroupNameTransactionHelper(tests
[i
].url
, session
));
8049 EXPECT_EQ(tests
[i
].expected_group_name
,
8050 ssl_conn_pool
->last_group_name_received());
8052 EXPECT_EQ(tests
[i
].expected_group_name
,
8053 http_proxy_pool
->last_group_name_received());
8057 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8058 const GroupNameTest tests
[] = {
8060 "socks4://socks_proxy:1080",
8061 "http://www.example.org/socks4_direct",
8062 "socks4/www.example.org:80",
8066 "socks5://socks_proxy:1080",
8067 "http://www.example.org/socks5_direct",
8068 "socks5/www.example.org:80",
8074 "socks4://socks_proxy:1080",
8075 "https://www.example.org/socks4_ssl",
8076 "socks4/ssl/www.example.org:443",
8080 "socks5://socks_proxy:1080",
8081 "https://www.example.org/socks5_ssl",
8082 "socks5/ssl/www.example.org:443",
8087 "socks4://socks_proxy:1080",
8088 "http://host.with.alternate/direct",
8089 "socks4/ssl/host.with.alternate:443",
8094 session_deps_
.use_alternate_protocols
= true;
8096 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8097 session_deps_
.proxy_service
.reset(
8098 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8099 scoped_refptr
<HttpNetworkSession
> session(
8100 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8102 HttpNetworkSessionPeer
peer(session
);
8104 HostPortPair
proxy_host("socks_proxy", 1080);
8105 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8106 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8107 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8108 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8110 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8111 new MockClientSocketPoolManager
);
8112 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8113 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8114 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8116 scoped_ptr
<HttpTransaction
> trans(
8117 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8119 EXPECT_EQ(ERR_IO_PENDING
,
8120 GroupNameTransactionHelper(tests
[i
].url
, session
));
8122 EXPECT_EQ(tests
[i
].expected_group_name
,
8123 ssl_conn_pool
->last_group_name_received());
8125 EXPECT_EQ(tests
[i
].expected_group_name
,
8126 socks_conn_pool
->last_group_name_received());
8130 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8131 HttpRequestInfo request
;
8132 request
.method
= "GET";
8133 request
.url
= GURL("http://www.example.org/");
8135 session_deps_
.proxy_service
.reset(
8136 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8138 // This simulates failure resolving all hostnames; that means we will fail
8139 // connecting to both proxies (myproxy:70 and foobar:80).
8140 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8142 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8143 scoped_ptr
<HttpTransaction
> trans(
8144 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8146 TestCompletionCallback callback
;
8148 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8149 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8151 rv
= callback
.WaitForResult();
8152 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8155 // Base test to make sure that when the load flags for a request specify to
8156 // bypass the cache, the DNS cache is not used.
8157 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8159 // Issue a request, asking to bypass the cache(s).
8160 HttpRequestInfo request
;
8161 request
.method
= "GET";
8162 request
.load_flags
= load_flags
;
8163 request
.url
= GURL("http://www.example.org/");
8165 // Select a host resolver that does caching.
8166 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8168 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8169 scoped_ptr
<HttpTransaction
> trans(
8170 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8172 // Warm up the host cache so it has an entry for "www.example.org".
8173 AddressList addrlist
;
8174 TestCompletionCallback callback
;
8175 int rv
= session_deps_
.host_resolver
->Resolve(
8176 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8177 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8178 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8179 rv
= callback
.WaitForResult();
8182 // Verify that it was added to host cache, by doing a subsequent async lookup
8183 // and confirming it completes synchronously.
8184 rv
= session_deps_
.host_resolver
->Resolve(
8185 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8186 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8189 // Inject a failure the next time that "www.example.org" is resolved. This way
8190 // we can tell if the next lookup hit the cache, or the "network".
8191 // (cache --> success, "network" --> failure).
8192 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8194 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8195 // first read -- this won't be reached as the host resolution will fail first.
8196 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8197 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8198 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8201 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8202 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8203 rv
= callback
.WaitForResult();
8205 // If we bypassed the cache, we would have gotten a failure while resolving
8206 // "www.example.org".
8207 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8210 // There are multiple load flags that should trigger the host cache bypass.
8211 // Test each in isolation:
8212 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8213 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8216 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8217 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8220 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8221 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8224 // Make sure we can handle an error when writing the request.
8225 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8226 HttpRequestInfo request
;
8227 request
.method
= "GET";
8228 request
.url
= GURL("http://www.foo.com/");
8229 request
.load_flags
= 0;
8231 MockWrite write_failure
[] = {
8232 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8234 StaticSocketDataProvider
data(NULL
, 0,
8235 write_failure
, arraysize(write_failure
));
8236 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8237 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8239 TestCompletionCallback callback
;
8241 scoped_ptr
<HttpTransaction
> trans(
8242 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8244 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8245 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8247 rv
= callback
.WaitForResult();
8248 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8251 // Check that a connection closed after the start of the headers finishes ok.
8252 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8253 HttpRequestInfo request
;
8254 request
.method
= "GET";
8255 request
.url
= GURL("http://www.foo.com/");
8256 request
.load_flags
= 0;
8258 MockRead data_reads
[] = {
8259 MockRead("HTTP/1."),
8260 MockRead(SYNCHRONOUS
, OK
),
8263 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8264 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8265 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8267 TestCompletionCallback callback
;
8269 scoped_ptr
<HttpTransaction
> trans(
8270 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8272 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8273 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8275 rv
= callback
.WaitForResult();
8278 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8279 ASSERT_TRUE(response
!= NULL
);
8281 EXPECT_TRUE(response
->headers
.get() != NULL
);
8282 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8284 std::string response_data
;
8285 rv
= ReadTransaction(trans
.get(), &response_data
);
8287 EXPECT_EQ("", response_data
);
8290 // Make sure that a dropped connection while draining the body for auth
8291 // restart does the right thing.
8292 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8293 HttpRequestInfo request
;
8294 request
.method
= "GET";
8295 request
.url
= GURL("http://www.example.org/");
8296 request
.load_flags
= 0;
8298 MockWrite data_writes1
[] = {
8300 "GET / HTTP/1.1\r\n"
8301 "Host: www.example.org\r\n"
8302 "Connection: keep-alive\r\n\r\n"),
8305 MockRead data_reads1
[] = {
8306 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8307 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8308 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8309 MockRead("Content-Length: 14\r\n\r\n"),
8311 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8314 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8315 data_writes1
, arraysize(data_writes1
));
8316 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8318 // After calling trans->RestartWithAuth(), this is the request we should
8319 // be issuing -- the final header line contains the credentials.
8320 MockWrite data_writes2
[] = {
8322 "GET / HTTP/1.1\r\n"
8323 "Host: www.example.org\r\n"
8324 "Connection: keep-alive\r\n"
8325 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8328 // Lastly, the server responds with the actual content.
8329 MockRead data_reads2
[] = {
8330 MockRead("HTTP/1.1 200 OK\r\n"),
8331 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8332 MockRead("Content-Length: 100\r\n\r\n"),
8333 MockRead(SYNCHRONOUS
, OK
),
8336 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8337 data_writes2
, arraysize(data_writes2
));
8338 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8339 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8341 TestCompletionCallback callback1
;
8343 scoped_ptr
<HttpTransaction
> trans(
8344 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8346 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8347 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8349 rv
= callback1
.WaitForResult();
8352 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8353 ASSERT_TRUE(response
!= NULL
);
8354 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8356 TestCompletionCallback callback2
;
8358 rv
= trans
->RestartWithAuth(
8359 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8360 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8362 rv
= callback2
.WaitForResult();
8365 response
= trans
->GetResponseInfo();
8366 ASSERT_TRUE(response
!= NULL
);
8367 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8368 EXPECT_EQ(100, response
->headers
->GetContentLength());
8371 // Test HTTPS connections going through a proxy that sends extra data.
8372 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8373 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8375 HttpRequestInfo request
;
8376 request
.method
= "GET";
8377 request
.url
= GURL("https://www.example.org/");
8378 request
.load_flags
= 0;
8380 MockRead proxy_reads
[] = {
8381 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8382 MockRead(SYNCHRONOUS
, OK
)
8385 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8386 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8388 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8389 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8391 TestCompletionCallback callback
;
8393 session_deps_
.socket_factory
->ResetNextMockIndexes();
8395 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8396 scoped_ptr
<HttpTransaction
> trans(
8397 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8399 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8402 rv
= callback
.WaitForResult();
8403 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8406 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8407 HttpRequestInfo request
;
8408 request
.method
= "GET";
8409 request
.url
= GURL("http://www.example.org/");
8410 request
.load_flags
= 0;
8412 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8413 scoped_ptr
<HttpTransaction
> trans(
8414 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8416 MockRead data_reads
[] = {
8417 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8418 MockRead(SYNCHRONOUS
, OK
),
8421 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8422 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8424 TestCompletionCallback callback
;
8426 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8427 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8429 EXPECT_EQ(OK
, callback
.WaitForResult());
8431 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8432 ASSERT_TRUE(response
!= NULL
);
8434 EXPECT_TRUE(response
->headers
.get() != NULL
);
8435 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8437 std::string response_data
;
8438 rv
= ReadTransaction(trans
.get(), &response_data
);
8439 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8442 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8443 base::FilePath temp_file_path
;
8444 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8445 const uint64 kFakeSize
= 100000; // file is actually blank
8446 UploadFileElementReader::ScopedOverridingContentLengthForTests
8447 overriding_content_length(kFakeSize
);
8449 ScopedVector
<UploadElementReader
> element_readers
;
8450 element_readers
.push_back(
8451 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8456 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8458 HttpRequestInfo request
;
8459 request
.method
= "POST";
8460 request
.url
= GURL("http://www.example.org/upload");
8461 request
.upload_data_stream
= &upload_data_stream
;
8462 request
.load_flags
= 0;
8464 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8465 scoped_ptr
<HttpTransaction
> trans(
8466 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8468 MockRead data_reads
[] = {
8469 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8470 MockRead("hello world"),
8471 MockRead(SYNCHRONOUS
, OK
),
8473 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8474 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8476 TestCompletionCallback callback
;
8478 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8479 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8481 rv
= callback
.WaitForResult();
8484 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8485 ASSERT_TRUE(response
!= NULL
);
8487 EXPECT_TRUE(response
->headers
.get() != NULL
);
8488 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8490 std::string response_data
;
8491 rv
= ReadTransaction(trans
.get(), &response_data
);
8493 EXPECT_EQ("hello world", response_data
);
8495 base::DeleteFile(temp_file_path
, false);
8498 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8499 base::FilePath temp_file
;
8500 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8501 std::string
temp_file_content("Unreadable file.");
8502 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8503 temp_file_content
.length()));
8504 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8506 ScopedVector
<UploadElementReader
> element_readers
;
8507 element_readers
.push_back(
8508 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8513 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8515 HttpRequestInfo request
;
8516 request
.method
= "POST";
8517 request
.url
= GURL("http://www.example.org/upload");
8518 request
.upload_data_stream
= &upload_data_stream
;
8519 request
.load_flags
= 0;
8521 // If we try to upload an unreadable file, the transaction should fail.
8522 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8523 scoped_ptr
<HttpTransaction
> trans(
8524 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8526 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8527 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8529 TestCompletionCallback callback
;
8531 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8532 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8534 rv
= callback
.WaitForResult();
8535 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8537 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8538 EXPECT_FALSE(response
);
8540 base::DeleteFile(temp_file
, false);
8543 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8544 class FakeUploadElementReader
: public UploadElementReader
{
8546 FakeUploadElementReader() {}
8547 ~FakeUploadElementReader() override
{}
8549 const CompletionCallback
& callback() const { return callback_
; }
8551 // UploadElementReader overrides:
8552 int Init(const CompletionCallback
& callback
) override
{
8553 callback_
= callback
;
8554 return ERR_IO_PENDING
;
8556 uint64
GetContentLength() const override
{ return 0; }
8557 uint64
BytesRemaining() const override
{ return 0; }
8558 int Read(IOBuffer
* buf
,
8560 const CompletionCallback
& callback
) override
{
8565 CompletionCallback callback_
;
8568 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8569 ScopedVector
<UploadElementReader
> element_readers
;
8570 element_readers
.push_back(fake_reader
);
8571 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8573 HttpRequestInfo request
;
8574 request
.method
= "POST";
8575 request
.url
= GURL("http://www.example.org/upload");
8576 request
.upload_data_stream
= &upload_data_stream
;
8577 request
.load_flags
= 0;
8579 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8580 scoped_ptr
<HttpTransaction
> trans(
8581 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8583 StaticSocketDataProvider data
;
8584 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8586 TestCompletionCallback callback
;
8587 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8588 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8589 base::MessageLoop::current()->RunUntilIdle();
8591 // Transaction is pending on request body initialization.
8592 ASSERT_FALSE(fake_reader
->callback().is_null());
8594 // Return Init()'s result after the transaction gets destroyed.
8596 fake_reader
->callback().Run(OK
); // Should not crash.
8599 // Tests that changes to Auth realms are treated like auth rejections.
8600 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8602 HttpRequestInfo request
;
8603 request
.method
= "GET";
8604 request
.url
= GURL("http://www.example.org/");
8605 request
.load_flags
= 0;
8607 // First transaction will request a resource and receive a Basic challenge
8608 // with realm="first_realm".
8609 MockWrite data_writes1
[] = {
8611 "GET / HTTP/1.1\r\n"
8612 "Host: www.example.org\r\n"
8613 "Connection: keep-alive\r\n"
8616 MockRead data_reads1
[] = {
8617 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8618 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8622 // After calling trans->RestartWithAuth(), provide an Authentication header
8623 // for first_realm. The server will reject and provide a challenge with
8625 MockWrite data_writes2
[] = {
8627 "GET / HTTP/1.1\r\n"
8628 "Host: www.example.org\r\n"
8629 "Connection: keep-alive\r\n"
8630 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8633 MockRead data_reads2
[] = {
8634 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8635 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8639 // This again fails, and goes back to first_realm. Make sure that the
8640 // entry is removed from cache.
8641 MockWrite data_writes3
[] = {
8643 "GET / HTTP/1.1\r\n"
8644 "Host: www.example.org\r\n"
8645 "Connection: keep-alive\r\n"
8646 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8649 MockRead data_reads3
[] = {
8650 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8651 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8655 // Try one last time (with the correct password) and get the resource.
8656 MockWrite data_writes4
[] = {
8658 "GET / HTTP/1.1\r\n"
8659 "Host: www.example.org\r\n"
8660 "Connection: keep-alive\r\n"
8661 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8664 MockRead data_reads4
[] = {
8665 MockRead("HTTP/1.1 200 OK\r\n"
8666 "Content-Type: text/html; charset=iso-8859-1\r\n"
8667 "Content-Length: 5\r\n"
8672 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8673 data_writes1
, arraysize(data_writes1
));
8674 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8675 data_writes2
, arraysize(data_writes2
));
8676 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8677 data_writes3
, arraysize(data_writes3
));
8678 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8679 data_writes4
, arraysize(data_writes4
));
8680 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8681 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8682 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8683 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8685 TestCompletionCallback callback1
;
8687 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8688 scoped_ptr
<HttpTransaction
> trans(
8689 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8691 // Issue the first request with Authorize headers. There should be a
8692 // password prompt for first_realm waiting to be filled in after the
8693 // transaction completes.
8694 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8696 rv
= callback1
.WaitForResult();
8698 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8699 ASSERT_TRUE(response
!= NULL
);
8700 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8701 ASSERT_FALSE(challenge
== NULL
);
8702 EXPECT_FALSE(challenge
->is_proxy
);
8703 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8704 EXPECT_EQ("first_realm", challenge
->realm
);
8705 EXPECT_EQ("basic", challenge
->scheme
);
8707 // Issue the second request with an incorrect password. There should be a
8708 // password prompt for second_realm waiting to be filled in after the
8709 // transaction completes.
8710 TestCompletionCallback callback2
;
8711 rv
= trans
->RestartWithAuth(
8712 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8713 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8714 rv
= callback2
.WaitForResult();
8716 response
= trans
->GetResponseInfo();
8717 ASSERT_TRUE(response
!= NULL
);
8718 challenge
= response
->auth_challenge
.get();
8719 ASSERT_FALSE(challenge
== NULL
);
8720 EXPECT_FALSE(challenge
->is_proxy
);
8721 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8722 EXPECT_EQ("second_realm", challenge
->realm
);
8723 EXPECT_EQ("basic", challenge
->scheme
);
8725 // Issue the third request with another incorrect password. There should be
8726 // a password prompt for first_realm waiting to be filled in. If the password
8727 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8728 // first_realm was not correctly removed.
8729 TestCompletionCallback callback3
;
8730 rv
= trans
->RestartWithAuth(
8731 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8732 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8733 rv
= callback3
.WaitForResult();
8735 response
= trans
->GetResponseInfo();
8736 ASSERT_TRUE(response
!= NULL
);
8737 challenge
= response
->auth_challenge
.get();
8738 ASSERT_FALSE(challenge
== NULL
);
8739 EXPECT_FALSE(challenge
->is_proxy
);
8740 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8741 EXPECT_EQ("first_realm", challenge
->realm
);
8742 EXPECT_EQ("basic", challenge
->scheme
);
8744 // Issue the fourth request with the correct password and username.
8745 TestCompletionCallback callback4
;
8746 rv
= trans
->RestartWithAuth(
8747 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8748 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8749 rv
= callback4
.WaitForResult();
8751 response
= trans
->GetResponseInfo();
8752 ASSERT_TRUE(response
!= NULL
);
8753 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8756 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8757 session_deps_
.next_protos
= SpdyNextProtos();
8758 session_deps_
.use_alternate_protocols
= true;
8760 std::string alternate_protocol_http_header
=
8761 GetAlternateProtocolHttpHeader();
8763 MockRead data_reads
[] = {
8764 MockRead("HTTP/1.1 200 OK\r\n"),
8765 MockRead(alternate_protocol_http_header
.c_str()),
8766 MockRead("hello world"),
8767 MockRead(SYNCHRONOUS
, OK
),
8770 HttpRequestInfo request
;
8771 request
.method
= "GET";
8772 request
.url
= GURL("http://www.example.org/");
8773 request
.load_flags
= 0;
8775 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8777 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8779 TestCompletionCallback callback
;
8781 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8782 scoped_ptr
<HttpTransaction
> trans(
8783 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8785 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8786 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8788 HostPortPair
http_host_port_pair("www.example.org", 80);
8789 HttpServerProperties
& http_server_properties
=
8790 *session
->http_server_properties();
8791 AlternativeService alternative_service
=
8792 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8793 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8795 EXPECT_EQ(OK
, callback
.WaitForResult());
8797 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8798 ASSERT_TRUE(response
!= NULL
);
8799 ASSERT_TRUE(response
->headers
.get() != NULL
);
8800 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8801 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8802 EXPECT_FALSE(response
->was_npn_negotiated
);
8804 std::string response_data
;
8805 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8806 EXPECT_EQ("hello world", response_data
);
8808 alternative_service
=
8809 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8810 EXPECT_EQ(443, alternative_service
.port
);
8811 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8812 alternative_service
.protocol
);
8815 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8816 session_deps_
.next_protos
= SpdyNextProtos();
8817 session_deps_
.use_alternate_protocols
= true;
8819 MockRead data_reads
[] = {
8820 MockRead("HTTP/1.1 200 OK\r\n"),
8821 MockRead("Alternate-Protocol: \r\n\r\n"),
8822 MockRead("hello world"),
8823 MockRead(SYNCHRONOUS
, OK
),
8826 HttpRequestInfo request
;
8827 request
.method
= "GET";
8828 request
.url
= GURL("http://www.example.org/");
8829 request
.load_flags
= 0;
8831 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8833 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8835 TestCompletionCallback callback
;
8837 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8839 HostPortPair
http_host_port_pair("www.example.org", 80);
8840 HttpServerProperties
& http_server_properties
=
8841 *session
->http_server_properties();
8842 AlternativeService
alternative_service(QUIC
, "", 80);
8843 http_server_properties
.SetAlternativeService(http_host_port_pair
,
8844 alternative_service
, 1.0);
8846 alternative_service
=
8847 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8848 EXPECT_EQ(alternative_service
.protocol
, QUIC
);
8850 scoped_ptr
<HttpTransaction
> trans(
8851 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8853 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8854 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8856 EXPECT_EQ(OK
, callback
.WaitForResult());
8858 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8859 ASSERT_TRUE(response
!= NULL
);
8860 ASSERT_TRUE(response
->headers
.get() != NULL
);
8861 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8862 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8863 EXPECT_FALSE(response
->was_npn_negotiated
);
8865 std::string response_data
;
8866 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8867 EXPECT_EQ("hello world", response_data
);
8869 alternative_service
=
8870 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8871 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8874 TEST_P(HttpNetworkTransactionTest
,
8875 MarkBrokenAlternateProtocolAndFallback
) {
8876 session_deps_
.use_alternate_protocols
= true;
8878 HttpRequestInfo request
;
8879 request
.method
= "GET";
8880 request
.url
= GURL("http://www.example.org/");
8881 request
.load_flags
= 0;
8883 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8884 StaticSocketDataProvider first_data
;
8885 first_data
.set_connect_data(mock_connect
);
8886 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8888 MockRead data_reads
[] = {
8889 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8890 MockRead("hello world"),
8891 MockRead(ASYNC
, OK
),
8893 StaticSocketDataProvider
second_data(
8894 data_reads
, arraysize(data_reads
), NULL
, 0);
8895 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8897 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8899 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8900 session
->http_server_properties();
8901 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
8902 // Port must be < 1024, or the header will be ignored (since initial port was
8903 // port 80 (another restricted port).
8904 AlternativeService
alternative_service(
8905 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8906 666); /* port is ignored by MockConnect anyway */
8907 http_server_properties
->SetAlternativeService(host_port_pair
,
8908 alternative_service
, 1.0);
8910 scoped_ptr
<HttpTransaction
> trans(
8911 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8912 TestCompletionCallback callback
;
8914 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8915 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8916 EXPECT_EQ(OK
, callback
.WaitForResult());
8918 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8919 ASSERT_TRUE(response
!= NULL
);
8920 ASSERT_TRUE(response
->headers
.get() != NULL
);
8921 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8923 std::string response_data
;
8924 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8925 EXPECT_EQ("hello world", response_data
);
8927 alternative_service
=
8928 http_server_properties
->GetAlternativeService(host_port_pair
);
8929 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL
, alternative_service
.protocol
);
8931 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
8934 TEST_P(HttpNetworkTransactionTest
,
8935 AlternateProtocolPortRestrictedBlocked
) {
8936 // Ensure that we're not allowed to redirect traffic via an alternate
8937 // protocol to an unrestricted (port >= 1024) when the original traffic was
8938 // on a restricted port (port < 1024). Ensure that we can redirect in all
8940 session_deps_
.use_alternate_protocols
= true;
8942 HttpRequestInfo restricted_port_request
;
8943 restricted_port_request
.method
= "GET";
8944 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8945 restricted_port_request
.load_flags
= 0;
8947 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8948 StaticSocketDataProvider first_data
;
8949 first_data
.set_connect_data(mock_connect
);
8950 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8952 MockRead data_reads
[] = {
8953 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8954 MockRead("hello world"),
8955 MockRead(ASYNC
, OK
),
8957 StaticSocketDataProvider
second_data(
8958 data_reads
, arraysize(data_reads
), NULL
, 0);
8959 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8961 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8963 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8964 session
->http_server_properties();
8965 const int kUnrestrictedAlternatePort
= 1024;
8966 AlternativeService
alternative_service(
8967 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8968 kUnrestrictedAlternatePort
);
8969 http_server_properties
->SetAlternativeService(
8970 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8973 scoped_ptr
<HttpTransaction
> trans(
8974 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8975 TestCompletionCallback callback
;
8977 int rv
= trans
->Start(
8978 &restricted_port_request
,
8979 callback
.callback(), BoundNetLog());
8980 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8981 // Invalid change to unrestricted port should fail.
8982 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
8985 TEST_P(HttpNetworkTransactionTest
,
8986 AlternateProtocolPortRestrictedPermitted
) {
8987 // Ensure that we're allowed to redirect traffic via an alternate
8988 // protocol to an unrestricted (port >= 1024) when the original traffic was
8989 // on a restricted port (port < 1024) if we set
8990 // enable_user_alternate_protocol_ports.
8992 session_deps_
.use_alternate_protocols
= true;
8993 session_deps_
.enable_user_alternate_protocol_ports
= true;
8995 HttpRequestInfo restricted_port_request
;
8996 restricted_port_request
.method
= "GET";
8997 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8998 restricted_port_request
.load_flags
= 0;
9000 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9001 StaticSocketDataProvider first_data
;
9002 first_data
.set_connect_data(mock_connect
);
9003 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9005 MockRead data_reads
[] = {
9006 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9007 MockRead("hello world"),
9008 MockRead(ASYNC
, OK
),
9010 StaticSocketDataProvider
second_data(
9011 data_reads
, arraysize(data_reads
), NULL
, 0);
9012 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9014 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9016 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9017 session
->http_server_properties();
9018 const int kUnrestrictedAlternatePort
= 1024;
9019 AlternativeService
alternative_service(
9020 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9021 kUnrestrictedAlternatePort
);
9022 http_server_properties
->SetAlternativeService(
9023 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9026 scoped_ptr
<HttpTransaction
> trans(
9027 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9028 TestCompletionCallback callback
;
9030 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9031 &restricted_port_request
,
9032 callback
.callback(), BoundNetLog()));
9033 // Change to unrestricted port should succeed.
9034 EXPECT_EQ(OK
, callback
.WaitForResult());
9037 TEST_P(HttpNetworkTransactionTest
,
9038 AlternateProtocolPortRestrictedAllowed
) {
9039 // Ensure that we're not allowed to redirect traffic via an alternate
9040 // protocol to an unrestricted (port >= 1024) when the original traffic was
9041 // on a restricted port (port < 1024). Ensure that we can redirect in all
9043 session_deps_
.use_alternate_protocols
= true;
9045 HttpRequestInfo restricted_port_request
;
9046 restricted_port_request
.method
= "GET";
9047 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9048 restricted_port_request
.load_flags
= 0;
9050 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9051 StaticSocketDataProvider first_data
;
9052 first_data
.set_connect_data(mock_connect
);
9053 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9055 MockRead data_reads
[] = {
9056 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9057 MockRead("hello world"),
9058 MockRead(ASYNC
, OK
),
9060 StaticSocketDataProvider
second_data(
9061 data_reads
, arraysize(data_reads
), NULL
, 0);
9062 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9064 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9066 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9067 session
->http_server_properties();
9068 const int kRestrictedAlternatePort
= 80;
9069 AlternativeService
alternative_service(
9070 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9071 kRestrictedAlternatePort
);
9072 http_server_properties
->SetAlternativeService(
9073 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9076 scoped_ptr
<HttpTransaction
> trans(
9077 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9078 TestCompletionCallback callback
;
9080 int rv
= trans
->Start(
9081 &restricted_port_request
,
9082 callback
.callback(), BoundNetLog());
9083 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9084 // Valid change to restricted port should pass.
9085 EXPECT_EQ(OK
, callback
.WaitForResult());
9088 TEST_P(HttpNetworkTransactionTest
,
9089 AlternateProtocolPortUnrestrictedAllowed1
) {
9090 // Ensure that we're not allowed to redirect traffic via an alternate
9091 // protocol to an unrestricted (port >= 1024) when the original traffic was
9092 // on a restricted port (port < 1024). Ensure that we can redirect in all
9094 session_deps_
.use_alternate_protocols
= true;
9096 HttpRequestInfo unrestricted_port_request
;
9097 unrestricted_port_request
.method
= "GET";
9098 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9099 unrestricted_port_request
.load_flags
= 0;
9101 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9102 StaticSocketDataProvider first_data
;
9103 first_data
.set_connect_data(mock_connect
);
9104 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9106 MockRead data_reads
[] = {
9107 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9108 MockRead("hello world"),
9109 MockRead(ASYNC
, OK
),
9111 StaticSocketDataProvider
second_data(
9112 data_reads
, arraysize(data_reads
), NULL
, 0);
9113 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9115 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9117 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9118 session
->http_server_properties();
9119 const int kRestrictedAlternatePort
= 80;
9120 AlternativeService
alternative_service(
9121 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9122 kRestrictedAlternatePort
);
9123 http_server_properties
->SetAlternativeService(
9124 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9127 scoped_ptr
<HttpTransaction
> trans(
9128 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9129 TestCompletionCallback callback
;
9131 int rv
= trans
->Start(
9132 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9133 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9134 // Valid change to restricted port should pass.
9135 EXPECT_EQ(OK
, callback
.WaitForResult());
9138 TEST_P(HttpNetworkTransactionTest
,
9139 AlternateProtocolPortUnrestrictedAllowed2
) {
9140 // Ensure that we're not allowed to redirect traffic via an alternate
9141 // protocol to an unrestricted (port >= 1024) when the original traffic was
9142 // on a restricted port (port < 1024). Ensure that we can redirect in all
9144 session_deps_
.use_alternate_protocols
= true;
9146 HttpRequestInfo unrestricted_port_request
;
9147 unrestricted_port_request
.method
= "GET";
9148 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9149 unrestricted_port_request
.load_flags
= 0;
9151 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9152 StaticSocketDataProvider first_data
;
9153 first_data
.set_connect_data(mock_connect
);
9154 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9156 MockRead data_reads
[] = {
9157 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9158 MockRead("hello world"),
9159 MockRead(ASYNC
, OK
),
9161 StaticSocketDataProvider
second_data(
9162 data_reads
, arraysize(data_reads
), NULL
, 0);
9163 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9165 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9167 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9168 session
->http_server_properties();
9169 const int kUnrestrictedAlternatePort
= 1024;
9170 AlternativeService
alternative_service(
9171 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9172 kUnrestrictedAlternatePort
);
9173 http_server_properties
->SetAlternativeService(
9174 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9177 scoped_ptr
<HttpTransaction
> trans(
9178 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9179 TestCompletionCallback callback
;
9181 int rv
= trans
->Start(
9182 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9183 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9184 // Valid change to an unrestricted port should pass.
9185 EXPECT_EQ(OK
, callback
.WaitForResult());
9188 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9189 // Ensure that we're not allowed to redirect traffic via an alternate
9190 // protocol to an unsafe port, and that we resume the second
9191 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9192 session_deps_
.use_alternate_protocols
= true;
9194 HttpRequestInfo request
;
9195 request
.method
= "GET";
9196 request
.url
= GURL("http://www.example.org/");
9197 request
.load_flags
= 0;
9199 // The alternate protocol request will error out before we attempt to connect,
9200 // so only the standard HTTP request will try to connect.
9201 MockRead data_reads
[] = {
9202 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9203 MockRead("hello world"),
9204 MockRead(ASYNC
, OK
),
9206 StaticSocketDataProvider
data(
9207 data_reads
, arraysize(data_reads
), NULL
, 0);
9208 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9210 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9212 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9213 session
->http_server_properties();
9214 const int kUnsafePort
= 7;
9215 AlternativeService
alternative_service(
9216 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9218 http_server_properties
->SetAlternativeService(
9219 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0);
9221 scoped_ptr
<HttpTransaction
> trans(
9222 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9223 TestCompletionCallback callback
;
9225 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9226 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9227 // The HTTP request should succeed.
9228 EXPECT_EQ(OK
, callback
.WaitForResult());
9230 // Disable alternate protocol before the asserts.
9231 // HttpStreamFactory::set_use_alternate_protocols(false);
9233 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9234 ASSERT_TRUE(response
!= NULL
);
9235 ASSERT_TRUE(response
->headers
.get() != NULL
);
9236 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9238 std::string response_data
;
9239 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9240 EXPECT_EQ("hello world", response_data
);
9243 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9244 session_deps_
.use_alternate_protocols
= true;
9245 session_deps_
.next_protos
= SpdyNextProtos();
9247 HttpRequestInfo request
;
9248 request
.method
= "GET";
9249 request
.url
= GURL("http://www.example.org/");
9250 request
.load_flags
= 0;
9252 std::string alternate_protocol_http_header
=
9253 GetAlternateProtocolHttpHeader();
9255 MockRead data_reads
[] = {
9256 MockRead("HTTP/1.1 200 OK\r\n"),
9257 MockRead(alternate_protocol_http_header
.c_str()),
9258 MockRead("hello world"),
9259 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9263 StaticSocketDataProvider
first_transaction(
9264 data_reads
, arraysize(data_reads
), NULL
, 0);
9265 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9267 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9268 ssl
.SetNextProto(GetParam());
9269 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9270 ASSERT_TRUE(ssl
.cert
.get());
9271 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9273 scoped_ptr
<SpdyFrame
> req(
9274 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9275 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9277 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9278 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9279 MockRead spdy_reads
[] = {
9280 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9283 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9284 arraysize(spdy_writes
));
9285 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9287 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9288 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9290 hanging_non_alternate_protocol_socket
.set_connect_data(
9291 never_finishing_connect
);
9292 session_deps_
.socket_factory
->AddSocketDataProvider(
9293 &hanging_non_alternate_protocol_socket
);
9295 TestCompletionCallback callback
;
9297 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9298 scoped_ptr
<HttpTransaction
> trans(
9299 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9301 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9302 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9303 EXPECT_EQ(OK
, callback
.WaitForResult());
9305 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9306 ASSERT_TRUE(response
!= NULL
);
9307 ASSERT_TRUE(response
->headers
.get() != NULL
);
9308 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9310 std::string response_data
;
9311 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9312 EXPECT_EQ("hello world", response_data
);
9314 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9316 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9317 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9318 EXPECT_EQ(OK
, callback
.WaitForResult());
9320 response
= trans
->GetResponseInfo();
9321 ASSERT_TRUE(response
!= NULL
);
9322 ASSERT_TRUE(response
->headers
.get() != NULL
);
9323 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9324 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9325 EXPECT_TRUE(response
->was_npn_negotiated
);
9327 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9328 EXPECT_EQ("hello!", response_data
);
9331 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9332 session_deps_
.use_alternate_protocols
= true;
9333 session_deps_
.next_protos
= SpdyNextProtos();
9335 HttpRequestInfo request
;
9336 request
.method
= "GET";
9337 request
.url
= GURL("http://www.example.org/");
9338 request
.load_flags
= 0;
9340 std::string alternate_protocol_http_header
=
9341 GetAlternateProtocolHttpHeader();
9343 MockRead data_reads
[] = {
9344 MockRead("HTTP/1.1 200 OK\r\n"),
9345 MockRead(alternate_protocol_http_header
.c_str()),
9346 MockRead("hello world"),
9347 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9348 MockRead(ASYNC
, OK
),
9351 StaticSocketDataProvider
first_transaction(
9352 data_reads
, arraysize(data_reads
), NULL
, 0);
9353 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9354 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9356 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9357 StaticSocketDataProvider
hanging_socket(
9359 hanging_socket
.set_connect_data(never_finishing_connect
);
9360 // Socket 2 and 3 are the hanging Alternate-Protocol and
9361 // non-Alternate-Protocol jobs from the 2nd transaction.
9362 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9363 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9365 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9366 ssl
.SetNextProto(GetParam());
9367 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9368 ASSERT_TRUE(ssl
.cert
.get());
9369 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9371 scoped_ptr
<SpdyFrame
> req1(
9372 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9373 scoped_ptr
<SpdyFrame
> req2(
9374 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9375 MockWrite spdy_writes
[] = {
9376 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9378 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9379 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9380 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9381 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9382 MockRead spdy_reads
[] = {
9383 CreateMockRead(*resp1
, 2),
9384 CreateMockRead(*data1
, 3),
9385 CreateMockRead(*resp2
, 4),
9386 CreateMockRead(*data2
, 5),
9387 MockRead(ASYNC
, 0, 6),
9390 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9391 arraysize(spdy_writes
));
9392 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9393 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9395 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9396 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9398 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9399 TestCompletionCallback callback1
;
9400 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9402 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9403 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9404 EXPECT_EQ(OK
, callback1
.WaitForResult());
9406 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9407 ASSERT_TRUE(response
!= NULL
);
9408 ASSERT_TRUE(response
->headers
.get() != NULL
);
9409 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9411 std::string response_data
;
9412 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9413 EXPECT_EQ("hello world", response_data
);
9415 TestCompletionCallback callback2
;
9416 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9417 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9418 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9420 TestCompletionCallback callback3
;
9421 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9422 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9423 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9425 EXPECT_EQ(OK
, callback2
.WaitForResult());
9426 EXPECT_EQ(OK
, callback3
.WaitForResult());
9428 response
= trans2
.GetResponseInfo();
9429 ASSERT_TRUE(response
!= NULL
);
9430 ASSERT_TRUE(response
->headers
.get() != NULL
);
9431 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9432 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9433 EXPECT_TRUE(response
->was_npn_negotiated
);
9434 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9435 EXPECT_EQ("hello!", response_data
);
9437 response
= trans3
.GetResponseInfo();
9438 ASSERT_TRUE(response
!= NULL
);
9439 ASSERT_TRUE(response
->headers
.get() != NULL
);
9440 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9441 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9442 EXPECT_TRUE(response
->was_npn_negotiated
);
9443 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9444 EXPECT_EQ("hello!", response_data
);
9447 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9448 session_deps_
.use_alternate_protocols
= true;
9449 session_deps_
.next_protos
= SpdyNextProtos();
9451 HttpRequestInfo request
;
9452 request
.method
= "GET";
9453 request
.url
= GURL("http://www.example.org/");
9454 request
.load_flags
= 0;
9456 std::string alternate_protocol_http_header
=
9457 GetAlternateProtocolHttpHeader();
9459 MockRead data_reads
[] = {
9460 MockRead("HTTP/1.1 200 OK\r\n"),
9461 MockRead(alternate_protocol_http_header
.c_str()),
9462 MockRead("hello world"),
9463 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9464 MockRead(ASYNC
, OK
),
9467 StaticSocketDataProvider
first_transaction(
9468 data_reads
, arraysize(data_reads
), NULL
, 0);
9469 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9471 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9472 ssl
.SetNextProto(GetParam());
9473 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9475 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9476 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9478 hanging_alternate_protocol_socket
.set_connect_data(
9479 never_finishing_connect
);
9480 session_deps_
.socket_factory
->AddSocketDataProvider(
9481 &hanging_alternate_protocol_socket
);
9483 // 2nd request is just a copy of the first one, over HTTP again.
9484 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9486 TestCompletionCallback callback
;
9488 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9489 scoped_ptr
<HttpTransaction
> trans(
9490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9492 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9493 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9494 EXPECT_EQ(OK
, callback
.WaitForResult());
9496 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9497 ASSERT_TRUE(response
!= NULL
);
9498 ASSERT_TRUE(response
->headers
.get() != NULL
);
9499 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9501 std::string response_data
;
9502 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9503 EXPECT_EQ("hello world", response_data
);
9505 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9507 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9508 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9509 EXPECT_EQ(OK
, callback
.WaitForResult());
9511 response
= trans
->GetResponseInfo();
9512 ASSERT_TRUE(response
!= NULL
);
9513 ASSERT_TRUE(response
->headers
.get() != NULL
);
9514 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9515 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9516 EXPECT_FALSE(response
->was_npn_negotiated
);
9518 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9519 EXPECT_EQ("hello world", response_data
);
9522 class CapturingProxyResolver
: public ProxyResolver
{
9524 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9525 ~CapturingProxyResolver() override
{}
9527 int GetProxyForURL(const GURL
& url
,
9529 const CompletionCallback
& callback
,
9530 RequestHandle
* request
,
9531 const BoundNetLog
& net_log
) override
{
9532 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9533 HostPortPair("myproxy", 80));
9534 results
->UseProxyServer(proxy_server
);
9535 resolved_
.push_back(url
);
9539 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9541 LoadState
GetLoadState(RequestHandle request
) const override
{
9543 return LOAD_STATE_IDLE
;
9546 void CancelSetPacScript() override
{ NOTREACHED(); }
9548 int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9549 const CompletionCallback
& /*callback*/) override
{
9553 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9556 std::vector
<GURL
> resolved_
;
9558 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9561 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9563 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9564 : ProxyResolverFactory(false), resolver_(resolver
) {}
9566 int CreateProxyResolver(
9567 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9568 scoped_ptr
<ProxyResolver
>* resolver
,
9569 const net::CompletionCallback
& callback
,
9570 scoped_ptr
<Request
>* request
) override
{
9571 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9576 ProxyResolver
* resolver_
;
9579 TEST_P(HttpNetworkTransactionTest
,
9580 UseAlternateProtocolForTunneledNpnSpdy
) {
9581 session_deps_
.use_alternate_protocols
= true;
9582 session_deps_
.next_protos
= SpdyNextProtos();
9584 ProxyConfig proxy_config
;
9585 proxy_config
.set_auto_detect(true);
9586 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9588 CapturingProxyResolver capturing_proxy_resolver
;
9589 session_deps_
.proxy_service
.reset(new ProxyService(
9590 new ProxyConfigServiceFixed(proxy_config
),
9592 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9595 session_deps_
.net_log
= &net_log
;
9597 HttpRequestInfo request
;
9598 request
.method
= "GET";
9599 request
.url
= GURL("http://www.example.org/");
9600 request
.load_flags
= 0;
9602 std::string alternate_protocol_http_header
=
9603 GetAlternateProtocolHttpHeader();
9605 MockRead data_reads
[] = {
9606 MockRead("HTTP/1.1 200 OK\r\n"),
9607 MockRead(alternate_protocol_http_header
.c_str()),
9608 MockRead("hello world"),
9609 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9610 MockRead(ASYNC
, OK
),
9613 StaticSocketDataProvider
first_transaction(
9614 data_reads
, arraysize(data_reads
), NULL
, 0);
9615 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9617 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9618 ssl
.SetNextProto(GetParam());
9619 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9620 ASSERT_TRUE(ssl
.cert
.get());
9621 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9623 scoped_ptr
<SpdyFrame
> req(
9624 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9625 MockWrite spdy_writes
[] = {
9627 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9628 "Host: www.example.org\r\n"
9629 "Proxy-Connection: keep-alive\r\n\r\n"),
9630 CreateMockWrite(*req
, 2),
9633 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9635 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9636 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9637 MockRead spdy_reads
[] = {
9638 MockRead(ASYNC
, 1, kCONNECTResponse
),
9639 CreateMockRead(*resp
.get(), 3),
9640 CreateMockRead(*data
.get(), 4),
9641 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
9644 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9645 arraysize(spdy_writes
));
9646 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9648 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9649 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9651 hanging_non_alternate_protocol_socket
.set_connect_data(
9652 never_finishing_connect
);
9653 session_deps_
.socket_factory
->AddSocketDataProvider(
9654 &hanging_non_alternate_protocol_socket
);
9656 TestCompletionCallback callback
;
9658 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9659 scoped_ptr
<HttpTransaction
> trans(
9660 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9662 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9663 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9664 EXPECT_EQ(OK
, callback
.WaitForResult());
9666 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9667 ASSERT_TRUE(response
!= NULL
);
9668 ASSERT_TRUE(response
->headers
.get() != NULL
);
9669 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9670 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9671 EXPECT_FALSE(response
->was_npn_negotiated
);
9673 std::string response_data
;
9674 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9675 EXPECT_EQ("hello world", response_data
);
9677 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9679 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9680 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9681 EXPECT_EQ(OK
, callback
.WaitForResult());
9683 response
= trans
->GetResponseInfo();
9684 ASSERT_TRUE(response
!= NULL
);
9685 ASSERT_TRUE(response
->headers
.get() != NULL
);
9686 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9687 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9688 EXPECT_TRUE(response
->was_npn_negotiated
);
9690 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9691 EXPECT_EQ("hello!", response_data
);
9692 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9693 EXPECT_EQ("http://www.example.org/",
9694 capturing_proxy_resolver
.resolved()[0].spec());
9695 EXPECT_EQ("https://www.example.org/",
9696 capturing_proxy_resolver
.resolved()[1].spec());
9698 LoadTimingInfo load_timing_info
;
9699 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9700 TestLoadTimingNotReusedWithPac(load_timing_info
,
9701 CONNECT_TIMING_HAS_SSL_TIMES
);
9704 TEST_P(HttpNetworkTransactionTest
,
9705 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9706 session_deps_
.use_alternate_protocols
= true;
9707 session_deps_
.next_protos
= SpdyNextProtos();
9709 HttpRequestInfo request
;
9710 request
.method
= "GET";
9711 request
.url
= GURL("http://www.example.org/");
9712 request
.load_flags
= 0;
9714 std::string alternate_protocol_http_header
=
9715 GetAlternateProtocolHttpHeader();
9717 MockRead data_reads
[] = {
9718 MockRead("HTTP/1.1 200 OK\r\n"),
9719 MockRead(alternate_protocol_http_header
.c_str()),
9720 MockRead("hello world"),
9721 MockRead(ASYNC
, OK
),
9724 StaticSocketDataProvider
first_transaction(
9725 data_reads
, arraysize(data_reads
), NULL
, 0);
9726 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9728 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9729 ssl
.SetNextProto(GetParam());
9730 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9731 ASSERT_TRUE(ssl
.cert
.get());
9732 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9734 scoped_ptr
<SpdyFrame
> req(
9735 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9736 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9738 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9739 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9740 MockRead spdy_reads
[] = {
9741 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9744 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9745 arraysize(spdy_writes
));
9746 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9748 TestCompletionCallback callback
;
9750 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9752 scoped_ptr
<HttpTransaction
> trans(
9753 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9755 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9757 EXPECT_EQ(OK
, callback
.WaitForResult());
9759 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9760 ASSERT_TRUE(response
!= NULL
);
9761 ASSERT_TRUE(response
->headers
.get() != NULL
);
9762 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9764 std::string response_data
;
9765 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9766 EXPECT_EQ("hello world", response_data
);
9768 // Set up an initial SpdySession in the pool to reuse.
9769 HostPortPair
host_port_pair("www.example.org", 443);
9770 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9771 PRIVACY_MODE_DISABLED
);
9772 base::WeakPtr
<SpdySession
> spdy_session
=
9773 CreateSecureSpdySession(session
, key
, BoundNetLog());
9775 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9777 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9778 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9779 EXPECT_EQ(OK
, callback
.WaitForResult());
9781 response
= trans
->GetResponseInfo();
9782 ASSERT_TRUE(response
!= NULL
);
9783 ASSERT_TRUE(response
->headers
.get() != NULL
);
9784 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9785 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9786 EXPECT_TRUE(response
->was_npn_negotiated
);
9788 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9789 EXPECT_EQ("hello!", response_data
);
9792 // GenerateAuthToken is a mighty big test.
9793 // It tests all permutation of GenerateAuthToken behavior:
9794 // - Synchronous and Asynchronous completion.
9795 // - OK or error on completion.
9796 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9797 // - HTTP or HTTPS backend (to include proxy tunneling).
9798 // - Non-authenticating and authenticating backend.
9800 // In all, there are 44 reasonable permuations (for example, if there are
9801 // problems generating an auth token for an authenticating proxy, we don't
9802 // need to test all permutations of the backend server).
9804 // The test proceeds by going over each of the configuration cases, and
9805 // potentially running up to three rounds in each of the tests. The TestConfig
9806 // specifies both the configuration for the test as well as the expectations
9808 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9809 static const char kServer
[] = "http://www.example.com";
9810 static const char kSecureServer
[] = "https://www.example.com";
9811 static const char kProxy
[] = "myproxy:70";
9812 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9820 const MockWrite
kGet(
9821 "GET / HTTP/1.1\r\n"
9822 "Host: www.example.com\r\n"
9823 "Connection: keep-alive\r\n\r\n");
9824 const MockWrite
kGetProxy(
9825 "GET http://www.example.com/ HTTP/1.1\r\n"
9826 "Host: www.example.com\r\n"
9827 "Proxy-Connection: keep-alive\r\n\r\n");
9828 const MockWrite
kGetAuth(
9829 "GET / HTTP/1.1\r\n"
9830 "Host: www.example.com\r\n"
9831 "Connection: keep-alive\r\n"
9832 "Authorization: auth_token\r\n\r\n");
9833 const MockWrite
kGetProxyAuth(
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\r\n");
9838 const MockWrite
kGetAuthThroughProxy(
9839 "GET http://www.example.com/ HTTP/1.1\r\n"
9840 "Host: www.example.com\r\n"
9841 "Proxy-Connection: keep-alive\r\n"
9842 "Authorization: auth_token\r\n\r\n");
9843 const MockWrite
kGetAuthWithProxyAuth(
9844 "GET http://www.example.com/ 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"
9848 "Authorization: auth_token\r\n\r\n");
9849 const MockWrite
kConnect(
9850 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9851 "Host: www.example.com\r\n"
9852 "Proxy-Connection: keep-alive\r\n\r\n");
9853 const MockWrite
kConnectProxyAuth(
9854 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9855 "Host: www.example.com\r\n"
9856 "Proxy-Connection: keep-alive\r\n"
9857 "Proxy-Authorization: auth_token\r\n\r\n");
9859 const MockRead
kSuccess(
9860 "HTTP/1.1 200 OK\r\n"
9861 "Content-Type: text/html; charset=iso-8859-1\r\n"
9862 "Content-Length: 3\r\n\r\n"
9864 const MockRead
kFailure(
9865 "Should not be called.");
9866 const MockRead
kServerChallenge(
9867 "HTTP/1.1 401 Unauthorized\r\n"
9868 "WWW-Authenticate: Mock realm=server\r\n"
9869 "Content-Type: text/html; charset=iso-8859-1\r\n"
9870 "Content-Length: 14\r\n\r\n"
9871 "Unauthorized\r\n");
9872 const MockRead
kProxyChallenge(
9873 "HTTP/1.1 407 Unauthorized\r\n"
9874 "Proxy-Authenticate: Mock realm=proxy\r\n"
9875 "Proxy-Connection: close\r\n"
9876 "Content-Type: text/html; charset=iso-8859-1\r\n"
9877 "Content-Length: 14\r\n\r\n"
9878 "Unauthorized\r\n");
9879 const MockRead
kProxyConnected(
9880 "HTTP/1.1 200 Connection Established\r\n\r\n");
9882 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9883 // no constructors, but the C++ compiler on Windows warns about
9884 // unspecified data in compound literals. So, moved to using constructors,
9885 // and TestRound's created with the default constructor should not be used.
9888 : expected_rv(ERR_UNEXPECTED
),
9892 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9893 int expected_rv_arg
)
9896 expected_rv(expected_rv_arg
),
9900 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9901 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9902 const MockRead
* extra_read_arg
)
9905 expected_rv(expected_rv_arg
),
9906 extra_write(extra_write_arg
),
9907 extra_read(extra_read_arg
) {
9912 const MockWrite
* extra_write
;
9913 const MockRead
* extra_read
;
9916 static const int kNoSSL
= 500;
9919 const char* const proxy_url
;
9920 AuthTiming proxy_auth_timing
;
9922 const char* const server_url
;
9923 AuthTiming server_auth_timing
;
9925 int num_auth_rounds
;
9926 int first_ssl_round
;
9927 TestRound rounds
[3];
9928 } test_configs
[] = {
9929 // Non-authenticating HTTP server with a direct connection.
9930 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9931 { TestRound(kGet
, kSuccess
, OK
)}},
9932 // Authenticating HTTP server with a direct connection.
9933 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9934 { TestRound(kGet
, kServerChallenge
, OK
),
9935 TestRound(kGetAuth
, kSuccess
, OK
)}},
9936 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9937 { TestRound(kGet
, kServerChallenge
, OK
),
9938 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9939 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9940 { TestRound(kGet
, kServerChallenge
, OK
),
9941 TestRound(kGetAuth
, kSuccess
, OK
)}},
9942 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9943 { TestRound(kGet
, kServerChallenge
, OK
),
9944 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9945 // Non-authenticating HTTP server through a non-authenticating proxy.
9946 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9947 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9948 // Authenticating HTTP server through a non-authenticating proxy.
9949 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9950 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9951 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9952 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9953 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9954 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9955 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9956 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9957 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9958 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9959 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9960 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9961 // Non-authenticating HTTP server through an authenticating proxy.
9962 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9963 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9964 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9965 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9966 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9967 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9968 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9969 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9970 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
9971 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9972 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9973 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
9974 // Authenticating HTTP server through an authenticating proxy.
9975 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9976 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9977 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9978 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9979 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9980 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9981 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9982 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9983 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
9984 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9985 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9986 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9987 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
9988 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9989 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9990 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9991 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
9992 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9993 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9994 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
9995 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
9996 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
9997 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
9998 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
9999 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10000 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10001 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10002 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10003 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10004 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10005 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10006 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10007 // Non-authenticating HTTPS server with a direct connection.
10008 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10009 { TestRound(kGet
, kSuccess
, OK
)}},
10010 // Authenticating HTTPS server with a direct connection.
10011 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10012 { TestRound(kGet
, kServerChallenge
, OK
),
10013 TestRound(kGetAuth
, kSuccess
, OK
)}},
10014 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10015 { TestRound(kGet
, kServerChallenge
, OK
),
10016 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10017 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10018 { TestRound(kGet
, kServerChallenge
, OK
),
10019 TestRound(kGetAuth
, kSuccess
, OK
)}},
10020 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10021 { TestRound(kGet
, kServerChallenge
, OK
),
10022 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10023 // Non-authenticating HTTPS server with a non-authenticating proxy.
10024 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10025 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10026 // Authenticating HTTPS server through a non-authenticating proxy.
10027 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10028 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10029 TestRound(kGetAuth
, kSuccess
, OK
)}},
10030 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10031 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10032 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10033 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10034 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10035 TestRound(kGetAuth
, kSuccess
, OK
)}},
10036 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10037 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10038 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10039 // Non-Authenticating HTTPS server through an authenticating proxy.
10040 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10041 { TestRound(kConnect
, kProxyChallenge
, OK
),
10042 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10043 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10044 { TestRound(kConnect
, kProxyChallenge
, OK
),
10045 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10046 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10047 { TestRound(kConnect
, kProxyChallenge
, OK
),
10048 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10049 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10050 { TestRound(kConnect
, kProxyChallenge
, OK
),
10051 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10052 // Authenticating HTTPS server through an authenticating proxy.
10053 { kProxy
, AUTH_SYNC
, 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_SYNC
, 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_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10064 { TestRound(kConnect
, kProxyChallenge
, OK
),
10065 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10066 &kGet
, &kServerChallenge
),
10067 TestRound(kGetAuth
, kSuccess
, OK
)}},
10068 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10069 { TestRound(kConnect
, kProxyChallenge
, OK
),
10070 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10071 &kGet
, &kServerChallenge
),
10072 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10073 { kProxy
, AUTH_SYNC
, 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_SYNC
, 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
)}},
10083 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10084 { TestRound(kConnect
, kProxyChallenge
, OK
),
10085 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10086 &kGet
, &kServerChallenge
),
10087 TestRound(kGetAuth
, kSuccess
, OK
)}},
10088 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10089 { TestRound(kConnect
, kProxyChallenge
, OK
),
10090 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10091 &kGet
, &kServerChallenge
),
10092 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10095 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10096 HttpAuthHandlerMock::Factory
* auth_factory(
10097 new HttpAuthHandlerMock::Factory());
10098 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10099 const TestConfig
& test_config
= test_configs
[i
];
10101 // Set up authentication handlers as necessary.
10102 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10103 for (int n
= 0; n
< 2; n
++) {
10104 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10105 std::string auth_challenge
= "Mock realm=proxy";
10106 GURL
origin(test_config
.proxy_url
);
10107 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10108 auth_challenge
.end());
10109 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10110 origin
, BoundNetLog());
10111 auth_handler
->SetGenerateExpectation(
10112 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10113 test_config
.proxy_auth_rv
);
10114 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10117 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10118 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10119 std::string auth_challenge
= "Mock realm=server";
10120 GURL
origin(test_config
.server_url
);
10121 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10122 auth_challenge
.end());
10123 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10124 origin
, BoundNetLog());
10125 auth_handler
->SetGenerateExpectation(
10126 test_config
.server_auth_timing
== AUTH_ASYNC
,
10127 test_config
.server_auth_rv
);
10128 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10130 if (test_config
.proxy_url
) {
10131 session_deps_
.proxy_service
.reset(
10132 ProxyService::CreateFixed(test_config
.proxy_url
));
10134 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10137 HttpRequestInfo request
;
10138 request
.method
= "GET";
10139 request
.url
= GURL(test_config
.server_url
);
10140 request
.load_flags
= 0;
10142 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10143 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10145 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10146 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10148 // Set up expected reads and writes.
10150 reads
[0] = read_write_round
.read
;
10151 size_t length_reads
= 1;
10152 if (read_write_round
.extra_read
) {
10153 reads
[1] = *read_write_round
.extra_read
;
10157 MockWrite writes
[2];
10158 writes
[0] = read_write_round
.write
;
10159 size_t length_writes
= 1;
10160 if (read_write_round
.extra_write
) {
10161 writes
[1] = *read_write_round
.extra_write
;
10164 StaticSocketDataProvider
data_provider(
10165 reads
, length_reads
, writes
, length_writes
);
10166 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10168 // Add an SSL sequence if necessary.
10169 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10170 if (round
>= test_config
.first_ssl_round
)
10171 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10172 &ssl_socket_data_provider
);
10174 // Start or restart the transaction.
10175 TestCompletionCallback callback
;
10178 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10180 rv
= trans
.RestartWithAuth(
10181 AuthCredentials(kFoo
, kBar
), callback
.callback());
10183 if (rv
== ERR_IO_PENDING
)
10184 rv
= callback
.WaitForResult();
10186 // Compare results with expected data.
10187 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10188 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10189 if (read_write_round
.expected_rv
== OK
) {
10190 ASSERT_TRUE(response
!= NULL
);
10192 EXPECT_TRUE(response
== NULL
);
10193 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10196 if (round
+ 1 < test_config
.num_auth_rounds
) {
10197 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10199 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10205 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10206 // Do multi-round authentication and make sure it works correctly.
10207 HttpAuthHandlerMock::Factory
* auth_factory(
10208 new HttpAuthHandlerMock::Factory());
10209 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10210 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10211 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10212 session_deps_
.host_resolver
->set_synchronous_mode(true);
10214 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10215 auth_handler
->set_connection_based(true);
10216 std::string auth_challenge
= "Mock realm=server";
10217 GURL
origin("http://www.example.com");
10218 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10219 auth_challenge
.end());
10220 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10221 origin
, BoundNetLog());
10222 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10225 const HttpResponseInfo
* response
= NULL
;
10226 HttpRequestInfo request
;
10227 request
.method
= "GET";
10228 request
.url
= origin
;
10229 request
.load_flags
= 0;
10231 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10233 // Use a TCP Socket Pool with only one connection per group. This is used
10234 // to validate that the TCP socket is not released to the pool between
10235 // each round of multi-round authentication.
10236 HttpNetworkSessionPeer
session_peer(session
);
10237 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10238 50, // Max sockets for pool
10239 1, // Max sockets per group
10240 session_deps_
.host_resolver
.get(),
10241 session_deps_
.socket_factory
.get(),
10242 session_deps_
.net_log
);
10243 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10244 new MockClientSocketPoolManager
);
10245 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10246 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10248 scoped_ptr
<HttpTransaction
> trans(
10249 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10250 TestCompletionCallback callback
;
10252 const MockWrite
kGet(
10253 "GET / HTTP/1.1\r\n"
10254 "Host: www.example.com\r\n"
10255 "Connection: keep-alive\r\n\r\n");
10256 const MockWrite
kGetAuth(
10257 "GET / HTTP/1.1\r\n"
10258 "Host: www.example.com\r\n"
10259 "Connection: keep-alive\r\n"
10260 "Authorization: auth_token\r\n\r\n");
10262 const MockRead
kServerChallenge(
10263 "HTTP/1.1 401 Unauthorized\r\n"
10264 "WWW-Authenticate: Mock realm=server\r\n"
10265 "Content-Type: text/html; charset=iso-8859-1\r\n"
10266 "Content-Length: 14\r\n\r\n"
10267 "Unauthorized\r\n");
10268 const MockRead
kSuccess(
10269 "HTTP/1.1 200 OK\r\n"
10270 "Content-Type: text/html; charset=iso-8859-1\r\n"
10271 "Content-Length: 3\r\n\r\n"
10274 MockWrite writes
[] = {
10283 // Competing request
10286 MockRead reads
[] = {
10295 // Competing response
10298 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10299 writes
, arraysize(writes
));
10300 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10302 const char kSocketGroup
[] = "www.example.com:80";
10304 // First round of authentication.
10305 auth_handler
->SetGenerateExpectation(false, OK
);
10306 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10307 if (rv
== ERR_IO_PENDING
)
10308 rv
= callback
.WaitForResult();
10310 response
= trans
->GetResponseInfo();
10311 ASSERT_TRUE(response
!= NULL
);
10312 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10313 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10315 // In between rounds, another request comes in for the same domain.
10316 // It should not be able to grab the TCP socket that trans has already
10318 scoped_ptr
<HttpTransaction
> trans_compete(
10319 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10320 TestCompletionCallback callback_compete
;
10321 rv
= trans_compete
->Start(
10322 &request
, callback_compete
.callback(), BoundNetLog());
10323 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10324 // callback_compete.WaitForResult at this point would stall forever,
10325 // since the HttpNetworkTransaction does not release the request back to
10326 // the pool until after authentication completes.
10328 // Second round of authentication.
10329 auth_handler
->SetGenerateExpectation(false, OK
);
10330 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10331 if (rv
== ERR_IO_PENDING
)
10332 rv
= callback
.WaitForResult();
10334 response
= trans
->GetResponseInfo();
10335 ASSERT_TRUE(response
!= NULL
);
10336 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10337 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10339 // Third round of authentication.
10340 auth_handler
->SetGenerateExpectation(false, OK
);
10341 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10342 if (rv
== ERR_IO_PENDING
)
10343 rv
= callback
.WaitForResult();
10345 response
= trans
->GetResponseInfo();
10346 ASSERT_TRUE(response
!= NULL
);
10347 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10348 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10350 // Fourth round of authentication, which completes successfully.
10351 auth_handler
->SetGenerateExpectation(false, OK
);
10352 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10353 if (rv
== ERR_IO_PENDING
)
10354 rv
= callback
.WaitForResult();
10356 response
= trans
->GetResponseInfo();
10357 ASSERT_TRUE(response
!= NULL
);
10358 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10359 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10361 // Read the body since the fourth round was successful. This will also
10362 // release the socket back to the pool.
10363 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10364 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10365 if (rv
== ERR_IO_PENDING
)
10366 rv
= callback
.WaitForResult();
10368 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10370 // There are still 0 idle sockets, since the trans_compete transaction
10371 // will be handed it immediately after trans releases it to the group.
10372 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10374 // The competing request can now finish. Wait for the headers and then
10376 rv
= callback_compete
.WaitForResult();
10378 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10379 if (rv
== ERR_IO_PENDING
)
10380 rv
= callback
.WaitForResult();
10382 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10385 // Finally, the socket is released to the group.
10386 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10389 // This tests the case that a request is issued via http instead of spdy after
10390 // npn is negotiated.
10391 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10392 session_deps_
.use_alternate_protocols
= true;
10393 NextProtoVector next_protos
;
10394 next_protos
.push_back(kProtoHTTP11
);
10395 session_deps_
.next_protos
= next_protos
;
10397 HttpRequestInfo request
;
10398 request
.method
= "GET";
10399 request
.url
= GURL("https://www.example.org/");
10400 request
.load_flags
= 0;
10402 MockWrite data_writes
[] = {
10404 "GET / HTTP/1.1\r\n"
10405 "Host: www.example.org\r\n"
10406 "Connection: keep-alive\r\n\r\n"),
10409 std::string alternate_protocol_http_header
=
10410 GetAlternateProtocolHttpHeader();
10412 MockRead data_reads
[] = {
10413 MockRead("HTTP/1.1 200 OK\r\n"),
10414 MockRead(alternate_protocol_http_header
.c_str()),
10415 MockRead("hello world"),
10416 MockRead(SYNCHRONOUS
, OK
),
10419 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10420 ssl
.SetNextProto(kProtoHTTP11
);
10422 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10424 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10425 data_writes
, arraysize(data_writes
));
10426 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10428 TestCompletionCallback callback
;
10430 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10431 scoped_ptr
<HttpTransaction
> trans(
10432 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10434 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10436 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10437 EXPECT_EQ(OK
, callback
.WaitForResult());
10439 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10440 ASSERT_TRUE(response
!= NULL
);
10441 ASSERT_TRUE(response
->headers
.get() != NULL
);
10442 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10444 std::string response_data
;
10445 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10446 EXPECT_EQ("hello world", response_data
);
10448 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10449 EXPECT_TRUE(response
->was_npn_negotiated
);
10452 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10453 // Simulate the SSL handshake completing with an NPN negotiation
10454 // followed by an immediate server closing of the socket.
10455 // Fix crash: http://crbug.com/46369
10456 session_deps_
.use_alternate_protocols
= true;
10457 session_deps_
.next_protos
= SpdyNextProtos();
10459 HttpRequestInfo request
;
10460 request
.method
= "GET";
10461 request
.url
= GURL("https://www.example.org/");
10462 request
.load_flags
= 0;
10464 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10465 ssl
.SetNextProto(GetParam());
10466 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10468 scoped_ptr
<SpdyFrame
> req(
10469 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10470 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10472 MockRead spdy_reads
[] = {
10473 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10476 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10477 arraysize(spdy_writes
));
10478 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10480 TestCompletionCallback callback
;
10482 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10483 scoped_ptr
<HttpTransaction
> trans(
10484 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10486 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10487 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10488 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10491 // A subclass of HttpAuthHandlerMock that records the request URL when
10492 // it gets it. This is needed since the auth handler may get destroyed
10493 // before we get a chance to query it.
10494 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10496 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10498 ~UrlRecordingHttpAuthHandlerMock() override
{}
10501 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10502 const HttpRequestInfo
* request
,
10503 const CompletionCallback
& callback
,
10504 std::string
* auth_token
) override
{
10505 *url_
= request
->url
;
10506 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10507 credentials
, request
, callback
, auth_token
);
10514 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10515 // This test ensures that the URL passed into the proxy is upgraded
10516 // to https when doing an Alternate Protocol upgrade.
10517 session_deps_
.use_alternate_protocols
= true;
10518 session_deps_
.next_protos
= SpdyNextProtos();
10520 session_deps_
.proxy_service
.reset(
10521 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10522 TestNetLog net_log
;
10523 session_deps_
.net_log
= &net_log
;
10526 HttpAuthHandlerMock::Factory
* auth_factory
=
10527 new HttpAuthHandlerMock::Factory();
10528 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10529 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10530 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10531 auth_factory
->set_do_init_from_challenge(true);
10532 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10535 HttpRequestInfo request
;
10536 request
.method
= "GET";
10537 request
.url
= GURL("http://www.example.org");
10538 request
.load_flags
= 0;
10540 // First round goes unauthenticated through the proxy.
10541 MockWrite data_writes_1
[] = {
10543 "GET http://www.example.org/ HTTP/1.1\r\n"
10544 "Host: www.example.org\r\n"
10545 "Proxy-Connection: keep-alive\r\n"
10548 MockRead data_reads_1
[] = {
10549 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10550 MockRead("HTTP/1.1 200 OK\r\n"),
10551 MockRead("Alternate-Protocol: 443:"),
10552 MockRead(GetAlternateProtocolFromParam()),
10554 MockRead("Proxy-Connection: close\r\n"),
10557 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10558 data_writes_1
, arraysize(data_writes_1
));
10560 // Second round tries to tunnel to www.example.org due to the
10561 // Alternate-Protocol announcement in the first round. It fails due
10562 // to a proxy authentication challenge.
10563 // After the failure, a tunnel is established to www.example.org using
10564 // Proxy-Authorization headers. There is then a SPDY request round.
10566 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10567 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10568 // does a Disconnect and Connect on the same socket, rather than trying
10569 // to obtain a new one.
10571 // NOTE: Originally, the proxy response to the second CONNECT request
10572 // simply returned another 407 so the unit test could skip the SSL connection
10573 // establishment and SPDY framing issues. Alas, the
10574 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10575 // complicated to set up expectations for than the SPDY session.
10577 scoped_ptr
<SpdyFrame
> req(
10578 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10579 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10580 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10582 MockWrite data_writes_2
[] = {
10583 // First connection attempt without Proxy-Authorization.
10584 MockWrite(ASYNC
, 0,
10585 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10586 "Host: www.example.org\r\n"
10587 "Proxy-Connection: keep-alive\r\n"
10590 // Second connection attempt with Proxy-Authorization.
10591 MockWrite(ASYNC
, 2,
10592 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10593 "Host: www.example.org\r\n"
10594 "Proxy-Connection: keep-alive\r\n"
10595 "Proxy-Authorization: auth_token\r\n"
10599 CreateMockWrite(*req
, 4),
10601 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10602 "Proxy-Authenticate: Mock\r\n"
10603 "Proxy-Connection: close\r\n"
10605 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10606 MockRead data_reads_2
[] = {
10607 // First connection attempt fails
10608 MockRead(ASYNC
, kRejectConnectResponse
,
10609 arraysize(kRejectConnectResponse
) - 1, 1),
10611 // Second connection attempt passes
10612 MockRead(ASYNC
, kAcceptConnectResponse
,
10613 arraysize(kAcceptConnectResponse
) - 1, 3),
10616 CreateMockRead(*resp
.get(), 5),
10617 CreateMockRead(*data
.get(), 6),
10618 MockRead(ASYNC
, 0, 0, 7),
10620 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10621 data_writes_2
, arraysize(data_writes_2
));
10623 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10624 ssl
.SetNextProto(GetParam());
10625 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10626 ASSERT_TRUE(ssl
.cert
.get());
10628 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10629 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10631 hanging_non_alternate_protocol_socket
.set_connect_data(
10632 never_finishing_connect
);
10634 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10635 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10636 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10637 session_deps_
.socket_factory
->AddSocketDataProvider(
10638 &hanging_non_alternate_protocol_socket
);
10639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10641 // First round should work and provide the Alternate-Protocol state.
10642 TestCompletionCallback callback_1
;
10643 scoped_ptr
<HttpTransaction
> trans_1(
10644 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10645 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10646 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10647 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10649 // Second round should attempt a tunnel connect and get an auth challenge.
10650 TestCompletionCallback callback_2
;
10651 scoped_ptr
<HttpTransaction
> trans_2(
10652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10653 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10654 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10655 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10656 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10657 ASSERT_TRUE(response
!= NULL
);
10658 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10660 // Restart with auth. Tunnel should work and response received.
10661 TestCompletionCallback callback_3
;
10662 rv
= trans_2
->RestartWithAuth(
10663 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10664 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10665 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10667 // After all that work, these two lines (or actually, just the scheme) are
10668 // what this test is all about. Make sure it happens correctly.
10669 EXPECT_EQ("https", request_url
.scheme());
10670 EXPECT_EQ("www.example.org", request_url
.host());
10672 LoadTimingInfo load_timing_info
;
10673 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10674 TestLoadTimingNotReusedWithPac(load_timing_info
,
10675 CONNECT_TIMING_HAS_SSL_TIMES
);
10678 // Test that if we cancel the transaction as the connection is completing, that
10679 // everything tears down correctly.
10680 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10681 // Setup everything about the connection to complete synchronously, so that
10682 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10683 // for is the callback from the HttpStreamRequest.
10684 // Then cancel the transaction.
10685 // Verify that we don't crash.
10686 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10687 MockRead data_reads
[] = {
10688 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10689 MockRead(SYNCHRONOUS
, "hello world"),
10690 MockRead(SYNCHRONOUS
, OK
),
10693 HttpRequestInfo request
;
10694 request
.method
= "GET";
10695 request
.url
= GURL("http://www.example.org/");
10696 request
.load_flags
= 0;
10698 session_deps_
.host_resolver
->set_synchronous_mode(true);
10699 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10700 scoped_ptr
<HttpTransaction
> trans(
10701 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10703 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10704 data
.set_connect_data(mock_connect
);
10705 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10707 TestCompletionCallback callback
;
10709 BoundTestNetLog log
;
10710 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10711 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10712 trans
.reset(); // Cancel the transaction here.
10714 base::MessageLoop::current()->RunUntilIdle();
10717 // Test that if a transaction is cancelled after receiving the headers, the
10718 // stream is drained properly and added back to the socket pool. The main
10719 // purpose of this test is to make sure that an HttpStreamParser can be read
10720 // from after the HttpNetworkTransaction and the objects it owns have been
10722 // See http://crbug.com/368418
10723 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10724 MockRead data_reads
[] = {
10725 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10726 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10727 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10728 MockRead(ASYNC
, "1"),
10729 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10730 // HttpNetworkTransaction has been deleted.
10731 MockRead(ASYNC
, "2"),
10732 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10734 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10735 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10737 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10740 HttpRequestInfo request
;
10741 request
.method
= "GET";
10742 request
.url
= GURL("http://www.example.org/");
10743 request
.load_flags
= 0;
10745 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10746 TestCompletionCallback callback
;
10748 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10749 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10750 callback
.WaitForResult();
10752 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10753 ASSERT_TRUE(response
!= NULL
);
10754 EXPECT_TRUE(response
->headers
.get() != NULL
);
10755 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10757 // The transaction and HttpRequestInfo are deleted.
10760 // Let the HttpResponseBodyDrainer drain the socket.
10761 base::MessageLoop::current()->RunUntilIdle();
10763 // Socket should now be idle, waiting to be reused.
10764 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10767 // Test a basic GET request through a proxy.
10768 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10769 session_deps_
.proxy_service
.reset(
10770 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10771 BoundTestNetLog log
;
10772 session_deps_
.net_log
= log
.bound().net_log();
10773 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10775 HttpRequestInfo request
;
10776 request
.method
= "GET";
10777 request
.url
= GURL("http://www.example.org/");
10779 MockWrite data_writes1
[] = {
10781 "GET http://www.example.org/ HTTP/1.1\r\n"
10782 "Host: www.example.org\r\n"
10783 "Proxy-Connection: keep-alive\r\n\r\n"),
10786 MockRead data_reads1
[] = {
10787 MockRead("HTTP/1.1 200 OK\r\n"),
10788 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10789 MockRead("Content-Length: 100\r\n\r\n"),
10790 MockRead(SYNCHRONOUS
, OK
),
10793 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10794 data_writes1
, arraysize(data_writes1
));
10795 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10797 TestCompletionCallback callback1
;
10799 scoped_ptr
<HttpTransaction
> trans(
10800 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10801 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10802 trans
->SetBeforeProxyHeadersSentCallback(
10803 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10804 base::Unretained(&proxy_headers_handler
)));
10806 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10809 rv
= callback1
.WaitForResult();
10812 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10813 ASSERT_TRUE(response
!= NULL
);
10815 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10816 EXPECT_EQ(200, response
->headers
->response_code());
10817 EXPECT_EQ(100, response
->headers
->GetContentLength());
10818 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10820 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10821 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10822 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10823 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10825 LoadTimingInfo load_timing_info
;
10826 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10827 TestLoadTimingNotReusedWithPac(load_timing_info
,
10828 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10831 // Test a basic HTTPS GET request through a proxy.
10832 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10833 session_deps_
.proxy_service
.reset(
10834 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10835 BoundTestNetLog log
;
10836 session_deps_
.net_log
= log
.bound().net_log();
10837 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10839 HttpRequestInfo request
;
10840 request
.method
= "GET";
10841 request
.url
= GURL("https://www.example.org/");
10843 // Since we have proxy, should try to establish tunnel.
10844 MockWrite data_writes1
[] = {
10846 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10847 "Host: www.example.org\r\n"
10848 "Proxy-Connection: keep-alive\r\n\r\n"),
10851 "GET / HTTP/1.1\r\n"
10852 "Host: www.example.org\r\n"
10853 "Connection: keep-alive\r\n\r\n"),
10856 MockRead data_reads1
[] = {
10857 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10859 MockRead("HTTP/1.1 200 OK\r\n"),
10860 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10861 MockRead("Content-Length: 100\r\n\r\n"),
10862 MockRead(SYNCHRONOUS
, OK
),
10865 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10866 data_writes1
, arraysize(data_writes1
));
10867 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10868 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10869 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10871 TestCompletionCallback callback1
;
10873 scoped_ptr
<HttpTransaction
> trans(
10874 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10876 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10877 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10879 rv
= callback1
.WaitForResult();
10881 TestNetLogEntry::List entries
;
10882 log
.GetEntries(&entries
);
10883 size_t pos
= ExpectLogContainsSomewhere(
10884 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10885 NetLog::PHASE_NONE
);
10886 ExpectLogContainsSomewhere(
10888 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10889 NetLog::PHASE_NONE
);
10891 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10892 ASSERT_TRUE(response
!= NULL
);
10894 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10895 EXPECT_EQ(200, response
->headers
->response_code());
10896 EXPECT_EQ(100, response
->headers
->GetContentLength());
10897 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10898 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10900 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10902 LoadTimingInfo load_timing_info
;
10903 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10904 TestLoadTimingNotReusedWithPac(load_timing_info
,
10905 CONNECT_TIMING_HAS_SSL_TIMES
);
10908 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10909 // while establishing the tunnel.
10910 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10911 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10912 BoundTestNetLog log
;
10913 session_deps_
.net_log
= log
.bound().net_log();
10914 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10916 HttpRequestInfo request
;
10917 request
.method
= "GET";
10918 request
.url
= GURL("https://www.example.org/");
10920 // Since we have proxy, should try to establish tunnel.
10921 MockWrite data_writes1
[] = {
10923 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10924 "Host: www.example.org\r\n"
10925 "Proxy-Connection: keep-alive\r\n\r\n"),
10928 "GET / HTTP/1.1\r\n"
10929 "Host: www.example.org\r\n"
10930 "Connection: keep-alive\r\n\r\n"),
10933 MockRead data_reads1
[] = {
10934 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10935 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10936 MockRead(ASYNC
, 0, 0), // EOF
10939 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10940 data_writes1
, arraysize(data_writes1
));
10941 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10942 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10943 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10945 TestCompletionCallback callback1
;
10947 scoped_ptr
<HttpTransaction
> trans(
10948 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10950 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10951 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10953 rv
= callback1
.WaitForResult();
10954 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10955 TestNetLogEntry::List entries
;
10956 log
.GetEntries(&entries
);
10957 size_t pos
= ExpectLogContainsSomewhere(
10958 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10959 NetLog::PHASE_NONE
);
10960 ExpectLogContainsSomewhere(
10962 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10963 NetLog::PHASE_NONE
);
10966 // Test for crbug.com/55424.
10967 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
10968 scoped_ptr
<SpdyFrame
> req(
10969 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
10970 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
10972 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10973 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10974 MockRead spdy_reads
[] = {
10975 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
10978 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10979 arraysize(spdy_writes
));
10980 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10982 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10983 ssl
.SetNextProto(GetParam());
10984 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10986 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10988 // Set up an initial SpdySession in the pool to reuse.
10989 HostPortPair
host_port_pair("www.example.org", 443);
10990 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
10991 PRIVACY_MODE_DISABLED
);
10992 base::WeakPtr
<SpdySession
> spdy_session
=
10993 CreateInsecureSpdySession(session
, key
, BoundNetLog());
10995 HttpRequestInfo request
;
10996 request
.method
= "GET";
10997 request
.url
= GURL("https://www.example.org/");
10998 request
.load_flags
= 0;
11000 // This is the important line that marks this as a preconnect.
11001 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11003 scoped_ptr
<HttpTransaction
> trans(
11004 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11006 TestCompletionCallback callback
;
11007 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11008 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11009 EXPECT_EQ(OK
, callback
.WaitForResult());
11012 // Given a net error, cause that error to be returned from the first Write()
11013 // call and verify that the HttpTransaction fails with that error.
11014 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11015 int error
, IoMode mode
) {
11016 HttpRequestInfo request_info
;
11017 request_info
.url
= GURL("https://www.example.com/");
11018 request_info
.method
= "GET";
11019 request_info
.load_flags
= LOAD_NORMAL
;
11021 SSLSocketDataProvider
ssl_data(mode
, OK
);
11022 MockWrite data_writes
[] = {
11023 MockWrite(mode
, error
),
11025 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11026 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11027 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11029 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11030 scoped_ptr
<HttpTransaction
> trans(
11031 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11033 TestCompletionCallback callback
;
11034 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11035 if (rv
== ERR_IO_PENDING
)
11036 rv
= callback
.WaitForResult();
11037 ASSERT_EQ(error
, rv
);
11040 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11041 // Just check a grab bag of cert errors.
11042 static const int kErrors
[] = {
11043 ERR_CERT_COMMON_NAME_INVALID
,
11044 ERR_CERT_AUTHORITY_INVALID
,
11045 ERR_CERT_DATE_INVALID
,
11047 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11048 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11049 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11053 // Ensure that a client certificate is removed from the SSL client auth
11055 // 1) No proxy is involved.
11056 // 2) TLS False Start is disabled.
11057 // 3) The initial TLS handshake requests a client certificate.
11058 // 4) The client supplies an invalid/unacceptable certificate.
11059 TEST_P(HttpNetworkTransactionTest
,
11060 ClientAuthCertCache_Direct_NoFalseStart
) {
11061 HttpRequestInfo request_info
;
11062 request_info
.url
= GURL("https://www.example.com/");
11063 request_info
.method
= "GET";
11064 request_info
.load_flags
= LOAD_NORMAL
;
11066 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11067 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11069 // [ssl_]data1 contains the data for the first SSL handshake. When a
11070 // CertificateRequest is received for the first time, the handshake will
11071 // be aborted to allow the caller to provide a certificate.
11072 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11073 ssl_data1
.cert_request_info
= cert_request
.get();
11074 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11075 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11076 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11078 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11079 // False Start is not being used, the result of the SSL handshake will be
11080 // returned as part of the SSLClientSocket::Connect() call. This test
11081 // matches the result of a server sending a handshake_failure alert,
11082 // rather than a Finished message, because it requires a client
11083 // certificate and none was supplied.
11084 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11085 ssl_data2
.cert_request_info
= cert_request
.get();
11086 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11087 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11088 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11090 // [ssl_]data3 contains the data for the third SSL handshake. When a
11091 // connection to a server fails during an SSL handshake,
11092 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11093 // connection was attempted with TLSv1.1. This is transparent to the caller
11094 // of the HttpNetworkTransaction. Because this test failure is due to
11095 // requiring a client certificate, this fallback handshake should also
11097 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11098 ssl_data3
.cert_request_info
= cert_request
.get();
11099 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11100 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11101 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11103 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11104 // connection to a server fails during an SSL handshake,
11105 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
11106 // connection was attempted with TLSv1. This is transparent to the caller
11107 // of the HttpNetworkTransaction. Because this test failure is due to
11108 // requiring a client certificate, this fallback handshake should also
11110 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11111 ssl_data4
.cert_request_info
= cert_request
.get();
11112 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11113 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11114 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11116 // Need one more if TLSv1.2 is enabled.
11117 SSLSocketDataProvider
ssl_data5(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11118 ssl_data5
.cert_request_info
= cert_request
.get();
11119 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11120 StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
11121 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11123 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11124 scoped_ptr
<HttpTransaction
> trans(
11125 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11127 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11128 TestCompletionCallback callback
;
11129 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11130 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11132 // Complete the SSL handshake, which should abort due to requiring a
11133 // client certificate.
11134 rv
= callback
.WaitForResult();
11135 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11137 // Indicate that no certificate should be supplied. From the perspective
11138 // of SSLClientCertCache, NULL is just as meaningful as a real
11139 // certificate, so this is the same as supply a
11140 // legitimate-but-unacceptable certificate.
11141 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11142 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11144 // Ensure the certificate was added to the client auth cache before
11145 // allowing the connection to continue restarting.
11146 scoped_refptr
<X509Certificate
> client_cert
;
11147 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11148 HostPortPair("www.example.com", 443), &client_cert
));
11149 ASSERT_EQ(NULL
, client_cert
.get());
11151 // Restart the handshake. This will consume ssl_data2, which fails, and
11152 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11153 // The result code is checked against what ssl_data4 should return.
11154 rv
= callback
.WaitForResult();
11155 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11157 // Ensure that the client certificate is removed from the cache on a
11158 // handshake failure.
11159 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11160 HostPortPair("www.example.com", 443), &client_cert
));
11163 // Ensure that a client certificate is removed from the SSL client auth
11165 // 1) No proxy is involved.
11166 // 2) TLS False Start is enabled.
11167 // 3) The initial TLS handshake requests a client certificate.
11168 // 4) The client supplies an invalid/unacceptable certificate.
11169 TEST_P(HttpNetworkTransactionTest
,
11170 ClientAuthCertCache_Direct_FalseStart
) {
11171 HttpRequestInfo request_info
;
11172 request_info
.url
= GURL("https://www.example.com/");
11173 request_info
.method
= "GET";
11174 request_info
.load_flags
= LOAD_NORMAL
;
11176 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11177 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11179 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11180 // return successfully after reading up to the peer's Certificate message.
11181 // This is to allow the caller to call SSLClientSocket::Write(), which can
11182 // enqueue application data to be sent in the same packet as the
11183 // ChangeCipherSpec and Finished messages.
11184 // The actual handshake will be finished when SSLClientSocket::Read() is
11185 // called, which expects to process the peer's ChangeCipherSpec and
11186 // Finished messages. If there was an error negotiating with the peer,
11187 // such as due to the peer requiring a client certificate when none was
11188 // supplied, the alert sent by the peer won't be processed until Read() is
11191 // Like the non-False Start case, when a client certificate is requested by
11192 // the peer, the handshake is aborted during the Connect() call.
11193 // [ssl_]data1 represents the initial SSL handshake with the peer.
11194 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11195 ssl_data1
.cert_request_info
= cert_request
.get();
11196 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11197 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11198 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11200 // When a client certificate is supplied, Connect() will not be aborted
11201 // when the peer requests the certificate. Instead, the handshake will
11202 // artificially succeed, allowing the caller to write the HTTP request to
11203 // the socket. The handshake messages are not processed until Read() is
11204 // called, which then detects that the handshake was aborted, due to the
11205 // peer sending a handshake_failure because it requires a client
11207 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11208 ssl_data2
.cert_request_info
= cert_request
.get();
11209 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11210 MockRead data2_reads
[] = {
11211 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11213 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11214 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11216 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11217 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11218 // TLSv1. It has the same behaviour as [ssl_]data2.
11219 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11220 ssl_data3
.cert_request_info
= cert_request
.get();
11221 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11222 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11223 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11225 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11226 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11227 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11228 ssl_data4
.cert_request_info
= cert_request
.get();
11229 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11230 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11231 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11233 // Need one more if TLSv1.2 is enabled.
11234 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11235 ssl_data5
.cert_request_info
= cert_request
.get();
11236 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11237 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11238 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11240 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11241 scoped_ptr
<HttpTransaction
> trans(
11242 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11244 // Begin the initial SSL handshake.
11245 TestCompletionCallback callback
;
11246 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11247 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11249 // Complete the SSL handshake, which should abort due to requiring a
11250 // client certificate.
11251 rv
= callback
.WaitForResult();
11252 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11254 // Indicate that no certificate should be supplied. From the perspective
11255 // of SSLClientCertCache, NULL is just as meaningful as a real
11256 // certificate, so this is the same as supply a
11257 // legitimate-but-unacceptable certificate.
11258 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11259 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11261 // Ensure the certificate was added to the client auth cache before
11262 // allowing the connection to continue restarting.
11263 scoped_refptr
<X509Certificate
> client_cert
;
11264 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11265 HostPortPair("www.example.com", 443), &client_cert
));
11266 ASSERT_EQ(NULL
, client_cert
.get());
11268 // Restart the handshake. This will consume ssl_data2, which fails, and
11269 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11270 // The result code is checked against what ssl_data4 should return.
11271 rv
= callback
.WaitForResult();
11272 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11274 // Ensure that the client certificate is removed from the cache on a
11275 // handshake failure.
11276 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11277 HostPortPair("www.example.com", 443), &client_cert
));
11280 // Ensure that a client certificate is removed from the SSL client auth
11282 // 1) An HTTPS proxy is involved.
11283 // 3) The HTTPS proxy requests a client certificate.
11284 // 4) The client supplies an invalid/unacceptable certificate for the
11286 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11287 // then for connecting to an HTTP endpoint.
11288 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11289 session_deps_
.proxy_service
.reset(
11290 ProxyService::CreateFixed("https://proxy:70"));
11291 BoundTestNetLog log
;
11292 session_deps_
.net_log
= log
.bound().net_log();
11294 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11295 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11297 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11298 // [ssl_]data[1-3]. Rather than represending the endpoint
11299 // (www.example.com:443), they represent failures with the HTTPS proxy
11301 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11302 ssl_data1
.cert_request_info
= cert_request
.get();
11303 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11304 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11305 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11307 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11308 ssl_data2
.cert_request_info
= cert_request
.get();
11309 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11310 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11311 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11313 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11315 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11316 ssl_data3
.cert_request_info
= cert_request
.get();
11317 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11318 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11319 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11322 HttpRequestInfo requests
[2];
11323 requests
[0].url
= GURL("https://www.example.com/");
11324 requests
[0].method
= "GET";
11325 requests
[0].load_flags
= LOAD_NORMAL
;
11327 requests
[1].url
= GURL("http://www.example.com/");
11328 requests
[1].method
= "GET";
11329 requests
[1].load_flags
= LOAD_NORMAL
;
11331 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11332 session_deps_
.socket_factory
->ResetNextMockIndexes();
11333 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11334 scoped_ptr
<HttpNetworkTransaction
> trans(
11335 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11337 // Begin the SSL handshake with the proxy.
11338 TestCompletionCallback callback
;
11339 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11340 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11342 // Complete the SSL handshake, which should abort due to requiring a
11343 // client certificate.
11344 rv
= callback
.WaitForResult();
11345 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11347 // Indicate that no certificate should be supplied. From the perspective
11348 // of SSLClientCertCache, NULL is just as meaningful as a real
11349 // certificate, so this is the same as supply a
11350 // legitimate-but-unacceptable certificate.
11351 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11352 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11354 // Ensure the certificate was added to the client auth cache before
11355 // allowing the connection to continue restarting.
11356 scoped_refptr
<X509Certificate
> client_cert
;
11357 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11358 HostPortPair("proxy", 70), &client_cert
));
11359 ASSERT_EQ(NULL
, client_cert
.get());
11360 // Ensure the certificate was NOT cached for the endpoint. This only
11361 // applies to HTTPS requests, but is fine to check for HTTP requests.
11362 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11363 HostPortPair("www.example.com", 443), &client_cert
));
11365 // Restart the handshake. This will consume ssl_data2, which fails, and
11366 // then consume ssl_data3, which should also fail. The result code is
11367 // checked against what ssl_data3 should return.
11368 rv
= callback
.WaitForResult();
11369 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11371 // Now that the new handshake has failed, ensure that the client
11372 // certificate was removed from the client auth cache.
11373 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11374 HostPortPair("proxy", 70), &client_cert
));
11375 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11376 HostPortPair("www.example.com", 443), &client_cert
));
11380 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11381 // TEST_P is a macro that expands directly to code that stringizes the
11382 // arguments. As a result, macros passed as parameters (such as prefix
11383 // or test_case_name) will not be expanded by the preprocessor. To
11384 // work around this, indirect the macro for TEST_P, so that the
11385 // pre-processor will expand macros such as MAYBE_test_name before
11386 // instantiating the test.
11387 #define WRAPPED_TEST_P(test_case_name, test_name) \
11388 TEST_P(test_case_name, test_name)
11390 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11391 #if defined(OS_WIN)
11392 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11394 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11396 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
11397 session_deps_
.use_alternate_protocols
= true;
11398 session_deps_
.next_protos
= SpdyNextProtos();
11400 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11401 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11402 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11403 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11404 pool_peer
.DisableDomainAuthenticationVerification();
11406 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11407 ssl
.SetNextProto(GetParam());
11408 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11410 scoped_ptr
<SpdyFrame
> host1_req(
11411 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11412 scoped_ptr
<SpdyFrame
> host2_req(
11413 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11414 MockWrite spdy_writes
[] = {
11415 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11417 scoped_ptr
<SpdyFrame
> host1_resp(
11418 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11419 scoped_ptr
<SpdyFrame
> host1_resp_body(
11420 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11421 scoped_ptr
<SpdyFrame
> host2_resp(
11422 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11423 scoped_ptr
<SpdyFrame
> host2_resp_body(
11424 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11425 MockRead spdy_reads
[] = {
11426 CreateMockRead(*host1_resp
, 1),
11427 CreateMockRead(*host1_resp_body
, 2),
11428 CreateMockRead(*host2_resp
, 4),
11429 CreateMockRead(*host2_resp_body
, 5),
11430 MockRead(ASYNC
, 0, 6),
11433 IPAddressNumber ip
;
11434 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11435 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11436 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11437 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11438 spdy_writes
, arraysize(spdy_writes
));
11439 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11441 TestCompletionCallback callback
;
11442 HttpRequestInfo request1
;
11443 request1
.method
= "GET";
11444 request1
.url
= GURL("https://www.example.org/");
11445 request1
.load_flags
= 0;
11446 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11448 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11449 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11450 EXPECT_EQ(OK
, callback
.WaitForResult());
11452 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11453 ASSERT_TRUE(response
!= NULL
);
11454 ASSERT_TRUE(response
->headers
.get() != NULL
);
11455 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11457 std::string response_data
;
11458 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11459 EXPECT_EQ("hello!", response_data
);
11461 // Preload www.gmail.com into HostCache.
11462 HostPortPair
host_port("www.gmail.com", 443);
11463 HostResolver::RequestInfo
resolve_info(host_port
);
11464 AddressList ignored
;
11465 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11468 callback
.callback(),
11471 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11472 rv
= callback
.WaitForResult();
11475 HttpRequestInfo request2
;
11476 request2
.method
= "GET";
11477 request2
.url
= GURL("https://www.gmail.com/");
11478 request2
.load_flags
= 0;
11479 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11481 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11482 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11483 EXPECT_EQ(OK
, callback
.WaitForResult());
11485 response
= trans2
.GetResponseInfo();
11486 ASSERT_TRUE(response
!= NULL
);
11487 ASSERT_TRUE(response
->headers
.get() != NULL
);
11488 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11489 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11490 EXPECT_TRUE(response
->was_npn_negotiated
);
11491 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11492 EXPECT_EQ("hello!", response_data
);
11494 #undef MAYBE_UseIPConnectionPooling
11496 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11497 session_deps_
.use_alternate_protocols
= true;
11498 session_deps_
.next_protos
= SpdyNextProtos();
11500 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11501 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11502 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11503 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11504 pool_peer
.DisableDomainAuthenticationVerification();
11506 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11507 ssl
.SetNextProto(GetParam());
11508 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11510 scoped_ptr
<SpdyFrame
> host1_req(
11511 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11512 scoped_ptr
<SpdyFrame
> host2_req(
11513 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11514 MockWrite spdy_writes
[] = {
11515 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11517 scoped_ptr
<SpdyFrame
> host1_resp(
11518 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11519 scoped_ptr
<SpdyFrame
> host1_resp_body(
11520 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11521 scoped_ptr
<SpdyFrame
> host2_resp(
11522 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11523 scoped_ptr
<SpdyFrame
> host2_resp_body(
11524 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11525 MockRead spdy_reads
[] = {
11526 CreateMockRead(*host1_resp
, 1),
11527 CreateMockRead(*host1_resp_body
, 2),
11528 CreateMockRead(*host2_resp
, 4),
11529 CreateMockRead(*host2_resp_body
, 5),
11530 MockRead(ASYNC
, 0, 6),
11533 IPAddressNumber ip
;
11534 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11535 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11536 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11537 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11538 spdy_writes
, arraysize(spdy_writes
));
11539 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11541 TestCompletionCallback callback
;
11542 HttpRequestInfo request1
;
11543 request1
.method
= "GET";
11544 request1
.url
= GURL("https://www.example.org/");
11545 request1
.load_flags
= 0;
11546 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11548 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11549 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11550 EXPECT_EQ(OK
, callback
.WaitForResult());
11552 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11553 ASSERT_TRUE(response
!= NULL
);
11554 ASSERT_TRUE(response
->headers
.get() != NULL
);
11555 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11557 std::string response_data
;
11558 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11559 EXPECT_EQ("hello!", response_data
);
11561 HttpRequestInfo request2
;
11562 request2
.method
= "GET";
11563 request2
.url
= GURL("https://www.gmail.com/");
11564 request2
.load_flags
= 0;
11565 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11567 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11569 EXPECT_EQ(OK
, callback
.WaitForResult());
11571 response
= trans2
.GetResponseInfo();
11572 ASSERT_TRUE(response
!= NULL
);
11573 ASSERT_TRUE(response
->headers
.get() != NULL
);
11574 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11575 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11576 EXPECT_TRUE(response
->was_npn_negotiated
);
11577 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11578 EXPECT_EQ("hello!", response_data
);
11581 class OneTimeCachingHostResolver
: public HostResolver
{
11583 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11584 : host_port_(host_port
) {}
11585 ~OneTimeCachingHostResolver() override
{}
11587 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11589 // HostResolver methods:
11590 int Resolve(const RequestInfo
& info
,
11591 RequestPriority priority
,
11592 AddressList
* addresses
,
11593 const CompletionCallback
& callback
,
11594 RequestHandle
* out_req
,
11595 const BoundNetLog
& net_log
) override
{
11596 return host_resolver_
.Resolve(
11597 info
, priority
, addresses
, callback
, out_req
, net_log
);
11600 int ResolveFromCache(const RequestInfo
& info
,
11601 AddressList
* addresses
,
11602 const BoundNetLog
& net_log
) override
{
11603 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11604 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11605 host_resolver_
.GetHostCache()->clear();
11609 void CancelRequest(RequestHandle req
) override
{
11610 host_resolver_
.CancelRequest(req
);
11613 MockCachingHostResolver
* GetMockHostResolver() {
11614 return &host_resolver_
;
11618 MockCachingHostResolver host_resolver_
;
11619 const HostPortPair host_port_
;
11622 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11623 #if defined(OS_WIN)
11624 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11625 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11627 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11628 UseIPConnectionPoolingWithHostCacheExpiration
11630 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11631 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11632 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11633 // prefix doesn't work with parametrized tests).
11634 #if defined(OS_WIN)
11637 session_deps_
.use_alternate_protocols
= true;
11638 session_deps_
.next_protos
= SpdyNextProtos();
11640 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11641 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11642 HttpNetworkSession::Params params
=
11643 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11644 params
.host_resolver
= &host_resolver
;
11645 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11646 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11647 pool_peer
.DisableDomainAuthenticationVerification();
11649 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11650 ssl
.SetNextProto(GetParam());
11651 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11653 scoped_ptr
<SpdyFrame
> host1_req(
11654 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11655 scoped_ptr
<SpdyFrame
> host2_req(
11656 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11657 MockWrite spdy_writes
[] = {
11658 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11660 scoped_ptr
<SpdyFrame
> host1_resp(
11661 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11662 scoped_ptr
<SpdyFrame
> host1_resp_body(
11663 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11664 scoped_ptr
<SpdyFrame
> host2_resp(
11665 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11666 scoped_ptr
<SpdyFrame
> host2_resp_body(
11667 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11668 MockRead spdy_reads
[] = {
11669 CreateMockRead(*host1_resp
, 1),
11670 CreateMockRead(*host1_resp_body
, 2),
11671 CreateMockRead(*host2_resp
, 4),
11672 CreateMockRead(*host2_resp_body
, 5),
11673 MockRead(ASYNC
, 0, 6),
11676 IPAddressNumber ip
;
11677 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11678 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11679 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11680 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11681 spdy_writes
, arraysize(spdy_writes
));
11682 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11684 TestCompletionCallback callback
;
11685 HttpRequestInfo request1
;
11686 request1
.method
= "GET";
11687 request1
.url
= GURL("https://www.example.org/");
11688 request1
.load_flags
= 0;
11689 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11691 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11692 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11693 EXPECT_EQ(OK
, callback
.WaitForResult());
11695 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11696 ASSERT_TRUE(response
!= NULL
);
11697 ASSERT_TRUE(response
->headers
.get() != NULL
);
11698 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11700 std::string response_data
;
11701 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11702 EXPECT_EQ("hello!", response_data
);
11704 // Preload cache entries into HostCache.
11705 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11706 AddressList ignored
;
11707 rv
= host_resolver
.Resolve(resolve_info
,
11710 callback
.callback(),
11713 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11714 rv
= callback
.WaitForResult();
11717 HttpRequestInfo request2
;
11718 request2
.method
= "GET";
11719 request2
.url
= GURL("https://www.gmail.com/");
11720 request2
.load_flags
= 0;
11721 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11723 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11724 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11725 EXPECT_EQ(OK
, callback
.WaitForResult());
11727 response
= trans2
.GetResponseInfo();
11728 ASSERT_TRUE(response
!= NULL
);
11729 ASSERT_TRUE(response
->headers
.get() != NULL
);
11730 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11731 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11732 EXPECT_TRUE(response
->was_npn_negotiated
);
11733 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11734 EXPECT_EQ("hello!", response_data
);
11737 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11739 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11740 const std::string https_url
= "https://www.example.org:8080/";
11741 const std::string http_url
= "http://www.example.org:8080/";
11743 // SPDY GET for HTTPS URL
11744 scoped_ptr
<SpdyFrame
> req1(
11745 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11747 MockWrite writes1
[] = {
11748 CreateMockWrite(*req1
, 0),
11751 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11752 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11753 MockRead reads1
[] = {
11754 CreateMockRead(*resp1
, 1),
11755 CreateMockRead(*body1
, 2),
11756 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11759 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
11760 arraysize(writes1
));
11761 MockConnect
connect_data1(ASYNC
, OK
);
11762 data1
.set_connect_data(connect_data1
);
11764 // HTTP GET for the HTTP URL
11765 MockWrite writes2
[] = {
11766 MockWrite(ASYNC
, 0,
11767 "GET / HTTP/1.1\r\n"
11768 "Host: www.example.org:8080\r\n"
11769 "Connection: keep-alive\r\n\r\n"),
11772 MockRead reads2
[] = {
11773 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11774 MockRead(ASYNC
, 2, "hello"),
11775 MockRead(ASYNC
, OK
, 3),
11778 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
11779 arraysize(writes2
));
11781 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11782 ssl
.SetNextProto(GetParam());
11783 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11784 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11785 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11787 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11789 // Start the first transaction to set up the SpdySession
11790 HttpRequestInfo request1
;
11791 request1
.method
= "GET";
11792 request1
.url
= GURL(https_url
);
11793 request1
.load_flags
= 0;
11794 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11795 TestCompletionCallback callback1
;
11796 EXPECT_EQ(ERR_IO_PENDING
,
11797 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11798 base::MessageLoop::current()->RunUntilIdle();
11800 EXPECT_EQ(OK
, callback1
.WaitForResult());
11801 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11803 // Now, start the HTTP request
11804 HttpRequestInfo request2
;
11805 request2
.method
= "GET";
11806 request2
.url
= GURL(http_url
);
11807 request2
.load_flags
= 0;
11808 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11809 TestCompletionCallback callback2
;
11810 EXPECT_EQ(ERR_IO_PENDING
,
11811 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11812 base::MessageLoop::current()->RunUntilIdle();
11814 EXPECT_EQ(OK
, callback2
.WaitForResult());
11815 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11818 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
11820 void Run(bool pooling
, bool valid
) {
11821 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
11823 HostPortPair
alternative("www.example.org", 443);
11825 base::FilePath certs_dir
= GetTestCertsDirectory();
11826 scoped_refptr
<X509Certificate
> cert(
11827 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
11828 ASSERT_TRUE(cert
.get());
11829 bool common_name_fallback_used
;
11831 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
11833 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
11834 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11835 ssl
.SetNextProto(GetParam());
11837 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11839 // If pooling, then start a request to alternative first to create a
11841 std::string url0
= "https://www.example.org:443";
11842 // Second request to origin, which has an alternative service, and could
11843 // open a connection to the alternative host or pool to the existing one.
11844 std::string
url1("https://");
11845 url1
.append(origin
.host());
11846 url1
.append(":443");
11848 scoped_ptr
<SpdyFrame
> req0
;
11849 scoped_ptr
<SpdyFrame
> req1
;
11850 scoped_ptr
<SpdyFrame
> resp0
;
11851 scoped_ptr
<SpdyFrame
> body0
;
11852 scoped_ptr
<SpdyFrame
> resp1
;
11853 scoped_ptr
<SpdyFrame
> body1
;
11854 std::vector
<MockWrite
> writes
;
11855 std::vector
<MockRead
> reads
;
11858 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
11859 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
11861 writes
.push_back(CreateMockWrite(*req0
, 0));
11862 writes
.push_back(CreateMockWrite(*req1
, 3));
11864 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11865 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11866 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11867 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11869 reads
.push_back(CreateMockRead(*resp0
, 1));
11870 reads
.push_back(CreateMockRead(*body0
, 2));
11871 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
11872 reads
.push_back(CreateMockRead(*resp1
, 5));
11873 reads
.push_back(CreateMockRead(*body1
, 6));
11874 reads
.push_back(MockRead(ASYNC
, OK
, 7));
11876 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
11878 writes
.push_back(CreateMockWrite(*req1
, 0));
11880 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11881 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11883 reads
.push_back(CreateMockRead(*resp1
, 1));
11884 reads
.push_back(CreateMockRead(*body1
, 2));
11885 reads
.push_back(MockRead(ASYNC
, OK
, 3));
11888 OrderedSocketData
data(vector_as_array(&reads
), reads
.size(),
11889 vector_as_array(&writes
), writes
.size());
11890 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11892 // Connection to the origin fails.
11893 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11894 StaticSocketDataProvider data_refused
;
11895 data_refused
.set_connect_data(mock_connect
);
11896 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
11898 session_deps_
.use_alternate_protocols
= true;
11899 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11900 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
11901 session
->http_server_properties();
11902 AlternativeService
alternative_service(
11903 AlternateProtocolFromNextProto(GetParam()), alternative
);
11904 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
11907 // First request to alternative.
11909 scoped_ptr
<HttpTransaction
> trans0(
11910 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11911 HttpRequestInfo request0
;
11912 request0
.method
= "GET";
11913 request0
.url
= GURL(url0
);
11914 request0
.load_flags
= 0;
11915 TestCompletionCallback callback0
;
11917 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
11918 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11919 rv
= callback0
.WaitForResult();
11923 // Second request to origin.
11924 scoped_ptr
<HttpTransaction
> trans1(
11925 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11926 HttpRequestInfo request1
;
11927 request1
.method
= "GET";
11928 request1
.url
= GURL(url1
);
11929 request1
.load_flags
= 0;
11930 TestCompletionCallback callback1
;
11932 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
11933 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11934 rv
= callback1
.WaitForResult();
11939 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11941 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
11947 INSTANTIATE_TEST_CASE_P(NextProto
,
11948 AltSvcCertificateVerificationTest
,
11949 testing::Values(kProtoSPDY31
,
11953 // The alternative service host must exhibit a certificate that is valid for the
11954 // origin host. Test that this is enforced when pooling to an existing
11956 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
11960 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
11964 // The alternative service host must exhibit a certificate that is valid for the
11965 // origin host. Test that this is enforced when opening a new connection.
11966 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
11970 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
11974 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
11975 const std::string https_url
= "https://www.example.org:8080/";
11976 const std::string http_url
= "http://www.example.org:8080/";
11978 // SPDY GET for HTTPS URL (through CONNECT tunnel)
11979 const HostPortPair
host_port_pair("www.example.org", 8080);
11980 scoped_ptr
<SpdyFrame
> connect(
11981 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
11982 scoped_ptr
<SpdyFrame
> req1(
11983 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11984 scoped_ptr
<SpdyFrame
> wrapped_req1(
11985 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
11987 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
11988 SpdyHeaderBlock req2_block
;
11989 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
11990 req2_block
[spdy_util_
.GetPathKey()] = "/";
11991 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
11992 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
11993 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
11994 scoped_ptr
<SpdyFrame
> req2(
11995 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
11997 MockWrite writes1
[] = {
11998 CreateMockWrite(*connect
, 0),
11999 CreateMockWrite(*wrapped_req1
, 2),
12000 CreateMockWrite(*req2
, 5),
12003 scoped_ptr
<SpdyFrame
> conn_resp(
12004 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12005 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12006 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12007 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12008 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12009 scoped_ptr
<SpdyFrame
> wrapped_body1(
12010 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12011 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12012 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12013 MockRead reads1
[] = {
12014 CreateMockRead(*conn_resp
, 1),
12015 CreateMockRead(*wrapped_resp1
, 3),
12016 CreateMockRead(*wrapped_body1
, 4),
12017 CreateMockRead(*resp2
, 6),
12018 CreateMockRead(*body2
, 7),
12019 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12022 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12023 writes1
, arraysize(writes1
));
12024 MockConnect
connect_data1(ASYNC
, OK
);
12025 data1
.set_connect_data(connect_data1
);
12027 session_deps_
.proxy_service
.reset(
12028 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12030 session_deps_
.net_log
= &log
;
12031 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12032 ssl1
.SetNextProto(GetParam());
12033 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12034 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12035 ssl2
.SetNextProto(GetParam());
12036 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12037 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12039 scoped_refptr
<HttpNetworkSession
> session(
12040 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12042 // Start the first transaction to set up the SpdySession
12043 HttpRequestInfo request1
;
12044 request1
.method
= "GET";
12045 request1
.url
= GURL(https_url
);
12046 request1
.load_flags
= 0;
12047 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12048 TestCompletionCallback callback1
;
12049 EXPECT_EQ(ERR_IO_PENDING
,
12050 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12051 base::MessageLoop::current()->RunUntilIdle();
12054 EXPECT_EQ(OK
, callback1
.WaitForResult());
12055 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12057 LoadTimingInfo load_timing_info1
;
12058 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12059 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12060 CONNECT_TIMING_HAS_SSL_TIMES
);
12062 // Now, start the HTTP request
12063 HttpRequestInfo request2
;
12064 request2
.method
= "GET";
12065 request2
.url
= GURL(http_url
);
12066 request2
.load_flags
= 0;
12067 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12068 TestCompletionCallback callback2
;
12069 EXPECT_EQ(ERR_IO_PENDING
,
12070 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12071 base::MessageLoop::current()->RunUntilIdle();
12074 EXPECT_EQ(OK
, callback2
.WaitForResult());
12075 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12077 LoadTimingInfo load_timing_info2
;
12078 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12079 // The established SPDY sessions is considered reused by the HTTP request.
12080 TestLoadTimingReusedWithPac(load_timing_info2
);
12081 // HTTP requests over a SPDY session should have a different connection
12082 // socket_log_id than requests over a tunnel.
12083 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12086 // Test that in the case where we have a SPDY session to a SPDY proxy
12087 // that we do not pool other origins that resolve to the same IP when
12088 // the certificate does not match the new origin.
12089 // http://crbug.com/134690
12090 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12091 const std::string url1
= "http://www.example.org/";
12092 const std::string url2
= "https://news.example.org/";
12093 const std::string ip_addr
= "1.2.3.4";
12095 // SPDY GET for HTTP URL (through SPDY proxy)
12096 scoped_ptr
<SpdyHeaderBlock
> headers(
12097 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12098 scoped_ptr
<SpdyFrame
> req1(
12099 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12101 MockWrite writes1
[] = {
12102 CreateMockWrite(*req1
, 0),
12105 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12106 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12107 MockRead reads1
[] = {
12108 CreateMockRead(*resp1
, 1),
12109 CreateMockRead(*body1
, 2),
12110 MockRead(ASYNC
, OK
, 3) // EOF
12113 scoped_ptr
<DeterministicSocketData
> data1(
12114 new DeterministicSocketData(reads1
, arraysize(reads1
),
12115 writes1
, arraysize(writes1
)));
12116 IPAddressNumber ip
;
12117 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12118 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12119 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12120 data1
->set_connect_data(connect_data1
);
12122 // SPDY GET for HTTPS URL (direct)
12123 scoped_ptr
<SpdyFrame
> req2(
12124 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12126 MockWrite writes2
[] = {
12127 CreateMockWrite(*req2
, 0),
12130 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12131 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12132 MockRead reads2
[] = {
12133 CreateMockRead(*resp2
, 1),
12134 CreateMockRead(*body2
, 2),
12135 MockRead(ASYNC
, OK
, 3) // EOF
12138 scoped_ptr
<DeterministicSocketData
> data2(
12139 new DeterministicSocketData(reads2
, arraysize(reads2
),
12140 writes2
, arraysize(writes2
)));
12141 MockConnect
connect_data2(ASYNC
, OK
);
12142 data2
->set_connect_data(connect_data2
);
12144 // Set up a proxy config that sends HTTP requests to a proxy, and
12145 // all others direct.
12146 ProxyConfig proxy_config
;
12147 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12148 session_deps_
.proxy_service
.reset(new ProxyService(
12149 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12151 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12152 ssl1
.SetNextProto(GetParam());
12153 // Load a valid cert. Note, that this does not need to
12154 // be valid for proxy because the MockSSLClientSocket does
12155 // not actually verify it. But SpdySession will use this
12156 // to see if it is valid for the new origin
12157 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12158 ASSERT_TRUE(ssl1
.cert
.get());
12159 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12160 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12163 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12164 ssl2
.SetNextProto(GetParam());
12165 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12166 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12169 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12170 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12171 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12173 scoped_refptr
<HttpNetworkSession
> session(
12174 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12176 // Start the first transaction to set up the SpdySession
12177 HttpRequestInfo request1
;
12178 request1
.method
= "GET";
12179 request1
.url
= GURL(url1
);
12180 request1
.load_flags
= 0;
12181 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12182 TestCompletionCallback callback1
;
12183 ASSERT_EQ(ERR_IO_PENDING
,
12184 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12187 ASSERT_TRUE(callback1
.have_result());
12188 EXPECT_EQ(OK
, callback1
.WaitForResult());
12189 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12191 // Now, start the HTTP request
12192 HttpRequestInfo request2
;
12193 request2
.method
= "GET";
12194 request2
.url
= GURL(url2
);
12195 request2
.load_flags
= 0;
12196 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12197 TestCompletionCallback callback2
;
12198 EXPECT_EQ(ERR_IO_PENDING
,
12199 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12200 base::MessageLoop::current()->RunUntilIdle();
12203 ASSERT_TRUE(callback2
.have_result());
12204 EXPECT_EQ(OK
, callback2
.WaitForResult());
12205 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12208 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12209 // error) in SPDY session, removes the socket from pool and closes the SPDY
12210 // session. Verify that new url's from the same HttpNetworkSession (and a new
12211 // SpdySession) do work. http://crbug.com/224701
12212 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12213 const std::string https_url
= "https://www.example.org/";
12215 MockRead reads1
[] = {
12216 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12219 scoped_ptr
<DeterministicSocketData
> data1(
12220 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
12223 scoped_ptr
<SpdyFrame
> req2(
12224 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12225 MockWrite writes2
[] = {
12226 CreateMockWrite(*req2
, 0),
12229 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12230 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12231 MockRead reads2
[] = {
12232 CreateMockRead(*resp2
, 1),
12233 CreateMockRead(*body2
, 2),
12234 MockRead(ASYNC
, OK
, 3) // EOF
12237 scoped_ptr
<DeterministicSocketData
> data2(
12238 new DeterministicSocketData(reads2
, arraysize(reads2
),
12239 writes2
, arraysize(writes2
)));
12241 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12242 ssl1
.SetNextProto(GetParam());
12243 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12244 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12247 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12248 ssl2
.SetNextProto(GetParam());
12249 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12250 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12253 scoped_refptr
<HttpNetworkSession
> session(
12254 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12256 // Start the first transaction to set up the SpdySession and verify that
12257 // connection was closed.
12258 HttpRequestInfo request1
;
12259 request1
.method
= "GET";
12260 request1
.url
= GURL(https_url
);
12261 request1
.load_flags
= 0;
12262 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12263 TestCompletionCallback callback1
;
12264 EXPECT_EQ(ERR_IO_PENDING
,
12265 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12266 base::MessageLoop::current()->RunUntilIdle();
12267 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12269 // Now, start the second request and make sure it succeeds.
12270 HttpRequestInfo request2
;
12271 request2
.method
= "GET";
12272 request2
.url
= GURL(https_url
);
12273 request2
.load_flags
= 0;
12274 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12275 TestCompletionCallback callback2
;
12276 EXPECT_EQ(ERR_IO_PENDING
,
12277 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12278 base::MessageLoop::current()->RunUntilIdle();
12281 ASSERT_TRUE(callback2
.have_result());
12282 EXPECT_EQ(OK
, callback2
.WaitForResult());
12283 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12286 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12287 session_deps_
.next_protos
= SpdyNextProtos();
12288 ClientSocketPoolManager::set_max_sockets_per_group(
12289 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12290 ClientSocketPoolManager::set_max_sockets_per_pool(
12291 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12293 // Use two different hosts with different IPs so they don't get pooled.
12294 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12295 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12296 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12298 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12299 ssl1
.SetNextProto(GetParam());
12300 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12301 ssl2
.SetNextProto(GetParam());
12302 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12303 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12305 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12306 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12307 MockWrite spdy1_writes
[] = {
12308 CreateMockWrite(*host1_req
, 0),
12310 scoped_ptr
<SpdyFrame
> host1_resp(
12311 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12312 scoped_ptr
<SpdyFrame
> host1_resp_body(
12313 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12314 MockRead spdy1_reads
[] = {
12315 CreateMockRead(*host1_resp
, 1),
12316 CreateMockRead(*host1_resp_body
, 2),
12317 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12320 scoped_ptr
<SequencedSocketData
> spdy1_data(
12321 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12322 arraysize(spdy1_writes
)));
12323 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12325 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12326 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12327 MockWrite spdy2_writes
[] = {
12328 CreateMockWrite(*host2_req
, 0),
12330 scoped_ptr
<SpdyFrame
> host2_resp(
12331 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12332 scoped_ptr
<SpdyFrame
> host2_resp_body(
12333 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12334 MockRead spdy2_reads
[] = {
12335 CreateMockRead(*host2_resp
, 1),
12336 CreateMockRead(*host2_resp_body
, 2),
12337 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12340 scoped_ptr
<SequencedSocketData
> spdy2_data(
12341 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12342 arraysize(spdy2_writes
)));
12343 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12345 MockWrite http_write
[] = {
12346 MockWrite("GET / HTTP/1.1\r\n"
12347 "Host: www.a.com\r\n"
12348 "Connection: keep-alive\r\n\r\n"),
12351 MockRead http_read
[] = {
12352 MockRead("HTTP/1.1 200 OK\r\n"),
12353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12354 MockRead("Content-Length: 6\r\n\r\n"),
12355 MockRead("hello!"),
12357 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12358 http_write
, arraysize(http_write
));
12359 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12361 HostPortPair
host_port_pair_a("www.a.com", 443);
12362 SpdySessionKey
spdy_session_key_a(
12363 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12365 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12367 TestCompletionCallback callback
;
12368 HttpRequestInfo request1
;
12369 request1
.method
= "GET";
12370 request1
.url
= GURL("https://www.a.com/");
12371 request1
.load_flags
= 0;
12372 scoped_ptr
<HttpNetworkTransaction
> trans(
12373 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12375 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12376 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12377 EXPECT_EQ(OK
, callback
.WaitForResult());
12379 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12380 ASSERT_TRUE(response
!= NULL
);
12381 ASSERT_TRUE(response
->headers
.get() != NULL
);
12382 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12383 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12384 EXPECT_TRUE(response
->was_npn_negotiated
);
12386 std::string response_data
;
12387 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12388 EXPECT_EQ("hello!", response_data
);
12391 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12393 HostPortPair
host_port_pair_b("www.b.com", 443);
12394 SpdySessionKey
spdy_session_key_b(
12395 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12397 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12398 HttpRequestInfo request2
;
12399 request2
.method
= "GET";
12400 request2
.url
= GURL("https://www.b.com/");
12401 request2
.load_flags
= 0;
12402 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12404 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12405 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12406 EXPECT_EQ(OK
, callback
.WaitForResult());
12408 response
= trans
->GetResponseInfo();
12409 ASSERT_TRUE(response
!= NULL
);
12410 ASSERT_TRUE(response
->headers
.get() != NULL
);
12411 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12412 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12413 EXPECT_TRUE(response
->was_npn_negotiated
);
12414 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12415 EXPECT_EQ("hello!", response_data
);
12417 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12419 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12421 HostPortPair
host_port_pair_a1("www.a.com", 80);
12422 SpdySessionKey
spdy_session_key_a1(
12423 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12425 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12426 HttpRequestInfo request3
;
12427 request3
.method
= "GET";
12428 request3
.url
= GURL("http://www.a.com/");
12429 request3
.load_flags
= 0;
12430 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12432 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12433 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12434 EXPECT_EQ(OK
, callback
.WaitForResult());
12436 response
= trans
->GetResponseInfo();
12437 ASSERT_TRUE(response
!= NULL
);
12438 ASSERT_TRUE(response
->headers
.get() != NULL
);
12439 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12440 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12441 EXPECT_FALSE(response
->was_npn_negotiated
);
12442 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12443 EXPECT_EQ("hello!", response_data
);
12445 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12447 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12450 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12451 HttpRequestInfo request
;
12452 request
.method
= "GET";
12453 request
.url
= GURL("http://www.example.org/");
12454 request
.load_flags
= 0;
12456 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12457 scoped_ptr
<HttpTransaction
> trans(
12458 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12460 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12461 StaticSocketDataProvider data
;
12462 data
.set_connect_data(mock_connect
);
12463 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12465 TestCompletionCallback callback
;
12467 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12470 rv
= callback
.WaitForResult();
12471 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12473 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12475 // We don't care whether this succeeds or fails, but it shouldn't crash.
12476 HttpRequestHeaders request_headers
;
12477 trans
->GetFullRequestHeaders(&request_headers
);
12479 ConnectionAttempts attempts
;
12480 trans
->GetConnectionAttempts(&attempts
);
12481 ASSERT_EQ(1u, attempts
.size());
12482 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12485 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12486 HttpRequestInfo request
;
12487 request
.method
= "GET";
12488 request
.url
= GURL("http://www.example.org/");
12489 request
.load_flags
= 0;
12491 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12492 scoped_ptr
<HttpTransaction
> trans(
12493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12495 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12496 StaticSocketDataProvider data
;
12497 data
.set_connect_data(mock_connect
);
12498 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12500 TestCompletionCallback callback
;
12502 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12505 rv
= callback
.WaitForResult();
12506 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12508 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12510 // We don't care whether this succeeds or fails, but it shouldn't crash.
12511 HttpRequestHeaders request_headers
;
12512 trans
->GetFullRequestHeaders(&request_headers
);
12514 ConnectionAttempts attempts
;
12515 trans
->GetConnectionAttempts(&attempts
);
12516 ASSERT_EQ(1u, attempts
.size());
12517 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12520 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12521 HttpRequestInfo request
;
12522 request
.method
= "GET";
12523 request
.url
= GURL("http://www.example.org/");
12524 request
.load_flags
= 0;
12526 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12527 scoped_ptr
<HttpTransaction
> trans(
12528 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12530 MockWrite data_writes
[] = {
12531 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12533 MockRead data_reads
[] = {
12534 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12537 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12538 data_writes
, arraysize(data_writes
));
12539 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12541 TestCompletionCallback callback
;
12543 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12544 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12546 rv
= callback
.WaitForResult();
12547 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12549 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12551 HttpRequestHeaders request_headers
;
12552 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12553 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12556 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12557 HttpRequestInfo request
;
12558 request
.method
= "GET";
12559 request
.url
= GURL("http://www.example.org/");
12560 request
.load_flags
= 0;
12562 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12563 scoped_ptr
<HttpTransaction
> trans(
12564 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12566 MockWrite data_writes
[] = {
12567 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12569 MockRead data_reads
[] = {
12570 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12573 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12574 data_writes
, arraysize(data_writes
));
12575 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12577 TestCompletionCallback callback
;
12579 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12582 rv
= callback
.WaitForResult();
12583 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12585 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12587 HttpRequestHeaders request_headers
;
12588 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12589 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12592 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12593 HttpRequestInfo request
;
12594 request
.method
= "GET";
12595 request
.url
= GURL("http://www.example.org/");
12596 request
.load_flags
= 0;
12598 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12599 scoped_ptr
<HttpTransaction
> trans(
12600 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12602 MockWrite data_writes
[] = {
12604 "GET / HTTP/1.1\r\n"
12605 "Host: www.example.org\r\n"
12606 "Connection: keep-alive\r\n\r\n"),
12608 MockRead data_reads
[] = {
12609 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12612 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12613 data_writes
, arraysize(data_writes
));
12614 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12616 TestCompletionCallback callback
;
12618 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12619 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12621 rv
= callback
.WaitForResult();
12622 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12624 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12626 HttpRequestHeaders request_headers
;
12627 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12628 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12631 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12632 HttpRequestInfo request
;
12633 request
.method
= "GET";
12634 request
.url
= GURL("http://www.example.org/");
12635 request
.load_flags
= 0;
12637 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12638 scoped_ptr
<HttpTransaction
> trans(
12639 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12641 MockWrite data_writes
[] = {
12643 "GET / HTTP/1.1\r\n"
12644 "Host: www.example.org\r\n"
12645 "Connection: keep-alive\r\n\r\n"),
12647 MockRead data_reads
[] = {
12648 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12651 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12652 data_writes
, arraysize(data_writes
));
12653 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12655 TestCompletionCallback callback
;
12657 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12658 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12660 rv
= callback
.WaitForResult();
12661 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12663 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12665 HttpRequestHeaders request_headers
;
12666 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12667 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12670 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12671 HttpRequestInfo request
;
12672 request
.method
= "GET";
12673 request
.url
= GURL("http://www.example.org/");
12674 request
.load_flags
= 0;
12675 request
.extra_headers
.SetHeader("X-Foo", "bar");
12677 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12678 scoped_ptr
<HttpTransaction
> trans(
12679 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12681 MockWrite data_writes
[] = {
12683 "GET / HTTP/1.1\r\n"
12684 "Host: www.example.org\r\n"
12685 "Connection: keep-alive\r\n"
12686 "X-Foo: bar\r\n\r\n"),
12688 MockRead data_reads
[] = {
12689 MockRead("HTTP/1.1 200 OK\r\n"
12690 "Content-Length: 5\r\n\r\n"
12692 MockRead(ASYNC
, ERR_UNEXPECTED
),
12695 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12696 data_writes
, arraysize(data_writes
));
12697 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12699 TestCompletionCallback callback
;
12701 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12702 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12704 rv
= callback
.WaitForResult();
12707 HttpRequestHeaders request_headers
;
12708 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12710 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12711 EXPECT_EQ("bar", foo
);
12716 // Fake HttpStream that simply records calls to SetPriority().
12717 class FakeStream
: public HttpStream
,
12718 public base::SupportsWeakPtr
<FakeStream
> {
12720 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12721 ~FakeStream() override
{}
12723 RequestPriority
priority() const { return priority_
; }
12725 int InitializeStream(const HttpRequestInfo
* request_info
,
12726 RequestPriority priority
,
12727 const BoundNetLog
& net_log
,
12728 const CompletionCallback
& callback
) override
{
12729 return ERR_IO_PENDING
;
12732 int SendRequest(const HttpRequestHeaders
& request_headers
,
12733 HttpResponseInfo
* response
,
12734 const CompletionCallback
& callback
) override
{
12736 return ERR_UNEXPECTED
;
12739 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12741 return ERR_UNEXPECTED
;
12744 int ReadResponseBody(IOBuffer
* buf
,
12746 const CompletionCallback
& callback
) override
{
12748 return ERR_UNEXPECTED
;
12751 void Close(bool not_reusable
) override
{}
12753 bool IsResponseBodyComplete() const override
{
12758 bool CanFindEndOfResponse() const override
{ return false; }
12760 bool IsConnectionReused() const override
{
12765 void SetConnectionReused() override
{ ADD_FAILURE(); }
12767 bool IsConnectionReusable() const override
{
12772 int64
GetTotalReceivedBytes() const override
{
12777 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12782 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
12784 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12788 bool IsSpdyHttpStream() const override
{
12793 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
12795 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12797 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
12799 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
12802 RequestPriority priority_
;
12804 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12807 // Fake HttpStreamRequest that simply records calls to SetPriority()
12808 // and vends FakeStreams with its current priority.
12809 class FakeStreamRequest
: public HttpStreamRequest
,
12810 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12812 FakeStreamRequest(RequestPriority priority
,
12813 HttpStreamRequest::Delegate
* delegate
)
12814 : priority_(priority
),
12815 delegate_(delegate
),
12816 websocket_stream_create_helper_(NULL
) {}
12818 FakeStreamRequest(RequestPriority priority
,
12819 HttpStreamRequest::Delegate
* delegate
,
12820 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12821 : priority_(priority
),
12822 delegate_(delegate
),
12823 websocket_stream_create_helper_(create_helper
) {}
12825 ~FakeStreamRequest() override
{}
12827 RequestPriority
priority() const { return priority_
; }
12829 const WebSocketHandshakeStreamBase::CreateHelper
*
12830 websocket_stream_create_helper() const {
12831 return websocket_stream_create_helper_
;
12834 // Create a new FakeStream and pass it to the request's
12835 // delegate. Returns a weak pointer to the FakeStream.
12836 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12837 FakeStream
* fake_stream
= new FakeStream(priority_
);
12838 // Do this before calling OnStreamReady() as OnStreamReady() may
12839 // immediately delete |fake_stream|.
12840 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12841 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12842 return weak_stream
;
12845 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
12847 return ERR_UNEXPECTED
;
12850 LoadState
GetLoadState() const override
{
12852 return LoadState();
12855 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12857 bool was_npn_negotiated() const override
{ return false; }
12859 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
12861 bool using_spdy() const override
{ return false; }
12863 const ConnectionAttempts
& connection_attempts() const override
{
12864 static ConnectionAttempts no_attempts
;
12865 return no_attempts
;
12869 RequestPriority priority_
;
12870 HttpStreamRequest::Delegate
* const delegate_
;
12871 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12873 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12876 // Fake HttpStreamFactory that vends FakeStreamRequests.
12877 class FakeStreamFactory
: public HttpStreamFactory
{
12879 FakeStreamFactory() {}
12880 ~FakeStreamFactory() override
{}
12882 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12883 // RequestStream() (which may be NULL if it was destroyed already).
12884 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12885 return last_stream_request_
;
12888 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
12889 RequestPriority priority
,
12890 const SSLConfig
& server_ssl_config
,
12891 const SSLConfig
& proxy_ssl_config
,
12892 HttpStreamRequest::Delegate
* delegate
,
12893 const BoundNetLog
& net_log
) override
{
12894 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12895 last_stream_request_
= fake_request
->AsWeakPtr();
12896 return fake_request
;
12899 HttpStreamRequest
* RequestWebSocketHandshakeStream(
12900 const HttpRequestInfo
& info
,
12901 RequestPriority priority
,
12902 const SSLConfig
& server_ssl_config
,
12903 const SSLConfig
& proxy_ssl_config
,
12904 HttpStreamRequest::Delegate
* delegate
,
12905 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12906 const BoundNetLog
& net_log
) override
{
12907 FakeStreamRequest
* fake_request
=
12908 new FakeStreamRequest(priority
, delegate
, create_helper
);
12909 last_stream_request_
= fake_request
->AsWeakPtr();
12910 return fake_request
;
12913 void PreconnectStreams(int num_streams
,
12914 const HttpRequestInfo
& info
,
12915 RequestPriority priority
,
12916 const SSLConfig
& server_ssl_config
,
12917 const SSLConfig
& proxy_ssl_config
) override
{
12921 const HostMappingRules
* GetHostMappingRules() const override
{
12927 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12929 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12932 // TODO(ricea): Maybe unify this with the one in
12933 // url_request_http_job_unittest.cc ?
12934 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
12936 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
12938 : state_(connection
.release(), using_proxy
) {}
12940 // Fake implementation of HttpStreamBase methods.
12941 // This ends up being quite "real" because this object has to really send data
12942 // on the mock socket. It might be easier to use the real implementation, but
12943 // the fact that the WebSocket code is not compiled on iOS makes that
12945 int InitializeStream(const HttpRequestInfo
* request_info
,
12946 RequestPriority priority
,
12947 const BoundNetLog
& net_log
,
12948 const CompletionCallback
& callback
) override
{
12949 state_
.Initialize(request_info
, priority
, net_log
, callback
);
12953 int SendRequest(const HttpRequestHeaders
& request_headers
,
12954 HttpResponseInfo
* response
,
12955 const CompletionCallback
& callback
) override
{
12956 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
12957 response
, callback
);
12960 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12961 return parser()->ReadResponseHeaders(callback
);
12964 int ReadResponseBody(IOBuffer
* buf
,
12966 const CompletionCallback
& callback
) override
{
12968 return ERR_IO_PENDING
;
12971 void Close(bool not_reusable
) override
{
12973 parser()->Close(true);
12976 bool IsResponseBodyComplete() const override
{
12981 bool CanFindEndOfResponse() const override
{
12982 return parser()->CanFindEndOfResponse();
12985 bool IsConnectionReused() const override
{
12989 void SetConnectionReused() override
{ NOTREACHED(); }
12991 bool IsConnectionReusable() const override
{
12996 int64
GetTotalReceivedBytes() const override
{
13001 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13006 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13008 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13012 bool IsSpdyHttpStream() const override
{
13017 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13019 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13021 UploadProgress
GetUploadProgress() const override
{
13023 return UploadProgress();
13026 HttpStream
* RenewStreamForAuth() override
{
13031 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13032 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13034 return scoped_ptr
<WebSocketStream
>();
13038 HttpStreamParser
* parser() const { return state_
.parser(); }
13039 HttpBasicState state_
;
13041 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13044 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13046 class FakeWebSocketStreamCreateHelper
:
13047 public WebSocketHandshakeStreamBase::CreateHelper
{
13049 WebSocketHandshakeStreamBase
* CreateBasicStream(
13050 scoped_ptr
<ClientSocketHandle
> connection
,
13051 bool using_proxy
) override
{
13052 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13056 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13057 const base::WeakPtr
<SpdySession
>& session
,
13058 bool use_relative_url
) override
{
13063 ~FakeWebSocketStreamCreateHelper() override
{}
13065 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13067 return scoped_ptr
<WebSocketStream
>();
13073 // Make sure that HttpNetworkTransaction passes on its priority to its
13074 // stream request on start.
13075 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13076 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13077 HttpNetworkSessionPeer
peer(session
);
13078 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13079 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13081 HttpNetworkTransaction
trans(LOW
, session
.get());
13083 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13085 HttpRequestInfo request
;
13086 TestCompletionCallback callback
;
13087 EXPECT_EQ(ERR_IO_PENDING
,
13088 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13090 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13091 fake_factory
->last_stream_request();
13092 ASSERT_TRUE(fake_request
!= NULL
);
13093 EXPECT_EQ(LOW
, fake_request
->priority());
13096 // Make sure that HttpNetworkTransaction passes on its priority
13097 // updates to its stream request.
13098 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13099 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13100 HttpNetworkSessionPeer
peer(session
);
13101 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13102 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13104 HttpNetworkTransaction
trans(LOW
, session
.get());
13106 HttpRequestInfo request
;
13107 TestCompletionCallback callback
;
13108 EXPECT_EQ(ERR_IO_PENDING
,
13109 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13111 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13112 fake_factory
->last_stream_request();
13113 ASSERT_TRUE(fake_request
!= NULL
);
13114 EXPECT_EQ(LOW
, fake_request
->priority());
13116 trans
.SetPriority(LOWEST
);
13117 ASSERT_TRUE(fake_request
!= NULL
);
13118 EXPECT_EQ(LOWEST
, fake_request
->priority());
13121 // Make sure that HttpNetworkTransaction passes on its priority
13122 // updates to its stream.
13123 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13124 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13125 HttpNetworkSessionPeer
peer(session
);
13126 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13127 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13129 HttpNetworkTransaction
trans(LOW
, session
.get());
13131 HttpRequestInfo request
;
13132 TestCompletionCallback callback
;
13133 EXPECT_EQ(ERR_IO_PENDING
,
13134 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13136 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13137 fake_factory
->last_stream_request();
13138 ASSERT_TRUE(fake_request
!= NULL
);
13139 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13140 ASSERT_TRUE(fake_stream
!= NULL
);
13141 EXPECT_EQ(LOW
, fake_stream
->priority());
13143 trans
.SetPriority(LOWEST
);
13144 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13147 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13148 // The same logic needs to be tested for both ws: and wss: schemes, but this
13149 // test is already parameterised on NextProto, so it uses a loop to verify
13150 // that the different schemes work.
13151 std::string test_cases
[] = {"ws://www.example.org/",
13152 "wss://www.example.org/"};
13153 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13154 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13155 HttpNetworkSessionPeer
peer(session
);
13156 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13157 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13158 peer
.SetHttpStreamFactoryForWebSocket(
13159 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13161 HttpNetworkTransaction
trans(LOW
, session
.get());
13162 trans
.SetWebSocketHandshakeStreamCreateHelper(
13163 &websocket_stream_create_helper
);
13165 HttpRequestInfo request
;
13166 TestCompletionCallback callback
;
13167 request
.method
= "GET";
13168 request
.url
= GURL(test_cases
[i
]);
13170 EXPECT_EQ(ERR_IO_PENDING
,
13171 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13173 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13174 fake_factory
->last_stream_request();
13175 ASSERT_TRUE(fake_request
!= NULL
);
13176 EXPECT_EQ(&websocket_stream_create_helper
,
13177 fake_request
->websocket_stream_create_helper());
13181 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13182 // if the transport socket pool is stalled on the global socket limit.
13183 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13184 ClientSocketPoolManager::set_max_sockets_per_group(
13185 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13186 ClientSocketPoolManager::set_max_sockets_per_pool(
13187 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13189 // Set up SSL request.
13191 HttpRequestInfo ssl_request
;
13192 ssl_request
.method
= "GET";
13193 ssl_request
.url
= GURL("https://www.example.org/");
13195 MockWrite ssl_writes
[] = {
13197 "GET / HTTP/1.1\r\n"
13198 "Host: www.example.org\r\n"
13199 "Connection: keep-alive\r\n\r\n"),
13201 MockRead ssl_reads
[] = {
13202 MockRead("HTTP/1.1 200 OK\r\n"),
13203 MockRead("Content-Length: 11\r\n\r\n"),
13204 MockRead("hello world"),
13205 MockRead(SYNCHRONOUS
, OK
),
13207 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13208 ssl_writes
, arraysize(ssl_writes
));
13209 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13211 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13212 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13214 // Set up HTTP request.
13216 HttpRequestInfo http_request
;
13217 http_request
.method
= "GET";
13218 http_request
.url
= GURL("http://www.example.org/");
13220 MockWrite http_writes
[] = {
13222 "GET / HTTP/1.1\r\n"
13223 "Host: www.example.org\r\n"
13224 "Connection: keep-alive\r\n\r\n"),
13226 MockRead http_reads
[] = {
13227 MockRead("HTTP/1.1 200 OK\r\n"),
13228 MockRead("Content-Length: 7\r\n\r\n"),
13229 MockRead("falafel"),
13230 MockRead(SYNCHRONOUS
, OK
),
13232 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13233 http_writes
, arraysize(http_writes
));
13234 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13236 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13238 // Start the SSL request.
13239 TestCompletionCallback ssl_callback
;
13240 scoped_ptr
<HttpTransaction
> ssl_trans(
13241 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13242 ASSERT_EQ(ERR_IO_PENDING
,
13243 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13246 // Start the HTTP request. Pool should stall.
13247 TestCompletionCallback http_callback
;
13248 scoped_ptr
<HttpTransaction
> http_trans(
13249 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13250 ASSERT_EQ(ERR_IO_PENDING
,
13251 http_trans
->Start(&http_request
, http_callback
.callback(),
13253 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13255 // Wait for response from SSL request.
13256 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13257 std::string response_data
;
13258 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13259 EXPECT_EQ("hello world", response_data
);
13261 // The SSL socket should automatically be closed, so the HTTP request can
13263 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13264 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13266 // The HTTP request can now complete.
13267 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13268 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13269 EXPECT_EQ("falafel", response_data
);
13271 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13274 // Tests that when a SSL connection is established but there's no corresponding
13275 // request that needs it, the new socket is closed if the transport socket pool
13276 // is stalled on the global socket limit.
13277 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13278 ClientSocketPoolManager::set_max_sockets_per_group(
13279 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13280 ClientSocketPoolManager::set_max_sockets_per_pool(
13281 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13283 // Set up an ssl request.
13285 HttpRequestInfo ssl_request
;
13286 ssl_request
.method
= "GET";
13287 ssl_request
.url
= GURL("https://www.foopy.com/");
13289 // No data will be sent on the SSL socket.
13290 StaticSocketDataProvider ssl_data
;
13291 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13293 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13294 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13296 // Set up HTTP request.
13298 HttpRequestInfo http_request
;
13299 http_request
.method
= "GET";
13300 http_request
.url
= GURL("http://www.example.org/");
13302 MockWrite http_writes
[] = {
13304 "GET / HTTP/1.1\r\n"
13305 "Host: www.example.org\r\n"
13306 "Connection: keep-alive\r\n\r\n"),
13308 MockRead http_reads
[] = {
13309 MockRead("HTTP/1.1 200 OK\r\n"),
13310 MockRead("Content-Length: 7\r\n\r\n"),
13311 MockRead("falafel"),
13312 MockRead(SYNCHRONOUS
, OK
),
13314 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13315 http_writes
, arraysize(http_writes
));
13316 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13318 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13320 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13321 // cancelled when a normal transaction is cancelled.
13322 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13323 SSLConfig ssl_config
;
13324 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13325 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
13326 ssl_config
, ssl_config
);
13327 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13329 // Start the HTTP request. Pool should stall.
13330 TestCompletionCallback http_callback
;
13331 scoped_ptr
<HttpTransaction
> http_trans(
13332 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13333 ASSERT_EQ(ERR_IO_PENDING
,
13334 http_trans
->Start(&http_request
, http_callback
.callback(),
13336 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13338 // The SSL connection will automatically be closed once the connection is
13339 // established, to let the HTTP request start.
13340 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13341 std::string response_data
;
13342 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13343 EXPECT_EQ("falafel", response_data
);
13345 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13348 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13349 ScopedVector
<UploadElementReader
> element_readers
;
13350 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13351 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13353 HttpRequestInfo request
;
13354 request
.method
= "POST";
13355 request
.url
= GURL("http://www.foo.com/");
13356 request
.upload_data_stream
= &upload_data_stream
;
13357 request
.load_flags
= 0;
13359 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13360 scoped_ptr
<HttpTransaction
> trans(
13361 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13362 // Send headers successfully, but get an error while sending the body.
13363 MockWrite data_writes
[] = {
13364 MockWrite("POST / HTTP/1.1\r\n"
13365 "Host: www.foo.com\r\n"
13366 "Connection: keep-alive\r\n"
13367 "Content-Length: 3\r\n\r\n"),
13368 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13371 MockRead data_reads
[] = {
13372 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13373 MockRead("hello world"),
13374 MockRead(SYNCHRONOUS
, OK
),
13376 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13377 arraysize(data_writes
));
13378 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13380 TestCompletionCallback callback
;
13382 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13383 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13385 rv
= callback
.WaitForResult();
13388 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13389 ASSERT_TRUE(response
!= NULL
);
13391 EXPECT_TRUE(response
->headers
.get() != NULL
);
13392 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13394 std::string response_data
;
13395 rv
= ReadTransaction(trans
.get(), &response_data
);
13397 EXPECT_EQ("hello world", response_data
);
13400 // This test makes sure the retry logic doesn't trigger when reading an error
13401 // response from a server that rejected a POST with a CONNECTION_RESET.
13402 TEST_P(HttpNetworkTransactionTest
,
13403 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13404 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13405 MockWrite data_writes
[] = {
13406 MockWrite("GET / HTTP/1.1\r\n"
13407 "Host: www.foo.com\r\n"
13408 "Connection: keep-alive\r\n\r\n"),
13409 MockWrite("POST / HTTP/1.1\r\n"
13410 "Host: www.foo.com\r\n"
13411 "Connection: keep-alive\r\n"
13412 "Content-Length: 3\r\n\r\n"),
13413 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13416 MockRead data_reads
[] = {
13417 MockRead("HTTP/1.1 200 Peachy\r\n"
13418 "Content-Length: 14\r\n\r\n"),
13419 MockRead("first response"),
13420 MockRead("HTTP/1.1 400 Not OK\r\n"
13421 "Content-Length: 15\r\n\r\n"),
13422 MockRead("second response"),
13423 MockRead(SYNCHRONOUS
, OK
),
13425 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13426 arraysize(data_writes
));
13427 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13429 TestCompletionCallback callback
;
13430 HttpRequestInfo request1
;
13431 request1
.method
= "GET";
13432 request1
.url
= GURL("http://www.foo.com/");
13433 request1
.load_flags
= 0;
13435 scoped_ptr
<HttpTransaction
> trans1(
13436 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13437 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13438 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13440 rv
= callback
.WaitForResult();
13443 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13444 ASSERT_TRUE(response1
!= NULL
);
13446 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13447 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13449 std::string response_data1
;
13450 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13452 EXPECT_EQ("first response", response_data1
);
13453 // Delete the transaction to release the socket back into the socket pool.
13456 ScopedVector
<UploadElementReader
> element_readers
;
13457 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13458 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13460 HttpRequestInfo request2
;
13461 request2
.method
= "POST";
13462 request2
.url
= GURL("http://www.foo.com/");
13463 request2
.upload_data_stream
= &upload_data_stream
;
13464 request2
.load_flags
= 0;
13466 scoped_ptr
<HttpTransaction
> trans2(
13467 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13468 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13469 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13471 rv
= callback
.WaitForResult();
13474 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13475 ASSERT_TRUE(response2
!= NULL
);
13477 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13478 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13480 std::string response_data2
;
13481 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13483 EXPECT_EQ("second response", response_data2
);
13486 TEST_P(HttpNetworkTransactionTest
,
13487 PostReadsErrorResponseAfterResetPartialBodySent
) {
13488 ScopedVector
<UploadElementReader
> element_readers
;
13489 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13490 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13492 HttpRequestInfo request
;
13493 request
.method
= "POST";
13494 request
.url
= GURL("http://www.foo.com/");
13495 request
.upload_data_stream
= &upload_data_stream
;
13496 request
.load_flags
= 0;
13498 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13499 scoped_ptr
<HttpTransaction
> trans(
13500 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13501 // Send headers successfully, but get an error while sending the body.
13502 MockWrite data_writes
[] = {
13503 MockWrite("POST / HTTP/1.1\r\n"
13504 "Host: www.foo.com\r\n"
13505 "Connection: keep-alive\r\n"
13506 "Content-Length: 3\r\n\r\n"
13508 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13511 MockRead data_reads
[] = {
13512 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13513 MockRead("hello world"),
13514 MockRead(SYNCHRONOUS
, OK
),
13516 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13517 arraysize(data_writes
));
13518 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13520 TestCompletionCallback callback
;
13522 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13523 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13525 rv
= callback
.WaitForResult();
13528 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13529 ASSERT_TRUE(response
!= NULL
);
13531 EXPECT_TRUE(response
->headers
.get() != NULL
);
13532 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13534 std::string response_data
;
13535 rv
= ReadTransaction(trans
.get(), &response_data
);
13537 EXPECT_EQ("hello world", response_data
);
13540 // This tests the more common case than the previous test, where headers and
13541 // body are not merged into a single request.
13542 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13543 ScopedVector
<UploadElementReader
> element_readers
;
13544 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13545 ChunkedUploadDataStream
upload_data_stream(0);
13547 HttpRequestInfo request
;
13548 request
.method
= "POST";
13549 request
.url
= GURL("http://www.foo.com/");
13550 request
.upload_data_stream
= &upload_data_stream
;
13551 request
.load_flags
= 0;
13553 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13554 scoped_ptr
<HttpTransaction
> trans(
13555 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13556 // Send headers successfully, but get an error while sending the body.
13557 MockWrite data_writes
[] = {
13558 MockWrite("POST / HTTP/1.1\r\n"
13559 "Host: www.foo.com\r\n"
13560 "Connection: keep-alive\r\n"
13561 "Transfer-Encoding: chunked\r\n\r\n"),
13562 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13565 MockRead data_reads
[] = {
13566 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13567 MockRead("hello world"),
13568 MockRead(SYNCHRONOUS
, OK
),
13570 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13571 arraysize(data_writes
));
13572 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13574 TestCompletionCallback callback
;
13576 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13577 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13578 // Make sure the headers are sent before adding a chunk. This ensures that
13579 // they can't be merged with the body in a single send. Not currently
13580 // necessary since a chunked body is never merged with headers, but this makes
13581 // the test more future proof.
13582 base::RunLoop().RunUntilIdle();
13584 upload_data_stream
.AppendData("last chunk", 10, true);
13586 rv
= callback
.WaitForResult();
13589 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13590 ASSERT_TRUE(response
!= NULL
);
13592 EXPECT_TRUE(response
->headers
.get() != NULL
);
13593 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13595 std::string response_data
;
13596 rv
= ReadTransaction(trans
.get(), &response_data
);
13598 EXPECT_EQ("hello world", response_data
);
13601 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13602 ScopedVector
<UploadElementReader
> element_readers
;
13603 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13604 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13606 HttpRequestInfo request
;
13607 request
.method
= "POST";
13608 request
.url
= GURL("http://www.foo.com/");
13609 request
.upload_data_stream
= &upload_data_stream
;
13610 request
.load_flags
= 0;
13612 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13613 scoped_ptr
<HttpTransaction
> trans(
13614 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13616 MockWrite data_writes
[] = {
13617 MockWrite("POST / HTTP/1.1\r\n"
13618 "Host: www.foo.com\r\n"
13619 "Connection: keep-alive\r\n"
13620 "Content-Length: 3\r\n\r\n"),
13621 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13624 MockRead data_reads
[] = {
13625 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13626 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13627 MockRead("hello world"),
13628 MockRead(SYNCHRONOUS
, OK
),
13630 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13631 arraysize(data_writes
));
13632 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13634 TestCompletionCallback callback
;
13636 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13637 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13639 rv
= callback
.WaitForResult();
13642 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13643 ASSERT_TRUE(response
!= NULL
);
13645 EXPECT_TRUE(response
->headers
.get() != NULL
);
13646 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13648 std::string response_data
;
13649 rv
= ReadTransaction(trans
.get(), &response_data
);
13651 EXPECT_EQ("hello world", response_data
);
13654 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13655 ScopedVector
<UploadElementReader
> element_readers
;
13656 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13657 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13659 HttpRequestInfo request
;
13660 request
.method
= "POST";
13661 request
.url
= GURL("http://www.foo.com/");
13662 request
.upload_data_stream
= &upload_data_stream
;
13663 request
.load_flags
= 0;
13665 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13666 scoped_ptr
<HttpTransaction
> trans(
13667 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13668 // Send headers successfully, but get an error while sending the body.
13669 MockWrite data_writes
[] = {
13670 MockWrite("POST / HTTP/1.1\r\n"
13671 "Host: www.foo.com\r\n"
13672 "Connection: keep-alive\r\n"
13673 "Content-Length: 3\r\n\r\n"),
13674 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13677 MockRead data_reads
[] = {
13678 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13679 MockRead("hello world"),
13680 MockRead(SYNCHRONOUS
, OK
),
13682 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13683 arraysize(data_writes
));
13684 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13686 TestCompletionCallback callback
;
13688 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13689 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13691 rv
= callback
.WaitForResult();
13692 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13694 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13695 EXPECT_TRUE(response
== NULL
);
13698 TEST_P(HttpNetworkTransactionTest
,
13699 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13700 ScopedVector
<UploadElementReader
> element_readers
;
13701 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13702 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13704 HttpRequestInfo request
;
13705 request
.method
= "POST";
13706 request
.url
= GURL("http://www.foo.com/");
13707 request
.upload_data_stream
= &upload_data_stream
;
13708 request
.load_flags
= 0;
13710 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13711 scoped_ptr
<HttpTransaction
> trans(
13712 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13713 // Send headers successfully, but get an error while sending the body.
13714 MockWrite data_writes
[] = {
13715 MockWrite("POST / HTTP/1.1\r\n"
13716 "Host: www.foo.com\r\n"
13717 "Connection: keep-alive\r\n"
13718 "Content-Length: 3\r\n\r\n"),
13719 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13722 MockRead data_reads
[] = {
13723 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13724 MockRead("HTTP/1.0 302 Redirect\r\n"),
13725 MockRead("Location: http://somewhere-else.com/\r\n"),
13726 MockRead("Content-Length: 0\r\n\r\n"),
13727 MockRead(SYNCHRONOUS
, OK
),
13729 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13730 arraysize(data_writes
));
13731 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13733 TestCompletionCallback callback
;
13735 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13736 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13738 rv
= callback
.WaitForResult();
13739 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13741 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13742 EXPECT_TRUE(response
== NULL
);
13745 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13746 ScopedVector
<UploadElementReader
> element_readers
;
13747 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13748 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13750 HttpRequestInfo request
;
13751 request
.method
= "POST";
13752 request
.url
= GURL("http://www.foo.com/");
13753 request
.upload_data_stream
= &upload_data_stream
;
13754 request
.load_flags
= 0;
13756 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13757 scoped_ptr
<HttpTransaction
> trans(
13758 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13759 // Send headers successfully, but get an error while sending the body.
13760 MockWrite data_writes
[] = {
13761 MockWrite("POST / HTTP/1.1\r\n"
13762 "Host: www.foo.com\r\n"
13763 "Connection: keep-alive\r\n"
13764 "Content-Length: 3\r\n\r\n"),
13765 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13768 MockRead data_reads
[] = {
13769 MockRead("HTTP 0.9 rocks!"),
13770 MockRead(SYNCHRONOUS
, OK
),
13772 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13773 arraysize(data_writes
));
13774 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13776 TestCompletionCallback callback
;
13778 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13779 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13781 rv
= callback
.WaitForResult();
13782 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13784 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13785 EXPECT_TRUE(response
== NULL
);
13788 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13789 ScopedVector
<UploadElementReader
> element_readers
;
13790 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13791 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13793 HttpRequestInfo request
;
13794 request
.method
= "POST";
13795 request
.url
= GURL("http://www.foo.com/");
13796 request
.upload_data_stream
= &upload_data_stream
;
13797 request
.load_flags
= 0;
13799 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13800 scoped_ptr
<HttpTransaction
> trans(
13801 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13802 // Send headers successfully, but get an error while sending the body.
13803 MockWrite data_writes
[] = {
13804 MockWrite("POST / HTTP/1.1\r\n"
13805 "Host: www.foo.com\r\n"
13806 "Connection: keep-alive\r\n"
13807 "Content-Length: 3\r\n\r\n"),
13808 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13811 MockRead data_reads
[] = {
13812 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13813 MockRead(SYNCHRONOUS
, OK
),
13815 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13816 arraysize(data_writes
));
13817 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13819 TestCompletionCallback callback
;
13821 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13822 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13824 rv
= callback
.WaitForResult();
13825 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13827 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13828 EXPECT_TRUE(response
== NULL
);
13831 // Verify that proxy headers are not sent to the destination server when
13832 // establishing a tunnel for a secure WebSocket connection.
13833 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
13834 HttpRequestInfo request
;
13835 request
.method
= "GET";
13836 request
.url
= GURL("wss://www.example.org/");
13837 AddWebSocketHeaders(&request
.extra_headers
);
13839 // Configure against proxy server "myproxy:70".
13840 session_deps_
.proxy_service
.reset(
13841 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13843 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13845 // Since a proxy is configured, try to establish a tunnel.
13846 MockWrite data_writes
[] = {
13848 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13849 "Host: www.example.org\r\n"
13850 "Proxy-Connection: keep-alive\r\n\r\n"),
13852 // After calling trans->RestartWithAuth(), this is the request we should
13853 // be issuing -- the final header line contains the credentials.
13855 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13856 "Host: www.example.org\r\n"
13857 "Proxy-Connection: keep-alive\r\n"
13858 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13861 "GET / HTTP/1.1\r\n"
13862 "Host: www.example.org\r\n"
13863 "Connection: Upgrade\r\n"
13864 "Upgrade: websocket\r\n"
13865 "Origin: http://www.example.org\r\n"
13866 "Sec-WebSocket-Version: 13\r\n"
13867 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13870 // The proxy responds to the connect with a 407, using a persistent
13872 MockRead data_reads
[] = {
13874 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
13875 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13876 MockRead("Proxy-Connection: close\r\n\r\n"),
13878 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13880 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13881 MockRead("Upgrade: websocket\r\n"),
13882 MockRead("Connection: Upgrade\r\n"),
13883 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13886 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13887 arraysize(data_writes
));
13888 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13889 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13890 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13892 scoped_ptr
<HttpTransaction
> trans(
13893 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13894 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13895 trans
->SetWebSocketHandshakeStreamCreateHelper(
13896 &websocket_stream_create_helper
);
13899 TestCompletionCallback callback
;
13901 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13902 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13904 rv
= callback
.WaitForResult();
13908 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13909 ASSERT_TRUE(response
);
13910 ASSERT_TRUE(response
->headers
.get());
13911 EXPECT_EQ(407, response
->headers
->response_code());
13914 TestCompletionCallback callback
;
13916 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
13917 callback
.callback());
13918 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13920 rv
= callback
.WaitForResult();
13924 response
= trans
->GetResponseInfo();
13925 ASSERT_TRUE(response
);
13926 ASSERT_TRUE(response
->headers
.get());
13928 EXPECT_EQ(101, response
->headers
->response_code());
13931 session
->CloseAllConnections();
13934 // Verify that proxy headers are not sent to the destination server when
13935 // establishing a tunnel for an insecure WebSocket connection.
13936 // This requires the authentication info to be injected into the auth cache
13937 // due to crbug.com/395064
13938 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
13939 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
13940 HttpRequestInfo request
;
13941 request
.method
= "GET";
13942 request
.url
= GURL("ws://www.example.org/");
13943 AddWebSocketHeaders(&request
.extra_headers
);
13945 // Configure against proxy server "myproxy:70".
13946 session_deps_
.proxy_service
.reset(
13947 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13949 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13951 MockWrite data_writes
[] = {
13952 // Try to establish a tunnel for the WebSocket connection, with
13953 // credentials. Because WebSockets have a separate set of socket pools,
13954 // they cannot and will not use the same TCP/IP connection as the
13955 // preflight HTTP request.
13957 "CONNECT www.example.org:80 HTTP/1.1\r\n"
13958 "Host: www.example.org:80\r\n"
13959 "Proxy-Connection: keep-alive\r\n"
13960 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13963 "GET / HTTP/1.1\r\n"
13964 "Host: www.example.org\r\n"
13965 "Connection: Upgrade\r\n"
13966 "Upgrade: websocket\r\n"
13967 "Origin: http://www.example.org\r\n"
13968 "Sec-WebSocket-Version: 13\r\n"
13969 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13972 MockRead data_reads
[] = {
13973 // HTTP CONNECT with credentials.
13974 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13976 // WebSocket connection established inside tunnel.
13977 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13978 MockRead("Upgrade: websocket\r\n"),
13979 MockRead("Connection: Upgrade\r\n"),
13980 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13983 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13984 arraysize(data_writes
));
13985 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13987 session
->http_auth_cache()->Add(
13988 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
13989 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
13991 scoped_ptr
<HttpTransaction
> trans(
13992 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13993 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13994 trans
->SetWebSocketHandshakeStreamCreateHelper(
13995 &websocket_stream_create_helper
);
13997 TestCompletionCallback callback
;
13999 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14000 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14002 rv
= callback
.WaitForResult();
14005 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14006 ASSERT_TRUE(response
);
14007 ASSERT_TRUE(response
->headers
.get());
14009 EXPECT_EQ(101, response
->headers
->response_code());
14012 session
->CloseAllConnections();