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/captured_net_log_entry.h"
55 #include "net/log/net_log.h"
56 #include "net/log/net_log_unittest.h"
57 #include "net/log/test_net_log.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 CapturedNetLogEntry::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 OrderedSocketData
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 CapturedNetLogEntry::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 CapturedNetLogEntry::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 CapturedNetLogEntry::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 CapturedNetLogEntry::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 CapturedNetLogEntry::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
) };
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
),
3359 CreateMockRead(*data
),
3360 MockRead(ASYNC
, 0, 0),
3363 DelayedSocketData
spdy_data(
3364 1, // wait for one write to finish before reading.
3365 spdy_reads
, arraysize(spdy_reads
),
3366 spdy_writes
, arraysize(spdy_writes
));
3367 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3369 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3370 ssl
.SetNextProto(GetParam());
3371 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3373 TestCompletionCallback callback1
;
3375 scoped_ptr
<HttpTransaction
> trans(
3376 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3378 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3379 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3381 rv
= callback1
.WaitForResult();
3384 LoadTimingInfo load_timing_info
;
3385 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3386 TestLoadTimingNotReused(load_timing_info
,
3387 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3389 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3390 ASSERT_TRUE(response
!= NULL
);
3391 ASSERT_TRUE(response
->headers
.get() != NULL
);
3392 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3394 std::string response_data
;
3395 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3396 EXPECT_EQ(kUploadData
, response_data
);
3399 // Verifies that a session which races and wins against the owning transaction
3400 // (completing prior to host resolution), doesn't fail the transaction.
3401 // Regression test for crbug.com/334413.
3402 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithSessionRace
) {
3403 HttpRequestInfo request
;
3404 request
.method
= "GET";
3405 request
.url
= GURL("http://www.example.org/");
3406 request
.load_flags
= 0;
3408 // Configure SPDY proxy server "proxy:70".
3409 session_deps_
.proxy_service
.reset(
3410 ProxyService::CreateFixed("https://proxy:70"));
3411 BoundTestNetLog log
;
3412 session_deps_
.net_log
= log
.bound().net_log();
3413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3415 // Fetch http://www.example.org/ through the SPDY proxy.
3416 scoped_ptr
<SpdyFrame
> req(
3417 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3418 MockWrite spdy_writes
[] = {CreateMockWrite(*req
)};
3420 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3421 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3422 MockRead spdy_reads
[] = {
3423 CreateMockRead(*resp
), CreateMockRead(*data
), MockRead(ASYNC
, 0, 0),
3426 DelayedSocketData
spdy_data(
3427 1, // wait for one write to finish before reading.
3429 arraysize(spdy_reads
),
3431 arraysize(spdy_writes
));
3432 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3434 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3435 ssl
.SetNextProto(GetParam());
3436 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3438 TestCompletionCallback callback1
;
3440 scoped_ptr
<HttpTransaction
> trans(
3441 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3443 // Stall the hostname resolution begun by the transaction.
3444 session_deps_
.host_resolver
->set_synchronous_mode(false);
3445 session_deps_
.host_resolver
->set_ondemand_mode(true);
3447 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3448 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3450 // Race a session to the proxy, which completes first.
3451 session_deps_
.host_resolver
->set_ondemand_mode(false);
3453 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3454 base::WeakPtr
<SpdySession
> spdy_session
=
3455 CreateSecureSpdySession(session
, key
, log
.bound());
3457 // Unstall the resolution begun by the transaction.
3458 session_deps_
.host_resolver
->set_ondemand_mode(true);
3459 session_deps_
.host_resolver
->ResolveAllPending();
3461 EXPECT_FALSE(callback1
.have_result());
3462 rv
= callback1
.WaitForResult();
3465 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3466 ASSERT_TRUE(response
!= NULL
);
3467 ASSERT_TRUE(response
->headers
.get() != NULL
);
3468 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3470 std::string response_data
;
3471 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3472 EXPECT_EQ(kUploadData
, response_data
);
3475 // Test a SPDY get through an HTTPS Proxy.
3476 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3477 HttpRequestInfo request
;
3478 request
.method
= "GET";
3479 request
.url
= GURL("http://www.example.org/");
3480 request
.load_flags
= 0;
3482 // Configure against https proxy server "myproxy:70".
3483 session_deps_
.proxy_service
.reset(
3484 ProxyService::CreateFixed("https://myproxy:70"));
3485 BoundTestNetLog log
;
3486 session_deps_
.net_log
= log
.bound().net_log();
3487 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3489 // The first request will be a bare GET, the second request will be a
3490 // GET with a Proxy-Authorization header.
3491 scoped_ptr
<SpdyFrame
> req_get(
3492 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3493 const char* const kExtraAuthorizationHeaders
[] = {
3494 "proxy-authorization", "Basic Zm9vOmJhcg=="
3496 scoped_ptr
<SpdyFrame
> req_get_authorization(
3497 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3498 arraysize(kExtraAuthorizationHeaders
) / 2,
3503 MockWrite spdy_writes
[] = {
3504 CreateMockWrite(*req_get
, 1),
3505 CreateMockWrite(*req_get_authorization
, 4),
3508 // The first response is a 407 proxy authentication challenge, and the second
3509 // response will be a 200 response since the second request includes a valid
3510 // Authorization header.
3511 const char* const kExtraAuthenticationHeaders
[] = {
3512 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3514 scoped_ptr
<SpdyFrame
> resp_authentication(
3515 spdy_util_
.ConstructSpdySynReplyError(
3516 "407 Proxy Authentication Required",
3517 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3519 scoped_ptr
<SpdyFrame
> body_authentication(
3520 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3521 scoped_ptr
<SpdyFrame
> resp_data(
3522 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3523 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3524 MockRead spdy_reads
[] = {
3525 CreateMockRead(*resp_authentication
, 2),
3526 CreateMockRead(*body_authentication
, 3),
3527 CreateMockRead(*resp_data
, 5),
3528 CreateMockRead(*body_data
, 6),
3529 MockRead(ASYNC
, 0, 7),
3532 OrderedSocketData
data(
3533 spdy_reads
, arraysize(spdy_reads
),
3534 spdy_writes
, arraysize(spdy_writes
));
3535 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3537 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3538 ssl
.SetNextProto(GetParam());
3539 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3541 TestCompletionCallback callback1
;
3543 scoped_ptr
<HttpTransaction
> trans(
3544 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3546 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3547 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3549 rv
= callback1
.WaitForResult();
3552 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3554 ASSERT_TRUE(response
!= NULL
);
3555 ASSERT_TRUE(response
->headers
.get() != NULL
);
3556 EXPECT_EQ(407, response
->headers
->response_code());
3557 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3558 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3560 TestCompletionCallback callback2
;
3562 rv
= trans
->RestartWithAuth(
3563 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3564 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3566 rv
= callback2
.WaitForResult();
3569 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3571 ASSERT_TRUE(response_restart
!= NULL
);
3572 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3573 EXPECT_EQ(200, response_restart
->headers
->response_code());
3574 // The password prompt info should not be set.
3575 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3578 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3579 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3580 HttpRequestInfo request
;
3581 request
.method
= "GET";
3582 request
.url
= GURL("https://www.example.org/");
3583 request
.load_flags
= 0;
3585 // Configure against https proxy server "proxy:70".
3586 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3587 "https://proxy:70"));
3588 BoundTestNetLog log
;
3589 session_deps_
.net_log
= log
.bound().net_log();
3590 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3592 scoped_ptr
<HttpTransaction
> trans(
3593 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3595 // CONNECT to www.example.org:443 via SPDY
3596 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3597 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3598 // fetch https://www.example.org/ via HTTP
3601 "GET / HTTP/1.1\r\n"
3602 "Host: www.example.org\r\n"
3603 "Connection: keep-alive\r\n\r\n";
3604 scoped_ptr
<SpdyFrame
> wrapped_get(
3605 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3606 scoped_ptr
<SpdyFrame
> conn_resp(
3607 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3608 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3609 "Content-Length: 10\r\n\r\n";
3610 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3611 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3612 scoped_ptr
<SpdyFrame
> wrapped_body(
3613 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3614 scoped_ptr
<SpdyFrame
> window_update(
3615 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3617 MockWrite spdy_writes
[] = {
3618 CreateMockWrite(*connect
, 1),
3619 CreateMockWrite(*wrapped_get
, 3),
3620 CreateMockWrite(*window_update
, 5),
3623 MockRead spdy_reads
[] = {
3624 CreateMockRead(*conn_resp
, 2, ASYNC
),
3625 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3626 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3627 CreateMockRead(*wrapped_body
, 7, ASYNC
),
3628 MockRead(ASYNC
, 0, 8),
3631 OrderedSocketData
spdy_data(
3632 spdy_reads
, arraysize(spdy_reads
),
3633 spdy_writes
, arraysize(spdy_writes
));
3634 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3636 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3637 ssl
.SetNextProto(GetParam());
3638 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3639 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3640 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3642 TestCompletionCallback callback1
;
3644 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3645 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3647 rv
= callback1
.WaitForResult();
3650 LoadTimingInfo load_timing_info
;
3651 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3652 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3654 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3655 ASSERT_TRUE(response
!= NULL
);
3656 ASSERT_TRUE(response
->headers
.get() != NULL
);
3657 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3659 std::string response_data
;
3660 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3661 EXPECT_EQ("1234567890", response_data
);
3664 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3665 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3666 HttpRequestInfo request
;
3667 request
.method
= "GET";
3668 request
.url
= GURL("https://www.example.org/");
3669 request
.load_flags
= 0;
3671 // Configure against https proxy server "proxy:70".
3672 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3673 "https://proxy:70"));
3674 BoundTestNetLog log
;
3675 session_deps_
.net_log
= log
.bound().net_log();
3676 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3678 scoped_ptr
<HttpTransaction
> trans(
3679 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3681 // CONNECT to www.example.org:443 via SPDY
3682 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3683 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3684 // fetch https://www.example.org/ via SPDY
3685 const char kMyUrl
[] = "https://www.example.org/";
3686 scoped_ptr
<SpdyFrame
> get(
3687 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3688 scoped_ptr
<SpdyFrame
> wrapped_get(
3689 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3690 scoped_ptr
<SpdyFrame
> conn_resp(
3691 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3692 scoped_ptr
<SpdyFrame
> get_resp(
3693 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3694 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3695 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3696 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3697 scoped_ptr
<SpdyFrame
> wrapped_body(
3698 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3699 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3700 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3701 scoped_ptr
<SpdyFrame
> window_update_body(
3702 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3704 MockWrite spdy_writes
[] = {
3705 CreateMockWrite(*connect
, 1),
3706 CreateMockWrite(*wrapped_get
, 3),
3707 CreateMockWrite(*window_update_get_resp
, 5),
3708 CreateMockWrite(*window_update_body
, 7),
3711 MockRead spdy_reads
[] = {
3712 CreateMockRead(*conn_resp
, 2, ASYNC
),
3713 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3714 CreateMockRead(*wrapped_body
, 6, ASYNC
),
3715 MockRead(ASYNC
, 0, 8),
3718 OrderedSocketData
spdy_data(
3719 spdy_reads
, arraysize(spdy_reads
),
3720 spdy_writes
, arraysize(spdy_writes
));
3721 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3723 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3724 ssl
.SetNextProto(GetParam());
3725 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3726 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3727 ssl2
.SetNextProto(GetParam());
3728 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3730 TestCompletionCallback callback1
;
3732 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3733 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3735 rv
= callback1
.WaitForResult();
3738 LoadTimingInfo load_timing_info
;
3739 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3740 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3742 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3743 ASSERT_TRUE(response
!= NULL
);
3744 ASSERT_TRUE(response
->headers
.get() != NULL
);
3745 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3747 std::string response_data
;
3748 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3749 EXPECT_EQ(kUploadData
, response_data
);
3752 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3753 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3754 HttpRequestInfo request
;
3755 request
.method
= "GET";
3756 request
.url
= GURL("https://www.example.org/");
3757 request
.load_flags
= 0;
3759 // Configure against https proxy server "proxy:70".
3760 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3761 "https://proxy:70"));
3762 BoundTestNetLog log
;
3763 session_deps_
.net_log
= log
.bound().net_log();
3764 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3766 scoped_ptr
<HttpTransaction
> trans(
3767 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3769 // CONNECT to www.example.org:443 via SPDY
3770 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3771 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3772 scoped_ptr
<SpdyFrame
> get(
3773 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3775 MockWrite spdy_writes
[] = {
3776 CreateMockWrite(*connect
, 1),
3777 CreateMockWrite(*get
, 3),
3780 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3781 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3782 MockRead spdy_reads
[] = {
3783 CreateMockRead(*resp
, 2, ASYNC
),
3784 MockRead(ASYNC
, 0, 4),
3787 OrderedSocketData
spdy_data(
3788 spdy_reads
, arraysize(spdy_reads
),
3789 spdy_writes
, arraysize(spdy_writes
));
3790 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3792 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3793 ssl
.SetNextProto(GetParam());
3794 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3795 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3796 ssl2
.SetNextProto(GetParam());
3797 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3799 TestCompletionCallback callback1
;
3801 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3802 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3804 rv
= callback1
.WaitForResult();
3805 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3807 // TODO(ttuttle): Anything else to check here?
3810 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3811 // HTTPS Proxy to different servers.
3812 TEST_P(HttpNetworkTransactionTest
,
3813 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3814 // Configure against https proxy server "proxy:70".
3815 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3816 "https://proxy:70"));
3817 BoundTestNetLog log
;
3818 session_deps_
.net_log
= log
.bound().net_log();
3819 scoped_refptr
<HttpNetworkSession
> session(
3820 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3822 HttpRequestInfo request1
;
3823 request1
.method
= "GET";
3824 request1
.url
= GURL("https://www.example.org/");
3825 request1
.load_flags
= 0;
3827 HttpRequestInfo request2
;
3828 request2
.method
= "GET";
3829 request2
.url
= GURL("https://mail.example.org/");
3830 request2
.load_flags
= 0;
3832 // CONNECT to www.example.org:443 via SPDY.
3833 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3834 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3835 scoped_ptr
<SpdyFrame
> conn_resp1(
3836 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3838 // Fetch https://www.example.org/ via HTTP.
3840 "GET / HTTP/1.1\r\n"
3841 "Host: www.example.org\r\n"
3842 "Connection: keep-alive\r\n\r\n";
3843 scoped_ptr
<SpdyFrame
> wrapped_get1(
3844 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3845 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3846 "Content-Length: 1\r\n\r\n";
3847 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3848 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3849 scoped_ptr
<SpdyFrame
> wrapped_body1(
3850 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3851 scoped_ptr
<SpdyFrame
> window_update(
3852 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3854 // CONNECT to mail.example.org:443 via SPDY.
3855 SpdyHeaderBlock connect2_block
;
3856 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3857 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3858 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3859 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3860 scoped_ptr
<SpdyFrame
> connect2(
3861 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3863 scoped_ptr
<SpdyFrame
> conn_resp2(
3864 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3866 // Fetch https://mail.example.org/ via HTTP.
3868 "GET / HTTP/1.1\r\n"
3869 "Host: mail.example.org\r\n"
3870 "Connection: keep-alive\r\n\r\n";
3871 scoped_ptr
<SpdyFrame
> wrapped_get2(
3872 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3873 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3874 "Content-Length: 2\r\n\r\n";
3875 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3876 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3877 scoped_ptr
<SpdyFrame
> wrapped_body2(
3878 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3880 MockWrite spdy_writes
[] = {
3881 CreateMockWrite(*connect1
, 0),
3882 CreateMockWrite(*wrapped_get1
, 2),
3883 CreateMockWrite(*connect2
, 5),
3884 CreateMockWrite(*wrapped_get2
, 7),
3887 MockRead spdy_reads
[] = {
3888 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3889 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3890 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3891 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3892 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3893 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3894 MockRead(ASYNC
, 0, 10),
3897 DeterministicSocketData
spdy_data(
3898 spdy_reads
, arraysize(spdy_reads
),
3899 spdy_writes
, arraysize(spdy_writes
));
3900 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
3902 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3903 ssl
.SetNextProto(GetParam());
3904 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
3905 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3906 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3907 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3908 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3910 TestCompletionCallback callback
;
3912 scoped_ptr
<HttpTransaction
> trans(
3913 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3914 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3915 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3916 // The first connect and request, each of their responses, and the body.
3917 spdy_data
.RunFor(5);
3919 rv
= callback
.WaitForResult();
3922 LoadTimingInfo load_timing_info
;
3923 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3924 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3926 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3927 ASSERT_TRUE(response
!= NULL
);
3928 ASSERT_TRUE(response
->headers
.get() != NULL
);
3929 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3931 std::string response_data
;
3932 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3933 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
3935 scoped_ptr
<HttpTransaction
> trans2(
3936 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3937 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3938 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3940 // The second connect and request, each of their responses, and the body.
3941 spdy_data
.RunFor(5);
3942 rv
= callback
.WaitForResult();
3945 LoadTimingInfo load_timing_info2
;
3946 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3947 // Even though the SPDY connection is reused, a new tunnelled connection has
3948 // to be created, so the socket's load timing looks like a fresh connection.
3949 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3951 // The requests should have different IDs, since they each are using their own
3953 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3955 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
3958 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3959 // HTTPS Proxy to the same server.
3960 TEST_P(HttpNetworkTransactionTest
,
3961 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3962 // Configure against https proxy server "proxy:70".
3963 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3964 "https://proxy:70"));
3965 BoundTestNetLog log
;
3966 session_deps_
.net_log
= log
.bound().net_log();
3967 scoped_refptr
<HttpNetworkSession
> session(
3968 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
3970 HttpRequestInfo request1
;
3971 request1
.method
= "GET";
3972 request1
.url
= GURL("https://www.example.org/");
3973 request1
.load_flags
= 0;
3975 HttpRequestInfo request2
;
3976 request2
.method
= "GET";
3977 request2
.url
= GURL("https://www.example.org/2");
3978 request2
.load_flags
= 0;
3980 // CONNECT to www.example.org:443 via SPDY.
3981 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3982 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3983 scoped_ptr
<SpdyFrame
> conn_resp1(
3984 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3986 // Fetch https://www.example.org/ via HTTP.
3988 "GET / HTTP/1.1\r\n"
3989 "Host: www.example.org\r\n"
3990 "Connection: keep-alive\r\n\r\n";
3991 scoped_ptr
<SpdyFrame
> wrapped_get1(
3992 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3993 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3994 "Content-Length: 1\r\n\r\n";
3995 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3996 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3997 scoped_ptr
<SpdyFrame
> wrapped_body1(
3998 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3999 scoped_ptr
<SpdyFrame
> window_update(
4000 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
4002 // Fetch https://www.example.org/2 via HTTP.
4004 "GET /2 HTTP/1.1\r\n"
4005 "Host: www.example.org\r\n"
4006 "Connection: keep-alive\r\n\r\n";
4007 scoped_ptr
<SpdyFrame
> wrapped_get2(
4008 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
4009 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
4010 "Content-Length: 2\r\n\r\n";
4011 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
4012 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4013 scoped_ptr
<SpdyFrame
> wrapped_body2(
4014 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4016 MockWrite spdy_writes
[] = {
4017 CreateMockWrite(*connect1
, 0),
4018 CreateMockWrite(*wrapped_get1
, 2),
4019 CreateMockWrite(*wrapped_get2
, 5),
4022 MockRead spdy_reads
[] = {
4023 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4024 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4025 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4026 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4027 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4028 MockRead(ASYNC
, 0, 8),
4031 DeterministicSocketData
spdy_data(
4032 spdy_reads
, arraysize(spdy_reads
),
4033 spdy_writes
, arraysize(spdy_writes
));
4034 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4036 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4037 ssl
.SetNextProto(GetParam());
4038 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4039 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4040 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4042 TestCompletionCallback callback
;
4044 scoped_ptr
<HttpTransaction
> trans(
4045 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4046 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4047 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4048 // The first connect and request, each of their responses, and the body.
4049 spdy_data
.RunFor(5);
4051 rv
= callback
.WaitForResult();
4054 LoadTimingInfo load_timing_info
;
4055 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4056 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4058 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4059 ASSERT_TRUE(response
!= NULL
);
4060 ASSERT_TRUE(response
->headers
.get() != NULL
);
4061 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4063 std::string response_data
;
4064 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4065 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4068 scoped_ptr
<HttpTransaction
> trans2(
4069 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4070 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4071 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4073 // The second request, response, and body. There should not be a second
4075 spdy_data
.RunFor(3);
4076 rv
= callback
.WaitForResult();
4079 LoadTimingInfo load_timing_info2
;
4080 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4081 TestLoadTimingReused(load_timing_info2
);
4083 // The requests should have the same ID.
4084 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4086 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4089 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4090 // Proxy to different servers.
4091 TEST_P(HttpNetworkTransactionTest
,
4092 HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4093 // Configure against https proxy server "proxy:70".
4094 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4095 "https://proxy:70"));
4096 BoundTestNetLog log
;
4097 session_deps_
.net_log
= log
.bound().net_log();
4098 scoped_refptr
<HttpNetworkSession
> session(
4099 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
4101 HttpRequestInfo request1
;
4102 request1
.method
= "GET";
4103 request1
.url
= GURL("http://www.example.org/");
4104 request1
.load_flags
= 0;
4106 HttpRequestInfo request2
;
4107 request2
.method
= "GET";
4108 request2
.url
= GURL("http://mail.example.org/");
4109 request2
.load_flags
= 0;
4111 // http://www.example.org/
4112 scoped_ptr
<SpdyHeaderBlock
> headers(
4113 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4114 scoped_ptr
<SpdyFrame
> get1(
4115 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4116 scoped_ptr
<SpdyFrame
> get_resp1(
4117 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4118 scoped_ptr
<SpdyFrame
> body1(
4119 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4121 // http://mail.example.org/
4122 scoped_ptr
<SpdyHeaderBlock
> headers2(
4123 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4124 scoped_ptr
<SpdyFrame
> get2(
4125 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4126 scoped_ptr
<SpdyFrame
> get_resp2(
4127 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4128 scoped_ptr
<SpdyFrame
> body2(
4129 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4131 MockWrite spdy_writes
[] = {
4132 CreateMockWrite(*get1
, 0),
4133 CreateMockWrite(*get2
, 3),
4136 MockRead spdy_reads
[] = {
4137 CreateMockRead(*get_resp1
, 1, ASYNC
),
4138 CreateMockRead(*body1
, 2, ASYNC
),
4139 CreateMockRead(*get_resp2
, 4, ASYNC
),
4140 CreateMockRead(*body2
, 5, ASYNC
),
4141 MockRead(ASYNC
, 0, 6),
4144 DeterministicSocketData
spdy_data(
4145 spdy_reads
, arraysize(spdy_reads
),
4146 spdy_writes
, arraysize(spdy_writes
));
4147 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&spdy_data
);
4149 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4150 ssl
.SetNextProto(GetParam());
4151 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl
);
4153 TestCompletionCallback callback
;
4155 scoped_ptr
<HttpTransaction
> trans(
4156 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4157 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4158 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4159 spdy_data
.RunFor(2);
4161 rv
= callback
.WaitForResult();
4164 LoadTimingInfo load_timing_info
;
4165 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4166 TestLoadTimingNotReused(load_timing_info
,
4167 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4169 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4170 ASSERT_TRUE(response
!= NULL
);
4171 ASSERT_TRUE(response
->headers
.get() != NULL
);
4172 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4174 std::string response_data
;
4175 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4176 EXPECT_EQ(ERR_IO_PENDING
, trans
->Read(buf
.get(), 256, callback
.callback()));
4177 spdy_data
.RunFor(1);
4178 EXPECT_EQ(1, callback
.WaitForResult());
4179 // Delete the first request, so the second one can reuse the socket.
4182 scoped_ptr
<HttpTransaction
> trans2(
4183 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4184 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4185 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4187 spdy_data
.RunFor(2);
4188 rv
= callback
.WaitForResult();
4191 LoadTimingInfo load_timing_info2
;
4192 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4193 TestLoadTimingReused(load_timing_info2
);
4195 // The requests should have the same ID.
4196 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4198 EXPECT_EQ(ERR_IO_PENDING
, trans2
->Read(buf
.get(), 256, callback
.callback()));
4199 spdy_data
.RunFor(1);
4200 EXPECT_EQ(2, callback
.WaitForResult());
4203 // Test the challenge-response-retry sequence through an HTTPS Proxy
4204 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4205 HttpRequestInfo request
;
4206 request
.method
= "GET";
4207 request
.url
= GURL("http://www.example.org/");
4208 // when the no authentication data flag is set.
4209 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4211 // Configure against https proxy server "myproxy:70".
4212 session_deps_
.proxy_service
.reset(
4213 ProxyService::CreateFixed("https://myproxy:70"));
4214 BoundTestNetLog log
;
4215 session_deps_
.net_log
= log
.bound().net_log();
4216 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4218 // Since we have proxy, should use full url
4219 MockWrite data_writes1
[] = {
4221 "GET http://www.example.org/ HTTP/1.1\r\n"
4222 "Host: www.example.org\r\n"
4223 "Proxy-Connection: keep-alive\r\n\r\n"),
4225 // After calling trans->RestartWithAuth(), this is the request we should
4226 // be issuing -- the final header line contains the credentials.
4228 "GET http://www.example.org/ HTTP/1.1\r\n"
4229 "Host: www.example.org\r\n"
4230 "Proxy-Connection: keep-alive\r\n"
4231 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4234 // The proxy responds to the GET with a 407, using a persistent
4236 MockRead data_reads1
[] = {
4238 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4239 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4240 MockRead("Proxy-Connection: keep-alive\r\n"),
4241 MockRead("Content-Length: 0\r\n\r\n"),
4243 MockRead("HTTP/1.1 200 OK\r\n"),
4244 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4245 MockRead("Content-Length: 100\r\n\r\n"),
4246 MockRead(SYNCHRONOUS
, OK
),
4249 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4250 data_writes1
, arraysize(data_writes1
));
4251 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4252 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4253 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4255 TestCompletionCallback callback1
;
4257 scoped_ptr
<HttpTransaction
> trans(
4258 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4260 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4261 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4263 rv
= callback1
.WaitForResult();
4266 LoadTimingInfo load_timing_info
;
4267 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4268 TestLoadTimingNotReused(load_timing_info
,
4269 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4271 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4272 ASSERT_TRUE(response
!= NULL
);
4273 ASSERT_FALSE(response
->headers
.get() == NULL
);
4274 EXPECT_EQ(407, response
->headers
->response_code());
4275 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4276 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4278 TestCompletionCallback callback2
;
4280 rv
= trans
->RestartWithAuth(
4281 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4282 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4284 rv
= callback2
.WaitForResult();
4287 load_timing_info
= LoadTimingInfo();
4288 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4289 // Retrying with HTTP AUTH is considered to be reusing a socket.
4290 TestLoadTimingReused(load_timing_info
);
4292 response
= trans
->GetResponseInfo();
4293 ASSERT_TRUE(response
!= NULL
);
4295 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4296 EXPECT_EQ(200, response
->headers
->response_code());
4297 EXPECT_EQ(100, response
->headers
->GetContentLength());
4298 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4300 // The password prompt info should not be set.
4301 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4304 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4305 const MockRead
& status
, int expected_status
) {
4306 HttpRequestInfo request
;
4307 request
.method
= "GET";
4308 request
.url
= GURL("https://www.example.org/");
4309 request
.load_flags
= 0;
4311 // Configure against proxy server "myproxy:70".
4312 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4313 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4315 // Since we have proxy, should try to establish tunnel.
4316 MockWrite data_writes
[] = {
4318 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4319 "Host: www.example.org\r\n"
4320 "Proxy-Connection: keep-alive\r\n\r\n"),
4323 MockRead data_reads
[] = {
4325 MockRead("Content-Length: 10\r\n\r\n"),
4326 // No response body because the test stops reading here.
4327 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4330 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4331 data_writes
, arraysize(data_writes
));
4332 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4334 TestCompletionCallback callback
;
4336 scoped_ptr
<HttpTransaction
> trans(
4337 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4339 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4340 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4342 rv
= callback
.WaitForResult();
4343 EXPECT_EQ(expected_status
, rv
);
4346 void HttpNetworkTransactionTest::ConnectStatusHelper(
4347 const MockRead
& status
) {
4348 ConnectStatusHelperWithExpectedStatus(
4349 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4352 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4353 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4356 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4357 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4360 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4361 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4364 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4365 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4368 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4369 ConnectStatusHelper(
4370 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4373 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4374 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4377 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4378 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4381 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4382 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4385 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4386 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4389 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4390 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4393 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4394 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4397 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4398 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4401 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4402 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4405 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4406 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4409 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4410 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4413 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4414 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4417 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4418 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4421 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4422 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4425 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4426 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4429 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4430 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4433 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4434 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4437 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4438 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4441 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4442 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4445 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4446 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4449 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4450 ConnectStatusHelperWithExpectedStatus(
4451 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4452 ERR_PROXY_AUTH_UNSUPPORTED
);
4455 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4456 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4459 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4460 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4463 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4467 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4471 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4475 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4479 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4480 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4483 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4484 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4487 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4488 ConnectStatusHelper(
4489 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4492 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4493 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4496 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4497 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4500 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4501 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4504 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4505 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4508 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4509 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4512 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4513 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4516 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4517 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4520 // Test the flow when both the proxy server AND origin server require
4521 // authentication. Again, this uses basic auth for both since that is
4522 // the simplest to mock.
4523 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4524 HttpRequestInfo request
;
4525 request
.method
= "GET";
4526 request
.url
= GURL("http://www.example.org/");
4527 request
.load_flags
= 0;
4529 // Configure against proxy server "myproxy:70".
4530 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4531 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4533 scoped_ptr
<HttpTransaction
> trans(
4534 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4536 MockWrite data_writes1
[] = {
4538 "GET http://www.example.org/ HTTP/1.1\r\n"
4539 "Host: www.example.org\r\n"
4540 "Proxy-Connection: keep-alive\r\n\r\n"),
4543 MockRead data_reads1
[] = {
4544 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4545 // Give a couple authenticate options (only the middle one is actually
4547 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4548 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4549 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4550 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4551 // Large content-length -- won't matter, as connection will be reset.
4552 MockRead("Content-Length: 10000\r\n\r\n"),
4553 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4556 // After calling trans->RestartWithAuth() the first time, this is the
4557 // request we should be issuing -- the final header line contains the
4558 // proxy's credentials.
4559 MockWrite data_writes2
[] = {
4561 "GET http://www.example.org/ HTTP/1.1\r\n"
4562 "Host: www.example.org\r\n"
4563 "Proxy-Connection: keep-alive\r\n"
4564 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4567 // Now the proxy server lets the request pass through to origin server.
4568 // The origin server responds with a 401.
4569 MockRead data_reads2
[] = {
4570 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4571 // Note: We are using the same realm-name as the proxy server. This is
4572 // completely valid, as realms are unique across hosts.
4573 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4574 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4575 MockRead("Content-Length: 2000\r\n\r\n"),
4576 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4579 // After calling trans->RestartWithAuth() the second time, we should send
4580 // the credentials for both the proxy and origin server.
4581 MockWrite data_writes3
[] = {
4583 "GET http://www.example.org/ HTTP/1.1\r\n"
4584 "Host: www.example.org\r\n"
4585 "Proxy-Connection: keep-alive\r\n"
4586 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4587 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4590 // Lastly we get the desired content.
4591 MockRead data_reads3
[] = {
4592 MockRead("HTTP/1.0 200 OK\r\n"),
4593 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4594 MockRead("Content-Length: 100\r\n\r\n"),
4595 MockRead(SYNCHRONOUS
, OK
),
4598 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4599 data_writes1
, arraysize(data_writes1
));
4600 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4601 data_writes2
, arraysize(data_writes2
));
4602 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4603 data_writes3
, arraysize(data_writes3
));
4604 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4605 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4606 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4608 TestCompletionCallback callback1
;
4610 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4611 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4613 rv
= callback1
.WaitForResult();
4616 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4617 ASSERT_TRUE(response
!= NULL
);
4618 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4620 TestCompletionCallback callback2
;
4622 rv
= trans
->RestartWithAuth(
4623 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4624 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4626 rv
= callback2
.WaitForResult();
4629 response
= trans
->GetResponseInfo();
4630 ASSERT_TRUE(response
!= NULL
);
4631 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4633 TestCompletionCallback callback3
;
4635 rv
= trans
->RestartWithAuth(
4636 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4637 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4639 rv
= callback3
.WaitForResult();
4642 response
= trans
->GetResponseInfo();
4643 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4644 EXPECT_EQ(100, response
->headers
->GetContentLength());
4647 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4648 // can't hook into its internals to cause it to generate predictable NTLM
4649 // authorization headers.
4650 #if defined(NTLM_PORTABLE)
4651 // The NTLM authentication unit tests were generated by capturing the HTTP
4652 // requests and responses using Fiddler 2 and inspecting the generated random
4653 // bytes in the debugger.
4655 // Enter the correct password and authenticate successfully.
4656 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4657 HttpRequestInfo request
;
4658 request
.method
= "GET";
4659 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4661 // Ensure load is not disrupted by flags which suppress behaviour specific
4662 // to other auth schemes.
4663 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4665 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4667 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4669 MockWrite data_writes1
[] = {
4670 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4671 "Host: 172.22.68.17\r\n"
4672 "Connection: keep-alive\r\n\r\n"),
4675 MockRead data_reads1
[] = {
4676 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4677 // Negotiate and NTLM are often requested together. However, we only want
4678 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4679 // the header that requests Negotiate for this test.
4680 MockRead("WWW-Authenticate: NTLM\r\n"),
4681 MockRead("Connection: close\r\n"),
4682 MockRead("Content-Length: 42\r\n"),
4683 MockRead("Content-Type: text/html\r\n\r\n"),
4684 // Missing content -- won't matter, as connection will be reset.
4685 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4688 MockWrite data_writes2
[] = {
4689 // After restarting with a null identity, this is the
4690 // request we should be issuing -- the final header line contains a Type
4692 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4693 "Host: 172.22.68.17\r\n"
4694 "Connection: keep-alive\r\n"
4695 "Authorization: NTLM "
4696 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4698 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4699 // (the credentials for the origin server). The second request continues
4700 // on the same connection.
4701 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4702 "Host: 172.22.68.17\r\n"
4703 "Connection: keep-alive\r\n"
4704 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4705 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4706 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4707 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4708 "ahlhx5I=\r\n\r\n"),
4711 MockRead data_reads2
[] = {
4712 // The origin server responds with a Type 2 message.
4713 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4714 MockRead("WWW-Authenticate: NTLM "
4715 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4716 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4717 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4718 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4719 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4720 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4722 MockRead("Content-Length: 42\r\n"),
4723 MockRead("Content-Type: text/html\r\n\r\n"),
4724 MockRead("You are not authorized to view this page\r\n"),
4726 // Lastly we get the desired content.
4727 MockRead("HTTP/1.1 200 OK\r\n"),
4728 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4729 MockRead("Content-Length: 13\r\n\r\n"),
4730 MockRead("Please Login\r\n"),
4731 MockRead(SYNCHRONOUS
, OK
),
4734 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4735 data_writes1
, arraysize(data_writes1
));
4736 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4737 data_writes2
, arraysize(data_writes2
));
4738 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4739 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4741 TestCompletionCallback callback1
;
4743 scoped_ptr
<HttpTransaction
> trans(
4744 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4746 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4747 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4749 rv
= callback1
.WaitForResult();
4752 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4754 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4755 ASSERT_FALSE(response
== NULL
);
4756 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4758 TestCompletionCallback callback2
;
4760 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4761 callback2
.callback());
4762 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4764 rv
= callback2
.WaitForResult();
4767 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4769 response
= trans
->GetResponseInfo();
4770 ASSERT_TRUE(response
!= NULL
);
4771 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4773 TestCompletionCallback callback3
;
4775 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4778 rv
= callback3
.WaitForResult();
4781 response
= trans
->GetResponseInfo();
4782 ASSERT_TRUE(response
!= NULL
);
4783 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4784 EXPECT_EQ(13, response
->headers
->GetContentLength());
4787 // Enter a wrong password, and then the correct one.
4788 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4789 HttpRequestInfo request
;
4790 request
.method
= "GET";
4791 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4792 request
.load_flags
= 0;
4794 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4796 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4798 MockWrite data_writes1
[] = {
4799 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4800 "Host: 172.22.68.17\r\n"
4801 "Connection: keep-alive\r\n\r\n"),
4804 MockRead data_reads1
[] = {
4805 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4806 // Negotiate and NTLM are often requested together. However, we only want
4807 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4808 // the header that requests Negotiate for this test.
4809 MockRead("WWW-Authenticate: NTLM\r\n"),
4810 MockRead("Connection: close\r\n"),
4811 MockRead("Content-Length: 42\r\n"),
4812 MockRead("Content-Type: text/html\r\n\r\n"),
4813 // Missing content -- won't matter, as connection will be reset.
4814 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4817 MockWrite data_writes2
[] = {
4818 // After restarting with a null identity, this is the
4819 // request we should be issuing -- the final header line contains a Type
4821 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4822 "Host: 172.22.68.17\r\n"
4823 "Connection: keep-alive\r\n"
4824 "Authorization: NTLM "
4825 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4827 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4828 // (the credentials for the origin server). The second request continues
4829 // on the same connection.
4830 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4831 "Host: 172.22.68.17\r\n"
4832 "Connection: keep-alive\r\n"
4833 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4834 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4835 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4836 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4837 "4Ww7b7E=\r\n\r\n"),
4840 MockRead data_reads2
[] = {
4841 // The origin server responds with a Type 2 message.
4842 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4843 MockRead("WWW-Authenticate: NTLM "
4844 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4845 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4846 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4847 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4848 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4849 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4851 MockRead("Content-Length: 42\r\n"),
4852 MockRead("Content-Type: text/html\r\n\r\n"),
4853 MockRead("You are not authorized to view this page\r\n"),
4856 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4857 MockRead("WWW-Authenticate: NTLM\r\n"),
4858 MockRead("Connection: close\r\n"),
4859 MockRead("Content-Length: 42\r\n"),
4860 MockRead("Content-Type: text/html\r\n\r\n"),
4861 // Missing content -- won't matter, as connection will be reset.
4862 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4865 MockWrite data_writes3
[] = {
4866 // After restarting with a null identity, this is the
4867 // request we should be issuing -- the final header line contains a Type
4869 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4870 "Host: 172.22.68.17\r\n"
4871 "Connection: keep-alive\r\n"
4872 "Authorization: NTLM "
4873 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4875 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4876 // (the credentials for the origin server). The second request continues
4877 // on the same connection.
4878 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4879 "Host: 172.22.68.17\r\n"
4880 "Connection: keep-alive\r\n"
4881 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4882 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4883 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4884 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4885 "+4MUm7c=\r\n\r\n"),
4888 MockRead data_reads3
[] = {
4889 // The origin server responds with a Type 2 message.
4890 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4891 MockRead("WWW-Authenticate: NTLM "
4892 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4893 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4894 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4895 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4896 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4897 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4899 MockRead("Content-Length: 42\r\n"),
4900 MockRead("Content-Type: text/html\r\n\r\n"),
4901 MockRead("You are not authorized to view this page\r\n"),
4903 // Lastly we get the desired content.
4904 MockRead("HTTP/1.1 200 OK\r\n"),
4905 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4906 MockRead("Content-Length: 13\r\n\r\n"),
4907 MockRead("Please Login\r\n"),
4908 MockRead(SYNCHRONOUS
, OK
),
4911 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4912 data_writes1
, arraysize(data_writes1
));
4913 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4914 data_writes2
, arraysize(data_writes2
));
4915 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4916 data_writes3
, arraysize(data_writes3
));
4917 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4918 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4919 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4921 TestCompletionCallback callback1
;
4923 scoped_ptr
<HttpTransaction
> trans(
4924 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4926 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4927 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4929 rv
= callback1
.WaitForResult();
4932 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4934 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4935 ASSERT_TRUE(response
!= NULL
);
4936 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4938 TestCompletionCallback callback2
;
4940 // Enter the wrong password.
4941 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4942 callback2
.callback());
4943 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4945 rv
= callback2
.WaitForResult();
4948 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4949 TestCompletionCallback callback3
;
4950 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4951 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4952 rv
= callback3
.WaitForResult();
4954 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4956 response
= trans
->GetResponseInfo();
4957 ASSERT_FALSE(response
== NULL
);
4958 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4960 TestCompletionCallback callback4
;
4962 // Now enter the right password.
4963 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4964 callback4
.callback());
4965 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4967 rv
= callback4
.WaitForResult();
4970 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4972 TestCompletionCallback callback5
;
4974 // One more roundtrip
4975 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4976 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4978 rv
= callback5
.WaitForResult();
4981 response
= trans
->GetResponseInfo();
4982 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4983 EXPECT_EQ(13, response
->headers
->GetContentLength());
4985 #endif // NTLM_PORTABLE
4987 // Test reading a server response which has only headers, and no body.
4988 // After some maximum number of bytes is consumed, the transaction should
4989 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4990 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4991 HttpRequestInfo request
;
4992 request
.method
= "GET";
4993 request
.url
= GURL("http://www.example.org/");
4994 request
.load_flags
= 0;
4996 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4997 scoped_ptr
<HttpTransaction
> trans(
4998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5000 // Respond with 300 kb of headers (we should fail after 256 kb).
5001 std::string large_headers_string
;
5002 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
5004 MockRead data_reads
[] = {
5005 MockRead("HTTP/1.0 200 OK\r\n"),
5006 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
5007 MockRead("\r\nBODY"),
5008 MockRead(SYNCHRONOUS
, OK
),
5010 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5011 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5013 TestCompletionCallback callback
;
5015 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5016 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5018 rv
= callback
.WaitForResult();
5019 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
5021 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5022 EXPECT_TRUE(response
== NULL
);
5025 // Make sure that we don't try to reuse a TCPClientSocket when failing to
5026 // establish tunnel.
5027 // http://code.google.com/p/chromium/issues/detail?id=3772
5028 TEST_P(HttpNetworkTransactionTest
,
5029 DontRecycleTransportSocketForSSLTunnel
) {
5030 HttpRequestInfo request
;
5031 request
.method
= "GET";
5032 request
.url
= GURL("https://www.example.org/");
5033 request
.load_flags
= 0;
5035 // Configure against proxy server "myproxy:70".
5036 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5038 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5040 scoped_ptr
<HttpTransaction
> trans(
5041 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5043 // Since we have proxy, should try to establish tunnel.
5044 MockWrite data_writes1
[] = {
5046 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5047 "Host: www.example.org\r\n"
5048 "Proxy-Connection: keep-alive\r\n\r\n"),
5051 // The proxy responds to the connect with a 404, using a persistent
5052 // connection. Usually a proxy would return 501 (not implemented),
5053 // or 200 (tunnel established).
5054 MockRead data_reads1
[] = {
5055 MockRead("HTTP/1.1 404 Not Found\r\n"),
5056 MockRead("Content-Length: 10\r\n\r\n"),
5057 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5060 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5061 data_writes1
, arraysize(data_writes1
));
5062 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5064 TestCompletionCallback callback1
;
5066 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5067 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5069 rv
= callback1
.WaitForResult();
5070 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5072 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5073 EXPECT_TRUE(response
== NULL
);
5075 // Empty the current queue. This is necessary because idle sockets are
5076 // added to the connection pool asynchronously with a PostTask.
5077 base::MessageLoop::current()->RunUntilIdle();
5079 // We now check to make sure the TCPClientSocket was not added back to
5081 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5083 base::MessageLoop::current()->RunUntilIdle();
5084 // Make sure that the socket didn't get recycled after calling the destructor.
5085 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5088 // Make sure that we recycle a socket after reading all of the response body.
5089 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5090 HttpRequestInfo request
;
5091 request
.method
= "GET";
5092 request
.url
= GURL("http://www.example.org/");
5093 request
.load_flags
= 0;
5095 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5097 scoped_ptr
<HttpTransaction
> trans(
5098 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5100 MockRead data_reads
[] = {
5101 // A part of the response body is received with the response headers.
5102 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5103 // The rest of the response body is received in two parts.
5106 MockRead("junk"), // Should not be read!!
5107 MockRead(SYNCHRONOUS
, OK
),
5110 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5111 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5113 TestCompletionCallback callback
;
5115 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5116 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5118 rv
= callback
.WaitForResult();
5121 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5122 ASSERT_TRUE(response
!= NULL
);
5124 EXPECT_TRUE(response
->headers
.get() != NULL
);
5125 std::string status_line
= response
->headers
->GetStatusLine();
5126 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5128 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5130 std::string response_data
;
5131 rv
= ReadTransaction(trans
.get(), &response_data
);
5133 EXPECT_EQ("hello world", response_data
);
5135 // Empty the current queue. This is necessary because idle sockets are
5136 // added to the connection pool asynchronously with a PostTask.
5137 base::MessageLoop::current()->RunUntilIdle();
5139 // We now check to make sure the socket was added back to the pool.
5140 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5143 // Make sure that we recycle a SSL socket after reading all of the response
5145 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5146 HttpRequestInfo request
;
5147 request
.method
= "GET";
5148 request
.url
= GURL("https://www.example.org/");
5149 request
.load_flags
= 0;
5151 MockWrite data_writes
[] = {
5153 "GET / HTTP/1.1\r\n"
5154 "Host: www.example.org\r\n"
5155 "Connection: keep-alive\r\n\r\n"),
5158 MockRead data_reads
[] = {
5159 MockRead("HTTP/1.1 200 OK\r\n"),
5160 MockRead("Content-Length: 11\r\n\r\n"),
5161 MockRead("hello world"),
5162 MockRead(SYNCHRONOUS
, OK
),
5165 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5166 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5168 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5169 data_writes
, arraysize(data_writes
));
5170 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5172 TestCompletionCallback callback
;
5174 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5175 scoped_ptr
<HttpTransaction
> trans(
5176 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5178 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5181 EXPECT_EQ(OK
, callback
.WaitForResult());
5183 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5184 ASSERT_TRUE(response
!= NULL
);
5185 ASSERT_TRUE(response
->headers
.get() != NULL
);
5186 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5188 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5190 std::string response_data
;
5191 rv
= ReadTransaction(trans
.get(), &response_data
);
5193 EXPECT_EQ("hello world", response_data
);
5195 // Empty the current queue. This is necessary because idle sockets are
5196 // added to the connection pool asynchronously with a PostTask.
5197 base::MessageLoop::current()->RunUntilIdle();
5199 // We now check to make sure the socket was added back to the pool.
5200 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5203 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5204 // from the pool and make sure that we recover okay.
5205 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5206 HttpRequestInfo request
;
5207 request
.method
= "GET";
5208 request
.url
= GURL("https://www.example.org/");
5209 request
.load_flags
= 0;
5211 MockWrite data_writes
[] = {
5213 "GET / HTTP/1.1\r\n"
5214 "Host: www.example.org\r\n"
5215 "Connection: keep-alive\r\n\r\n"),
5217 "GET / HTTP/1.1\r\n"
5218 "Host: www.example.org\r\n"
5219 "Connection: keep-alive\r\n\r\n"),
5222 MockRead data_reads
[] = {
5223 MockRead("HTTP/1.1 200 OK\r\n"),
5224 MockRead("Content-Length: 11\r\n\r\n"),
5225 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5226 MockRead("hello world"),
5227 MockRead(ASYNC
, 0, 0) // EOF
5230 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5231 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5232 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5233 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5235 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5236 data_writes
, arraysize(data_writes
));
5237 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5238 data_writes
, arraysize(data_writes
));
5239 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5240 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5242 TestCompletionCallback callback
;
5244 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5245 scoped_ptr
<HttpTransaction
> trans(
5246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5248 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5251 EXPECT_EQ(OK
, callback
.WaitForResult());
5253 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5254 ASSERT_TRUE(response
!= NULL
);
5255 ASSERT_TRUE(response
->headers
.get() != NULL
);
5256 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5258 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5260 std::string response_data
;
5261 rv
= ReadTransaction(trans
.get(), &response_data
);
5263 EXPECT_EQ("hello world", response_data
);
5265 // Empty the current queue. This is necessary because idle sockets are
5266 // added to the connection pool asynchronously with a PostTask.
5267 base::MessageLoop::current()->RunUntilIdle();
5269 // We now check to make sure the socket was added back to the pool.
5270 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5272 // Now start the second transaction, which should reuse the previous socket.
5274 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5276 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5278 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5279 EXPECT_EQ(OK
, callback
.WaitForResult());
5281 response
= trans
->GetResponseInfo();
5282 ASSERT_TRUE(response
!= NULL
);
5283 ASSERT_TRUE(response
->headers
.get() != NULL
);
5284 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5286 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5288 rv
= ReadTransaction(trans
.get(), &response_data
);
5290 EXPECT_EQ("hello world", response_data
);
5292 // Empty the current queue. This is necessary because idle sockets are
5293 // added to the connection pool asynchronously with a PostTask.
5294 base::MessageLoop::current()->RunUntilIdle();
5296 // We now check to make sure the socket was added back to the pool.
5297 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5300 // Make sure that we recycle a socket after a zero-length response.
5301 // http://crbug.com/9880
5302 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5303 HttpRequestInfo request
;
5304 request
.method
= "GET";
5306 "http://www.example.org/csi?v=3&s=web&action=&"
5307 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5308 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5309 "rt=prt.2642,ol.2649,xjs.2951");
5310 request
.load_flags
= 0;
5312 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5314 scoped_ptr
<HttpTransaction
> trans(
5315 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5317 MockRead data_reads
[] = {
5318 MockRead("HTTP/1.1 204 No Content\r\n"
5319 "Content-Length: 0\r\n"
5320 "Content-Type: text/html\r\n\r\n"),
5321 MockRead("junk"), // Should not be read!!
5322 MockRead(SYNCHRONOUS
, OK
),
5325 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5326 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5328 TestCompletionCallback callback
;
5330 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5331 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5333 rv
= callback
.WaitForResult();
5336 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5337 ASSERT_TRUE(response
!= NULL
);
5339 EXPECT_TRUE(response
->headers
.get() != NULL
);
5340 std::string status_line
= response
->headers
->GetStatusLine();
5341 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5343 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5345 std::string response_data
;
5346 rv
= ReadTransaction(trans
.get(), &response_data
);
5348 EXPECT_EQ("", response_data
);
5350 // Empty the current queue. This is necessary because idle sockets are
5351 // added to the connection pool asynchronously with a PostTask.
5352 base::MessageLoop::current()->RunUntilIdle();
5354 // We now check to make sure the socket was added back to the pool.
5355 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5358 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5359 ScopedVector
<UploadElementReader
> element_readers
;
5360 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5361 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5363 HttpRequestInfo request
[2];
5364 // Transaction 1: a GET request that succeeds. The socket is recycled
5366 request
[0].method
= "GET";
5367 request
[0].url
= GURL("http://www.google.com/");
5368 request
[0].load_flags
= 0;
5369 // Transaction 2: a POST request. Reuses the socket kept alive from
5370 // transaction 1. The first attempts fails when writing the POST data.
5371 // This causes the transaction to retry with a new socket. The second
5372 // attempt succeeds.
5373 request
[1].method
= "POST";
5374 request
[1].url
= GURL("http://www.google.com/login.cgi");
5375 request
[1].upload_data_stream
= &upload_data_stream
;
5376 request
[1].load_flags
= 0;
5378 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5380 // The first socket is used for transaction 1 and the first attempt of
5383 // The response of transaction 1.
5384 MockRead data_reads1
[] = {
5385 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5386 MockRead("hello world"),
5387 MockRead(SYNCHRONOUS
, OK
),
5389 // The mock write results of transaction 1 and the first attempt of
5391 MockWrite data_writes1
[] = {
5392 MockWrite(SYNCHRONOUS
, 64), // GET
5393 MockWrite(SYNCHRONOUS
, 93), // POST
5394 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5396 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5397 data_writes1
, arraysize(data_writes1
));
5399 // The second socket is used for the second attempt of transaction 2.
5401 // The response of transaction 2.
5402 MockRead data_reads2
[] = {
5403 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5404 MockRead("welcome"),
5405 MockRead(SYNCHRONOUS
, OK
),
5407 // The mock write results of the second attempt of transaction 2.
5408 MockWrite data_writes2
[] = {
5409 MockWrite(SYNCHRONOUS
, 93), // POST
5410 MockWrite(SYNCHRONOUS
, 3), // POST data
5412 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5413 data_writes2
, arraysize(data_writes2
));
5415 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5416 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5418 const char* const kExpectedResponseData
[] = {
5419 "hello world", "welcome"
5422 for (int i
= 0; i
< 2; ++i
) {
5423 scoped_ptr
<HttpTransaction
> trans(
5424 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5426 TestCompletionCallback callback
;
5428 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5429 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5431 rv
= callback
.WaitForResult();
5434 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5435 ASSERT_TRUE(response
!= NULL
);
5437 EXPECT_TRUE(response
->headers
.get() != NULL
);
5438 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5440 std::string response_data
;
5441 rv
= ReadTransaction(trans
.get(), &response_data
);
5443 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5447 // Test the request-challenge-retry sequence for basic auth when there is
5448 // an identity in the URL. The request should be sent as normal, but when
5449 // it fails the identity from the URL is used to answer the challenge.
5450 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5451 HttpRequestInfo request
;
5452 request
.method
= "GET";
5453 request
.url
= GURL("http://foo:b@r@www.example.org/");
5454 request
.load_flags
= LOAD_NORMAL
;
5456 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5457 scoped_ptr
<HttpTransaction
> trans(
5458 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5460 // The password contains an escaped character -- for this test to pass it
5461 // will need to be unescaped by HttpNetworkTransaction.
5462 EXPECT_EQ("b%40r", request
.url
.password());
5464 MockWrite data_writes1
[] = {
5466 "GET / HTTP/1.1\r\n"
5467 "Host: www.example.org\r\n"
5468 "Connection: keep-alive\r\n\r\n"),
5471 MockRead data_reads1
[] = {
5472 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5473 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5474 MockRead("Content-Length: 10\r\n\r\n"),
5475 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5478 // After the challenge above, the transaction will be restarted using the
5479 // identity from the url (foo, b@r) to answer the challenge.
5480 MockWrite data_writes2
[] = {
5482 "GET / HTTP/1.1\r\n"
5483 "Host: www.example.org\r\n"
5484 "Connection: keep-alive\r\n"
5485 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5488 MockRead data_reads2
[] = {
5489 MockRead("HTTP/1.0 200 OK\r\n"),
5490 MockRead("Content-Length: 100\r\n\r\n"),
5491 MockRead(SYNCHRONOUS
, OK
),
5494 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5495 data_writes1
, arraysize(data_writes1
));
5496 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5497 data_writes2
, arraysize(data_writes2
));
5498 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5499 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5501 TestCompletionCallback callback1
;
5502 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5504 rv
= callback1
.WaitForResult();
5506 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5508 TestCompletionCallback callback2
;
5509 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5510 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5511 rv
= callback2
.WaitForResult();
5513 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5515 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5516 ASSERT_TRUE(response
!= NULL
);
5518 // There is no challenge info, since the identity in URL worked.
5519 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5521 EXPECT_EQ(100, response
->headers
->GetContentLength());
5523 // Empty the current queue.
5524 base::MessageLoop::current()->RunUntilIdle();
5527 // Test the request-challenge-retry sequence for basic auth when there is an
5528 // incorrect identity in the URL. The identity from the URL should be used only
5530 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5531 HttpRequestInfo request
;
5532 request
.method
= "GET";
5533 // Note: the URL has a username:password in it. The password "baz" is
5534 // wrong (should be "bar").
5535 request
.url
= GURL("http://foo:baz@www.example.org/");
5537 request
.load_flags
= LOAD_NORMAL
;
5539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5540 scoped_ptr
<HttpTransaction
> trans(
5541 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5543 MockWrite data_writes1
[] = {
5545 "GET / HTTP/1.1\r\n"
5546 "Host: www.example.org\r\n"
5547 "Connection: keep-alive\r\n\r\n"),
5550 MockRead data_reads1
[] = {
5551 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5552 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5553 MockRead("Content-Length: 10\r\n\r\n"),
5554 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5557 // After the challenge above, the transaction will be restarted using the
5558 // identity from the url (foo, baz) to answer the challenge.
5559 MockWrite data_writes2
[] = {
5561 "GET / HTTP/1.1\r\n"
5562 "Host: www.example.org\r\n"
5563 "Connection: keep-alive\r\n"
5564 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5567 MockRead data_reads2
[] = {
5568 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5569 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5570 MockRead("Content-Length: 10\r\n\r\n"),
5571 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5574 // After the challenge above, the transaction will be restarted using the
5575 // identity supplied by the user (foo, bar) to answer the challenge.
5576 MockWrite data_writes3
[] = {
5578 "GET / HTTP/1.1\r\n"
5579 "Host: www.example.org\r\n"
5580 "Connection: keep-alive\r\n"
5581 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5584 MockRead data_reads3
[] = {
5585 MockRead("HTTP/1.0 200 OK\r\n"),
5586 MockRead("Content-Length: 100\r\n\r\n"),
5587 MockRead(SYNCHRONOUS
, OK
),
5590 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5591 data_writes1
, arraysize(data_writes1
));
5592 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5593 data_writes2
, arraysize(data_writes2
));
5594 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5595 data_writes3
, arraysize(data_writes3
));
5596 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5597 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5598 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5600 TestCompletionCallback callback1
;
5602 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5603 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5605 rv
= callback1
.WaitForResult();
5608 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5609 TestCompletionCallback callback2
;
5610 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5611 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5612 rv
= callback2
.WaitForResult();
5614 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5616 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5617 ASSERT_TRUE(response
!= NULL
);
5618 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5620 TestCompletionCallback callback3
;
5621 rv
= trans
->RestartWithAuth(
5622 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5623 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5624 rv
= callback3
.WaitForResult();
5626 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5628 response
= trans
->GetResponseInfo();
5629 ASSERT_TRUE(response
!= NULL
);
5631 // There is no challenge info, since the identity worked.
5632 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5634 EXPECT_EQ(100, response
->headers
->GetContentLength());
5636 // Empty the current queue.
5637 base::MessageLoop::current()->RunUntilIdle();
5641 // Test the request-challenge-retry sequence for basic auth when there is a
5642 // correct identity in the URL, but its use is being suppressed. The identity
5643 // from the URL should never be used.
5644 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5645 HttpRequestInfo request
;
5646 request
.method
= "GET";
5647 request
.url
= GURL("http://foo:bar@www.example.org/");
5648 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5650 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5651 scoped_ptr
<HttpTransaction
> trans(
5652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5654 MockWrite data_writes1
[] = {
5656 "GET / HTTP/1.1\r\n"
5657 "Host: www.example.org\r\n"
5658 "Connection: keep-alive\r\n\r\n"),
5661 MockRead data_reads1
[] = {
5662 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5663 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5664 MockRead("Content-Length: 10\r\n\r\n"),
5665 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5668 // After the challenge above, the transaction will be restarted using the
5669 // identity supplied by the user, not the one in the URL, to answer the
5671 MockWrite data_writes3
[] = {
5673 "GET / HTTP/1.1\r\n"
5674 "Host: www.example.org\r\n"
5675 "Connection: keep-alive\r\n"
5676 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5679 MockRead data_reads3
[] = {
5680 MockRead("HTTP/1.0 200 OK\r\n"),
5681 MockRead("Content-Length: 100\r\n\r\n"),
5682 MockRead(SYNCHRONOUS
, OK
),
5685 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5686 data_writes1
, arraysize(data_writes1
));
5687 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5688 data_writes3
, arraysize(data_writes3
));
5689 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5690 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5692 TestCompletionCallback callback1
;
5693 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5694 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5695 rv
= callback1
.WaitForResult();
5697 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5699 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5700 ASSERT_TRUE(response
!= NULL
);
5701 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5703 TestCompletionCallback callback3
;
5704 rv
= trans
->RestartWithAuth(
5705 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5706 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5707 rv
= callback3
.WaitForResult();
5709 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5711 response
= trans
->GetResponseInfo();
5712 ASSERT_TRUE(response
!= NULL
);
5714 // There is no challenge info, since the identity worked.
5715 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5716 EXPECT_EQ(100, response
->headers
->GetContentLength());
5718 // Empty the current queue.
5719 base::MessageLoop::current()->RunUntilIdle();
5722 // Test that previously tried username/passwords for a realm get re-used.
5723 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5724 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5726 // Transaction 1: authenticate (foo, bar) on MyRealm1
5728 HttpRequestInfo request
;
5729 request
.method
= "GET";
5730 request
.url
= GURL("http://www.example.org/x/y/z");
5731 request
.load_flags
= 0;
5733 scoped_ptr
<HttpTransaction
> trans(
5734 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5736 MockWrite data_writes1
[] = {
5738 "GET /x/y/z HTTP/1.1\r\n"
5739 "Host: www.example.org\r\n"
5740 "Connection: keep-alive\r\n\r\n"),
5743 MockRead data_reads1
[] = {
5744 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5745 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5746 MockRead("Content-Length: 10000\r\n\r\n"),
5747 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5750 // Resend with authorization (username=foo, password=bar)
5751 MockWrite data_writes2
[] = {
5753 "GET /x/y/z HTTP/1.1\r\n"
5754 "Host: www.example.org\r\n"
5755 "Connection: keep-alive\r\n"
5756 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5759 // Sever accepts the authorization.
5760 MockRead data_reads2
[] = {
5761 MockRead("HTTP/1.0 200 OK\r\n"),
5762 MockRead("Content-Length: 100\r\n\r\n"),
5763 MockRead(SYNCHRONOUS
, OK
),
5766 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5767 data_writes1
, arraysize(data_writes1
));
5768 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5769 data_writes2
, arraysize(data_writes2
));
5770 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5771 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5773 TestCompletionCallback callback1
;
5775 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5776 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5778 rv
= callback1
.WaitForResult();
5781 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5782 ASSERT_TRUE(response
!= NULL
);
5783 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5785 TestCompletionCallback callback2
;
5787 rv
= trans
->RestartWithAuth(
5788 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5789 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5791 rv
= callback2
.WaitForResult();
5794 response
= trans
->GetResponseInfo();
5795 ASSERT_TRUE(response
!= NULL
);
5796 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5797 EXPECT_EQ(100, response
->headers
->GetContentLength());
5800 // ------------------------------------------------------------------------
5802 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5804 HttpRequestInfo request
;
5805 request
.method
= "GET";
5806 // Note that Transaction 1 was at /x/y/z, so this is in the same
5807 // protection space as MyRealm1.
5808 request
.url
= GURL("http://www.example.org/x/y/a/b");
5809 request
.load_flags
= 0;
5811 scoped_ptr
<HttpTransaction
> trans(
5812 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5814 MockWrite data_writes1
[] = {
5816 "GET /x/y/a/b HTTP/1.1\r\n"
5817 "Host: www.example.org\r\n"
5818 "Connection: keep-alive\r\n"
5819 // Send preemptive authorization for MyRealm1
5820 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5823 // The server didn't like the preemptive authorization, and
5824 // challenges us for a different realm (MyRealm2).
5825 MockRead data_reads1
[] = {
5826 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5827 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5828 MockRead("Content-Length: 10000\r\n\r\n"),
5829 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5832 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5833 MockWrite data_writes2
[] = {
5835 "GET /x/y/a/b HTTP/1.1\r\n"
5836 "Host: www.example.org\r\n"
5837 "Connection: keep-alive\r\n"
5838 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5841 // Sever accepts the authorization.
5842 MockRead data_reads2
[] = {
5843 MockRead("HTTP/1.0 200 OK\r\n"),
5844 MockRead("Content-Length: 100\r\n\r\n"),
5845 MockRead(SYNCHRONOUS
, OK
),
5848 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5849 data_writes1
, arraysize(data_writes1
));
5850 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5851 data_writes2
, arraysize(data_writes2
));
5852 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5853 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5855 TestCompletionCallback callback1
;
5857 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5858 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5860 rv
= callback1
.WaitForResult();
5863 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5864 ASSERT_TRUE(response
!= NULL
);
5865 ASSERT_TRUE(response
->auth_challenge
.get());
5866 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5867 EXPECT_EQ("www.example.org:80",
5868 response
->auth_challenge
->challenger
.ToString());
5869 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5870 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5872 TestCompletionCallback callback2
;
5874 rv
= trans
->RestartWithAuth(
5875 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5876 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5878 rv
= callback2
.WaitForResult();
5881 response
= trans
->GetResponseInfo();
5882 ASSERT_TRUE(response
!= NULL
);
5883 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5884 EXPECT_EQ(100, response
->headers
->GetContentLength());
5887 // ------------------------------------------------------------------------
5889 // Transaction 3: Resend a request in MyRealm's protection space --
5890 // succeed with preemptive authorization.
5892 HttpRequestInfo request
;
5893 request
.method
= "GET";
5894 request
.url
= GURL("http://www.example.org/x/y/z2");
5895 request
.load_flags
= 0;
5897 scoped_ptr
<HttpTransaction
> trans(
5898 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5900 MockWrite data_writes1
[] = {
5902 "GET /x/y/z2 HTTP/1.1\r\n"
5903 "Host: www.example.org\r\n"
5904 "Connection: keep-alive\r\n"
5905 // The authorization for MyRealm1 gets sent preemptively
5906 // (since the url is in the same protection space)
5907 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5910 // Sever accepts the preemptive authorization
5911 MockRead data_reads1
[] = {
5912 MockRead("HTTP/1.0 200 OK\r\n"),
5913 MockRead("Content-Length: 100\r\n\r\n"),
5914 MockRead(SYNCHRONOUS
, OK
),
5917 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5918 data_writes1
, arraysize(data_writes1
));
5919 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5921 TestCompletionCallback callback1
;
5923 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5924 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5926 rv
= callback1
.WaitForResult();
5929 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5930 ASSERT_TRUE(response
!= NULL
);
5932 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5933 EXPECT_EQ(100, response
->headers
->GetContentLength());
5936 // ------------------------------------------------------------------------
5938 // Transaction 4: request another URL in MyRealm (however the
5939 // url is not known to belong to the protection space, so no pre-auth).
5941 HttpRequestInfo request
;
5942 request
.method
= "GET";
5943 request
.url
= GURL("http://www.example.org/x/1");
5944 request
.load_flags
= 0;
5946 scoped_ptr
<HttpTransaction
> trans(
5947 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5949 MockWrite data_writes1
[] = {
5951 "GET /x/1 HTTP/1.1\r\n"
5952 "Host: www.example.org\r\n"
5953 "Connection: keep-alive\r\n\r\n"),
5956 MockRead data_reads1
[] = {
5957 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5958 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5959 MockRead("Content-Length: 10000\r\n\r\n"),
5960 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5963 // Resend with authorization from MyRealm's cache.
5964 MockWrite data_writes2
[] = {
5966 "GET /x/1 HTTP/1.1\r\n"
5967 "Host: www.example.org\r\n"
5968 "Connection: keep-alive\r\n"
5969 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5972 // Sever accepts the authorization.
5973 MockRead data_reads2
[] = {
5974 MockRead("HTTP/1.0 200 OK\r\n"),
5975 MockRead("Content-Length: 100\r\n\r\n"),
5976 MockRead(SYNCHRONOUS
, OK
),
5979 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5980 data_writes1
, arraysize(data_writes1
));
5981 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5982 data_writes2
, arraysize(data_writes2
));
5983 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5984 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5986 TestCompletionCallback callback1
;
5988 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5989 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5991 rv
= callback1
.WaitForResult();
5994 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5995 TestCompletionCallback callback2
;
5996 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5997 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5998 rv
= callback2
.WaitForResult();
6000 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6002 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6003 ASSERT_TRUE(response
!= NULL
);
6004 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6005 EXPECT_EQ(100, response
->headers
->GetContentLength());
6008 // ------------------------------------------------------------------------
6010 // Transaction 5: request a URL in MyRealm, but the server rejects the
6011 // cached identity. Should invalidate and re-prompt.
6013 HttpRequestInfo request
;
6014 request
.method
= "GET";
6015 request
.url
= GURL("http://www.example.org/p/q/t");
6016 request
.load_flags
= 0;
6018 scoped_ptr
<HttpTransaction
> trans(
6019 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6021 MockWrite data_writes1
[] = {
6023 "GET /p/q/t HTTP/1.1\r\n"
6024 "Host: www.example.org\r\n"
6025 "Connection: keep-alive\r\n\r\n"),
6028 MockRead data_reads1
[] = {
6029 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6030 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6031 MockRead("Content-Length: 10000\r\n\r\n"),
6032 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6035 // Resend with authorization from cache for MyRealm.
6036 MockWrite data_writes2
[] = {
6038 "GET /p/q/t HTTP/1.1\r\n"
6039 "Host: www.example.org\r\n"
6040 "Connection: keep-alive\r\n"
6041 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6044 // Sever rejects the authorization.
6045 MockRead data_reads2
[] = {
6046 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6047 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6048 MockRead("Content-Length: 10000\r\n\r\n"),
6049 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6052 // At this point we should prompt for new credentials for MyRealm.
6053 // Restart with username=foo3, password=foo4.
6054 MockWrite data_writes3
[] = {
6056 "GET /p/q/t HTTP/1.1\r\n"
6057 "Host: www.example.org\r\n"
6058 "Connection: keep-alive\r\n"
6059 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6062 // Sever accepts the authorization.
6063 MockRead data_reads3
[] = {
6064 MockRead("HTTP/1.0 200 OK\r\n"),
6065 MockRead("Content-Length: 100\r\n\r\n"),
6066 MockRead(SYNCHRONOUS
, OK
),
6069 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6070 data_writes1
, arraysize(data_writes1
));
6071 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6072 data_writes2
, arraysize(data_writes2
));
6073 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6074 data_writes3
, arraysize(data_writes3
));
6075 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6076 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6077 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6079 TestCompletionCallback callback1
;
6081 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6082 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6084 rv
= callback1
.WaitForResult();
6087 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6088 TestCompletionCallback callback2
;
6089 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6090 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6091 rv
= callback2
.WaitForResult();
6093 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6095 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6096 ASSERT_TRUE(response
!= NULL
);
6097 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6099 TestCompletionCallback callback3
;
6101 rv
= trans
->RestartWithAuth(
6102 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6103 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6105 rv
= callback3
.WaitForResult();
6108 response
= trans
->GetResponseInfo();
6109 ASSERT_TRUE(response
!= NULL
);
6110 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6111 EXPECT_EQ(100, response
->headers
->GetContentLength());
6115 // Tests that nonce count increments when multiple auth attempts
6116 // are started with the same nonce.
6117 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6118 HttpAuthHandlerDigest::Factory
* digest_factory
=
6119 new HttpAuthHandlerDigest::Factory();
6120 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6121 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6122 digest_factory
->set_nonce_generator(nonce_generator
);
6123 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6124 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6126 // Transaction 1: authenticate (foo, bar) on MyRealm1
6128 HttpRequestInfo request
;
6129 request
.method
= "GET";
6130 request
.url
= GURL("http://www.example.org/x/y/z");
6131 request
.load_flags
= 0;
6133 scoped_ptr
<HttpTransaction
> trans(
6134 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6136 MockWrite data_writes1
[] = {
6138 "GET /x/y/z HTTP/1.1\r\n"
6139 "Host: www.example.org\r\n"
6140 "Connection: keep-alive\r\n\r\n"),
6143 MockRead data_reads1
[] = {
6144 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6145 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6146 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6147 MockRead(SYNCHRONOUS
, OK
),
6150 // Resend with authorization (username=foo, password=bar)
6151 MockWrite data_writes2
[] = {
6153 "GET /x/y/z HTTP/1.1\r\n"
6154 "Host: www.example.org\r\n"
6155 "Connection: keep-alive\r\n"
6156 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6157 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6158 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6159 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6162 // Sever accepts the authorization.
6163 MockRead data_reads2
[] = {
6164 MockRead("HTTP/1.0 200 OK\r\n"),
6165 MockRead(SYNCHRONOUS
, OK
),
6168 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6169 data_writes1
, arraysize(data_writes1
));
6170 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6171 data_writes2
, arraysize(data_writes2
));
6172 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6173 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6175 TestCompletionCallback callback1
;
6177 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6178 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6180 rv
= callback1
.WaitForResult();
6183 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6184 ASSERT_TRUE(response
!= NULL
);
6185 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6187 TestCompletionCallback callback2
;
6189 rv
= trans
->RestartWithAuth(
6190 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6191 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6193 rv
= callback2
.WaitForResult();
6196 response
= trans
->GetResponseInfo();
6197 ASSERT_TRUE(response
!= NULL
);
6198 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6201 // ------------------------------------------------------------------------
6203 // Transaction 2: Request another resource in digestive's protection space.
6204 // This will preemptively add an Authorization header which should have an
6205 // "nc" value of 2 (as compared to 1 in the first use.
6207 HttpRequestInfo request
;
6208 request
.method
= "GET";
6209 // Note that Transaction 1 was at /x/y/z, so this is in the same
6210 // protection space as digest.
6211 request
.url
= GURL("http://www.example.org/x/y/a/b");
6212 request
.load_flags
= 0;
6214 scoped_ptr
<HttpTransaction
> trans(
6215 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6217 MockWrite data_writes1
[] = {
6219 "GET /x/y/a/b HTTP/1.1\r\n"
6220 "Host: www.example.org\r\n"
6221 "Connection: keep-alive\r\n"
6222 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6223 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6224 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6225 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6228 // Sever accepts the authorization.
6229 MockRead data_reads1
[] = {
6230 MockRead("HTTP/1.0 200 OK\r\n"),
6231 MockRead("Content-Length: 100\r\n\r\n"),
6232 MockRead(SYNCHRONOUS
, OK
),
6235 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6236 data_writes1
, arraysize(data_writes1
));
6237 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6239 TestCompletionCallback callback1
;
6241 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6242 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6244 rv
= callback1
.WaitForResult();
6247 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6248 ASSERT_TRUE(response
!= NULL
);
6249 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6253 // Test the ResetStateForRestart() private method.
6254 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6255 // Create a transaction (the dependencies aren't important).
6256 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6257 scoped_ptr
<HttpNetworkTransaction
> trans(
6258 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6260 // Setup some state (which we expect ResetStateForRestart() will clear).
6261 trans
->read_buf_
= new IOBuffer(15);
6262 trans
->read_buf_len_
= 15;
6263 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6265 // Setup state in response_
6266 HttpResponseInfo
* response
= &trans
->response_
;
6267 response
->auth_challenge
= new AuthChallengeInfo();
6268 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6269 response
->response_time
= base::Time::Now();
6270 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6272 { // Setup state for response_.vary_data
6273 HttpRequestInfo request
;
6274 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6275 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6276 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6277 request
.extra_headers
.SetHeader("Foo", "1");
6278 request
.extra_headers
.SetHeader("bar", "23");
6279 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6282 // Cause the above state to be reset.
6283 trans
->ResetStateForRestart();
6285 // Verify that the state that needed to be reset, has been reset.
6286 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6287 EXPECT_EQ(0, trans
->read_buf_len_
);
6288 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6289 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6290 EXPECT_TRUE(response
->headers
.get() == NULL
);
6291 EXPECT_FALSE(response
->was_cached
);
6292 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6293 EXPECT_FALSE(response
->vary_data
.is_valid());
6296 // Test HTTPS connections to a site with a bad certificate
6297 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6298 HttpRequestInfo request
;
6299 request
.method
= "GET";
6300 request
.url
= GURL("https://www.example.org/");
6301 request
.load_flags
= 0;
6303 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6304 scoped_ptr
<HttpTransaction
> trans(
6305 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6307 MockWrite data_writes
[] = {
6309 "GET / HTTP/1.1\r\n"
6310 "Host: www.example.org\r\n"
6311 "Connection: keep-alive\r\n\r\n"),
6314 MockRead data_reads
[] = {
6315 MockRead("HTTP/1.0 200 OK\r\n"),
6316 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6317 MockRead("Content-Length: 100\r\n\r\n"),
6318 MockRead(SYNCHRONOUS
, OK
),
6321 StaticSocketDataProvider ssl_bad_certificate
;
6322 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6323 data_writes
, arraysize(data_writes
));
6324 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6325 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6327 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6328 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6329 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6330 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6332 TestCompletionCallback callback
;
6334 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6335 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6337 rv
= callback
.WaitForResult();
6338 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6340 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6341 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6343 rv
= callback
.WaitForResult();
6346 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6348 ASSERT_TRUE(response
!= NULL
);
6349 EXPECT_EQ(100, response
->headers
->GetContentLength());
6352 // Test HTTPS connections to a site with a bad certificate, going through a
6354 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6355 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6357 HttpRequestInfo request
;
6358 request
.method
= "GET";
6359 request
.url
= GURL("https://www.example.org/");
6360 request
.load_flags
= 0;
6362 MockWrite proxy_writes
[] = {
6364 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6365 "Host: www.example.org\r\n"
6366 "Proxy-Connection: keep-alive\r\n\r\n"),
6369 MockRead proxy_reads
[] = {
6370 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6371 MockRead(SYNCHRONOUS
, OK
)
6374 MockWrite data_writes
[] = {
6376 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6377 "Host: www.example.org\r\n"
6378 "Proxy-Connection: keep-alive\r\n\r\n"),
6380 "GET / HTTP/1.1\r\n"
6381 "Host: www.example.org\r\n"
6382 "Connection: keep-alive\r\n\r\n"),
6385 MockRead data_reads
[] = {
6386 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6387 MockRead("HTTP/1.0 200 OK\r\n"),
6388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6389 MockRead("Content-Length: 100\r\n\r\n"),
6390 MockRead(SYNCHRONOUS
, OK
),
6393 StaticSocketDataProvider
ssl_bad_certificate(
6394 proxy_reads
, arraysize(proxy_reads
),
6395 proxy_writes
, arraysize(proxy_writes
));
6396 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6397 data_writes
, arraysize(data_writes
));
6398 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6399 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6401 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6402 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6403 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6404 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6406 TestCompletionCallback callback
;
6408 for (int i
= 0; i
< 2; i
++) {
6409 session_deps_
.socket_factory
->ResetNextMockIndexes();
6411 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6412 scoped_ptr
<HttpTransaction
> trans(
6413 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6415 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6416 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6418 rv
= callback
.WaitForResult();
6419 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6421 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6422 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6424 rv
= callback
.WaitForResult();
6427 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6429 ASSERT_TRUE(response
!= NULL
);
6430 EXPECT_EQ(100, response
->headers
->GetContentLength());
6435 // Test HTTPS connections to a site, going through an HTTPS proxy
6436 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6437 session_deps_
.proxy_service
.reset(
6438 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6440 session_deps_
.net_log
= &net_log
;
6442 HttpRequestInfo request
;
6443 request
.method
= "GET";
6444 request
.url
= GURL("https://www.example.org/");
6445 request
.load_flags
= 0;
6447 MockWrite data_writes
[] = {
6449 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6450 "Host: www.example.org\r\n"
6451 "Proxy-Connection: keep-alive\r\n\r\n"),
6453 "GET / HTTP/1.1\r\n"
6454 "Host: www.example.org\r\n"
6455 "Connection: keep-alive\r\n\r\n"),
6458 MockRead data_reads
[] = {
6459 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6460 MockRead("HTTP/1.1 200 OK\r\n"),
6461 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6462 MockRead("Content-Length: 100\r\n\r\n"),
6463 MockRead(SYNCHRONOUS
, OK
),
6466 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6467 data_writes
, arraysize(data_writes
));
6468 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6469 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6471 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6472 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6473 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6475 TestCompletionCallback callback
;
6477 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6478 scoped_ptr
<HttpTransaction
> trans(
6479 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6481 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6482 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6484 rv
= callback
.WaitForResult();
6486 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6488 ASSERT_TRUE(response
!= NULL
);
6490 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6491 EXPECT_EQ(200, response
->headers
->response_code());
6492 EXPECT_EQ(100, response
->headers
->GetContentLength());
6493 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6495 LoadTimingInfo load_timing_info
;
6496 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6497 TestLoadTimingNotReusedWithPac(load_timing_info
,
6498 CONNECT_TIMING_HAS_SSL_TIMES
);
6501 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6502 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6503 session_deps_
.proxy_service
.reset(
6504 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6506 session_deps_
.net_log
= &net_log
;
6508 HttpRequestInfo request
;
6509 request
.method
= "GET";
6510 request
.url
= GURL("https://www.example.org/");
6511 request
.load_flags
= 0;
6513 MockWrite data_writes
[] = {
6515 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6516 "Host: www.example.org\r\n"
6517 "Proxy-Connection: keep-alive\r\n\r\n"),
6520 MockRead data_reads
[] = {
6521 MockRead("HTTP/1.1 302 Redirect\r\n"),
6522 MockRead("Location: http://login.example.com/\r\n"),
6523 MockRead("Content-Length: 0\r\n\r\n"),
6524 MockRead(SYNCHRONOUS
, OK
),
6527 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6528 data_writes
, arraysize(data_writes
));
6529 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6531 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6532 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6534 TestCompletionCallback callback
;
6536 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6537 scoped_ptr
<HttpTransaction
> trans(
6538 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6540 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6541 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6543 rv
= callback
.WaitForResult();
6545 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6547 ASSERT_TRUE(response
!= NULL
);
6549 EXPECT_EQ(302, response
->headers
->response_code());
6551 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6552 EXPECT_EQ("http://login.example.com/", url
);
6554 // In the case of redirects from proxies, HttpNetworkTransaction returns
6555 // timing for the proxy connection instead of the connection to the host,
6556 // and no send / receive times.
6557 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6558 LoadTimingInfo load_timing_info
;
6559 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6561 EXPECT_FALSE(load_timing_info
.socket_reused
);
6562 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6564 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6565 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6566 load_timing_info
.proxy_resolve_end
);
6567 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6568 load_timing_info
.connect_timing
.connect_start
);
6569 ExpectConnectTimingHasTimes(
6570 load_timing_info
.connect_timing
,
6571 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6573 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6574 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6575 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6578 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6579 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6580 session_deps_
.proxy_service
.reset(
6581 ProxyService::CreateFixed("https://proxy:70"));
6583 HttpRequestInfo request
;
6584 request
.method
= "GET";
6585 request
.url
= GURL("https://www.example.org/");
6586 request
.load_flags
= 0;
6588 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6589 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6590 scoped_ptr
<SpdyFrame
> goaway(
6591 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6592 MockWrite data_writes
[] = {
6593 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6594 CreateMockWrite(*goaway
.get(), 3, SYNCHRONOUS
),
6597 static const char* const kExtraHeaders
[] = {
6599 "http://login.example.com/",
6601 scoped_ptr
<SpdyFrame
> resp(
6602 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6603 arraysize(kExtraHeaders
)/2, 1));
6604 MockRead data_reads
[] = {
6605 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6606 MockRead(ASYNC
, 0, 2), // EOF
6609 DelayedSocketData
data(
6610 1, // wait for one write to finish before reading.
6611 data_reads
, arraysize(data_reads
),
6612 data_writes
, arraysize(data_writes
));
6613 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6614 proxy_ssl
.SetNextProto(GetParam());
6616 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6617 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6619 TestCompletionCallback callback
;
6621 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6622 scoped_ptr
<HttpTransaction
> trans(
6623 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6625 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6626 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6628 rv
= callback
.WaitForResult();
6630 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6632 ASSERT_TRUE(response
!= NULL
);
6634 EXPECT_EQ(302, response
->headers
->response_code());
6636 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6637 EXPECT_EQ("http://login.example.com/", url
);
6640 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6641 TEST_P(HttpNetworkTransactionTest
,
6642 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6643 session_deps_
.proxy_service
.reset(
6644 ProxyService::CreateFixed("https://proxy:70"));
6646 HttpRequestInfo request
;
6647 request
.method
= "GET";
6648 request
.url
= GURL("https://www.example.org/");
6649 request
.load_flags
= 0;
6651 MockWrite data_writes
[] = {
6653 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6654 "Host: www.example.org\r\n"
6655 "Proxy-Connection: keep-alive\r\n\r\n"),
6658 MockRead data_reads
[] = {
6659 MockRead("HTTP/1.1 404 Not Found\r\n"),
6660 MockRead("Content-Length: 23\r\n\r\n"),
6661 MockRead("The host does not exist"),
6662 MockRead(SYNCHRONOUS
, OK
),
6665 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6666 data_writes
, arraysize(data_writes
));
6667 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6669 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6670 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6672 TestCompletionCallback callback
;
6674 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6675 scoped_ptr
<HttpTransaction
> trans(
6676 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6678 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6679 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6681 rv
= callback
.WaitForResult();
6682 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6684 // TODO(ttuttle): Anything else to check here?
6687 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6688 TEST_P(HttpNetworkTransactionTest
,
6689 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6690 session_deps_
.proxy_service
.reset(
6691 ProxyService::CreateFixed("https://proxy:70"));
6693 HttpRequestInfo request
;
6694 request
.method
= "GET";
6695 request
.url
= GURL("https://www.example.org/");
6696 request
.load_flags
= 0;
6698 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6699 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6700 scoped_ptr
<SpdyFrame
> rst(
6701 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6702 MockWrite data_writes
[] = {
6703 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6704 CreateMockWrite(*rst
.get(), 3, SYNCHRONOUS
),
6707 static const char* const kExtraHeaders
[] = {
6709 "http://login.example.com/",
6711 scoped_ptr
<SpdyFrame
> resp(
6712 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6713 arraysize(kExtraHeaders
)/2, 1));
6714 scoped_ptr
<SpdyFrame
> body(
6715 spdy_util_
.ConstructSpdyBodyFrame(
6716 1, "The host does not exist", 23, true));
6717 MockRead data_reads
[] = {
6718 CreateMockRead(*resp
.get(), 1, SYNCHRONOUS
),
6719 CreateMockRead(*body
.get(), 2, SYNCHRONOUS
),
6720 MockRead(ASYNC
, 0, 4), // EOF
6723 DelayedSocketData
data(
6724 1, // wait for one write to finish before reading.
6725 data_reads
, arraysize(data_reads
),
6726 data_writes
, arraysize(data_writes
));
6727 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6728 proxy_ssl
.SetNextProto(GetParam());
6730 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6731 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6733 TestCompletionCallback callback
;
6735 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6736 scoped_ptr
<HttpTransaction
> trans(
6737 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6739 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6740 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6742 rv
= callback
.WaitForResult();
6743 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6745 // TODO(ttuttle): Anything else to check here?
6748 // Test the request-challenge-retry sequence for basic auth, through
6749 // a SPDY proxy over a single SPDY session.
6750 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6751 HttpRequestInfo request
;
6752 request
.method
= "GET";
6753 request
.url
= GURL("https://www.example.org/");
6754 // when the no authentication data flag is set.
6755 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6757 // Configure against https proxy server "myproxy:70".
6758 session_deps_
.proxy_service
.reset(
6759 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6760 BoundTestNetLog log
;
6761 session_deps_
.net_log
= log
.bound().net_log();
6762 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6764 // Since we have proxy, should try to establish tunnel.
6765 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6766 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6767 scoped_ptr
<SpdyFrame
> rst(
6768 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6770 // After calling trans->RestartWithAuth(), this is the request we should
6771 // be issuing -- the final header line contains the credentials.
6772 const char* const kAuthCredentials
[] = {
6773 "proxy-authorization", "Basic Zm9vOmJhcg==",
6775 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6776 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6777 HostPortPair("www.example.org", 443)));
6778 // fetch https://www.example.org/ via HTTP
6780 "GET / HTTP/1.1\r\n"
6781 "Host: www.example.org\r\n"
6782 "Connection: keep-alive\r\n\r\n";
6783 scoped_ptr
<SpdyFrame
> wrapped_get(
6784 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6786 MockWrite spdy_writes
[] = {
6787 CreateMockWrite(*req
, 1, ASYNC
),
6788 CreateMockWrite(*rst
, 4, ASYNC
),
6789 CreateMockWrite(*connect2
, 5),
6790 CreateMockWrite(*wrapped_get
, 8),
6793 // The proxy responds to the connect with a 407, using a persistent
6795 const char kAuthStatus
[] = "407";
6796 const char* const kAuthChallenge
[] = {
6797 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6799 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6800 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6802 scoped_ptr
<SpdyFrame
> conn_resp(
6803 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6804 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6805 "Content-Length: 5\r\n\r\n";
6807 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6808 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6809 scoped_ptr
<SpdyFrame
> wrapped_body(
6810 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6811 MockRead spdy_reads
[] = {
6812 CreateMockRead(*conn_auth_resp
, 2, ASYNC
),
6813 CreateMockRead(*conn_resp
, 6, ASYNC
),
6814 CreateMockRead(*wrapped_get_resp
, 9, ASYNC
),
6815 CreateMockRead(*wrapped_body
, 10, ASYNC
),
6816 MockRead(ASYNC
, OK
, 11), // EOF. May or may not be read.
6819 OrderedSocketData
spdy_data(
6820 spdy_reads
, arraysize(spdy_reads
),
6821 spdy_writes
, arraysize(spdy_writes
));
6822 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6823 // Negotiate SPDY to the proxy
6824 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6825 proxy
.SetNextProto(GetParam());
6826 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6827 // Vanilla SSL to the server
6828 SSLSocketDataProvider
server(ASYNC
, OK
);
6829 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6831 TestCompletionCallback callback1
;
6833 scoped_ptr
<HttpTransaction
> trans(
6834 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6836 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6837 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6839 rv
= callback1
.WaitForResult();
6841 CapturedNetLogEntry::List entries
;
6842 log
.GetEntries(&entries
);
6843 size_t pos
= ExpectLogContainsSomewhere(
6844 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6845 NetLog::PHASE_NONE
);
6846 ExpectLogContainsSomewhere(
6848 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6849 NetLog::PHASE_NONE
);
6851 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6852 ASSERT_TRUE(response
!= NULL
);
6853 ASSERT_FALSE(response
->headers
.get() == NULL
);
6854 EXPECT_EQ(407, response
->headers
->response_code());
6855 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6856 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6857 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6859 TestCompletionCallback callback2
;
6861 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6862 callback2
.callback());
6863 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6865 rv
= callback2
.WaitForResult();
6868 response
= trans
->GetResponseInfo();
6869 ASSERT_TRUE(response
!= NULL
);
6871 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6872 EXPECT_EQ(200, response
->headers
->response_code());
6873 EXPECT_EQ(5, response
->headers
->GetContentLength());
6874 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6876 // The password prompt info should not be set.
6877 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6879 LoadTimingInfo load_timing_info
;
6880 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6881 TestLoadTimingNotReusedWithPac(load_timing_info
,
6882 CONNECT_TIMING_HAS_SSL_TIMES
);
6885 session
->CloseAllConnections();
6888 // Test that an explicitly trusted SPDY proxy can push a resource from an
6889 // origin that is different from that of its associated resource.
6890 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6891 HttpRequestInfo request
;
6892 HttpRequestInfo push_request
;
6894 request
.method
= "GET";
6895 request
.url
= GURL("http://www.example.org/");
6896 push_request
.method
= "GET";
6897 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6899 // Configure against https proxy server "myproxy:70".
6900 session_deps_
.proxy_service
.reset(
6901 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6902 BoundTestNetLog log
;
6903 session_deps_
.net_log
= log
.bound().net_log();
6905 // Enable cross-origin push.
6906 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6908 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6910 scoped_ptr
<SpdyFrame
> stream1_syn(
6911 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6913 MockWrite spdy_writes
[] = {
6914 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
6917 scoped_ptr
<SpdyFrame
>
6918 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6920 scoped_ptr
<SpdyFrame
>
6921 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6923 scoped_ptr
<SpdyFrame
>
6924 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6928 "http://www.another-origin.com/foo.dat"));
6929 const char kPushedData
[] = "pushed";
6930 scoped_ptr
<SpdyFrame
> stream2_body(
6931 spdy_util_
.ConstructSpdyBodyFrame(
6932 2, kPushedData
, strlen(kPushedData
), true));
6934 MockRead spdy_reads
[] = {
6935 CreateMockRead(*stream1_reply
, 2, ASYNC
),
6936 CreateMockRead(*stream2_syn
, 3, ASYNC
),
6937 CreateMockRead(*stream1_body
, 4, ASYNC
),
6938 CreateMockRead(*stream2_body
, 5, ASYNC
),
6939 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
6942 OrderedSocketData
spdy_data(
6943 spdy_reads
, arraysize(spdy_reads
),
6944 spdy_writes
, arraysize(spdy_writes
));
6945 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6946 // Negotiate SPDY to the proxy
6947 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6948 proxy
.SetNextProto(GetParam());
6949 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6951 scoped_ptr
<HttpTransaction
> trans(
6952 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6953 TestCompletionCallback callback
;
6954 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6955 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6957 rv
= callback
.WaitForResult();
6959 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6961 scoped_ptr
<HttpTransaction
> push_trans(
6962 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6963 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6964 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6966 rv
= callback
.WaitForResult();
6968 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6970 ASSERT_TRUE(response
!= NULL
);
6971 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6973 EXPECT_EQ(200, response
->headers
->response_code());
6974 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6976 std::string response_data
;
6977 rv
= ReadTransaction(trans
.get(), &response_data
);
6979 EXPECT_EQ("hello!", response_data
);
6981 LoadTimingInfo load_timing_info
;
6982 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6983 TestLoadTimingNotReusedWithPac(load_timing_info
,
6984 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6986 // Verify the pushed stream.
6987 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6988 EXPECT_EQ(200, push_response
->headers
->response_code());
6990 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6992 EXPECT_EQ("pushed", response_data
);
6994 LoadTimingInfo push_load_timing_info
;
6995 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6996 TestLoadTimingReusedWithPac(push_load_timing_info
);
6997 // The transactions should share a socket ID, despite being for different
6999 EXPECT_EQ(load_timing_info
.socket_log_id
,
7000 push_load_timing_info
.socket_log_id
);
7004 session
->CloseAllConnections();
7007 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
7008 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
7009 HttpRequestInfo request
;
7011 request
.method
= "GET";
7012 request
.url
= GURL("http://www.example.org/");
7014 // Configure against https proxy server "myproxy:70".
7015 session_deps_
.proxy_service
.reset(
7016 ProxyService::CreateFixed("https://myproxy:70"));
7017 BoundTestNetLog log
;
7018 session_deps_
.net_log
= log
.bound().net_log();
7020 // Enable cross-origin push.
7021 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
7023 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7025 scoped_ptr
<SpdyFrame
> stream1_syn(
7026 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
7028 scoped_ptr
<SpdyFrame
> push_rst(
7029 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
7031 MockWrite spdy_writes
[] = {
7032 CreateMockWrite(*stream1_syn
, 1, ASYNC
),
7033 CreateMockWrite(*push_rst
, 4),
7036 scoped_ptr
<SpdyFrame
>
7037 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
7039 scoped_ptr
<SpdyFrame
>
7040 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
7042 scoped_ptr
<SpdyFrame
>
7043 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7047 "https://www.another-origin.com/foo.dat"));
7049 MockRead spdy_reads
[] = {
7050 CreateMockRead(*stream1_reply
, 2, ASYNC
),
7051 CreateMockRead(*stream2_syn
, 3, ASYNC
),
7052 CreateMockRead(*stream1_body
, 5, ASYNC
),
7053 MockRead(ASYNC
, ERR_IO_PENDING
, 6), // Force a pause
7056 OrderedSocketData
spdy_data(
7057 spdy_reads
, arraysize(spdy_reads
),
7058 spdy_writes
, arraysize(spdy_writes
));
7059 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7060 // Negotiate SPDY to the proxy
7061 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7062 proxy
.SetNextProto(GetParam());
7063 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7065 scoped_ptr
<HttpTransaction
> trans(
7066 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7067 TestCompletionCallback callback
;
7068 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7069 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7071 rv
= callback
.WaitForResult();
7073 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7075 ASSERT_TRUE(response
!= NULL
);
7076 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7078 EXPECT_EQ(200, response
->headers
->response_code());
7079 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7081 std::string response_data
;
7082 rv
= ReadTransaction(trans
.get(), &response_data
);
7084 EXPECT_EQ("hello!", response_data
);
7087 session
->CloseAllConnections();
7090 // Test HTTPS connections to a site with a bad certificate, going through an
7092 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7093 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7094 "https://proxy:70"));
7096 HttpRequestInfo request
;
7097 request
.method
= "GET";
7098 request
.url
= GURL("https://www.example.org/");
7099 request
.load_flags
= 0;
7101 // Attempt to fetch the URL from a server with a bad cert
7102 MockWrite bad_cert_writes
[] = {
7104 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7105 "Host: www.example.org\r\n"
7106 "Proxy-Connection: keep-alive\r\n\r\n"),
7109 MockRead bad_cert_reads
[] = {
7110 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7111 MockRead(SYNCHRONOUS
, OK
)
7114 // Attempt to fetch the URL with a good cert
7115 MockWrite good_data_writes
[] = {
7117 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7118 "Host: www.example.org\r\n"
7119 "Proxy-Connection: keep-alive\r\n\r\n"),
7121 "GET / HTTP/1.1\r\n"
7122 "Host: www.example.org\r\n"
7123 "Connection: keep-alive\r\n\r\n"),
7126 MockRead good_cert_reads
[] = {
7127 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7128 MockRead("HTTP/1.0 200 OK\r\n"),
7129 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7130 MockRead("Content-Length: 100\r\n\r\n"),
7131 MockRead(SYNCHRONOUS
, OK
),
7134 StaticSocketDataProvider
ssl_bad_certificate(
7135 bad_cert_reads
, arraysize(bad_cert_reads
),
7136 bad_cert_writes
, arraysize(bad_cert_writes
));
7137 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7138 good_data_writes
, arraysize(good_data_writes
));
7139 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7140 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7142 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7143 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7144 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7145 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7147 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7148 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7149 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7150 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7152 TestCompletionCallback callback
;
7154 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7155 scoped_ptr
<HttpTransaction
> trans(
7156 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7158 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7159 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7161 rv
= callback
.WaitForResult();
7162 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7164 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7167 rv
= callback
.WaitForResult();
7170 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7172 ASSERT_TRUE(response
!= NULL
);
7173 EXPECT_EQ(100, response
->headers
->GetContentLength());
7176 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7177 HttpRequestInfo request
;
7178 request
.method
= "GET";
7179 request
.url
= GURL("http://www.example.org/");
7180 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7181 "Chromium Ultra Awesome X Edition");
7183 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7184 scoped_ptr
<HttpTransaction
> trans(
7185 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7187 MockWrite data_writes
[] = {
7189 "GET / HTTP/1.1\r\n"
7190 "Host: www.example.org\r\n"
7191 "Connection: keep-alive\r\n"
7192 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7195 // Lastly, the server responds with the actual content.
7196 MockRead data_reads
[] = {
7197 MockRead("HTTP/1.0 200 OK\r\n"),
7198 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7199 MockRead("Content-Length: 100\r\n\r\n"),
7200 MockRead(SYNCHRONOUS
, OK
),
7203 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7204 data_writes
, arraysize(data_writes
));
7205 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7207 TestCompletionCallback callback
;
7209 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7210 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7212 rv
= callback
.WaitForResult();
7216 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7217 HttpRequestInfo request
;
7218 request
.method
= "GET";
7219 request
.url
= GURL("https://www.example.org/");
7220 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7221 "Chromium Ultra Awesome X Edition");
7223 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7224 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7225 scoped_ptr
<HttpTransaction
> trans(
7226 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7228 MockWrite data_writes
[] = {
7230 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7231 "Host: www.example.org\r\n"
7232 "Proxy-Connection: keep-alive\r\n"
7233 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7235 MockRead data_reads
[] = {
7236 // Return an error, so the transaction stops here (this test isn't
7237 // interested in the rest).
7238 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7239 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7240 MockRead("Proxy-Connection: close\r\n\r\n"),
7243 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7244 data_writes
, arraysize(data_writes
));
7245 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7247 TestCompletionCallback callback
;
7249 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7252 rv
= callback
.WaitForResult();
7256 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7257 HttpRequestInfo request
;
7258 request
.method
= "GET";
7259 request
.url
= GURL("http://www.example.org/");
7260 request
.load_flags
= 0;
7261 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7262 "http://the.previous.site.com/");
7264 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7265 scoped_ptr
<HttpTransaction
> trans(
7266 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7268 MockWrite data_writes
[] = {
7270 "GET / HTTP/1.1\r\n"
7271 "Host: www.example.org\r\n"
7272 "Connection: keep-alive\r\n"
7273 "Referer: http://the.previous.site.com/\r\n\r\n"),
7276 // Lastly, the server responds with the actual content.
7277 MockRead data_reads
[] = {
7278 MockRead("HTTP/1.0 200 OK\r\n"),
7279 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7280 MockRead("Content-Length: 100\r\n\r\n"),
7281 MockRead(SYNCHRONOUS
, OK
),
7284 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7285 data_writes
, arraysize(data_writes
));
7286 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7288 TestCompletionCallback callback
;
7290 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7291 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7293 rv
= callback
.WaitForResult();
7297 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7298 HttpRequestInfo request
;
7299 request
.method
= "POST";
7300 request
.url
= GURL("http://www.example.org/");
7302 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7303 scoped_ptr
<HttpTransaction
> trans(
7304 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7306 MockWrite data_writes
[] = {
7308 "POST / HTTP/1.1\r\n"
7309 "Host: www.example.org\r\n"
7310 "Connection: keep-alive\r\n"
7311 "Content-Length: 0\r\n\r\n"),
7314 // Lastly, the server responds with the actual content.
7315 MockRead data_reads
[] = {
7316 MockRead("HTTP/1.0 200 OK\r\n"),
7317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7318 MockRead("Content-Length: 100\r\n\r\n"),
7319 MockRead(SYNCHRONOUS
, OK
),
7322 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7323 data_writes
, arraysize(data_writes
));
7324 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7326 TestCompletionCallback callback
;
7328 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7329 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7331 rv
= callback
.WaitForResult();
7335 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7336 HttpRequestInfo request
;
7337 request
.method
= "PUT";
7338 request
.url
= GURL("http://www.example.org/");
7340 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7341 scoped_ptr
<HttpTransaction
> trans(
7342 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7344 MockWrite data_writes
[] = {
7346 "PUT / HTTP/1.1\r\n"
7347 "Host: www.example.org\r\n"
7348 "Connection: keep-alive\r\n"
7349 "Content-Length: 0\r\n\r\n"),
7352 // Lastly, the server responds with the actual content.
7353 MockRead data_reads
[] = {
7354 MockRead("HTTP/1.0 200 OK\r\n"),
7355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7356 MockRead("Content-Length: 100\r\n\r\n"),
7357 MockRead(SYNCHRONOUS
, OK
),
7360 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7361 data_writes
, arraysize(data_writes
));
7362 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7364 TestCompletionCallback callback
;
7366 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7367 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7369 rv
= callback
.WaitForResult();
7373 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7374 HttpRequestInfo request
;
7375 request
.method
= "HEAD";
7376 request
.url
= GURL("http://www.example.org/");
7378 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7379 scoped_ptr
<HttpTransaction
> trans(
7380 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7382 MockWrite data_writes
[] = {
7384 "HEAD / HTTP/1.1\r\n"
7385 "Host: www.example.org\r\n"
7386 "Connection: keep-alive\r\n"
7387 "Content-Length: 0\r\n\r\n"),
7390 // Lastly, the server responds with the actual content.
7391 MockRead data_reads
[] = {
7392 MockRead("HTTP/1.0 200 OK\r\n"),
7393 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7394 MockRead("Content-Length: 100\r\n\r\n"),
7395 MockRead(SYNCHRONOUS
, OK
),
7398 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7399 data_writes
, arraysize(data_writes
));
7400 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7402 TestCompletionCallback callback
;
7404 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7405 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7407 rv
= callback
.WaitForResult();
7411 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7412 HttpRequestInfo request
;
7413 request
.method
= "GET";
7414 request
.url
= GURL("http://www.example.org/");
7415 request
.load_flags
= LOAD_BYPASS_CACHE
;
7417 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7418 scoped_ptr
<HttpTransaction
> trans(
7419 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7421 MockWrite data_writes
[] = {
7423 "GET / HTTP/1.1\r\n"
7424 "Host: www.example.org\r\n"
7425 "Connection: keep-alive\r\n"
7426 "Pragma: no-cache\r\n"
7427 "Cache-Control: no-cache\r\n\r\n"),
7430 // Lastly, the server responds with the actual content.
7431 MockRead data_reads
[] = {
7432 MockRead("HTTP/1.0 200 OK\r\n"),
7433 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7434 MockRead("Content-Length: 100\r\n\r\n"),
7435 MockRead(SYNCHRONOUS
, OK
),
7438 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7439 data_writes
, arraysize(data_writes
));
7440 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7442 TestCompletionCallback callback
;
7444 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7445 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7447 rv
= callback
.WaitForResult();
7451 TEST_P(HttpNetworkTransactionTest
,
7452 BuildRequest_CacheControlValidateCache
) {
7453 HttpRequestInfo request
;
7454 request
.method
= "GET";
7455 request
.url
= GURL("http://www.example.org/");
7456 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7458 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7459 scoped_ptr
<HttpTransaction
> trans(
7460 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7462 MockWrite data_writes
[] = {
7464 "GET / HTTP/1.1\r\n"
7465 "Host: www.example.org\r\n"
7466 "Connection: keep-alive\r\n"
7467 "Cache-Control: max-age=0\r\n\r\n"),
7470 // Lastly, the server responds with the actual content.
7471 MockRead data_reads
[] = {
7472 MockRead("HTTP/1.0 200 OK\r\n"),
7473 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7474 MockRead("Content-Length: 100\r\n\r\n"),
7475 MockRead(SYNCHRONOUS
, OK
),
7478 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7479 data_writes
, arraysize(data_writes
));
7480 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7482 TestCompletionCallback callback
;
7484 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7485 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7487 rv
= callback
.WaitForResult();
7491 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7492 HttpRequestInfo request
;
7493 request
.method
= "GET";
7494 request
.url
= GURL("http://www.example.org/");
7495 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7497 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7498 scoped_ptr
<HttpTransaction
> trans(
7499 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7501 MockWrite data_writes
[] = {
7503 "GET / HTTP/1.1\r\n"
7504 "Host: www.example.org\r\n"
7505 "Connection: keep-alive\r\n"
7506 "FooHeader: Bar\r\n\r\n"),
7509 // Lastly, the server responds with the actual content.
7510 MockRead data_reads
[] = {
7511 MockRead("HTTP/1.0 200 OK\r\n"),
7512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7513 MockRead("Content-Length: 100\r\n\r\n"),
7514 MockRead(SYNCHRONOUS
, OK
),
7517 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7518 data_writes
, arraysize(data_writes
));
7519 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7521 TestCompletionCallback callback
;
7523 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7524 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7526 rv
= callback
.WaitForResult();
7530 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7531 HttpRequestInfo request
;
7532 request
.method
= "GET";
7533 request
.url
= GURL("http://www.example.org/");
7534 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7535 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7536 request
.extra_headers
.SetHeader("FoO", "bar");
7538 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7539 scoped_ptr
<HttpTransaction
> trans(
7540 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7542 MockWrite data_writes
[] = {
7544 "GET / HTTP/1.1\r\n"
7545 "Host: www.example.org\r\n"
7546 "Connection: keep-alive\r\n"
7547 "referer: www.foo.com\r\n"
7549 "FoO: bar\r\n\r\n"),
7552 // Lastly, the server responds with the actual content.
7553 MockRead data_reads
[] = {
7554 MockRead("HTTP/1.0 200 OK\r\n"),
7555 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7556 MockRead("Content-Length: 100\r\n\r\n"),
7557 MockRead(SYNCHRONOUS
, OK
),
7560 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7561 data_writes
, arraysize(data_writes
));
7562 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7564 TestCompletionCallback callback
;
7566 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7567 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7569 rv
= callback
.WaitForResult();
7573 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7574 HttpRequestInfo request
;
7575 request
.method
= "GET";
7576 request
.url
= GURL("http://www.example.org/");
7577 request
.load_flags
= 0;
7579 session_deps_
.proxy_service
.reset(
7580 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7582 session_deps_
.net_log
= &net_log
;
7584 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7585 scoped_ptr
<HttpTransaction
> trans(
7586 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7588 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7589 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7591 MockWrite data_writes
[] = {
7592 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7594 "GET / HTTP/1.1\r\n"
7595 "Host: www.example.org\r\n"
7596 "Connection: keep-alive\r\n\r\n")};
7598 MockRead data_reads
[] = {
7599 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7600 MockRead("HTTP/1.0 200 OK\r\n"),
7601 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7602 MockRead("Payload"),
7603 MockRead(SYNCHRONOUS
, OK
)
7606 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7607 data_writes
, arraysize(data_writes
));
7608 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7610 TestCompletionCallback callback
;
7612 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7613 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7615 rv
= callback
.WaitForResult();
7618 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7619 ASSERT_TRUE(response
!= NULL
);
7621 LoadTimingInfo load_timing_info
;
7622 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7623 TestLoadTimingNotReusedWithPac(load_timing_info
,
7624 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7626 std::string response_text
;
7627 rv
= ReadTransaction(trans
.get(), &response_text
);
7629 EXPECT_EQ("Payload", response_text
);
7632 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7633 HttpRequestInfo request
;
7634 request
.method
= "GET";
7635 request
.url
= GURL("https://www.example.org/");
7636 request
.load_flags
= 0;
7638 session_deps_
.proxy_service
.reset(
7639 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7641 session_deps_
.net_log
= &net_log
;
7643 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7644 scoped_ptr
<HttpTransaction
> trans(
7645 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7647 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7648 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7650 MockWrite data_writes
[] = {
7651 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7652 arraysize(write_buffer
)),
7654 "GET / HTTP/1.1\r\n"
7655 "Host: www.example.org\r\n"
7656 "Connection: keep-alive\r\n\r\n")};
7658 MockRead data_reads
[] = {
7659 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7660 arraysize(read_buffer
)),
7661 MockRead("HTTP/1.0 200 OK\r\n"),
7662 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7663 MockRead("Payload"),
7664 MockRead(SYNCHRONOUS
, OK
)
7667 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7668 data_writes
, arraysize(data_writes
));
7669 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7671 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7672 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7674 TestCompletionCallback callback
;
7676 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7677 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7679 rv
= callback
.WaitForResult();
7682 LoadTimingInfo load_timing_info
;
7683 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7684 TestLoadTimingNotReusedWithPac(load_timing_info
,
7685 CONNECT_TIMING_HAS_SSL_TIMES
);
7687 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7688 ASSERT_TRUE(response
!= NULL
);
7690 std::string response_text
;
7691 rv
= ReadTransaction(trans
.get(), &response_text
);
7693 EXPECT_EQ("Payload", response_text
);
7696 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7697 HttpRequestInfo request
;
7698 request
.method
= "GET";
7699 request
.url
= GURL("http://www.example.org/");
7700 request
.load_flags
= 0;
7702 session_deps_
.proxy_service
.reset(
7703 ProxyService::CreateFixed("socks4://myproxy:1080"));
7705 session_deps_
.net_log
= &net_log
;
7707 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7708 scoped_ptr
<HttpTransaction
> trans(
7709 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7711 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7712 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7714 MockWrite data_writes
[] = {
7715 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7717 "GET / HTTP/1.1\r\n"
7718 "Host: www.example.org\r\n"
7719 "Connection: keep-alive\r\n\r\n")};
7721 MockRead data_reads
[] = {
7722 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7723 MockRead("HTTP/1.0 200 OK\r\n"),
7724 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7725 MockRead("Payload"),
7726 MockRead(SYNCHRONOUS
, OK
)
7729 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7730 data_writes
, arraysize(data_writes
));
7731 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7733 TestCompletionCallback callback
;
7735 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7736 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7738 rv
= callback
.WaitForResult();
7741 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7742 ASSERT_TRUE(response
!= NULL
);
7744 LoadTimingInfo load_timing_info
;
7745 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7746 TestLoadTimingNotReused(load_timing_info
,
7747 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7749 std::string response_text
;
7750 rv
= ReadTransaction(trans
.get(), &response_text
);
7752 EXPECT_EQ("Payload", response_text
);
7755 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7756 HttpRequestInfo request
;
7757 request
.method
= "GET";
7758 request
.url
= GURL("http://www.example.org/");
7759 request
.load_flags
= 0;
7761 session_deps_
.proxy_service
.reset(
7762 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7764 session_deps_
.net_log
= &net_log
;
7766 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7767 scoped_ptr
<HttpTransaction
> trans(
7768 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7770 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7771 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7772 const char kSOCKS5OkRequest
[] = {
7774 0x01, // Command (CONNECT)
7776 0x03, // Address type (DOMAINNAME).
7777 0x0F, // Length of domain (15)
7778 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7779 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7781 const char kSOCKS5OkResponse
[] =
7782 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7784 MockWrite data_writes
[] = {
7785 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7786 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7788 "GET / HTTP/1.1\r\n"
7789 "Host: www.example.org\r\n"
7790 "Connection: keep-alive\r\n\r\n")};
7792 MockRead data_reads
[] = {
7793 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7794 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7795 MockRead("HTTP/1.0 200 OK\r\n"),
7796 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7797 MockRead("Payload"),
7798 MockRead(SYNCHRONOUS
, OK
)
7801 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7802 data_writes
, arraysize(data_writes
));
7803 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7805 TestCompletionCallback callback
;
7807 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7808 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7810 rv
= callback
.WaitForResult();
7813 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7814 ASSERT_TRUE(response
!= NULL
);
7816 LoadTimingInfo load_timing_info
;
7817 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7818 TestLoadTimingNotReusedWithPac(load_timing_info
,
7819 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7821 std::string response_text
;
7822 rv
= ReadTransaction(trans
.get(), &response_text
);
7824 EXPECT_EQ("Payload", response_text
);
7827 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7828 HttpRequestInfo request
;
7829 request
.method
= "GET";
7830 request
.url
= GURL("https://www.example.org/");
7831 request
.load_flags
= 0;
7833 session_deps_
.proxy_service
.reset(
7834 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7836 session_deps_
.net_log
= &net_log
;
7838 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7839 scoped_ptr
<HttpTransaction
> trans(
7840 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7842 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7843 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7844 const unsigned char kSOCKS5OkRequest
[] = {
7846 0x01, // Command (CONNECT)
7848 0x03, // Address type (DOMAINNAME).
7849 0x0F, // Length of domain (15)
7850 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7851 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7854 const char kSOCKS5OkResponse
[] =
7855 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7857 MockWrite data_writes
[] = {
7858 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7859 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7860 arraysize(kSOCKS5OkRequest
)),
7862 "GET / HTTP/1.1\r\n"
7863 "Host: www.example.org\r\n"
7864 "Connection: keep-alive\r\n\r\n")};
7866 MockRead data_reads
[] = {
7867 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7868 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7869 MockRead("HTTP/1.0 200 OK\r\n"),
7870 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7871 MockRead("Payload"),
7872 MockRead(SYNCHRONOUS
, OK
)
7875 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7876 data_writes
, arraysize(data_writes
));
7877 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7879 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7880 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7882 TestCompletionCallback callback
;
7884 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7885 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7887 rv
= callback
.WaitForResult();
7890 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7891 ASSERT_TRUE(response
!= NULL
);
7893 LoadTimingInfo load_timing_info
;
7894 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7895 TestLoadTimingNotReusedWithPac(load_timing_info
,
7896 CONNECT_TIMING_HAS_SSL_TIMES
);
7898 std::string response_text
;
7899 rv
= ReadTransaction(trans
.get(), &response_text
);
7901 EXPECT_EQ("Payload", response_text
);
7906 // Tests that for connection endpoints the group names are correctly set.
7908 struct GroupNameTest
{
7909 std::string proxy_server
;
7911 std::string expected_group_name
;
7915 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7916 NextProto next_proto
,
7917 SpdySessionDependencies
* session_deps_
) {
7918 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7920 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7921 session
->http_server_properties();
7922 AlternativeService
alternative_service(
7923 AlternateProtocolFromNextProto(next_proto
), "", 443);
7924 http_server_properties
->SetAlternativeService(
7925 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0);
7930 int GroupNameTransactionHelper(
7931 const std::string
& url
,
7932 const scoped_refptr
<HttpNetworkSession
>& session
) {
7933 HttpRequestInfo request
;
7934 request
.method
= "GET";
7935 request
.url
= GURL(url
);
7936 request
.load_flags
= 0;
7938 scoped_ptr
<HttpTransaction
> trans(
7939 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7941 TestCompletionCallback callback
;
7943 // We do not complete this request, the dtor will clean the transaction up.
7944 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7949 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7950 const GroupNameTest tests
[] = {
7953 "http://www.example.org/direct",
7954 "www.example.org:80",
7959 "http://[2001:1418:13:1::25]/direct",
7960 "[2001:1418:13:1::25]:80",
7967 "https://www.example.org/direct_ssl",
7968 "ssl/www.example.org:443",
7973 "https://[2001:1418:13:1::25]/direct",
7974 "ssl/[2001:1418:13:1::25]:443",
7979 "http://host.with.alternate/direct",
7980 "ssl/host.with.alternate:443",
7985 session_deps_
.use_alternate_protocols
= true;
7987 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7988 session_deps_
.proxy_service
.reset(
7989 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7990 scoped_refptr
<HttpNetworkSession
> session(
7991 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7993 HttpNetworkSessionPeer
peer(session
);
7994 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7995 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7996 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7997 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7998 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7999 new MockClientSocketPoolManager
);
8000 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
8001 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
8002 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8004 EXPECT_EQ(ERR_IO_PENDING
,
8005 GroupNameTransactionHelper(tests
[i
].url
, session
));
8007 EXPECT_EQ(tests
[i
].expected_group_name
,
8008 ssl_conn_pool
->last_group_name_received());
8010 EXPECT_EQ(tests
[i
].expected_group_name
,
8011 transport_conn_pool
->last_group_name_received());
8016 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
8017 const GroupNameTest tests
[] = {
8020 "http://www.example.org/http_proxy_normal",
8021 "www.example.org:80",
8028 "https://www.example.org/http_connect_ssl",
8029 "ssl/www.example.org:443",
8035 "http://host.with.alternate/direct",
8036 "ssl/host.with.alternate:443",
8042 "ftp://ftp.google.com/http_proxy_normal",
8043 "ftp/ftp.google.com:21",
8048 session_deps_
.use_alternate_protocols
= true;
8050 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8051 session_deps_
.proxy_service
.reset(
8052 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8053 scoped_refptr
<HttpNetworkSession
> session(
8054 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8056 HttpNetworkSessionPeer
peer(session
);
8058 HostPortPair
proxy_host("http_proxy", 80);
8059 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8060 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8061 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8062 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8064 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8065 new MockClientSocketPoolManager
);
8066 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8067 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8068 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8070 EXPECT_EQ(ERR_IO_PENDING
,
8071 GroupNameTransactionHelper(tests
[i
].url
, session
));
8073 EXPECT_EQ(tests
[i
].expected_group_name
,
8074 ssl_conn_pool
->last_group_name_received());
8076 EXPECT_EQ(tests
[i
].expected_group_name
,
8077 http_proxy_pool
->last_group_name_received());
8081 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8082 const GroupNameTest tests
[] = {
8084 "socks4://socks_proxy:1080",
8085 "http://www.example.org/socks4_direct",
8086 "socks4/www.example.org:80",
8090 "socks5://socks_proxy:1080",
8091 "http://www.example.org/socks5_direct",
8092 "socks5/www.example.org:80",
8098 "socks4://socks_proxy:1080",
8099 "https://www.example.org/socks4_ssl",
8100 "socks4/ssl/www.example.org:443",
8104 "socks5://socks_proxy:1080",
8105 "https://www.example.org/socks5_ssl",
8106 "socks5/ssl/www.example.org:443",
8111 "socks4://socks_proxy:1080",
8112 "http://host.with.alternate/direct",
8113 "socks4/ssl/host.with.alternate:443",
8118 session_deps_
.use_alternate_protocols
= true;
8120 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8121 session_deps_
.proxy_service
.reset(
8122 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8123 scoped_refptr
<HttpNetworkSession
> session(
8124 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8126 HttpNetworkSessionPeer
peer(session
);
8128 HostPortPair
proxy_host("socks_proxy", 1080);
8129 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8130 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8131 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8132 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8134 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8135 new MockClientSocketPoolManager
);
8136 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8137 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8138 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8140 scoped_ptr
<HttpTransaction
> trans(
8141 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8143 EXPECT_EQ(ERR_IO_PENDING
,
8144 GroupNameTransactionHelper(tests
[i
].url
, session
));
8146 EXPECT_EQ(tests
[i
].expected_group_name
,
8147 ssl_conn_pool
->last_group_name_received());
8149 EXPECT_EQ(tests
[i
].expected_group_name
,
8150 socks_conn_pool
->last_group_name_received());
8154 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8155 HttpRequestInfo request
;
8156 request
.method
= "GET";
8157 request
.url
= GURL("http://www.example.org/");
8159 session_deps_
.proxy_service
.reset(
8160 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8162 // This simulates failure resolving all hostnames; that means we will fail
8163 // connecting to both proxies (myproxy:70 and foobar:80).
8164 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8166 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8167 scoped_ptr
<HttpTransaction
> trans(
8168 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8170 TestCompletionCallback callback
;
8172 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8173 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8175 rv
= callback
.WaitForResult();
8176 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8179 // Base test to make sure that when the load flags for a request specify to
8180 // bypass the cache, the DNS cache is not used.
8181 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8183 // Issue a request, asking to bypass the cache(s).
8184 HttpRequestInfo request
;
8185 request
.method
= "GET";
8186 request
.load_flags
= load_flags
;
8187 request
.url
= GURL("http://www.example.org/");
8189 // Select a host resolver that does caching.
8190 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8192 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8193 scoped_ptr
<HttpTransaction
> trans(
8194 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8196 // Warm up the host cache so it has an entry for "www.example.org".
8197 AddressList addrlist
;
8198 TestCompletionCallback callback
;
8199 int rv
= session_deps_
.host_resolver
->Resolve(
8200 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8201 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8202 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8203 rv
= callback
.WaitForResult();
8206 // Verify that it was added to host cache, by doing a subsequent async lookup
8207 // and confirming it completes synchronously.
8208 rv
= session_deps_
.host_resolver
->Resolve(
8209 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8210 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8213 // Inject a failure the next time that "www.example.org" is resolved. This way
8214 // we can tell if the next lookup hit the cache, or the "network".
8215 // (cache --> success, "network" --> failure).
8216 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8218 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8219 // first read -- this won't be reached as the host resolution will fail first.
8220 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8221 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8222 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8225 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8226 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8227 rv
= callback
.WaitForResult();
8229 // If we bypassed the cache, we would have gotten a failure while resolving
8230 // "www.example.org".
8231 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8234 // There are multiple load flags that should trigger the host cache bypass.
8235 // Test each in isolation:
8236 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8237 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8240 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8241 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8244 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8245 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8248 // Make sure we can handle an error when writing the request.
8249 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8250 HttpRequestInfo request
;
8251 request
.method
= "GET";
8252 request
.url
= GURL("http://www.foo.com/");
8253 request
.load_flags
= 0;
8255 MockWrite write_failure
[] = {
8256 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8258 StaticSocketDataProvider
data(NULL
, 0,
8259 write_failure
, arraysize(write_failure
));
8260 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8261 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8263 TestCompletionCallback callback
;
8265 scoped_ptr
<HttpTransaction
> trans(
8266 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8268 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8269 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8271 rv
= callback
.WaitForResult();
8272 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8275 // Check that a connection closed after the start of the headers finishes ok.
8276 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8277 HttpRequestInfo request
;
8278 request
.method
= "GET";
8279 request
.url
= GURL("http://www.foo.com/");
8280 request
.load_flags
= 0;
8282 MockRead data_reads
[] = {
8283 MockRead("HTTP/1."),
8284 MockRead(SYNCHRONOUS
, OK
),
8287 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8288 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8289 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8291 TestCompletionCallback callback
;
8293 scoped_ptr
<HttpTransaction
> trans(
8294 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8296 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8297 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8299 rv
= callback
.WaitForResult();
8302 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8303 ASSERT_TRUE(response
!= NULL
);
8305 EXPECT_TRUE(response
->headers
.get() != NULL
);
8306 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8308 std::string response_data
;
8309 rv
= ReadTransaction(trans
.get(), &response_data
);
8311 EXPECT_EQ("", response_data
);
8314 // Make sure that a dropped connection while draining the body for auth
8315 // restart does the right thing.
8316 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8317 HttpRequestInfo request
;
8318 request
.method
= "GET";
8319 request
.url
= GURL("http://www.example.org/");
8320 request
.load_flags
= 0;
8322 MockWrite data_writes1
[] = {
8324 "GET / HTTP/1.1\r\n"
8325 "Host: www.example.org\r\n"
8326 "Connection: keep-alive\r\n\r\n"),
8329 MockRead data_reads1
[] = {
8330 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8331 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8332 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8333 MockRead("Content-Length: 14\r\n\r\n"),
8335 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8338 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8339 data_writes1
, arraysize(data_writes1
));
8340 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8342 // After calling trans->RestartWithAuth(), this is the request we should
8343 // be issuing -- the final header line contains the credentials.
8344 MockWrite data_writes2
[] = {
8346 "GET / HTTP/1.1\r\n"
8347 "Host: www.example.org\r\n"
8348 "Connection: keep-alive\r\n"
8349 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8352 // Lastly, the server responds with the actual content.
8353 MockRead data_reads2
[] = {
8354 MockRead("HTTP/1.1 200 OK\r\n"),
8355 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8356 MockRead("Content-Length: 100\r\n\r\n"),
8357 MockRead(SYNCHRONOUS
, OK
),
8360 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8361 data_writes2
, arraysize(data_writes2
));
8362 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8363 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8365 TestCompletionCallback callback1
;
8367 scoped_ptr
<HttpTransaction
> trans(
8368 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8370 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8371 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8373 rv
= callback1
.WaitForResult();
8376 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8377 ASSERT_TRUE(response
!= NULL
);
8378 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8380 TestCompletionCallback callback2
;
8382 rv
= trans
->RestartWithAuth(
8383 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8384 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8386 rv
= callback2
.WaitForResult();
8389 response
= trans
->GetResponseInfo();
8390 ASSERT_TRUE(response
!= NULL
);
8391 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8392 EXPECT_EQ(100, response
->headers
->GetContentLength());
8395 // Test HTTPS connections going through a proxy that sends extra data.
8396 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8397 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8399 HttpRequestInfo request
;
8400 request
.method
= "GET";
8401 request
.url
= GURL("https://www.example.org/");
8402 request
.load_flags
= 0;
8404 MockRead proxy_reads
[] = {
8405 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8406 MockRead(SYNCHRONOUS
, OK
)
8409 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8410 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8412 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8413 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8415 TestCompletionCallback callback
;
8417 session_deps_
.socket_factory
->ResetNextMockIndexes();
8419 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8420 scoped_ptr
<HttpTransaction
> trans(
8421 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8423 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8424 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8426 rv
= callback
.WaitForResult();
8427 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8430 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8431 HttpRequestInfo request
;
8432 request
.method
= "GET";
8433 request
.url
= GURL("http://www.example.org/");
8434 request
.load_flags
= 0;
8436 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8437 scoped_ptr
<HttpTransaction
> trans(
8438 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8440 MockRead data_reads
[] = {
8441 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8442 MockRead(SYNCHRONOUS
, OK
),
8445 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8446 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8448 TestCompletionCallback callback
;
8450 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8451 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8453 EXPECT_EQ(OK
, callback
.WaitForResult());
8455 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8456 ASSERT_TRUE(response
!= NULL
);
8458 EXPECT_TRUE(response
->headers
.get() != NULL
);
8459 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8461 std::string response_data
;
8462 rv
= ReadTransaction(trans
.get(), &response_data
);
8463 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8466 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8467 base::FilePath temp_file_path
;
8468 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8469 const uint64 kFakeSize
= 100000; // file is actually blank
8470 UploadFileElementReader::ScopedOverridingContentLengthForTests
8471 overriding_content_length(kFakeSize
);
8473 ScopedVector
<UploadElementReader
> element_readers
;
8474 element_readers
.push_back(
8475 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8480 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8482 HttpRequestInfo request
;
8483 request
.method
= "POST";
8484 request
.url
= GURL("http://www.example.org/upload");
8485 request
.upload_data_stream
= &upload_data_stream
;
8486 request
.load_flags
= 0;
8488 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8489 scoped_ptr
<HttpTransaction
> trans(
8490 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8492 MockRead data_reads
[] = {
8493 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8494 MockRead("hello world"),
8495 MockRead(SYNCHRONOUS
, OK
),
8497 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8498 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8500 TestCompletionCallback callback
;
8502 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8503 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8505 rv
= callback
.WaitForResult();
8508 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8509 ASSERT_TRUE(response
!= NULL
);
8511 EXPECT_TRUE(response
->headers
.get() != NULL
);
8512 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8514 std::string response_data
;
8515 rv
= ReadTransaction(trans
.get(), &response_data
);
8517 EXPECT_EQ("hello world", response_data
);
8519 base::DeleteFile(temp_file_path
, false);
8522 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8523 base::FilePath temp_file
;
8524 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8525 std::string
temp_file_content("Unreadable file.");
8526 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8527 temp_file_content
.length()));
8528 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8530 ScopedVector
<UploadElementReader
> element_readers
;
8531 element_readers
.push_back(
8532 new UploadFileElementReader(base::MessageLoopProxy::current().get(),
8537 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8539 HttpRequestInfo request
;
8540 request
.method
= "POST";
8541 request
.url
= GURL("http://www.example.org/upload");
8542 request
.upload_data_stream
= &upload_data_stream
;
8543 request
.load_flags
= 0;
8545 // If we try to upload an unreadable file, the transaction should fail.
8546 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8547 scoped_ptr
<HttpTransaction
> trans(
8548 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8550 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8551 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8553 TestCompletionCallback callback
;
8555 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8556 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8558 rv
= callback
.WaitForResult();
8559 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8561 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8562 EXPECT_FALSE(response
);
8564 base::DeleteFile(temp_file
, false);
8567 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8568 class FakeUploadElementReader
: public UploadElementReader
{
8570 FakeUploadElementReader() {}
8571 ~FakeUploadElementReader() override
{}
8573 const CompletionCallback
& callback() const { return callback_
; }
8575 // UploadElementReader overrides:
8576 int Init(const CompletionCallback
& callback
) override
{
8577 callback_
= callback
;
8578 return ERR_IO_PENDING
;
8580 uint64
GetContentLength() const override
{ return 0; }
8581 uint64
BytesRemaining() const override
{ return 0; }
8582 int Read(IOBuffer
* buf
,
8584 const CompletionCallback
& callback
) override
{
8589 CompletionCallback callback_
;
8592 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8593 ScopedVector
<UploadElementReader
> element_readers
;
8594 element_readers
.push_back(fake_reader
);
8595 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8597 HttpRequestInfo request
;
8598 request
.method
= "POST";
8599 request
.url
= GURL("http://www.example.org/upload");
8600 request
.upload_data_stream
= &upload_data_stream
;
8601 request
.load_flags
= 0;
8603 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8604 scoped_ptr
<HttpTransaction
> trans(
8605 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8607 StaticSocketDataProvider data
;
8608 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8610 TestCompletionCallback callback
;
8611 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8612 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8613 base::MessageLoop::current()->RunUntilIdle();
8615 // Transaction is pending on request body initialization.
8616 ASSERT_FALSE(fake_reader
->callback().is_null());
8618 // Return Init()'s result after the transaction gets destroyed.
8620 fake_reader
->callback().Run(OK
); // Should not crash.
8623 // Tests that changes to Auth realms are treated like auth rejections.
8624 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8626 HttpRequestInfo request
;
8627 request
.method
= "GET";
8628 request
.url
= GURL("http://www.example.org/");
8629 request
.load_flags
= 0;
8631 // First transaction will request a resource and receive a Basic challenge
8632 // with realm="first_realm".
8633 MockWrite data_writes1
[] = {
8635 "GET / HTTP/1.1\r\n"
8636 "Host: www.example.org\r\n"
8637 "Connection: keep-alive\r\n"
8640 MockRead data_reads1
[] = {
8641 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8642 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8646 // After calling trans->RestartWithAuth(), provide an Authentication header
8647 // for first_realm. The server will reject and provide a challenge with
8649 MockWrite data_writes2
[] = {
8651 "GET / HTTP/1.1\r\n"
8652 "Host: www.example.org\r\n"
8653 "Connection: keep-alive\r\n"
8654 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8657 MockRead data_reads2
[] = {
8658 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8659 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8663 // This again fails, and goes back to first_realm. Make sure that the
8664 // entry is removed from cache.
8665 MockWrite data_writes3
[] = {
8667 "GET / HTTP/1.1\r\n"
8668 "Host: www.example.org\r\n"
8669 "Connection: keep-alive\r\n"
8670 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8673 MockRead data_reads3
[] = {
8674 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8675 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8679 // Try one last time (with the correct password) and get the resource.
8680 MockWrite data_writes4
[] = {
8682 "GET / HTTP/1.1\r\n"
8683 "Host: www.example.org\r\n"
8684 "Connection: keep-alive\r\n"
8685 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8688 MockRead data_reads4
[] = {
8689 MockRead("HTTP/1.1 200 OK\r\n"
8690 "Content-Type: text/html; charset=iso-8859-1\r\n"
8691 "Content-Length: 5\r\n"
8696 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8697 data_writes1
, arraysize(data_writes1
));
8698 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8699 data_writes2
, arraysize(data_writes2
));
8700 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8701 data_writes3
, arraysize(data_writes3
));
8702 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8703 data_writes4
, arraysize(data_writes4
));
8704 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8705 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8706 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8707 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8709 TestCompletionCallback callback1
;
8711 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8712 scoped_ptr
<HttpTransaction
> trans(
8713 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8715 // Issue the first request with Authorize headers. There should be a
8716 // password prompt for first_realm waiting to be filled in after the
8717 // transaction completes.
8718 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8719 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8720 rv
= callback1
.WaitForResult();
8722 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8723 ASSERT_TRUE(response
!= NULL
);
8724 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8725 ASSERT_FALSE(challenge
== NULL
);
8726 EXPECT_FALSE(challenge
->is_proxy
);
8727 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8728 EXPECT_EQ("first_realm", challenge
->realm
);
8729 EXPECT_EQ("basic", challenge
->scheme
);
8731 // Issue the second request with an incorrect password. There should be a
8732 // password prompt for second_realm waiting to be filled in after the
8733 // transaction completes.
8734 TestCompletionCallback callback2
;
8735 rv
= trans
->RestartWithAuth(
8736 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8737 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8738 rv
= callback2
.WaitForResult();
8740 response
= trans
->GetResponseInfo();
8741 ASSERT_TRUE(response
!= NULL
);
8742 challenge
= response
->auth_challenge
.get();
8743 ASSERT_FALSE(challenge
== NULL
);
8744 EXPECT_FALSE(challenge
->is_proxy
);
8745 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8746 EXPECT_EQ("second_realm", challenge
->realm
);
8747 EXPECT_EQ("basic", challenge
->scheme
);
8749 // Issue the third request with another incorrect password. There should be
8750 // a password prompt for first_realm waiting to be filled in. If the password
8751 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8752 // first_realm was not correctly removed.
8753 TestCompletionCallback callback3
;
8754 rv
= trans
->RestartWithAuth(
8755 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8756 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8757 rv
= callback3
.WaitForResult();
8759 response
= trans
->GetResponseInfo();
8760 ASSERT_TRUE(response
!= NULL
);
8761 challenge
= response
->auth_challenge
.get();
8762 ASSERT_FALSE(challenge
== NULL
);
8763 EXPECT_FALSE(challenge
->is_proxy
);
8764 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8765 EXPECT_EQ("first_realm", challenge
->realm
);
8766 EXPECT_EQ("basic", challenge
->scheme
);
8768 // Issue the fourth request with the correct password and username.
8769 TestCompletionCallback callback4
;
8770 rv
= trans
->RestartWithAuth(
8771 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8772 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8773 rv
= callback4
.WaitForResult();
8775 response
= trans
->GetResponseInfo();
8776 ASSERT_TRUE(response
!= NULL
);
8777 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8780 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8781 session_deps_
.next_protos
= SpdyNextProtos();
8782 session_deps_
.use_alternate_protocols
= true;
8784 std::string alternate_protocol_http_header
=
8785 GetAlternateProtocolHttpHeader();
8787 MockRead data_reads
[] = {
8788 MockRead("HTTP/1.1 200 OK\r\n"),
8789 MockRead(alternate_protocol_http_header
.c_str()),
8790 MockRead("hello world"),
8791 MockRead(SYNCHRONOUS
, OK
),
8794 HttpRequestInfo request
;
8795 request
.method
= "GET";
8796 request
.url
= GURL("http://www.example.org/");
8797 request
.load_flags
= 0;
8799 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8801 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8803 TestCompletionCallback callback
;
8805 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8806 scoped_ptr
<HttpTransaction
> trans(
8807 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8809 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8810 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8812 HostPortPair
http_host_port_pair("www.example.org", 80);
8813 HttpServerProperties
& http_server_properties
=
8814 *session
->http_server_properties();
8815 AlternativeService alternative_service
=
8816 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8817 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8819 EXPECT_EQ(OK
, callback
.WaitForResult());
8821 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8822 ASSERT_TRUE(response
!= NULL
);
8823 ASSERT_TRUE(response
->headers
.get() != NULL
);
8824 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8825 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8826 EXPECT_FALSE(response
->was_npn_negotiated
);
8828 std::string response_data
;
8829 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8830 EXPECT_EQ("hello world", response_data
);
8832 alternative_service
=
8833 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8834 EXPECT_EQ(443, alternative_service
.port
);
8835 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8836 alternative_service
.protocol
);
8839 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8840 session_deps_
.next_protos
= SpdyNextProtos();
8841 session_deps_
.use_alternate_protocols
= true;
8843 MockRead data_reads
[] = {
8844 MockRead("HTTP/1.1 200 OK\r\n"),
8845 MockRead("Alternate-Protocol: \r\n\r\n"),
8846 MockRead("hello world"),
8847 MockRead(SYNCHRONOUS
, OK
),
8850 HttpRequestInfo request
;
8851 request
.method
= "GET";
8852 request
.url
= GURL("http://www.example.org/");
8853 request
.load_flags
= 0;
8855 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8857 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8859 TestCompletionCallback callback
;
8861 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8863 HostPortPair
http_host_port_pair("www.example.org", 80);
8864 HttpServerProperties
& http_server_properties
=
8865 *session
->http_server_properties();
8866 AlternativeService
alternative_service(QUIC
, "", 80);
8867 http_server_properties
.SetAlternativeService(http_host_port_pair
,
8868 alternative_service
, 1.0);
8870 alternative_service
=
8871 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8872 EXPECT_EQ(alternative_service
.protocol
, QUIC
);
8874 scoped_ptr
<HttpTransaction
> trans(
8875 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8877 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8878 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8880 EXPECT_EQ(OK
, callback
.WaitForResult());
8882 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8883 ASSERT_TRUE(response
!= NULL
);
8884 ASSERT_TRUE(response
->headers
.get() != NULL
);
8885 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8886 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8887 EXPECT_FALSE(response
->was_npn_negotiated
);
8889 std::string response_data
;
8890 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8891 EXPECT_EQ("hello world", response_data
);
8893 alternative_service
=
8894 http_server_properties
.GetAlternativeService(http_host_port_pair
);
8895 EXPECT_EQ(alternative_service
.protocol
, UNINITIALIZED_ALTERNATE_PROTOCOL
);
8898 TEST_P(HttpNetworkTransactionTest
,
8899 MarkBrokenAlternateProtocolAndFallback
) {
8900 session_deps_
.use_alternate_protocols
= true;
8902 HttpRequestInfo request
;
8903 request
.method
= "GET";
8904 request
.url
= GURL("http://www.example.org/");
8905 request
.load_flags
= 0;
8907 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8908 StaticSocketDataProvider first_data
;
8909 first_data
.set_connect_data(mock_connect
);
8910 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8912 MockRead data_reads
[] = {
8913 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8914 MockRead("hello world"),
8915 MockRead(ASYNC
, OK
),
8917 StaticSocketDataProvider
second_data(
8918 data_reads
, arraysize(data_reads
), NULL
, 0);
8919 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8921 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8923 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8924 session
->http_server_properties();
8925 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
8926 // Port must be < 1024, or the header will be ignored (since initial port was
8927 // port 80 (another restricted port).
8928 AlternativeService
alternative_service(
8929 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8930 666); /* port is ignored by MockConnect anyway */
8931 http_server_properties
->SetAlternativeService(host_port_pair
,
8932 alternative_service
, 1.0);
8934 scoped_ptr
<HttpTransaction
> trans(
8935 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8936 TestCompletionCallback callback
;
8938 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8939 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8940 EXPECT_EQ(OK
, callback
.WaitForResult());
8942 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8943 ASSERT_TRUE(response
!= NULL
);
8944 ASSERT_TRUE(response
->headers
.get() != NULL
);
8945 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8947 std::string response_data
;
8948 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8949 EXPECT_EQ("hello world", response_data
);
8951 alternative_service
=
8952 http_server_properties
->GetAlternativeService(host_port_pair
);
8953 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL
, alternative_service
.protocol
);
8955 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
8958 TEST_P(HttpNetworkTransactionTest
,
8959 AlternateProtocolPortRestrictedBlocked
) {
8960 // Ensure that we're not allowed to redirect traffic via an alternate
8961 // protocol to an unrestricted (port >= 1024) when the original traffic was
8962 // on a restricted port (port < 1024). Ensure that we can redirect in all
8964 session_deps_
.use_alternate_protocols
= true;
8966 HttpRequestInfo restricted_port_request
;
8967 restricted_port_request
.method
= "GET";
8968 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
8969 restricted_port_request
.load_flags
= 0;
8971 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
8972 StaticSocketDataProvider first_data
;
8973 first_data
.set_connect_data(mock_connect
);
8974 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
8976 MockRead data_reads
[] = {
8977 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
8978 MockRead("hello world"),
8979 MockRead(ASYNC
, OK
),
8981 StaticSocketDataProvider
second_data(
8982 data_reads
, arraysize(data_reads
), NULL
, 0);
8983 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
8985 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8987 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
8988 session
->http_server_properties();
8989 const int kUnrestrictedAlternatePort
= 1024;
8990 AlternativeService
alternative_service(
8991 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
8992 kUnrestrictedAlternatePort
);
8993 http_server_properties
->SetAlternativeService(
8994 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
8997 scoped_ptr
<HttpTransaction
> trans(
8998 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8999 TestCompletionCallback callback
;
9001 int rv
= trans
->Start(
9002 &restricted_port_request
,
9003 callback
.callback(), BoundNetLog());
9004 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9005 // Invalid change to unrestricted port should fail.
9006 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9009 TEST_P(HttpNetworkTransactionTest
,
9010 AlternateProtocolPortRestrictedPermitted
) {
9011 // Ensure that we're allowed to redirect traffic via an alternate
9012 // protocol to an unrestricted (port >= 1024) when the original traffic was
9013 // on a restricted port (port < 1024) if we set
9014 // enable_user_alternate_protocol_ports.
9016 session_deps_
.use_alternate_protocols
= true;
9017 session_deps_
.enable_user_alternate_protocol_ports
= true;
9019 HttpRequestInfo restricted_port_request
;
9020 restricted_port_request
.method
= "GET";
9021 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9022 restricted_port_request
.load_flags
= 0;
9024 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9025 StaticSocketDataProvider first_data
;
9026 first_data
.set_connect_data(mock_connect
);
9027 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9029 MockRead data_reads
[] = {
9030 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9031 MockRead("hello world"),
9032 MockRead(ASYNC
, OK
),
9034 StaticSocketDataProvider
second_data(
9035 data_reads
, arraysize(data_reads
), NULL
, 0);
9036 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9038 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9040 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9041 session
->http_server_properties();
9042 const int kUnrestrictedAlternatePort
= 1024;
9043 AlternativeService
alternative_service(
9044 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9045 kUnrestrictedAlternatePort
);
9046 http_server_properties
->SetAlternativeService(
9047 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9050 scoped_ptr
<HttpTransaction
> trans(
9051 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9052 TestCompletionCallback callback
;
9054 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9055 &restricted_port_request
,
9056 callback
.callback(), BoundNetLog()));
9057 // Change to unrestricted port should succeed.
9058 EXPECT_EQ(OK
, callback
.WaitForResult());
9061 TEST_P(HttpNetworkTransactionTest
,
9062 AlternateProtocolPortRestrictedAllowed
) {
9063 // Ensure that we're not allowed to redirect traffic via an alternate
9064 // protocol to an unrestricted (port >= 1024) when the original traffic was
9065 // on a restricted port (port < 1024). Ensure that we can redirect in all
9067 session_deps_
.use_alternate_protocols
= true;
9069 HttpRequestInfo restricted_port_request
;
9070 restricted_port_request
.method
= "GET";
9071 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9072 restricted_port_request
.load_flags
= 0;
9074 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9075 StaticSocketDataProvider first_data
;
9076 first_data
.set_connect_data(mock_connect
);
9077 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9079 MockRead data_reads
[] = {
9080 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9081 MockRead("hello world"),
9082 MockRead(ASYNC
, OK
),
9084 StaticSocketDataProvider
second_data(
9085 data_reads
, arraysize(data_reads
), NULL
, 0);
9086 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9088 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9090 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9091 session
->http_server_properties();
9092 const int kRestrictedAlternatePort
= 80;
9093 AlternativeService
alternative_service(
9094 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9095 kRestrictedAlternatePort
);
9096 http_server_properties
->SetAlternativeService(
9097 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9100 scoped_ptr
<HttpTransaction
> trans(
9101 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9102 TestCompletionCallback callback
;
9104 int rv
= trans
->Start(
9105 &restricted_port_request
,
9106 callback
.callback(), BoundNetLog());
9107 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9108 // Valid change to restricted port should pass.
9109 EXPECT_EQ(OK
, callback
.WaitForResult());
9112 TEST_P(HttpNetworkTransactionTest
,
9113 AlternateProtocolPortUnrestrictedAllowed1
) {
9114 // Ensure that we're not allowed to redirect traffic via an alternate
9115 // protocol to an unrestricted (port >= 1024) when the original traffic was
9116 // on a restricted port (port < 1024). Ensure that we can redirect in all
9118 session_deps_
.use_alternate_protocols
= true;
9120 HttpRequestInfo unrestricted_port_request
;
9121 unrestricted_port_request
.method
= "GET";
9122 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9123 unrestricted_port_request
.load_flags
= 0;
9125 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9126 StaticSocketDataProvider first_data
;
9127 first_data
.set_connect_data(mock_connect
);
9128 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9130 MockRead data_reads
[] = {
9131 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9132 MockRead("hello world"),
9133 MockRead(ASYNC
, OK
),
9135 StaticSocketDataProvider
second_data(
9136 data_reads
, arraysize(data_reads
), NULL
, 0);
9137 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9139 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9141 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9142 session
->http_server_properties();
9143 const int kRestrictedAlternatePort
= 80;
9144 AlternativeService
alternative_service(
9145 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9146 kRestrictedAlternatePort
);
9147 http_server_properties
->SetAlternativeService(
9148 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9151 scoped_ptr
<HttpTransaction
> trans(
9152 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9153 TestCompletionCallback callback
;
9155 int rv
= trans
->Start(
9156 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9157 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9158 // Valid change to restricted port should pass.
9159 EXPECT_EQ(OK
, callback
.WaitForResult());
9162 TEST_P(HttpNetworkTransactionTest
,
9163 AlternateProtocolPortUnrestrictedAllowed2
) {
9164 // Ensure that we're not allowed to redirect traffic via an alternate
9165 // protocol to an unrestricted (port >= 1024) when the original traffic was
9166 // on a restricted port (port < 1024). Ensure that we can redirect in all
9168 session_deps_
.use_alternate_protocols
= true;
9170 HttpRequestInfo unrestricted_port_request
;
9171 unrestricted_port_request
.method
= "GET";
9172 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9173 unrestricted_port_request
.load_flags
= 0;
9175 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9176 StaticSocketDataProvider first_data
;
9177 first_data
.set_connect_data(mock_connect
);
9178 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9180 MockRead data_reads
[] = {
9181 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9182 MockRead("hello world"),
9183 MockRead(ASYNC
, OK
),
9185 StaticSocketDataProvider
second_data(
9186 data_reads
, arraysize(data_reads
), NULL
, 0);
9187 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9189 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9191 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9192 session
->http_server_properties();
9193 const int kUnrestrictedAlternatePort
= 1024;
9194 AlternativeService
alternative_service(
9195 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9196 kUnrestrictedAlternatePort
);
9197 http_server_properties
->SetAlternativeService(
9198 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9201 scoped_ptr
<HttpTransaction
> trans(
9202 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9203 TestCompletionCallback callback
;
9205 int rv
= trans
->Start(
9206 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9208 // Valid change to an unrestricted port should pass.
9209 EXPECT_EQ(OK
, callback
.WaitForResult());
9212 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9213 // Ensure that we're not allowed to redirect traffic via an alternate
9214 // protocol to an unsafe port, and that we resume the second
9215 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9216 session_deps_
.use_alternate_protocols
= true;
9218 HttpRequestInfo request
;
9219 request
.method
= "GET";
9220 request
.url
= GURL("http://www.example.org/");
9221 request
.load_flags
= 0;
9223 // The alternate protocol request will error out before we attempt to connect,
9224 // so only the standard HTTP request will try to connect.
9225 MockRead data_reads
[] = {
9226 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9227 MockRead("hello world"),
9228 MockRead(ASYNC
, OK
),
9230 StaticSocketDataProvider
data(
9231 data_reads
, arraysize(data_reads
), NULL
, 0);
9232 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9234 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9236 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9237 session
->http_server_properties();
9238 const int kUnsafePort
= 7;
9239 AlternativeService
alternative_service(
9240 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9242 http_server_properties
->SetAlternativeService(
9243 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0);
9245 scoped_ptr
<HttpTransaction
> trans(
9246 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9247 TestCompletionCallback callback
;
9249 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9251 // The HTTP request should succeed.
9252 EXPECT_EQ(OK
, callback
.WaitForResult());
9254 // Disable alternate protocol before the asserts.
9255 // HttpStreamFactory::set_use_alternate_protocols(false);
9257 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9258 ASSERT_TRUE(response
!= NULL
);
9259 ASSERT_TRUE(response
->headers
.get() != NULL
);
9260 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9262 std::string response_data
;
9263 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9264 EXPECT_EQ("hello world", response_data
);
9267 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9268 session_deps_
.use_alternate_protocols
= true;
9269 session_deps_
.next_protos
= SpdyNextProtos();
9271 HttpRequestInfo request
;
9272 request
.method
= "GET";
9273 request
.url
= GURL("http://www.example.org/");
9274 request
.load_flags
= 0;
9276 std::string alternate_protocol_http_header
=
9277 GetAlternateProtocolHttpHeader();
9279 MockRead data_reads
[] = {
9280 MockRead("HTTP/1.1 200 OK\r\n"),
9281 MockRead(alternate_protocol_http_header
.c_str()),
9282 MockRead("hello world"),
9283 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9287 StaticSocketDataProvider
first_transaction(
9288 data_reads
, arraysize(data_reads
), NULL
, 0);
9289 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9291 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9292 ssl
.SetNextProto(GetParam());
9293 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9294 ASSERT_TRUE(ssl
.cert
.get());
9295 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9297 scoped_ptr
<SpdyFrame
> req(
9298 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9299 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9301 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9302 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9303 MockRead spdy_reads
[] = {
9304 CreateMockRead(*resp
),
9305 CreateMockRead(*data
),
9306 MockRead(ASYNC
, 0, 0),
9309 DelayedSocketData
spdy_data(
9310 1, // wait for one write to finish before reading.
9311 spdy_reads
, arraysize(spdy_reads
),
9312 spdy_writes
, arraysize(spdy_writes
));
9313 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9315 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9316 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9318 hanging_non_alternate_protocol_socket
.set_connect_data(
9319 never_finishing_connect
);
9320 session_deps_
.socket_factory
->AddSocketDataProvider(
9321 &hanging_non_alternate_protocol_socket
);
9323 TestCompletionCallback callback
;
9325 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9326 scoped_ptr
<HttpTransaction
> trans(
9327 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9329 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9330 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9331 EXPECT_EQ(OK
, callback
.WaitForResult());
9333 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9334 ASSERT_TRUE(response
!= NULL
);
9335 ASSERT_TRUE(response
->headers
.get() != NULL
);
9336 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9338 std::string response_data
;
9339 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9340 EXPECT_EQ("hello world", response_data
);
9342 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9344 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9345 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9346 EXPECT_EQ(OK
, callback
.WaitForResult());
9348 response
= trans
->GetResponseInfo();
9349 ASSERT_TRUE(response
!= NULL
);
9350 ASSERT_TRUE(response
->headers
.get() != NULL
);
9351 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9352 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9353 EXPECT_TRUE(response
->was_npn_negotiated
);
9355 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9356 EXPECT_EQ("hello!", response_data
);
9359 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9360 session_deps_
.use_alternate_protocols
= true;
9361 session_deps_
.next_protos
= SpdyNextProtos();
9363 HttpRequestInfo request
;
9364 request
.method
= "GET";
9365 request
.url
= GURL("http://www.example.org/");
9366 request
.load_flags
= 0;
9368 std::string alternate_protocol_http_header
=
9369 GetAlternateProtocolHttpHeader();
9371 MockRead data_reads
[] = {
9372 MockRead("HTTP/1.1 200 OK\r\n"),
9373 MockRead(alternate_protocol_http_header
.c_str()),
9374 MockRead("hello world"),
9375 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9376 MockRead(ASYNC
, OK
),
9379 StaticSocketDataProvider
first_transaction(
9380 data_reads
, arraysize(data_reads
), NULL
, 0);
9381 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9382 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9384 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9385 StaticSocketDataProvider
hanging_socket(
9387 hanging_socket
.set_connect_data(never_finishing_connect
);
9388 // Socket 2 and 3 are the hanging Alternate-Protocol and
9389 // non-Alternate-Protocol jobs from the 2nd transaction.
9390 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9391 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9393 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9394 ssl
.SetNextProto(GetParam());
9395 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9396 ASSERT_TRUE(ssl
.cert
.get());
9397 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9399 scoped_ptr
<SpdyFrame
> req1(
9400 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9401 scoped_ptr
<SpdyFrame
> req2(
9402 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9403 MockWrite spdy_writes
[] = {
9404 CreateMockWrite(*req1
),
9405 CreateMockWrite(*req2
),
9407 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9408 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9409 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9410 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9411 MockRead spdy_reads
[] = {
9412 CreateMockRead(*resp1
),
9413 CreateMockRead(*data1
),
9414 CreateMockRead(*resp2
),
9415 CreateMockRead(*data2
),
9416 MockRead(ASYNC
, 0, 0),
9419 DelayedSocketData
spdy_data(
9420 2, // wait for writes to finish before reading.
9421 spdy_reads
, arraysize(spdy_reads
),
9422 spdy_writes
, arraysize(spdy_writes
));
9423 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9424 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9426 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9427 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9429 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9430 TestCompletionCallback callback1
;
9431 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9433 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9434 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9435 EXPECT_EQ(OK
, callback1
.WaitForResult());
9437 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9438 ASSERT_TRUE(response
!= NULL
);
9439 ASSERT_TRUE(response
->headers
.get() != NULL
);
9440 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9442 std::string response_data
;
9443 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9444 EXPECT_EQ("hello world", response_data
);
9446 TestCompletionCallback callback2
;
9447 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9448 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9449 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9451 TestCompletionCallback callback3
;
9452 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9453 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9454 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9456 EXPECT_EQ(OK
, callback2
.WaitForResult());
9457 EXPECT_EQ(OK
, callback3
.WaitForResult());
9459 response
= trans2
.GetResponseInfo();
9460 ASSERT_TRUE(response
!= NULL
);
9461 ASSERT_TRUE(response
->headers
.get() != NULL
);
9462 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9463 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9464 EXPECT_TRUE(response
->was_npn_negotiated
);
9465 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9466 EXPECT_EQ("hello!", response_data
);
9468 response
= trans3
.GetResponseInfo();
9469 ASSERT_TRUE(response
!= NULL
);
9470 ASSERT_TRUE(response
->headers
.get() != NULL
);
9471 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9472 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9473 EXPECT_TRUE(response
->was_npn_negotiated
);
9474 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9475 EXPECT_EQ("hello!", response_data
);
9478 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9479 session_deps_
.use_alternate_protocols
= true;
9480 session_deps_
.next_protos
= SpdyNextProtos();
9482 HttpRequestInfo request
;
9483 request
.method
= "GET";
9484 request
.url
= GURL("http://www.example.org/");
9485 request
.load_flags
= 0;
9487 std::string alternate_protocol_http_header
=
9488 GetAlternateProtocolHttpHeader();
9490 MockRead data_reads
[] = {
9491 MockRead("HTTP/1.1 200 OK\r\n"),
9492 MockRead(alternate_protocol_http_header
.c_str()),
9493 MockRead("hello world"),
9494 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9495 MockRead(ASYNC
, OK
),
9498 StaticSocketDataProvider
first_transaction(
9499 data_reads
, arraysize(data_reads
), NULL
, 0);
9500 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9502 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9503 ssl
.SetNextProto(GetParam());
9504 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9506 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9507 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9509 hanging_alternate_protocol_socket
.set_connect_data(
9510 never_finishing_connect
);
9511 session_deps_
.socket_factory
->AddSocketDataProvider(
9512 &hanging_alternate_protocol_socket
);
9514 // 2nd request is just a copy of the first one, over HTTP again.
9515 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9517 TestCompletionCallback callback
;
9519 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9520 scoped_ptr
<HttpTransaction
> trans(
9521 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9523 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9524 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9525 EXPECT_EQ(OK
, callback
.WaitForResult());
9527 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9528 ASSERT_TRUE(response
!= NULL
);
9529 ASSERT_TRUE(response
->headers
.get() != NULL
);
9530 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9532 std::string response_data
;
9533 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9534 EXPECT_EQ("hello world", response_data
);
9536 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9538 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9539 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9540 EXPECT_EQ(OK
, callback
.WaitForResult());
9542 response
= trans
->GetResponseInfo();
9543 ASSERT_TRUE(response
!= NULL
);
9544 ASSERT_TRUE(response
->headers
.get() != NULL
);
9545 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9546 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9547 EXPECT_FALSE(response
->was_npn_negotiated
);
9549 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9550 EXPECT_EQ("hello world", response_data
);
9553 class CapturingProxyResolver
: public ProxyResolver
{
9555 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
9556 ~CapturingProxyResolver() override
{}
9558 int GetProxyForURL(const GURL
& url
,
9560 const CompletionCallback
& callback
,
9561 RequestHandle
* request
,
9562 const BoundNetLog
& net_log
) override
{
9563 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9564 HostPortPair("myproxy", 80));
9565 results
->UseProxyServer(proxy_server
);
9566 resolved_
.push_back(url
);
9570 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9572 LoadState
GetLoadState(RequestHandle request
) const override
{
9574 return LOAD_STATE_IDLE
;
9577 void CancelSetPacScript() override
{ NOTREACHED(); }
9579 int SetPacScript(const scoped_refptr
<ProxyResolverScriptData
>&,
9580 const CompletionCallback
& /*callback*/) override
{
9584 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9587 std::vector
<GURL
> resolved_
;
9589 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9592 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9594 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9595 : ProxyResolverFactory(false), resolver_(resolver
) {}
9597 int CreateProxyResolver(
9598 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9599 scoped_ptr
<ProxyResolver
>* resolver
,
9600 const net::CompletionCallback
& callback
,
9601 scoped_ptr
<Request
>* request
) override
{
9602 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9607 ProxyResolver
* resolver_
;
9610 TEST_P(HttpNetworkTransactionTest
,
9611 UseAlternateProtocolForTunneledNpnSpdy
) {
9612 session_deps_
.use_alternate_protocols
= true;
9613 session_deps_
.next_protos
= SpdyNextProtos();
9615 ProxyConfig proxy_config
;
9616 proxy_config
.set_auto_detect(true);
9617 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9619 CapturingProxyResolver capturing_proxy_resolver
;
9620 session_deps_
.proxy_service
.reset(new ProxyService(
9621 new ProxyConfigServiceFixed(proxy_config
),
9623 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9626 session_deps_
.net_log
= &net_log
;
9628 HttpRequestInfo request
;
9629 request
.method
= "GET";
9630 request
.url
= GURL("http://www.example.org/");
9631 request
.load_flags
= 0;
9633 std::string alternate_protocol_http_header
=
9634 GetAlternateProtocolHttpHeader();
9636 MockRead data_reads
[] = {
9637 MockRead("HTTP/1.1 200 OK\r\n"),
9638 MockRead(alternate_protocol_http_header
.c_str()),
9639 MockRead("hello world"),
9640 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9641 MockRead(ASYNC
, OK
),
9644 StaticSocketDataProvider
first_transaction(
9645 data_reads
, arraysize(data_reads
), NULL
, 0);
9646 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9648 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9649 ssl
.SetNextProto(GetParam());
9650 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9651 ASSERT_TRUE(ssl
.cert
.get());
9652 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9654 scoped_ptr
<SpdyFrame
> req(
9655 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9656 MockWrite spdy_writes
[] = {
9658 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9659 "Host: www.example.org\r\n"
9660 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
9661 CreateMockWrite(*req
), // 3
9664 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9666 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9667 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9668 MockRead spdy_reads
[] = {
9669 MockRead(ASYNC
, kCONNECTResponse
, arraysize(kCONNECTResponse
) - 1, 1), // 1
9670 CreateMockRead(*resp
.get(), 4), // 2, 4
9671 CreateMockRead(*data
.get(), 4), // 5
9672 MockRead(ASYNC
, 0, 0, 4), // 6
9675 OrderedSocketData
spdy_data(
9676 spdy_reads
, arraysize(spdy_reads
),
9677 spdy_writes
, arraysize(spdy_writes
));
9678 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9680 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9681 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9683 hanging_non_alternate_protocol_socket
.set_connect_data(
9684 never_finishing_connect
);
9685 session_deps_
.socket_factory
->AddSocketDataProvider(
9686 &hanging_non_alternate_protocol_socket
);
9688 TestCompletionCallback callback
;
9690 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9691 scoped_ptr
<HttpTransaction
> trans(
9692 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9694 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9695 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9696 EXPECT_EQ(OK
, callback
.WaitForResult());
9698 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9699 ASSERT_TRUE(response
!= NULL
);
9700 ASSERT_TRUE(response
->headers
.get() != NULL
);
9701 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9702 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9703 EXPECT_FALSE(response
->was_npn_negotiated
);
9705 std::string response_data
;
9706 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9707 EXPECT_EQ("hello world", response_data
);
9709 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9711 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9712 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9713 EXPECT_EQ(OK
, callback
.WaitForResult());
9715 response
= trans
->GetResponseInfo();
9716 ASSERT_TRUE(response
!= NULL
);
9717 ASSERT_TRUE(response
->headers
.get() != NULL
);
9718 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9719 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9720 EXPECT_TRUE(response
->was_npn_negotiated
);
9722 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9723 EXPECT_EQ("hello!", response_data
);
9724 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9725 EXPECT_EQ("http://www.example.org/",
9726 capturing_proxy_resolver
.resolved()[0].spec());
9727 EXPECT_EQ("https://www.example.org/",
9728 capturing_proxy_resolver
.resolved()[1].spec());
9730 LoadTimingInfo load_timing_info
;
9731 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9732 TestLoadTimingNotReusedWithPac(load_timing_info
,
9733 CONNECT_TIMING_HAS_SSL_TIMES
);
9736 TEST_P(HttpNetworkTransactionTest
,
9737 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9738 session_deps_
.use_alternate_protocols
= true;
9739 session_deps_
.next_protos
= SpdyNextProtos();
9741 HttpRequestInfo request
;
9742 request
.method
= "GET";
9743 request
.url
= GURL("http://www.example.org/");
9744 request
.load_flags
= 0;
9746 std::string alternate_protocol_http_header
=
9747 GetAlternateProtocolHttpHeader();
9749 MockRead data_reads
[] = {
9750 MockRead("HTTP/1.1 200 OK\r\n"),
9751 MockRead(alternate_protocol_http_header
.c_str()),
9752 MockRead("hello world"),
9753 MockRead(ASYNC
, OK
),
9756 StaticSocketDataProvider
first_transaction(
9757 data_reads
, arraysize(data_reads
), NULL
, 0);
9758 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9760 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9761 ssl
.SetNextProto(GetParam());
9762 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9763 ASSERT_TRUE(ssl
.cert
.get());
9764 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9766 scoped_ptr
<SpdyFrame
> req(
9767 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9768 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
9770 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9771 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9772 MockRead spdy_reads
[] = {
9773 CreateMockRead(*resp
),
9774 CreateMockRead(*data
),
9775 MockRead(ASYNC
, 0, 0),
9778 DelayedSocketData
spdy_data(
9779 1, // wait for one write to finish before reading.
9780 spdy_reads
, arraysize(spdy_reads
),
9781 spdy_writes
, arraysize(spdy_writes
));
9782 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9784 TestCompletionCallback callback
;
9786 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9788 scoped_ptr
<HttpTransaction
> trans(
9789 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9791 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9792 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9793 EXPECT_EQ(OK
, callback
.WaitForResult());
9795 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9796 ASSERT_TRUE(response
!= NULL
);
9797 ASSERT_TRUE(response
->headers
.get() != NULL
);
9798 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9800 std::string response_data
;
9801 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9802 EXPECT_EQ("hello world", response_data
);
9804 // Set up an initial SpdySession in the pool to reuse.
9805 HostPortPair
host_port_pair("www.example.org", 443);
9806 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9807 PRIVACY_MODE_DISABLED
);
9808 base::WeakPtr
<SpdySession
> spdy_session
=
9809 CreateSecureSpdySession(session
, key
, BoundNetLog());
9811 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9813 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9814 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9815 EXPECT_EQ(OK
, callback
.WaitForResult());
9817 response
= trans
->GetResponseInfo();
9818 ASSERT_TRUE(response
!= NULL
);
9819 ASSERT_TRUE(response
->headers
.get() != NULL
);
9820 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9821 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9822 EXPECT_TRUE(response
->was_npn_negotiated
);
9824 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9825 EXPECT_EQ("hello!", response_data
);
9828 // GenerateAuthToken is a mighty big test.
9829 // It tests all permutation of GenerateAuthToken behavior:
9830 // - Synchronous and Asynchronous completion.
9831 // - OK or error on completion.
9832 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9833 // - HTTP or HTTPS backend (to include proxy tunneling).
9834 // - Non-authenticating and authenticating backend.
9836 // In all, there are 44 reasonable permuations (for example, if there are
9837 // problems generating an auth token for an authenticating proxy, we don't
9838 // need to test all permutations of the backend server).
9840 // The test proceeds by going over each of the configuration cases, and
9841 // potentially running up to three rounds in each of the tests. The TestConfig
9842 // specifies both the configuration for the test as well as the expectations
9844 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9845 static const char kServer
[] = "http://www.example.com";
9846 static const char kSecureServer
[] = "https://www.example.com";
9847 static const char kProxy
[] = "myproxy:70";
9848 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9856 const MockWrite
kGet(
9857 "GET / HTTP/1.1\r\n"
9858 "Host: www.example.com\r\n"
9859 "Connection: keep-alive\r\n\r\n");
9860 const MockWrite
kGetProxy(
9861 "GET http://www.example.com/ HTTP/1.1\r\n"
9862 "Host: www.example.com\r\n"
9863 "Proxy-Connection: keep-alive\r\n\r\n");
9864 const MockWrite
kGetAuth(
9865 "GET / HTTP/1.1\r\n"
9866 "Host: www.example.com\r\n"
9867 "Connection: keep-alive\r\n"
9868 "Authorization: auth_token\r\n\r\n");
9869 const MockWrite
kGetProxyAuth(
9870 "GET http://www.example.com/ HTTP/1.1\r\n"
9871 "Host: www.example.com\r\n"
9872 "Proxy-Connection: keep-alive\r\n"
9873 "Proxy-Authorization: auth_token\r\n\r\n");
9874 const MockWrite
kGetAuthThroughProxy(
9875 "GET http://www.example.com/ HTTP/1.1\r\n"
9876 "Host: www.example.com\r\n"
9877 "Proxy-Connection: keep-alive\r\n"
9878 "Authorization: auth_token\r\n\r\n");
9879 const MockWrite
kGetAuthWithProxyAuth(
9880 "GET http://www.example.com/ HTTP/1.1\r\n"
9881 "Host: www.example.com\r\n"
9882 "Proxy-Connection: keep-alive\r\n"
9883 "Proxy-Authorization: auth_token\r\n"
9884 "Authorization: auth_token\r\n\r\n");
9885 const MockWrite
kConnect(
9886 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9887 "Host: www.example.com\r\n"
9888 "Proxy-Connection: keep-alive\r\n\r\n");
9889 const MockWrite
kConnectProxyAuth(
9890 "CONNECT www.example.com:443 HTTP/1.1\r\n"
9891 "Host: www.example.com\r\n"
9892 "Proxy-Connection: keep-alive\r\n"
9893 "Proxy-Authorization: auth_token\r\n\r\n");
9895 const MockRead
kSuccess(
9896 "HTTP/1.1 200 OK\r\n"
9897 "Content-Type: text/html; charset=iso-8859-1\r\n"
9898 "Content-Length: 3\r\n\r\n"
9900 const MockRead
kFailure(
9901 "Should not be called.");
9902 const MockRead
kServerChallenge(
9903 "HTTP/1.1 401 Unauthorized\r\n"
9904 "WWW-Authenticate: Mock realm=server\r\n"
9905 "Content-Type: text/html; charset=iso-8859-1\r\n"
9906 "Content-Length: 14\r\n\r\n"
9907 "Unauthorized\r\n");
9908 const MockRead
kProxyChallenge(
9909 "HTTP/1.1 407 Unauthorized\r\n"
9910 "Proxy-Authenticate: Mock realm=proxy\r\n"
9911 "Proxy-Connection: close\r\n"
9912 "Content-Type: text/html; charset=iso-8859-1\r\n"
9913 "Content-Length: 14\r\n\r\n"
9914 "Unauthorized\r\n");
9915 const MockRead
kProxyConnected(
9916 "HTTP/1.1 200 Connection Established\r\n\r\n");
9918 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
9919 // no constructors, but the C++ compiler on Windows warns about
9920 // unspecified data in compound literals. So, moved to using constructors,
9921 // and TestRound's created with the default constructor should not be used.
9924 : expected_rv(ERR_UNEXPECTED
),
9928 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9929 int expected_rv_arg
)
9932 expected_rv(expected_rv_arg
),
9936 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
9937 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
9938 const MockRead
* extra_read_arg
)
9941 expected_rv(expected_rv_arg
),
9942 extra_write(extra_write_arg
),
9943 extra_read(extra_read_arg
) {
9948 const MockWrite
* extra_write
;
9949 const MockRead
* extra_read
;
9952 static const int kNoSSL
= 500;
9955 const char* const proxy_url
;
9956 AuthTiming proxy_auth_timing
;
9958 const char* const server_url
;
9959 AuthTiming server_auth_timing
;
9961 int num_auth_rounds
;
9962 int first_ssl_round
;
9963 TestRound rounds
[3];
9964 } test_configs
[] = {
9965 // Non-authenticating HTTP server with a direct connection.
9966 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9967 { TestRound(kGet
, kSuccess
, OK
)}},
9968 // Authenticating HTTP server with a direct connection.
9969 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9970 { TestRound(kGet
, kServerChallenge
, OK
),
9971 TestRound(kGetAuth
, kSuccess
, OK
)}},
9972 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9973 { TestRound(kGet
, kServerChallenge
, OK
),
9974 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9975 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9976 { TestRound(kGet
, kServerChallenge
, OK
),
9977 TestRound(kGetAuth
, kSuccess
, OK
)}},
9978 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9979 { TestRound(kGet
, kServerChallenge
, OK
),
9980 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
9981 // Non-authenticating HTTP server through a non-authenticating proxy.
9982 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
9983 { TestRound(kGetProxy
, kSuccess
, OK
)}},
9984 // Authenticating HTTP server through a non-authenticating proxy.
9985 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
9986 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9987 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9988 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
9989 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9990 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9991 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
9992 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9993 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
9994 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
9995 { TestRound(kGetProxy
, kServerChallenge
, OK
),
9996 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
9997 // Non-authenticating HTTP server through an authenticating proxy.
9998 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
9999 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10000 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10001 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10002 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10003 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10004 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10005 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10006 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10007 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10008 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10009 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10010 // Authenticating HTTP server through an authenticating proxy.
10011 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10012 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10013 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10014 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10015 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10016 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10017 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10018 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10019 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10020 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10021 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10022 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10023 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10024 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10025 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10026 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10027 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10028 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10029 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10030 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10031 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10032 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10033 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10034 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10035 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10036 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10037 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10038 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10039 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10040 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10041 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10042 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10043 // Non-authenticating HTTPS server with a direct connection.
10044 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10045 { TestRound(kGet
, kSuccess
, OK
)}},
10046 // Authenticating HTTPS server with a direct connection.
10047 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10048 { TestRound(kGet
, kServerChallenge
, OK
),
10049 TestRound(kGetAuth
, kSuccess
, OK
)}},
10050 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10051 { TestRound(kGet
, kServerChallenge
, OK
),
10052 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10053 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10054 { TestRound(kGet
, kServerChallenge
, OK
),
10055 TestRound(kGetAuth
, kSuccess
, OK
)}},
10056 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10057 { TestRound(kGet
, kServerChallenge
, OK
),
10058 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10059 // Non-authenticating HTTPS server with a non-authenticating proxy.
10060 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10061 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10062 // Authenticating HTTPS server through a non-authenticating proxy.
10063 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10064 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10065 TestRound(kGetAuth
, kSuccess
, OK
)}},
10066 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10067 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10068 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10069 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10070 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10071 TestRound(kGetAuth
, kSuccess
, OK
)}},
10072 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10073 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10074 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10075 // Non-Authenticating HTTPS server through an authenticating proxy.
10076 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10077 { TestRound(kConnect
, kProxyChallenge
, OK
),
10078 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10079 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10080 { TestRound(kConnect
, kProxyChallenge
, OK
),
10081 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10082 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10083 { TestRound(kConnect
, kProxyChallenge
, OK
),
10084 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10085 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10086 { TestRound(kConnect
, kProxyChallenge
, OK
),
10087 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10088 // Authenticating HTTPS server through an authenticating proxy.
10089 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10090 { TestRound(kConnect
, kProxyChallenge
, OK
),
10091 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10092 &kGet
, &kServerChallenge
),
10093 TestRound(kGetAuth
, kSuccess
, OK
)}},
10094 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10095 { TestRound(kConnect
, kProxyChallenge
, OK
),
10096 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10097 &kGet
, &kServerChallenge
),
10098 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10099 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10100 { TestRound(kConnect
, kProxyChallenge
, OK
),
10101 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10102 &kGet
, &kServerChallenge
),
10103 TestRound(kGetAuth
, kSuccess
, OK
)}},
10104 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10105 { TestRound(kConnect
, kProxyChallenge
, OK
),
10106 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10107 &kGet
, &kServerChallenge
),
10108 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10109 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10110 { TestRound(kConnect
, kProxyChallenge
, OK
),
10111 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10112 &kGet
, &kServerChallenge
),
10113 TestRound(kGetAuth
, kSuccess
, OK
)}},
10114 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10115 { TestRound(kConnect
, kProxyChallenge
, OK
),
10116 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10117 &kGet
, &kServerChallenge
),
10118 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10119 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10120 { TestRound(kConnect
, kProxyChallenge
, OK
),
10121 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10122 &kGet
, &kServerChallenge
),
10123 TestRound(kGetAuth
, kSuccess
, OK
)}},
10124 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10125 { TestRound(kConnect
, kProxyChallenge
, OK
),
10126 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10127 &kGet
, &kServerChallenge
),
10128 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10131 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10132 HttpAuthHandlerMock::Factory
* auth_factory(
10133 new HttpAuthHandlerMock::Factory());
10134 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10135 const TestConfig
& test_config
= test_configs
[i
];
10137 // Set up authentication handlers as necessary.
10138 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10139 for (int n
= 0; n
< 2; n
++) {
10140 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10141 std::string auth_challenge
= "Mock realm=proxy";
10142 GURL
origin(test_config
.proxy_url
);
10143 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10144 auth_challenge
.end());
10145 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10146 origin
, BoundNetLog());
10147 auth_handler
->SetGenerateExpectation(
10148 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10149 test_config
.proxy_auth_rv
);
10150 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10153 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10154 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10155 std::string auth_challenge
= "Mock realm=server";
10156 GURL
origin(test_config
.server_url
);
10157 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10158 auth_challenge
.end());
10159 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10160 origin
, BoundNetLog());
10161 auth_handler
->SetGenerateExpectation(
10162 test_config
.server_auth_timing
== AUTH_ASYNC
,
10163 test_config
.server_auth_rv
);
10164 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10166 if (test_config
.proxy_url
) {
10167 session_deps_
.proxy_service
.reset(
10168 ProxyService::CreateFixed(test_config
.proxy_url
));
10170 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10173 HttpRequestInfo request
;
10174 request
.method
= "GET";
10175 request
.url
= GURL(test_config
.server_url
);
10176 request
.load_flags
= 0;
10178 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10179 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10181 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10182 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10184 // Set up expected reads and writes.
10186 reads
[0] = read_write_round
.read
;
10187 size_t length_reads
= 1;
10188 if (read_write_round
.extra_read
) {
10189 reads
[1] = *read_write_round
.extra_read
;
10193 MockWrite writes
[2];
10194 writes
[0] = read_write_round
.write
;
10195 size_t length_writes
= 1;
10196 if (read_write_round
.extra_write
) {
10197 writes
[1] = *read_write_round
.extra_write
;
10200 StaticSocketDataProvider
data_provider(
10201 reads
, length_reads
, writes
, length_writes
);
10202 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10204 // Add an SSL sequence if necessary.
10205 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10206 if (round
>= test_config
.first_ssl_round
)
10207 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10208 &ssl_socket_data_provider
);
10210 // Start or restart the transaction.
10211 TestCompletionCallback callback
;
10214 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10216 rv
= trans
.RestartWithAuth(
10217 AuthCredentials(kFoo
, kBar
), callback
.callback());
10219 if (rv
== ERR_IO_PENDING
)
10220 rv
= callback
.WaitForResult();
10222 // Compare results with expected data.
10223 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10224 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10225 if (read_write_round
.expected_rv
== OK
) {
10226 ASSERT_TRUE(response
!= NULL
);
10228 EXPECT_TRUE(response
== NULL
);
10229 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10232 if (round
+ 1 < test_config
.num_auth_rounds
) {
10233 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10235 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10241 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10242 // Do multi-round authentication and make sure it works correctly.
10243 HttpAuthHandlerMock::Factory
* auth_factory(
10244 new HttpAuthHandlerMock::Factory());
10245 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10246 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10247 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10248 session_deps_
.host_resolver
->set_synchronous_mode(true);
10250 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10251 auth_handler
->set_connection_based(true);
10252 std::string auth_challenge
= "Mock realm=server";
10253 GURL
origin("http://www.example.com");
10254 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10255 auth_challenge
.end());
10256 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10257 origin
, BoundNetLog());
10258 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10261 const HttpResponseInfo
* response
= NULL
;
10262 HttpRequestInfo request
;
10263 request
.method
= "GET";
10264 request
.url
= origin
;
10265 request
.load_flags
= 0;
10267 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10269 // Use a TCP Socket Pool with only one connection per group. This is used
10270 // to validate that the TCP socket is not released to the pool between
10271 // each round of multi-round authentication.
10272 HttpNetworkSessionPeer
session_peer(session
);
10273 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10274 50, // Max sockets for pool
10275 1, // Max sockets per group
10276 session_deps_
.host_resolver
.get(),
10277 session_deps_
.socket_factory
.get(),
10278 session_deps_
.net_log
);
10279 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10280 new MockClientSocketPoolManager
);
10281 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10282 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10284 scoped_ptr
<HttpTransaction
> trans(
10285 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10286 TestCompletionCallback callback
;
10288 const MockWrite
kGet(
10289 "GET / HTTP/1.1\r\n"
10290 "Host: www.example.com\r\n"
10291 "Connection: keep-alive\r\n\r\n");
10292 const MockWrite
kGetAuth(
10293 "GET / HTTP/1.1\r\n"
10294 "Host: www.example.com\r\n"
10295 "Connection: keep-alive\r\n"
10296 "Authorization: auth_token\r\n\r\n");
10298 const MockRead
kServerChallenge(
10299 "HTTP/1.1 401 Unauthorized\r\n"
10300 "WWW-Authenticate: Mock realm=server\r\n"
10301 "Content-Type: text/html; charset=iso-8859-1\r\n"
10302 "Content-Length: 14\r\n\r\n"
10303 "Unauthorized\r\n");
10304 const MockRead
kSuccess(
10305 "HTTP/1.1 200 OK\r\n"
10306 "Content-Type: text/html; charset=iso-8859-1\r\n"
10307 "Content-Length: 3\r\n\r\n"
10310 MockWrite writes
[] = {
10319 // Competing request
10322 MockRead reads
[] = {
10331 // Competing response
10334 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10335 writes
, arraysize(writes
));
10336 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10338 const char kSocketGroup
[] = "www.example.com:80";
10340 // First round of authentication.
10341 auth_handler
->SetGenerateExpectation(false, OK
);
10342 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10343 if (rv
== ERR_IO_PENDING
)
10344 rv
= callback
.WaitForResult();
10346 response
= trans
->GetResponseInfo();
10347 ASSERT_TRUE(response
!= NULL
);
10348 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10349 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10351 // In between rounds, another request comes in for the same domain.
10352 // It should not be able to grab the TCP socket that trans has already
10354 scoped_ptr
<HttpTransaction
> trans_compete(
10355 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10356 TestCompletionCallback callback_compete
;
10357 rv
= trans_compete
->Start(
10358 &request
, callback_compete
.callback(), BoundNetLog());
10359 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10360 // callback_compete.WaitForResult at this point would stall forever,
10361 // since the HttpNetworkTransaction does not release the request back to
10362 // the pool until after authentication completes.
10364 // Second round of authentication.
10365 auth_handler
->SetGenerateExpectation(false, OK
);
10366 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10367 if (rv
== ERR_IO_PENDING
)
10368 rv
= callback
.WaitForResult();
10370 response
= trans
->GetResponseInfo();
10371 ASSERT_TRUE(response
!= NULL
);
10372 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10373 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10375 // Third round of authentication.
10376 auth_handler
->SetGenerateExpectation(false, OK
);
10377 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10378 if (rv
== ERR_IO_PENDING
)
10379 rv
= callback
.WaitForResult();
10381 response
= trans
->GetResponseInfo();
10382 ASSERT_TRUE(response
!= NULL
);
10383 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10384 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10386 // Fourth round of authentication, which completes successfully.
10387 auth_handler
->SetGenerateExpectation(false, OK
);
10388 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10389 if (rv
== ERR_IO_PENDING
)
10390 rv
= callback
.WaitForResult();
10392 response
= trans
->GetResponseInfo();
10393 ASSERT_TRUE(response
!= NULL
);
10394 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10395 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10397 // Read the body since the fourth round was successful. This will also
10398 // release the socket back to the pool.
10399 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10400 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10401 if (rv
== ERR_IO_PENDING
)
10402 rv
= callback
.WaitForResult();
10404 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10406 // There are still 0 idle sockets, since the trans_compete transaction
10407 // will be handed it immediately after trans releases it to the group.
10408 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10410 // The competing request can now finish. Wait for the headers and then
10412 rv
= callback_compete
.WaitForResult();
10414 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10415 if (rv
== ERR_IO_PENDING
)
10416 rv
= callback
.WaitForResult();
10418 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10421 // Finally, the socket is released to the group.
10422 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10425 // This tests the case that a request is issued via http instead of spdy after
10426 // npn is negotiated.
10427 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10428 session_deps_
.use_alternate_protocols
= true;
10429 NextProtoVector next_protos
;
10430 next_protos
.push_back(kProtoHTTP11
);
10431 session_deps_
.next_protos
= next_protos
;
10433 HttpRequestInfo request
;
10434 request
.method
= "GET";
10435 request
.url
= GURL("https://www.example.org/");
10436 request
.load_flags
= 0;
10438 MockWrite data_writes
[] = {
10440 "GET / HTTP/1.1\r\n"
10441 "Host: www.example.org\r\n"
10442 "Connection: keep-alive\r\n\r\n"),
10445 std::string alternate_protocol_http_header
=
10446 GetAlternateProtocolHttpHeader();
10448 MockRead data_reads
[] = {
10449 MockRead("HTTP/1.1 200 OK\r\n"),
10450 MockRead(alternate_protocol_http_header
.c_str()),
10451 MockRead("hello world"),
10452 MockRead(SYNCHRONOUS
, OK
),
10455 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10456 ssl
.SetNextProto(kProtoHTTP11
);
10458 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10460 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10461 data_writes
, arraysize(data_writes
));
10462 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10464 TestCompletionCallback callback
;
10466 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10467 scoped_ptr
<HttpTransaction
> trans(
10468 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10470 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10472 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10473 EXPECT_EQ(OK
, callback
.WaitForResult());
10475 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10476 ASSERT_TRUE(response
!= NULL
);
10477 ASSERT_TRUE(response
->headers
.get() != NULL
);
10478 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10480 std::string response_data
;
10481 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10482 EXPECT_EQ("hello world", response_data
);
10484 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10485 EXPECT_TRUE(response
->was_npn_negotiated
);
10488 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10489 // Simulate the SSL handshake completing with an NPN negotiation
10490 // followed by an immediate server closing of the socket.
10491 // Fix crash: http://crbug.com/46369
10492 session_deps_
.use_alternate_protocols
= true;
10493 session_deps_
.next_protos
= SpdyNextProtos();
10495 HttpRequestInfo request
;
10496 request
.method
= "GET";
10497 request
.url
= GURL("https://www.example.org/");
10498 request
.load_flags
= 0;
10500 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10501 ssl
.SetNextProto(GetParam());
10502 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10504 scoped_ptr
<SpdyFrame
> req(
10505 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10506 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
10508 MockRead spdy_reads
[] = {
10509 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10512 DelayedSocketData
spdy_data(
10513 0, // don't wait in this case, immediate hangup.
10514 spdy_reads
, arraysize(spdy_reads
),
10515 spdy_writes
, arraysize(spdy_writes
));
10516 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10518 TestCompletionCallback callback
;
10520 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10521 scoped_ptr
<HttpTransaction
> trans(
10522 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10524 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10525 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10526 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10529 // A subclass of HttpAuthHandlerMock that records the request URL when
10530 // it gets it. This is needed since the auth handler may get destroyed
10531 // before we get a chance to query it.
10532 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10534 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10536 ~UrlRecordingHttpAuthHandlerMock() override
{}
10539 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10540 const HttpRequestInfo
* request
,
10541 const CompletionCallback
& callback
,
10542 std::string
* auth_token
) override
{
10543 *url_
= request
->url
;
10544 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10545 credentials
, request
, callback
, auth_token
);
10552 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10553 // This test ensures that the URL passed into the proxy is upgraded
10554 // to https when doing an Alternate Protocol upgrade.
10555 session_deps_
.use_alternate_protocols
= true;
10556 session_deps_
.next_protos
= SpdyNextProtos();
10558 session_deps_
.proxy_service
.reset(
10559 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10560 TestNetLog net_log
;
10561 session_deps_
.net_log
= &net_log
;
10564 HttpAuthHandlerMock::Factory
* auth_factory
=
10565 new HttpAuthHandlerMock::Factory();
10566 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10567 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10568 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10569 auth_factory
->set_do_init_from_challenge(true);
10570 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10573 HttpRequestInfo request
;
10574 request
.method
= "GET";
10575 request
.url
= GURL("http://www.example.org");
10576 request
.load_flags
= 0;
10578 // First round goes unauthenticated through the proxy.
10579 MockWrite data_writes_1
[] = {
10581 "GET http://www.example.org/ HTTP/1.1\r\n"
10582 "Host: www.example.org\r\n"
10583 "Proxy-Connection: keep-alive\r\n"
10586 MockRead data_reads_1
[] = {
10587 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10588 MockRead("HTTP/1.1 200 OK\r\n"),
10589 MockRead("Alternate-Protocol: 443:"),
10590 MockRead(GetAlternateProtocolFromParam()),
10592 MockRead("Proxy-Connection: close\r\n"),
10595 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10596 data_writes_1
, arraysize(data_writes_1
));
10598 // Second round tries to tunnel to www.example.org due to the
10599 // Alternate-Protocol announcement in the first round. It fails due
10600 // to a proxy authentication challenge.
10601 // After the failure, a tunnel is established to www.example.org using
10602 // Proxy-Authorization headers. There is then a SPDY request round.
10604 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10605 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10606 // does a Disconnect and Connect on the same socket, rather than trying
10607 // to obtain a new one.
10609 // NOTE: Originally, the proxy response to the second CONNECT request
10610 // simply returned another 407 so the unit test could skip the SSL connection
10611 // establishment and SPDY framing issues. Alas, the
10612 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10613 // complicated to set up expectations for than the SPDY session.
10615 scoped_ptr
<SpdyFrame
> req(
10616 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10617 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10618 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10620 MockWrite data_writes_2
[] = {
10621 // First connection attempt without Proxy-Authorization.
10623 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10624 "Host: www.example.org\r\n"
10625 "Proxy-Connection: keep-alive\r\n"
10628 // Second connection attempt with Proxy-Authorization.
10630 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10631 "Host: www.example.org\r\n"
10632 "Proxy-Connection: keep-alive\r\n"
10633 "Proxy-Authorization: auth_token\r\n"
10637 CreateMockWrite(*req
),
10639 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10640 "Proxy-Authenticate: Mock\r\n"
10641 "Proxy-Connection: close\r\n"
10643 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10644 MockRead data_reads_2
[] = {
10645 // First connection attempt fails
10646 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
, 1),
10647 MockRead(ASYNC
, kRejectConnectResponse
,
10648 arraysize(kRejectConnectResponse
) - 1, 1),
10650 // Second connection attempt passes
10651 MockRead(ASYNC
, kAcceptConnectResponse
,
10652 arraysize(kAcceptConnectResponse
) -1, 4),
10655 CreateMockRead(*resp
.get(), 6),
10656 CreateMockRead(*data
.get(), 6),
10657 MockRead(ASYNC
, 0, 0, 6),
10659 OrderedSocketData
data_2(
10660 data_reads_2
, arraysize(data_reads_2
),
10661 data_writes_2
, arraysize(data_writes_2
));
10663 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10664 ssl
.SetNextProto(GetParam());
10665 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10666 ASSERT_TRUE(ssl
.cert
.get());
10668 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10669 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10671 hanging_non_alternate_protocol_socket
.set_connect_data(
10672 never_finishing_connect
);
10674 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10675 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10676 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10677 session_deps_
.socket_factory
->AddSocketDataProvider(
10678 &hanging_non_alternate_protocol_socket
);
10679 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10681 // First round should work and provide the Alternate-Protocol state.
10682 TestCompletionCallback callback_1
;
10683 scoped_ptr
<HttpTransaction
> trans_1(
10684 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10685 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10686 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10687 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10689 // Second round should attempt a tunnel connect and get an auth challenge.
10690 TestCompletionCallback callback_2
;
10691 scoped_ptr
<HttpTransaction
> trans_2(
10692 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10693 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10694 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10695 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10696 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10697 ASSERT_TRUE(response
!= NULL
);
10698 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10700 // Restart with auth. Tunnel should work and response received.
10701 TestCompletionCallback callback_3
;
10702 rv
= trans_2
->RestartWithAuth(
10703 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10705 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10707 // After all that work, these two lines (or actually, just the scheme) are
10708 // what this test is all about. Make sure it happens correctly.
10709 EXPECT_EQ("https", request_url
.scheme());
10710 EXPECT_EQ("www.example.org", request_url
.host());
10712 LoadTimingInfo load_timing_info
;
10713 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10714 TestLoadTimingNotReusedWithPac(load_timing_info
,
10715 CONNECT_TIMING_HAS_SSL_TIMES
);
10718 // Test that if we cancel the transaction as the connection is completing, that
10719 // everything tears down correctly.
10720 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10721 // Setup everything about the connection to complete synchronously, so that
10722 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10723 // for is the callback from the HttpStreamRequest.
10724 // Then cancel the transaction.
10725 // Verify that we don't crash.
10726 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10727 MockRead data_reads
[] = {
10728 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10729 MockRead(SYNCHRONOUS
, "hello world"),
10730 MockRead(SYNCHRONOUS
, OK
),
10733 HttpRequestInfo request
;
10734 request
.method
= "GET";
10735 request
.url
= GURL("http://www.example.org/");
10736 request
.load_flags
= 0;
10738 session_deps_
.host_resolver
->set_synchronous_mode(true);
10739 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10740 scoped_ptr
<HttpTransaction
> trans(
10741 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10743 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10744 data
.set_connect_data(mock_connect
);
10745 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10747 TestCompletionCallback callback
;
10749 BoundTestNetLog log
;
10750 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10751 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10752 trans
.reset(); // Cancel the transaction here.
10754 base::MessageLoop::current()->RunUntilIdle();
10757 // Test that if a transaction is cancelled after receiving the headers, the
10758 // stream is drained properly and added back to the socket pool. The main
10759 // purpose of this test is to make sure that an HttpStreamParser can be read
10760 // from after the HttpNetworkTransaction and the objects it owns have been
10762 // See http://crbug.com/368418
10763 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10764 MockRead data_reads
[] = {
10765 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10766 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10767 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10768 MockRead(ASYNC
, "1"),
10769 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10770 // HttpNetworkTransaction has been deleted.
10771 MockRead(ASYNC
, "2"),
10772 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10774 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10775 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10777 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10780 HttpRequestInfo request
;
10781 request
.method
= "GET";
10782 request
.url
= GURL("http://www.example.org/");
10783 request
.load_flags
= 0;
10785 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10786 TestCompletionCallback callback
;
10788 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10789 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10790 callback
.WaitForResult();
10792 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10793 ASSERT_TRUE(response
!= NULL
);
10794 EXPECT_TRUE(response
->headers
.get() != NULL
);
10795 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10797 // The transaction and HttpRequestInfo are deleted.
10800 // Let the HttpResponseBodyDrainer drain the socket.
10801 base::MessageLoop::current()->RunUntilIdle();
10803 // Socket should now be idle, waiting to be reused.
10804 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10807 // Test a basic GET request through a proxy.
10808 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10809 session_deps_
.proxy_service
.reset(
10810 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10811 BoundTestNetLog log
;
10812 session_deps_
.net_log
= log
.bound().net_log();
10813 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10815 HttpRequestInfo request
;
10816 request
.method
= "GET";
10817 request
.url
= GURL("http://www.example.org/");
10819 MockWrite data_writes1
[] = {
10821 "GET http://www.example.org/ HTTP/1.1\r\n"
10822 "Host: www.example.org\r\n"
10823 "Proxy-Connection: keep-alive\r\n\r\n"),
10826 MockRead data_reads1
[] = {
10827 MockRead("HTTP/1.1 200 OK\r\n"),
10828 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10829 MockRead("Content-Length: 100\r\n\r\n"),
10830 MockRead(SYNCHRONOUS
, OK
),
10833 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10834 data_writes1
, arraysize(data_writes1
));
10835 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10837 TestCompletionCallback callback1
;
10839 scoped_ptr
<HttpTransaction
> trans(
10840 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10841 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10842 trans
->SetBeforeProxyHeadersSentCallback(
10843 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10844 base::Unretained(&proxy_headers_handler
)));
10846 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10847 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10849 rv
= callback1
.WaitForResult();
10852 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10853 ASSERT_TRUE(response
!= NULL
);
10855 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10856 EXPECT_EQ(200, response
->headers
->response_code());
10857 EXPECT_EQ(100, response
->headers
->GetContentLength());
10858 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10860 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10861 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
10862 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
10863 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10865 LoadTimingInfo load_timing_info
;
10866 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10867 TestLoadTimingNotReusedWithPac(load_timing_info
,
10868 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
10871 // Test a basic HTTPS GET request through a proxy.
10872 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
10873 session_deps_
.proxy_service
.reset(
10874 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10875 BoundTestNetLog log
;
10876 session_deps_
.net_log
= log
.bound().net_log();
10877 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10879 HttpRequestInfo request
;
10880 request
.method
= "GET";
10881 request
.url
= GURL("https://www.example.org/");
10883 // Since we have proxy, should try to establish tunnel.
10884 MockWrite data_writes1
[] = {
10886 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10887 "Host: www.example.org\r\n"
10888 "Proxy-Connection: keep-alive\r\n\r\n"),
10891 "GET / HTTP/1.1\r\n"
10892 "Host: www.example.org\r\n"
10893 "Connection: keep-alive\r\n\r\n"),
10896 MockRead data_reads1
[] = {
10897 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10899 MockRead("HTTP/1.1 200 OK\r\n"),
10900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10901 MockRead("Content-Length: 100\r\n\r\n"),
10902 MockRead(SYNCHRONOUS
, OK
),
10905 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10906 data_writes1
, arraysize(data_writes1
));
10907 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10908 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10909 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10911 TestCompletionCallback callback1
;
10913 scoped_ptr
<HttpTransaction
> trans(
10914 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10916 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10917 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10919 rv
= callback1
.WaitForResult();
10921 CapturedNetLogEntry::List entries
;
10922 log
.GetEntries(&entries
);
10923 size_t pos
= ExpectLogContainsSomewhere(
10924 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10925 NetLog::PHASE_NONE
);
10926 ExpectLogContainsSomewhere(
10928 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
10929 NetLog::PHASE_NONE
);
10931 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10932 ASSERT_TRUE(response
!= NULL
);
10934 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10935 EXPECT_EQ(200, response
->headers
->response_code());
10936 EXPECT_EQ(100, response
->headers
->GetContentLength());
10937 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
10938 EXPECT_TRUE(response
->was_fetched_via_proxy
);
10940 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
10942 LoadTimingInfo load_timing_info
;
10943 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
10944 TestLoadTimingNotReusedWithPac(load_timing_info
,
10945 CONNECT_TIMING_HAS_SSL_TIMES
);
10948 // Test a basic HTTPS GET request through a proxy, but the server hangs up
10949 // while establishing the tunnel.
10950 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
10951 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
10952 BoundTestNetLog log
;
10953 session_deps_
.net_log
= log
.bound().net_log();
10954 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10956 HttpRequestInfo request
;
10957 request
.method
= "GET";
10958 request
.url
= GURL("https://www.example.org/");
10960 // Since we have proxy, should try to establish tunnel.
10961 MockWrite data_writes1
[] = {
10963 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10964 "Host: www.example.org\r\n"
10965 "Proxy-Connection: keep-alive\r\n\r\n"),
10968 "GET / HTTP/1.1\r\n"
10969 "Host: www.example.org\r\n"
10970 "Connection: keep-alive\r\n\r\n"),
10973 MockRead data_reads1
[] = {
10974 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10975 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
10976 MockRead(ASYNC
, 0, 0), // EOF
10979 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10980 data_writes1
, arraysize(data_writes1
));
10981 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10982 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10983 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10985 TestCompletionCallback callback1
;
10987 scoped_ptr
<HttpTransaction
> trans(
10988 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10990 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10991 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10993 rv
= callback1
.WaitForResult();
10994 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
10995 CapturedNetLogEntry::List entries
;
10996 log
.GetEntries(&entries
);
10997 size_t pos
= ExpectLogContainsSomewhere(
10998 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
10999 NetLog::PHASE_NONE
);
11000 ExpectLogContainsSomewhere(
11002 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11003 NetLog::PHASE_NONE
);
11006 // Test for crbug.com/55424.
11007 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
11008 scoped_ptr
<SpdyFrame
> req(
11009 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11010 MockWrite spdy_writes
[] = { CreateMockWrite(*req
) };
11012 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11013 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11014 MockRead spdy_reads
[] = {
11015 CreateMockRead(*resp
),
11016 CreateMockRead(*data
),
11017 MockRead(ASYNC
, 0, 0),
11020 DelayedSocketData
spdy_data(
11021 1, // wait for one write to finish before reading.
11022 spdy_reads
, arraysize(spdy_reads
),
11023 spdy_writes
, arraysize(spdy_writes
));
11024 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11026 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11027 ssl
.SetNextProto(GetParam());
11028 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11030 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11032 // Set up an initial SpdySession in the pool to reuse.
11033 HostPortPair
host_port_pair("www.example.org", 443);
11034 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11035 PRIVACY_MODE_DISABLED
);
11036 base::WeakPtr
<SpdySession
> spdy_session
=
11037 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11039 HttpRequestInfo request
;
11040 request
.method
= "GET";
11041 request
.url
= GURL("https://www.example.org/");
11042 request
.load_flags
= 0;
11044 // This is the important line that marks this as a preconnect.
11045 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11047 scoped_ptr
<HttpTransaction
> trans(
11048 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11050 TestCompletionCallback callback
;
11051 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11052 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11053 EXPECT_EQ(OK
, callback
.WaitForResult());
11056 // Given a net error, cause that error to be returned from the first Write()
11057 // call and verify that the HttpTransaction fails with that error.
11058 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11059 int error
, IoMode mode
) {
11060 HttpRequestInfo request_info
;
11061 request_info
.url
= GURL("https://www.example.com/");
11062 request_info
.method
= "GET";
11063 request_info
.load_flags
= LOAD_NORMAL
;
11065 SSLSocketDataProvider
ssl_data(mode
, OK
);
11066 MockWrite data_writes
[] = {
11067 MockWrite(mode
, error
),
11069 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11070 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11071 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11073 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11074 scoped_ptr
<HttpTransaction
> trans(
11075 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11077 TestCompletionCallback callback
;
11078 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11079 if (rv
== ERR_IO_PENDING
)
11080 rv
= callback
.WaitForResult();
11081 ASSERT_EQ(error
, rv
);
11084 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11085 // Just check a grab bag of cert errors.
11086 static const int kErrors
[] = {
11087 ERR_CERT_COMMON_NAME_INVALID
,
11088 ERR_CERT_AUTHORITY_INVALID
,
11089 ERR_CERT_DATE_INVALID
,
11091 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11092 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11093 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11097 // Ensure that a client certificate is removed from the SSL client auth
11099 // 1) No proxy is involved.
11100 // 2) TLS False Start is disabled.
11101 // 3) The initial TLS handshake requests a client certificate.
11102 // 4) The client supplies an invalid/unacceptable certificate.
11103 TEST_P(HttpNetworkTransactionTest
,
11104 ClientAuthCertCache_Direct_NoFalseStart
) {
11105 HttpRequestInfo request_info
;
11106 request_info
.url
= GURL("https://www.example.com/");
11107 request_info
.method
= "GET";
11108 request_info
.load_flags
= LOAD_NORMAL
;
11110 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11111 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11113 // [ssl_]data1 contains the data for the first SSL handshake. When a
11114 // CertificateRequest is received for the first time, the handshake will
11115 // be aborted to allow the caller to provide a certificate.
11116 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11117 ssl_data1
.cert_request_info
= cert_request
.get();
11118 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11119 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11120 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11122 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11123 // False Start is not being used, the result of the SSL handshake will be
11124 // returned as part of the SSLClientSocket::Connect() call. This test
11125 // matches the result of a server sending a handshake_failure alert,
11126 // rather than a Finished message, because it requires a client
11127 // certificate and none was supplied.
11128 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11129 ssl_data2
.cert_request_info
= cert_request
.get();
11130 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11131 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11132 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11134 // [ssl_]data3 contains the data for the third SSL handshake. When a
11135 // connection to a server fails during an SSL handshake,
11136 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11137 // connection was attempted with TLSv1.1. This is transparent to the caller
11138 // of the HttpNetworkTransaction. Because this test failure is due to
11139 // requiring a client certificate, this fallback handshake should also
11141 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11142 ssl_data3
.cert_request_info
= cert_request
.get();
11143 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11144 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11145 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11147 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11148 // connection to a server fails during an SSL handshake,
11149 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
11150 // connection was attempted with TLSv1. This is transparent to the caller
11151 // of the HttpNetworkTransaction. Because this test failure is due to
11152 // requiring a client certificate, this fallback handshake should also
11154 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11155 ssl_data4
.cert_request_info
= cert_request
.get();
11156 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11157 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11158 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11160 // Need one more if TLSv1.2 is enabled.
11161 SSLSocketDataProvider
ssl_data5(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11162 ssl_data5
.cert_request_info
= cert_request
.get();
11163 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11164 StaticSocketDataProvider
data5(NULL
, 0, NULL
, 0);
11165 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11167 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11168 scoped_ptr
<HttpTransaction
> trans(
11169 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11171 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11172 TestCompletionCallback callback
;
11173 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11174 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11176 // Complete the SSL handshake, which should abort due to requiring a
11177 // client certificate.
11178 rv
= callback
.WaitForResult();
11179 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11181 // Indicate that no certificate should be supplied. From the perspective
11182 // of SSLClientCertCache, NULL is just as meaningful as a real
11183 // certificate, so this is the same as supply a
11184 // legitimate-but-unacceptable certificate.
11185 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11186 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11188 // Ensure the certificate was added to the client auth cache before
11189 // allowing the connection to continue restarting.
11190 scoped_refptr
<X509Certificate
> client_cert
;
11191 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11192 HostPortPair("www.example.com", 443), &client_cert
));
11193 ASSERT_EQ(NULL
, client_cert
.get());
11195 // Restart the handshake. This will consume ssl_data2, which fails, and
11196 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11197 // The result code is checked against what ssl_data4 should return.
11198 rv
= callback
.WaitForResult();
11199 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11201 // Ensure that the client certificate is removed from the cache on a
11202 // handshake failure.
11203 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11204 HostPortPair("www.example.com", 443), &client_cert
));
11207 // Ensure that a client certificate is removed from the SSL client auth
11209 // 1) No proxy is involved.
11210 // 2) TLS False Start is enabled.
11211 // 3) The initial TLS handshake requests a client certificate.
11212 // 4) The client supplies an invalid/unacceptable certificate.
11213 TEST_P(HttpNetworkTransactionTest
,
11214 ClientAuthCertCache_Direct_FalseStart
) {
11215 HttpRequestInfo request_info
;
11216 request_info
.url
= GURL("https://www.example.com/");
11217 request_info
.method
= "GET";
11218 request_info
.load_flags
= LOAD_NORMAL
;
11220 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11221 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11223 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11224 // return successfully after reading up to the peer's Certificate message.
11225 // This is to allow the caller to call SSLClientSocket::Write(), which can
11226 // enqueue application data to be sent in the same packet as the
11227 // ChangeCipherSpec and Finished messages.
11228 // The actual handshake will be finished when SSLClientSocket::Read() is
11229 // called, which expects to process the peer's ChangeCipherSpec and
11230 // Finished messages. If there was an error negotiating with the peer,
11231 // such as due to the peer requiring a client certificate when none was
11232 // supplied, the alert sent by the peer won't be processed until Read() is
11235 // Like the non-False Start case, when a client certificate is requested by
11236 // the peer, the handshake is aborted during the Connect() call.
11237 // [ssl_]data1 represents the initial SSL handshake with the peer.
11238 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11239 ssl_data1
.cert_request_info
= cert_request
.get();
11240 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11241 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11242 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11244 // When a client certificate is supplied, Connect() will not be aborted
11245 // when the peer requests the certificate. Instead, the handshake will
11246 // artificially succeed, allowing the caller to write the HTTP request to
11247 // the socket. The handshake messages are not processed until Read() is
11248 // called, which then detects that the handshake was aborted, due to the
11249 // peer sending a handshake_failure because it requires a client
11251 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11252 ssl_data2
.cert_request_info
= cert_request
.get();
11253 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11254 MockRead data2_reads
[] = {
11255 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11257 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11258 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11260 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11261 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11262 // TLSv1. It has the same behaviour as [ssl_]data2.
11263 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11264 ssl_data3
.cert_request_info
= cert_request
.get();
11265 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11266 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11267 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11269 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11270 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11271 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11272 ssl_data4
.cert_request_info
= cert_request
.get();
11273 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11274 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11275 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11277 // Need one more if TLSv1.2 is enabled.
11278 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11279 ssl_data5
.cert_request_info
= cert_request
.get();
11280 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11281 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11282 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11284 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11285 scoped_ptr
<HttpTransaction
> trans(
11286 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11288 // Begin the initial SSL handshake.
11289 TestCompletionCallback callback
;
11290 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11291 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11293 // Complete the SSL handshake, which should abort due to requiring a
11294 // client certificate.
11295 rv
= callback
.WaitForResult();
11296 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11298 // Indicate that no certificate should be supplied. From the perspective
11299 // of SSLClientCertCache, NULL is just as meaningful as a real
11300 // certificate, so this is the same as supply a
11301 // legitimate-but-unacceptable certificate.
11302 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11303 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11305 // Ensure the certificate was added to the client auth cache before
11306 // allowing the connection to continue restarting.
11307 scoped_refptr
<X509Certificate
> client_cert
;
11308 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11309 HostPortPair("www.example.com", 443), &client_cert
));
11310 ASSERT_EQ(NULL
, client_cert
.get());
11312 // Restart the handshake. This will consume ssl_data2, which fails, and
11313 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11314 // The result code is checked against what ssl_data4 should return.
11315 rv
= callback
.WaitForResult();
11316 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11318 // Ensure that the client certificate is removed from the cache on a
11319 // handshake failure.
11320 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11321 HostPortPair("www.example.com", 443), &client_cert
));
11324 // Ensure that a client certificate is removed from the SSL client auth
11326 // 1) An HTTPS proxy is involved.
11327 // 3) The HTTPS proxy requests a client certificate.
11328 // 4) The client supplies an invalid/unacceptable certificate for the
11330 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11331 // then for connecting to an HTTP endpoint.
11332 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11333 session_deps_
.proxy_service
.reset(
11334 ProxyService::CreateFixed("https://proxy:70"));
11335 BoundTestNetLog log
;
11336 session_deps_
.net_log
= log
.bound().net_log();
11338 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11339 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11341 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11342 // [ssl_]data[1-3]. Rather than represending the endpoint
11343 // (www.example.com:443), they represent failures with the HTTPS proxy
11345 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11346 ssl_data1
.cert_request_info
= cert_request
.get();
11347 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11348 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11349 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11351 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11352 ssl_data2
.cert_request_info
= cert_request
.get();
11353 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11354 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11355 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11357 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11359 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11360 ssl_data3
.cert_request_info
= cert_request
.get();
11361 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11362 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11363 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11366 HttpRequestInfo requests
[2];
11367 requests
[0].url
= GURL("https://www.example.com/");
11368 requests
[0].method
= "GET";
11369 requests
[0].load_flags
= LOAD_NORMAL
;
11371 requests
[1].url
= GURL("http://www.example.com/");
11372 requests
[1].method
= "GET";
11373 requests
[1].load_flags
= LOAD_NORMAL
;
11375 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11376 session_deps_
.socket_factory
->ResetNextMockIndexes();
11377 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11378 scoped_ptr
<HttpNetworkTransaction
> trans(
11379 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11381 // Begin the SSL handshake with the proxy.
11382 TestCompletionCallback callback
;
11383 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11384 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11386 // Complete the SSL handshake, which should abort due to requiring a
11387 // client certificate.
11388 rv
= callback
.WaitForResult();
11389 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11391 // Indicate that no certificate should be supplied. From the perspective
11392 // of SSLClientCertCache, NULL is just as meaningful as a real
11393 // certificate, so this is the same as supply a
11394 // legitimate-but-unacceptable certificate.
11395 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11396 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11398 // Ensure the certificate was added to the client auth cache before
11399 // allowing the connection to continue restarting.
11400 scoped_refptr
<X509Certificate
> client_cert
;
11401 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11402 HostPortPair("proxy", 70), &client_cert
));
11403 ASSERT_EQ(NULL
, client_cert
.get());
11404 // Ensure the certificate was NOT cached for the endpoint. This only
11405 // applies to HTTPS requests, but is fine to check for HTTP requests.
11406 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11407 HostPortPair("www.example.com", 443), &client_cert
));
11409 // Restart the handshake. This will consume ssl_data2, which fails, and
11410 // then consume ssl_data3, which should also fail. The result code is
11411 // checked against what ssl_data3 should return.
11412 rv
= callback
.WaitForResult();
11413 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11415 // Now that the new handshake has failed, ensure that the client
11416 // certificate was removed from the client auth cache.
11417 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11418 HostPortPair("proxy", 70), &client_cert
));
11419 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11420 HostPortPair("www.example.com", 443), &client_cert
));
11424 // Unlike TEST/TEST_F, which are macros that expand to further macros,
11425 // TEST_P is a macro that expands directly to code that stringizes the
11426 // arguments. As a result, macros passed as parameters (such as prefix
11427 // or test_case_name) will not be expanded by the preprocessor. To
11428 // work around this, indirect the macro for TEST_P, so that the
11429 // pre-processor will expand macros such as MAYBE_test_name before
11430 // instantiating the test.
11431 #define WRAPPED_TEST_P(test_case_name, test_name) \
11432 TEST_P(test_case_name, test_name)
11434 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11435 #if defined(OS_WIN)
11436 #define MAYBE_UseIPConnectionPooling DISABLED_UseIPConnectionPooling
11438 #define MAYBE_UseIPConnectionPooling UseIPConnectionPooling
11440 WRAPPED_TEST_P(HttpNetworkTransactionTest
, MAYBE_UseIPConnectionPooling
) {
11441 session_deps_
.use_alternate_protocols
= true;
11442 session_deps_
.next_protos
= SpdyNextProtos();
11444 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11445 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11446 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11447 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11448 pool_peer
.DisableDomainAuthenticationVerification();
11450 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11451 ssl
.SetNextProto(GetParam());
11452 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11454 scoped_ptr
<SpdyFrame
> host1_req(
11455 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11456 scoped_ptr
<SpdyFrame
> host2_req(
11457 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11458 MockWrite spdy_writes
[] = {
11459 CreateMockWrite(*host1_req
, 1),
11460 CreateMockWrite(*host2_req
, 4),
11462 scoped_ptr
<SpdyFrame
> host1_resp(
11463 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11464 scoped_ptr
<SpdyFrame
> host1_resp_body(
11465 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11466 scoped_ptr
<SpdyFrame
> host2_resp(
11467 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11468 scoped_ptr
<SpdyFrame
> host2_resp_body(
11469 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11470 MockRead spdy_reads
[] = {
11471 CreateMockRead(*host1_resp
, 2),
11472 CreateMockRead(*host1_resp_body
, 3),
11473 CreateMockRead(*host2_resp
, 5),
11474 CreateMockRead(*host2_resp_body
, 6),
11475 MockRead(ASYNC
, 0, 7),
11478 IPAddressNumber ip
;
11479 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11480 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11481 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11482 OrderedSocketData
spdy_data(
11484 spdy_reads
, arraysize(spdy_reads
),
11485 spdy_writes
, arraysize(spdy_writes
));
11486 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11488 TestCompletionCallback callback
;
11489 HttpRequestInfo request1
;
11490 request1
.method
= "GET";
11491 request1
.url
= GURL("https://www.example.org/");
11492 request1
.load_flags
= 0;
11493 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11495 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11496 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11497 EXPECT_EQ(OK
, callback
.WaitForResult());
11499 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11500 ASSERT_TRUE(response
!= NULL
);
11501 ASSERT_TRUE(response
->headers
.get() != NULL
);
11502 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11504 std::string response_data
;
11505 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11506 EXPECT_EQ("hello!", response_data
);
11508 // Preload www.gmail.com into HostCache.
11509 HostPortPair
host_port("www.gmail.com", 443);
11510 HostResolver::RequestInfo
resolve_info(host_port
);
11511 AddressList ignored
;
11512 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11515 callback
.callback(),
11518 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11519 rv
= callback
.WaitForResult();
11522 HttpRequestInfo request2
;
11523 request2
.method
= "GET";
11524 request2
.url
= GURL("https://www.gmail.com/");
11525 request2
.load_flags
= 0;
11526 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11528 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11529 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11530 EXPECT_EQ(OK
, callback
.WaitForResult());
11532 response
= trans2
.GetResponseInfo();
11533 ASSERT_TRUE(response
!= NULL
);
11534 ASSERT_TRUE(response
->headers
.get() != NULL
);
11535 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11536 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11537 EXPECT_TRUE(response
->was_npn_negotiated
);
11538 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11539 EXPECT_EQ("hello!", response_data
);
11541 #undef MAYBE_UseIPConnectionPooling
11543 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11544 session_deps_
.use_alternate_protocols
= true;
11545 session_deps_
.next_protos
= SpdyNextProtos();
11547 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11548 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11549 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11550 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11551 pool_peer
.DisableDomainAuthenticationVerification();
11553 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11554 ssl
.SetNextProto(GetParam());
11555 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11557 scoped_ptr
<SpdyFrame
> host1_req(
11558 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11559 scoped_ptr
<SpdyFrame
> host2_req(
11560 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11561 MockWrite spdy_writes
[] = {
11562 CreateMockWrite(*host1_req
, 1),
11563 CreateMockWrite(*host2_req
, 4),
11565 scoped_ptr
<SpdyFrame
> host1_resp(
11566 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11567 scoped_ptr
<SpdyFrame
> host1_resp_body(
11568 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11569 scoped_ptr
<SpdyFrame
> host2_resp(
11570 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11571 scoped_ptr
<SpdyFrame
> host2_resp_body(
11572 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11573 MockRead spdy_reads
[] = {
11574 CreateMockRead(*host1_resp
, 2),
11575 CreateMockRead(*host1_resp_body
, 3),
11576 CreateMockRead(*host2_resp
, 5),
11577 CreateMockRead(*host2_resp_body
, 6),
11578 MockRead(ASYNC
, 0, 7),
11581 IPAddressNumber ip
;
11582 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11583 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11584 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11585 OrderedSocketData
spdy_data(
11587 spdy_reads
, arraysize(spdy_reads
),
11588 spdy_writes
, arraysize(spdy_writes
));
11589 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11591 TestCompletionCallback callback
;
11592 HttpRequestInfo request1
;
11593 request1
.method
= "GET";
11594 request1
.url
= GURL("https://www.example.org/");
11595 request1
.load_flags
= 0;
11596 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11598 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11599 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11600 EXPECT_EQ(OK
, callback
.WaitForResult());
11602 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11603 ASSERT_TRUE(response
!= NULL
);
11604 ASSERT_TRUE(response
->headers
.get() != NULL
);
11605 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11607 std::string response_data
;
11608 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11609 EXPECT_EQ("hello!", response_data
);
11611 HttpRequestInfo request2
;
11612 request2
.method
= "GET";
11613 request2
.url
= GURL("https://www.gmail.com/");
11614 request2
.load_flags
= 0;
11615 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11617 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11618 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11619 EXPECT_EQ(OK
, callback
.WaitForResult());
11621 response
= trans2
.GetResponseInfo();
11622 ASSERT_TRUE(response
!= NULL
);
11623 ASSERT_TRUE(response
->headers
.get() != NULL
);
11624 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11625 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11626 EXPECT_TRUE(response
->was_npn_negotiated
);
11627 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11628 EXPECT_EQ("hello!", response_data
);
11631 class OneTimeCachingHostResolver
: public HostResolver
{
11633 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11634 : host_port_(host_port
) {}
11635 ~OneTimeCachingHostResolver() override
{}
11637 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11639 // HostResolver methods:
11640 int Resolve(const RequestInfo
& info
,
11641 RequestPriority priority
,
11642 AddressList
* addresses
,
11643 const CompletionCallback
& callback
,
11644 RequestHandle
* out_req
,
11645 const BoundNetLog
& net_log
) override
{
11646 return host_resolver_
.Resolve(
11647 info
, priority
, addresses
, callback
, out_req
, net_log
);
11650 int ResolveFromCache(const RequestInfo
& info
,
11651 AddressList
* addresses
,
11652 const BoundNetLog
& net_log
) override
{
11653 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11654 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11655 host_resolver_
.GetHostCache()->clear();
11659 void CancelRequest(RequestHandle req
) override
{
11660 host_resolver_
.CancelRequest(req
);
11663 MockCachingHostResolver
* GetMockHostResolver() {
11664 return &host_resolver_
;
11668 MockCachingHostResolver host_resolver_
;
11669 const HostPortPair host_port_
;
11672 // Times out on Win7 dbg(2) bot. http://crbug.com/124776
11673 #if defined(OS_WIN)
11674 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11675 DISABLED_UseIPConnectionPoolingWithHostCacheExpiration
11677 #define MAYBE_UseIPConnectionPoolingWithHostCacheExpiration \
11678 UseIPConnectionPoolingWithHostCacheExpiration
11680 WRAPPED_TEST_P(HttpNetworkTransactionTest
,
11681 MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
) {
11682 // Times out on Win7 dbg(2) bot. http://crbug.com/124776 . (MAYBE_
11683 // prefix doesn't work with parametrized tests).
11684 #if defined(OS_WIN)
11687 session_deps_
.use_alternate_protocols
= true;
11688 session_deps_
.next_protos
= SpdyNextProtos();
11690 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11691 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11692 HttpNetworkSession::Params params
=
11693 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11694 params
.host_resolver
= &host_resolver
;
11695 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11696 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11697 pool_peer
.DisableDomainAuthenticationVerification();
11699 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11700 ssl
.SetNextProto(GetParam());
11701 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11703 scoped_ptr
<SpdyFrame
> host1_req(
11704 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11705 scoped_ptr
<SpdyFrame
> host2_req(
11706 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11707 MockWrite spdy_writes
[] = {
11708 CreateMockWrite(*host1_req
, 1),
11709 CreateMockWrite(*host2_req
, 4),
11711 scoped_ptr
<SpdyFrame
> host1_resp(
11712 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11713 scoped_ptr
<SpdyFrame
> host1_resp_body(
11714 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11715 scoped_ptr
<SpdyFrame
> host2_resp(
11716 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11717 scoped_ptr
<SpdyFrame
> host2_resp_body(
11718 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11719 MockRead spdy_reads
[] = {
11720 CreateMockRead(*host1_resp
, 2),
11721 CreateMockRead(*host1_resp_body
, 3),
11722 CreateMockRead(*host2_resp
, 5),
11723 CreateMockRead(*host2_resp_body
, 6),
11724 MockRead(ASYNC
, 0, 7),
11727 IPAddressNumber ip
;
11728 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11729 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11730 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11731 OrderedSocketData
spdy_data(
11733 spdy_reads
, arraysize(spdy_reads
),
11734 spdy_writes
, arraysize(spdy_writes
));
11735 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11737 TestCompletionCallback callback
;
11738 HttpRequestInfo request1
;
11739 request1
.method
= "GET";
11740 request1
.url
= GURL("https://www.example.org/");
11741 request1
.load_flags
= 0;
11742 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11744 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11745 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11746 EXPECT_EQ(OK
, callback
.WaitForResult());
11748 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11749 ASSERT_TRUE(response
!= NULL
);
11750 ASSERT_TRUE(response
->headers
.get() != NULL
);
11751 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11753 std::string response_data
;
11754 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11755 EXPECT_EQ("hello!", response_data
);
11757 // Preload cache entries into HostCache.
11758 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11759 AddressList ignored
;
11760 rv
= host_resolver
.Resolve(resolve_info
,
11763 callback
.callback(),
11766 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11767 rv
= callback
.WaitForResult();
11770 HttpRequestInfo request2
;
11771 request2
.method
= "GET";
11772 request2
.url
= GURL("https://www.gmail.com/");
11773 request2
.load_flags
= 0;
11774 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11776 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11777 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11778 EXPECT_EQ(OK
, callback
.WaitForResult());
11780 response
= trans2
.GetResponseInfo();
11781 ASSERT_TRUE(response
!= NULL
);
11782 ASSERT_TRUE(response
->headers
.get() != NULL
);
11783 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11784 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11785 EXPECT_TRUE(response
->was_npn_negotiated
);
11786 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11787 EXPECT_EQ("hello!", response_data
);
11790 #undef MAYBE_UseIPConnectionPoolingWithHostCacheExpiration
11792 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11793 const std::string https_url
= "https://www.example.org:8080/";
11794 const std::string http_url
= "http://www.example.org:8080/";
11796 // SPDY GET for HTTPS URL
11797 scoped_ptr
<SpdyFrame
> req1(
11798 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11800 MockWrite writes1
[] = {
11801 CreateMockWrite(*req1
, 0),
11804 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11805 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11806 MockRead reads1
[] = {
11807 CreateMockRead(*resp1
, 1),
11808 CreateMockRead(*body1
, 2),
11809 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11812 DelayedSocketData
data1(
11813 1, reads1
, arraysize(reads1
),
11814 writes1
, arraysize(writes1
));
11815 MockConnect
connect_data1(ASYNC
, OK
);
11816 data1
.set_connect_data(connect_data1
);
11818 // HTTP GET for the HTTP URL
11819 MockWrite writes2
[] = {
11820 MockWrite(ASYNC
, 4,
11821 "GET / HTTP/1.1\r\n"
11822 "Host: www.example.org:8080\r\n"
11823 "Connection: keep-alive\r\n\r\n"),
11826 MockRead reads2
[] = {
11827 MockRead(ASYNC
, 5, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11828 MockRead(ASYNC
, 6, "hello"),
11829 MockRead(ASYNC
, 7, OK
),
11832 DelayedSocketData
data2(
11833 1, reads2
, arraysize(reads2
),
11834 writes2
, arraysize(writes2
));
11836 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11837 ssl
.SetNextProto(GetParam());
11838 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11839 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11840 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11842 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11844 // Start the first transaction to set up the SpdySession
11845 HttpRequestInfo request1
;
11846 request1
.method
= "GET";
11847 request1
.url
= GURL(https_url
);
11848 request1
.load_flags
= 0;
11849 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11850 TestCompletionCallback callback1
;
11851 EXPECT_EQ(ERR_IO_PENDING
,
11852 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11853 base::MessageLoop::current()->RunUntilIdle();
11855 EXPECT_EQ(OK
, callback1
.WaitForResult());
11856 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11858 // Now, start the HTTP request
11859 HttpRequestInfo request2
;
11860 request2
.method
= "GET";
11861 request2
.url
= GURL(http_url
);
11862 request2
.load_flags
= 0;
11863 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11864 TestCompletionCallback callback2
;
11865 EXPECT_EQ(ERR_IO_PENDING
,
11866 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11867 base::MessageLoop::current()->RunUntilIdle();
11869 EXPECT_EQ(OK
, callback2
.WaitForResult());
11870 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11873 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
11875 void Run(bool pooling
, bool valid
) {
11876 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
11878 HostPortPair
alternative("www.example.org", 443);
11880 base::FilePath certs_dir
= GetTestCertsDirectory();
11881 scoped_refptr
<X509Certificate
> cert(
11882 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
11883 ASSERT_TRUE(cert
.get());
11884 bool common_name_fallback_used
;
11886 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
11888 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
11889 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11890 ssl
.SetNextProto(GetParam());
11892 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11894 // If pooling, then start a request to alternative first to create a
11896 std::string url0
= "https://www.example.org:443";
11897 // Second request to origin, which has an alternative service, and could
11898 // open a connection to the alternative host or pool to the existing one.
11899 std::string
url1("https://");
11900 url1
.append(origin
.host());
11901 url1
.append(":443");
11903 scoped_ptr
<SpdyFrame
> req0
;
11904 scoped_ptr
<SpdyFrame
> req1
;
11905 scoped_ptr
<SpdyFrame
> resp0
;
11906 scoped_ptr
<SpdyFrame
> body0
;
11907 scoped_ptr
<SpdyFrame
> resp1
;
11908 scoped_ptr
<SpdyFrame
> body1
;
11909 std::vector
<MockWrite
> writes
;
11910 std::vector
<MockRead
> reads
;
11913 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
11914 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
11916 writes
.push_back(CreateMockWrite(*req0
, 0));
11917 writes
.push_back(CreateMockWrite(*req1
, 3));
11919 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11920 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11921 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11922 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
11924 reads
.push_back(CreateMockRead(*resp0
, 1));
11925 reads
.push_back(CreateMockRead(*body0
, 2));
11926 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
11927 reads
.push_back(CreateMockRead(*resp1
, 5));
11928 reads
.push_back(CreateMockRead(*body1
, 6));
11929 reads
.push_back(MockRead(ASYNC
, OK
, 7));
11931 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
11933 writes
.push_back(CreateMockWrite(*req1
, 0));
11935 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11936 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11938 reads
.push_back(CreateMockRead(*resp1
, 1));
11939 reads
.push_back(CreateMockRead(*body1
, 2));
11940 reads
.push_back(MockRead(ASYNC
, OK
, 3));
11943 OrderedSocketData
data(vector_as_array(&reads
), reads
.size(),
11944 vector_as_array(&writes
), writes
.size());
11945 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11947 // Connection to the origin fails.
11948 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
11949 StaticSocketDataProvider data_refused
;
11950 data_refused
.set_connect_data(mock_connect
);
11951 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
11953 session_deps_
.use_alternate_protocols
= true;
11954 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11955 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
11956 session
->http_server_properties();
11957 AlternativeService
alternative_service(
11958 AlternateProtocolFromNextProto(GetParam()), alternative
);
11959 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
11962 // First request to alternative.
11964 scoped_ptr
<HttpTransaction
> trans0(
11965 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11966 HttpRequestInfo request0
;
11967 request0
.method
= "GET";
11968 request0
.url
= GURL(url0
);
11969 request0
.load_flags
= 0;
11970 TestCompletionCallback callback0
;
11972 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
11973 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11974 rv
= callback0
.WaitForResult();
11978 // Second request to origin.
11979 scoped_ptr
<HttpTransaction
> trans1(
11980 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11981 HttpRequestInfo request1
;
11982 request1
.method
= "GET";
11983 request1
.url
= GURL(url1
);
11984 request1
.load_flags
= 0;
11985 TestCompletionCallback callback1
;
11987 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
11988 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11989 rv
= callback1
.WaitForResult();
11994 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
11996 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
12002 INSTANTIATE_TEST_CASE_P(NextProto
,
12003 AltSvcCertificateVerificationTest
,
12004 testing::Values(kProtoSPDY31
,
12008 // The alternative service host must exhibit a certificate that is valid for the
12009 // origin host. Test that this is enforced when pooling to an existing
12011 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
12015 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
12019 // The alternative service host must exhibit a certificate that is valid for the
12020 // origin host. Test that this is enforced when opening a new connection.
12021 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
12025 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
12029 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12030 const std::string https_url
= "https://www.example.org:8080/";
12031 const std::string http_url
= "http://www.example.org:8080/";
12033 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12034 const HostPortPair
host_port_pair("www.example.org", 8080);
12035 scoped_ptr
<SpdyFrame
> connect(
12036 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12037 scoped_ptr
<SpdyFrame
> req1(
12038 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12039 scoped_ptr
<SpdyFrame
> wrapped_req1(
12040 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12042 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12043 SpdyHeaderBlock req2_block
;
12044 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12045 req2_block
[spdy_util_
.GetPathKey()] = "/";
12046 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12047 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12048 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12049 scoped_ptr
<SpdyFrame
> req2(
12050 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12052 MockWrite writes1
[] = {
12053 CreateMockWrite(*connect
, 0),
12054 CreateMockWrite(*wrapped_req1
, 2),
12055 CreateMockWrite(*req2
, 5),
12058 scoped_ptr
<SpdyFrame
> conn_resp(
12059 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12060 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12061 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12062 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12063 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12064 scoped_ptr
<SpdyFrame
> wrapped_body1(
12065 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12066 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12067 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12068 MockRead reads1
[] = {
12069 CreateMockRead(*conn_resp
, 1),
12070 CreateMockRead(*wrapped_resp1
, 3),
12071 CreateMockRead(*wrapped_body1
, 4),
12072 CreateMockRead(*resp2
, 6),
12073 CreateMockRead(*body2
, 7),
12074 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12077 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12078 writes1
, arraysize(writes1
));
12079 MockConnect
connect_data1(ASYNC
, OK
);
12080 data1
.set_connect_data(connect_data1
);
12082 session_deps_
.proxy_service
.reset(
12083 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12085 session_deps_
.net_log
= &log
;
12086 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12087 ssl1
.SetNextProto(GetParam());
12088 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12089 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12090 ssl2
.SetNextProto(GetParam());
12091 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12092 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12094 scoped_refptr
<HttpNetworkSession
> session(
12095 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12097 // Start the first transaction to set up the SpdySession
12098 HttpRequestInfo request1
;
12099 request1
.method
= "GET";
12100 request1
.url
= GURL(https_url
);
12101 request1
.load_flags
= 0;
12102 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12103 TestCompletionCallback callback1
;
12104 EXPECT_EQ(ERR_IO_PENDING
,
12105 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12106 base::MessageLoop::current()->RunUntilIdle();
12109 EXPECT_EQ(OK
, callback1
.WaitForResult());
12110 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12112 LoadTimingInfo load_timing_info1
;
12113 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12114 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12115 CONNECT_TIMING_HAS_SSL_TIMES
);
12117 // Now, start the HTTP request
12118 HttpRequestInfo request2
;
12119 request2
.method
= "GET";
12120 request2
.url
= GURL(http_url
);
12121 request2
.load_flags
= 0;
12122 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12123 TestCompletionCallback callback2
;
12124 EXPECT_EQ(ERR_IO_PENDING
,
12125 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12126 base::MessageLoop::current()->RunUntilIdle();
12129 EXPECT_EQ(OK
, callback2
.WaitForResult());
12130 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12132 LoadTimingInfo load_timing_info2
;
12133 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12134 // The established SPDY sessions is considered reused by the HTTP request.
12135 TestLoadTimingReusedWithPac(load_timing_info2
);
12136 // HTTP requests over a SPDY session should have a different connection
12137 // socket_log_id than requests over a tunnel.
12138 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12141 // Test that in the case where we have a SPDY session to a SPDY proxy
12142 // that we do not pool other origins that resolve to the same IP when
12143 // the certificate does not match the new origin.
12144 // http://crbug.com/134690
12145 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12146 const std::string url1
= "http://www.example.org/";
12147 const std::string url2
= "https://news.example.org/";
12148 const std::string ip_addr
= "1.2.3.4";
12150 // SPDY GET for HTTP URL (through SPDY proxy)
12151 scoped_ptr
<SpdyHeaderBlock
> headers(
12152 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12153 scoped_ptr
<SpdyFrame
> req1(
12154 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12156 MockWrite writes1
[] = {
12157 CreateMockWrite(*req1
, 0),
12160 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12161 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12162 MockRead reads1
[] = {
12163 CreateMockRead(*resp1
, 1),
12164 CreateMockRead(*body1
, 2),
12165 MockRead(ASYNC
, OK
, 3) // EOF
12168 scoped_ptr
<DeterministicSocketData
> data1(
12169 new DeterministicSocketData(reads1
, arraysize(reads1
),
12170 writes1
, arraysize(writes1
)));
12171 IPAddressNumber ip
;
12172 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12173 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12174 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12175 data1
->set_connect_data(connect_data1
);
12177 // SPDY GET for HTTPS URL (direct)
12178 scoped_ptr
<SpdyFrame
> req2(
12179 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12181 MockWrite writes2
[] = {
12182 CreateMockWrite(*req2
, 0),
12185 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12186 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12187 MockRead reads2
[] = {
12188 CreateMockRead(*resp2
, 1),
12189 CreateMockRead(*body2
, 2),
12190 MockRead(ASYNC
, OK
, 3) // EOF
12193 scoped_ptr
<DeterministicSocketData
> data2(
12194 new DeterministicSocketData(reads2
, arraysize(reads2
),
12195 writes2
, arraysize(writes2
)));
12196 MockConnect
connect_data2(ASYNC
, OK
);
12197 data2
->set_connect_data(connect_data2
);
12199 // Set up a proxy config that sends HTTP requests to a proxy, and
12200 // all others direct.
12201 ProxyConfig proxy_config
;
12202 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12203 session_deps_
.proxy_service
.reset(new ProxyService(
12204 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12206 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12207 ssl1
.SetNextProto(GetParam());
12208 // Load a valid cert. Note, that this does not need to
12209 // be valid for proxy because the MockSSLClientSocket does
12210 // not actually verify it. But SpdySession will use this
12211 // to see if it is valid for the new origin
12212 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12213 ASSERT_TRUE(ssl1
.cert
.get());
12214 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12215 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12218 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12219 ssl2
.SetNextProto(GetParam());
12220 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12221 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12224 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12225 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12226 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12228 scoped_refptr
<HttpNetworkSession
> session(
12229 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12231 // Start the first transaction to set up the SpdySession
12232 HttpRequestInfo request1
;
12233 request1
.method
= "GET";
12234 request1
.url
= GURL(url1
);
12235 request1
.load_flags
= 0;
12236 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12237 TestCompletionCallback callback1
;
12238 ASSERT_EQ(ERR_IO_PENDING
,
12239 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12242 ASSERT_TRUE(callback1
.have_result());
12243 EXPECT_EQ(OK
, callback1
.WaitForResult());
12244 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12246 // Now, start the HTTP request
12247 HttpRequestInfo request2
;
12248 request2
.method
= "GET";
12249 request2
.url
= GURL(url2
);
12250 request2
.load_flags
= 0;
12251 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12252 TestCompletionCallback callback2
;
12253 EXPECT_EQ(ERR_IO_PENDING
,
12254 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12255 base::MessageLoop::current()->RunUntilIdle();
12258 ASSERT_TRUE(callback2
.have_result());
12259 EXPECT_EQ(OK
, callback2
.WaitForResult());
12260 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12263 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12264 // error) in SPDY session, removes the socket from pool and closes the SPDY
12265 // session. Verify that new url's from the same HttpNetworkSession (and a new
12266 // SpdySession) do work. http://crbug.com/224701
12267 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12268 const std::string https_url
= "https://www.example.org/";
12270 MockRead reads1
[] = {
12271 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12274 scoped_ptr
<DeterministicSocketData
> data1(
12275 new DeterministicSocketData(reads1
, arraysize(reads1
), NULL
, 0));
12278 scoped_ptr
<SpdyFrame
> req2(
12279 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12280 MockWrite writes2
[] = {
12281 CreateMockWrite(*req2
, 0),
12284 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12285 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12286 MockRead reads2
[] = {
12287 CreateMockRead(*resp2
, 1),
12288 CreateMockRead(*body2
, 2),
12289 MockRead(ASYNC
, OK
, 3) // EOF
12292 scoped_ptr
<DeterministicSocketData
> data2(
12293 new DeterministicSocketData(reads2
, arraysize(reads2
),
12294 writes2
, arraysize(writes2
)));
12296 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12297 ssl1
.SetNextProto(GetParam());
12298 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12299 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12302 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12303 ssl2
.SetNextProto(GetParam());
12304 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12305 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12308 scoped_refptr
<HttpNetworkSession
> session(
12309 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12311 // Start the first transaction to set up the SpdySession and verify that
12312 // connection was closed.
12313 HttpRequestInfo request1
;
12314 request1
.method
= "GET";
12315 request1
.url
= GURL(https_url
);
12316 request1
.load_flags
= 0;
12317 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12318 TestCompletionCallback callback1
;
12319 EXPECT_EQ(ERR_IO_PENDING
,
12320 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12321 base::MessageLoop::current()->RunUntilIdle();
12322 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12324 // Now, start the second request and make sure it succeeds.
12325 HttpRequestInfo request2
;
12326 request2
.method
= "GET";
12327 request2
.url
= GURL(https_url
);
12328 request2
.load_flags
= 0;
12329 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12330 TestCompletionCallback callback2
;
12331 EXPECT_EQ(ERR_IO_PENDING
,
12332 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12333 base::MessageLoop::current()->RunUntilIdle();
12336 ASSERT_TRUE(callback2
.have_result());
12337 EXPECT_EQ(OK
, callback2
.WaitForResult());
12338 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12341 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12342 session_deps_
.next_protos
= SpdyNextProtos();
12343 ClientSocketPoolManager::set_max_sockets_per_group(
12344 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12345 ClientSocketPoolManager::set_max_sockets_per_pool(
12346 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12348 // Use two different hosts with different IPs so they don't get pooled.
12349 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12350 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12351 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12353 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12354 ssl1
.SetNextProto(GetParam());
12355 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12356 ssl2
.SetNextProto(GetParam());
12357 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12358 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12360 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12361 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12362 MockWrite spdy1_writes
[] = {
12363 CreateMockWrite(*host1_req
, 1),
12365 scoped_ptr
<SpdyFrame
> host1_resp(
12366 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12367 scoped_ptr
<SpdyFrame
> host1_resp_body(
12368 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12369 MockRead spdy1_reads
[] = {
12370 CreateMockRead(*host1_resp
, 2),
12371 CreateMockRead(*host1_resp_body
, 3),
12372 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
12375 scoped_ptr
<OrderedSocketData
> spdy1_data(
12376 new OrderedSocketData(
12377 spdy1_reads
, arraysize(spdy1_reads
),
12378 spdy1_writes
, arraysize(spdy1_writes
)));
12379 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12381 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12382 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12383 MockWrite spdy2_writes
[] = {
12384 CreateMockWrite(*host2_req
, 1),
12386 scoped_ptr
<SpdyFrame
> host2_resp(
12387 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12388 scoped_ptr
<SpdyFrame
> host2_resp_body(
12389 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12390 MockRead spdy2_reads
[] = {
12391 CreateMockRead(*host2_resp
, 2),
12392 CreateMockRead(*host2_resp_body
, 3),
12393 MockRead(ASYNC
, ERR_IO_PENDING
, 4),
12396 scoped_ptr
<OrderedSocketData
> spdy2_data(
12397 new OrderedSocketData(
12398 spdy2_reads
, arraysize(spdy2_reads
),
12399 spdy2_writes
, arraysize(spdy2_writes
)));
12400 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12402 MockWrite http_write
[] = {
12403 MockWrite("GET / HTTP/1.1\r\n"
12404 "Host: www.a.com\r\n"
12405 "Connection: keep-alive\r\n\r\n"),
12408 MockRead http_read
[] = {
12409 MockRead("HTTP/1.1 200 OK\r\n"),
12410 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12411 MockRead("Content-Length: 6\r\n\r\n"),
12412 MockRead("hello!"),
12414 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12415 http_write
, arraysize(http_write
));
12416 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12418 HostPortPair
host_port_pair_a("www.a.com", 443);
12419 SpdySessionKey
spdy_session_key_a(
12420 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12422 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12424 TestCompletionCallback callback
;
12425 HttpRequestInfo request1
;
12426 request1
.method
= "GET";
12427 request1
.url
= GURL("https://www.a.com/");
12428 request1
.load_flags
= 0;
12429 scoped_ptr
<HttpNetworkTransaction
> trans(
12430 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12432 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12433 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12434 EXPECT_EQ(OK
, callback
.WaitForResult());
12436 const HttpResponseInfo
* 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_TRUE(response
->was_fetched_via_spdy
);
12441 EXPECT_TRUE(response
->was_npn_negotiated
);
12443 std::string response_data
;
12444 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12445 EXPECT_EQ("hello!", response_data
);
12448 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12450 HostPortPair
host_port_pair_b("www.b.com", 443);
12451 SpdySessionKey
spdy_session_key_b(
12452 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12454 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12455 HttpRequestInfo request2
;
12456 request2
.method
= "GET";
12457 request2
.url
= GURL("https://www.b.com/");
12458 request2
.load_flags
= 0;
12459 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12461 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12462 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12463 EXPECT_EQ(OK
, callback
.WaitForResult());
12465 response
= trans
->GetResponseInfo();
12466 ASSERT_TRUE(response
!= NULL
);
12467 ASSERT_TRUE(response
->headers
.get() != NULL
);
12468 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12469 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12470 EXPECT_TRUE(response
->was_npn_negotiated
);
12471 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12472 EXPECT_EQ("hello!", response_data
);
12474 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12476 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12478 HostPortPair
host_port_pair_a1("www.a.com", 80);
12479 SpdySessionKey
spdy_session_key_a1(
12480 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12482 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12483 HttpRequestInfo request3
;
12484 request3
.method
= "GET";
12485 request3
.url
= GURL("http://www.a.com/");
12486 request3
.load_flags
= 0;
12487 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12489 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12490 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12491 EXPECT_EQ(OK
, callback
.WaitForResult());
12493 response
= trans
->GetResponseInfo();
12494 ASSERT_TRUE(response
!= NULL
);
12495 ASSERT_TRUE(response
->headers
.get() != NULL
);
12496 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12497 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12498 EXPECT_FALSE(response
->was_npn_negotiated
);
12499 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12500 EXPECT_EQ("hello!", response_data
);
12502 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12504 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12507 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12508 HttpRequestInfo request
;
12509 request
.method
= "GET";
12510 request
.url
= GURL("http://www.example.org/");
12511 request
.load_flags
= 0;
12513 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12514 scoped_ptr
<HttpTransaction
> trans(
12515 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12517 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12518 StaticSocketDataProvider data
;
12519 data
.set_connect_data(mock_connect
);
12520 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12522 TestCompletionCallback callback
;
12524 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12525 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12527 rv
= callback
.WaitForResult();
12528 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12530 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12532 // We don't care whether this succeeds or fails, but it shouldn't crash.
12533 HttpRequestHeaders request_headers
;
12534 trans
->GetFullRequestHeaders(&request_headers
);
12536 ConnectionAttempts attempts
;
12537 trans
->GetConnectionAttempts(&attempts
);
12538 ASSERT_EQ(1u, attempts
.size());
12539 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12542 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12543 HttpRequestInfo request
;
12544 request
.method
= "GET";
12545 request
.url
= GURL("http://www.example.org/");
12546 request
.load_flags
= 0;
12548 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12549 scoped_ptr
<HttpTransaction
> trans(
12550 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12552 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12553 StaticSocketDataProvider data
;
12554 data
.set_connect_data(mock_connect
);
12555 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12557 TestCompletionCallback callback
;
12559 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12560 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12562 rv
= callback
.WaitForResult();
12563 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12565 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12567 // We don't care whether this succeeds or fails, but it shouldn't crash.
12568 HttpRequestHeaders request_headers
;
12569 trans
->GetFullRequestHeaders(&request_headers
);
12571 ConnectionAttempts attempts
;
12572 trans
->GetConnectionAttempts(&attempts
);
12573 ASSERT_EQ(1u, attempts
.size());
12574 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12577 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12578 HttpRequestInfo request
;
12579 request
.method
= "GET";
12580 request
.url
= GURL("http://www.example.org/");
12581 request
.load_flags
= 0;
12583 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12584 scoped_ptr
<HttpTransaction
> trans(
12585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12587 MockWrite data_writes
[] = {
12588 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12590 MockRead data_reads
[] = {
12591 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12594 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12595 data_writes
, arraysize(data_writes
));
12596 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12598 TestCompletionCallback callback
;
12600 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12601 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12603 rv
= callback
.WaitForResult();
12604 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12606 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12608 HttpRequestHeaders request_headers
;
12609 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12610 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12613 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12614 HttpRequestInfo request
;
12615 request
.method
= "GET";
12616 request
.url
= GURL("http://www.example.org/");
12617 request
.load_flags
= 0;
12619 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12620 scoped_ptr
<HttpTransaction
> trans(
12621 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12623 MockWrite data_writes
[] = {
12624 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12626 MockRead data_reads
[] = {
12627 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12630 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12631 data_writes
, arraysize(data_writes
));
12632 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12634 TestCompletionCallback callback
;
12636 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12637 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12639 rv
= callback
.WaitForResult();
12640 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12642 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12644 HttpRequestHeaders request_headers
;
12645 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12646 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12649 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
12650 HttpRequestInfo request
;
12651 request
.method
= "GET";
12652 request
.url
= GURL("http://www.example.org/");
12653 request
.load_flags
= 0;
12655 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12656 scoped_ptr
<HttpTransaction
> trans(
12657 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12659 MockWrite data_writes
[] = {
12661 "GET / HTTP/1.1\r\n"
12662 "Host: www.example.org\r\n"
12663 "Connection: keep-alive\r\n\r\n"),
12665 MockRead data_reads
[] = {
12666 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12669 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12670 data_writes
, arraysize(data_writes
));
12671 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12673 TestCompletionCallback callback
;
12675 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12676 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12678 rv
= callback
.WaitForResult();
12679 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12681 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12683 HttpRequestHeaders request_headers
;
12684 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12685 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12688 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
12689 HttpRequestInfo request
;
12690 request
.method
= "GET";
12691 request
.url
= GURL("http://www.example.org/");
12692 request
.load_flags
= 0;
12694 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12695 scoped_ptr
<HttpTransaction
> trans(
12696 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12698 MockWrite data_writes
[] = {
12700 "GET / HTTP/1.1\r\n"
12701 "Host: www.example.org\r\n"
12702 "Connection: keep-alive\r\n\r\n"),
12704 MockRead data_reads
[] = {
12705 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
12708 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12709 data_writes
, arraysize(data_writes
));
12710 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12712 TestCompletionCallback callback
;
12714 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12715 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12717 rv
= callback
.WaitForResult();
12718 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12720 EXPECT_EQ(NULL
, trans
->GetResponseInfo());
12722 HttpRequestHeaders request_headers
;
12723 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12724 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12727 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
12728 HttpRequestInfo request
;
12729 request
.method
= "GET";
12730 request
.url
= GURL("http://www.example.org/");
12731 request
.load_flags
= 0;
12732 request
.extra_headers
.SetHeader("X-Foo", "bar");
12734 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12735 scoped_ptr
<HttpTransaction
> trans(
12736 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12738 MockWrite data_writes
[] = {
12740 "GET / HTTP/1.1\r\n"
12741 "Host: www.example.org\r\n"
12742 "Connection: keep-alive\r\n"
12743 "X-Foo: bar\r\n\r\n"),
12745 MockRead data_reads
[] = {
12746 MockRead("HTTP/1.1 200 OK\r\n"
12747 "Content-Length: 5\r\n\r\n"
12749 MockRead(ASYNC
, ERR_UNEXPECTED
),
12752 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12753 data_writes
, arraysize(data_writes
));
12754 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12756 TestCompletionCallback callback
;
12758 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12761 rv
= callback
.WaitForResult();
12764 HttpRequestHeaders request_headers
;
12765 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12767 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
12768 EXPECT_EQ("bar", foo
);
12773 // Fake HttpStream that simply records calls to SetPriority().
12774 class FakeStream
: public HttpStream
,
12775 public base::SupportsWeakPtr
<FakeStream
> {
12777 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
12778 ~FakeStream() override
{}
12780 RequestPriority
priority() const { return priority_
; }
12782 int InitializeStream(const HttpRequestInfo
* request_info
,
12783 RequestPriority priority
,
12784 const BoundNetLog
& net_log
,
12785 const CompletionCallback
& callback
) override
{
12786 return ERR_IO_PENDING
;
12789 int SendRequest(const HttpRequestHeaders
& request_headers
,
12790 HttpResponseInfo
* response
,
12791 const CompletionCallback
& callback
) override
{
12793 return ERR_UNEXPECTED
;
12796 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
12798 return ERR_UNEXPECTED
;
12801 int ReadResponseBody(IOBuffer
* buf
,
12803 const CompletionCallback
& callback
) override
{
12805 return ERR_UNEXPECTED
;
12808 void Close(bool not_reusable
) override
{}
12810 bool IsResponseBodyComplete() const override
{
12815 bool CanFindEndOfResponse() const override
{ return false; }
12817 bool IsConnectionReused() const override
{
12822 void SetConnectionReused() override
{ ADD_FAILURE(); }
12824 bool IsConnectionReusable() const override
{
12829 int64
GetTotalReceivedBytes() const override
{
12834 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
12839 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
12841 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
12845 bool IsSpdyHttpStream() const override
{
12850 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
12852 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12854 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
12856 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
12859 RequestPriority priority_
;
12861 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
12864 // Fake HttpStreamRequest that simply records calls to SetPriority()
12865 // and vends FakeStreams with its current priority.
12866 class FakeStreamRequest
: public HttpStreamRequest
,
12867 public base::SupportsWeakPtr
<FakeStreamRequest
> {
12869 FakeStreamRequest(RequestPriority priority
,
12870 HttpStreamRequest::Delegate
* delegate
)
12871 : priority_(priority
),
12872 delegate_(delegate
),
12873 websocket_stream_create_helper_(NULL
) {}
12875 FakeStreamRequest(RequestPriority priority
,
12876 HttpStreamRequest::Delegate
* delegate
,
12877 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
12878 : priority_(priority
),
12879 delegate_(delegate
),
12880 websocket_stream_create_helper_(create_helper
) {}
12882 ~FakeStreamRequest() override
{}
12884 RequestPriority
priority() const { return priority_
; }
12886 const WebSocketHandshakeStreamBase::CreateHelper
*
12887 websocket_stream_create_helper() const {
12888 return websocket_stream_create_helper_
;
12891 // Create a new FakeStream and pass it to the request's
12892 // delegate. Returns a weak pointer to the FakeStream.
12893 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
12894 FakeStream
* fake_stream
= new FakeStream(priority_
);
12895 // Do this before calling OnStreamReady() as OnStreamReady() may
12896 // immediately delete |fake_stream|.
12897 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
12898 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
12899 return weak_stream
;
12902 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
12904 return ERR_UNEXPECTED
;
12907 LoadState
GetLoadState() const override
{
12909 return LoadState();
12912 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
12914 bool was_npn_negotiated() const override
{ return false; }
12916 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
12918 bool using_spdy() const override
{ return false; }
12920 const ConnectionAttempts
& connection_attempts() const override
{
12921 static ConnectionAttempts no_attempts
;
12922 return no_attempts
;
12926 RequestPriority priority_
;
12927 HttpStreamRequest::Delegate
* const delegate_
;
12928 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
12930 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
12933 // Fake HttpStreamFactory that vends FakeStreamRequests.
12934 class FakeStreamFactory
: public HttpStreamFactory
{
12936 FakeStreamFactory() {}
12937 ~FakeStreamFactory() override
{}
12939 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
12940 // RequestStream() (which may be NULL if it was destroyed already).
12941 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
12942 return last_stream_request_
;
12945 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
12946 RequestPriority priority
,
12947 const SSLConfig
& server_ssl_config
,
12948 const SSLConfig
& proxy_ssl_config
,
12949 HttpStreamRequest::Delegate
* delegate
,
12950 const BoundNetLog
& net_log
) override
{
12951 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
12952 last_stream_request_
= fake_request
->AsWeakPtr();
12953 return fake_request
;
12956 HttpStreamRequest
* RequestWebSocketHandshakeStream(
12957 const HttpRequestInfo
& info
,
12958 RequestPriority priority
,
12959 const SSLConfig
& server_ssl_config
,
12960 const SSLConfig
& proxy_ssl_config
,
12961 HttpStreamRequest::Delegate
* delegate
,
12962 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
12963 const BoundNetLog
& net_log
) override
{
12964 FakeStreamRequest
* fake_request
=
12965 new FakeStreamRequest(priority
, delegate
, create_helper
);
12966 last_stream_request_
= fake_request
->AsWeakPtr();
12967 return fake_request
;
12970 void PreconnectStreams(int num_streams
,
12971 const HttpRequestInfo
& info
,
12972 RequestPriority priority
,
12973 const SSLConfig
& server_ssl_config
,
12974 const SSLConfig
& proxy_ssl_config
) override
{
12978 const HostMappingRules
* GetHostMappingRules() const override
{
12984 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
12986 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
12989 // TODO(ricea): Maybe unify this with the one in
12990 // url_request_http_job_unittest.cc ?
12991 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
12993 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
12995 : state_(connection
.release(), using_proxy
) {}
12997 // Fake implementation of HttpStreamBase methods.
12998 // This ends up being quite "real" because this object has to really send data
12999 // on the mock socket. It might be easier to use the real implementation, but
13000 // the fact that the WebSocket code is not compiled on iOS makes that
13002 int InitializeStream(const HttpRequestInfo
* request_info
,
13003 RequestPriority priority
,
13004 const BoundNetLog
& net_log
,
13005 const CompletionCallback
& callback
) override
{
13006 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13010 int SendRequest(const HttpRequestHeaders
& request_headers
,
13011 HttpResponseInfo
* response
,
13012 const CompletionCallback
& callback
) override
{
13013 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13014 response
, callback
);
13017 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13018 return parser()->ReadResponseHeaders(callback
);
13021 int ReadResponseBody(IOBuffer
* buf
,
13023 const CompletionCallback
& callback
) override
{
13025 return ERR_IO_PENDING
;
13028 void Close(bool not_reusable
) override
{
13030 parser()->Close(true);
13033 bool IsResponseBodyComplete() const override
{
13038 bool CanFindEndOfResponse() const override
{
13039 return parser()->CanFindEndOfResponse();
13042 bool IsConnectionReused() const override
{
13046 void SetConnectionReused() override
{ NOTREACHED(); }
13048 bool IsConnectionReusable() const override
{
13053 int64
GetTotalReceivedBytes() const override
{
13058 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13063 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13065 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13069 bool IsSpdyHttpStream() const override
{
13074 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13076 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13078 UploadProgress
GetUploadProgress() const override
{
13080 return UploadProgress();
13083 HttpStream
* RenewStreamForAuth() override
{
13088 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13089 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13091 return scoped_ptr
<WebSocketStream
>();
13095 HttpStreamParser
* parser() const { return state_
.parser(); }
13096 HttpBasicState state_
;
13098 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13101 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13103 class FakeWebSocketStreamCreateHelper
:
13104 public WebSocketHandshakeStreamBase::CreateHelper
{
13106 WebSocketHandshakeStreamBase
* CreateBasicStream(
13107 scoped_ptr
<ClientSocketHandle
> connection
,
13108 bool using_proxy
) override
{
13109 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13113 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13114 const base::WeakPtr
<SpdySession
>& session
,
13115 bool use_relative_url
) override
{
13120 ~FakeWebSocketStreamCreateHelper() override
{}
13122 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13124 return scoped_ptr
<WebSocketStream
>();
13130 // Make sure that HttpNetworkTransaction passes on its priority to its
13131 // stream request on start.
13132 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13133 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13134 HttpNetworkSessionPeer
peer(session
);
13135 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13136 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13138 HttpNetworkTransaction
trans(LOW
, session
.get());
13140 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13142 HttpRequestInfo request
;
13143 TestCompletionCallback callback
;
13144 EXPECT_EQ(ERR_IO_PENDING
,
13145 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13147 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13148 fake_factory
->last_stream_request();
13149 ASSERT_TRUE(fake_request
!= NULL
);
13150 EXPECT_EQ(LOW
, fake_request
->priority());
13153 // Make sure that HttpNetworkTransaction passes on its priority
13154 // updates to its stream request.
13155 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13156 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13157 HttpNetworkSessionPeer
peer(session
);
13158 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13159 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13161 HttpNetworkTransaction
trans(LOW
, session
.get());
13163 HttpRequestInfo request
;
13164 TestCompletionCallback callback
;
13165 EXPECT_EQ(ERR_IO_PENDING
,
13166 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13168 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13169 fake_factory
->last_stream_request();
13170 ASSERT_TRUE(fake_request
!= NULL
);
13171 EXPECT_EQ(LOW
, fake_request
->priority());
13173 trans
.SetPriority(LOWEST
);
13174 ASSERT_TRUE(fake_request
!= NULL
);
13175 EXPECT_EQ(LOWEST
, fake_request
->priority());
13178 // Make sure that HttpNetworkTransaction passes on its priority
13179 // updates to its stream.
13180 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13181 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13182 HttpNetworkSessionPeer
peer(session
);
13183 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13184 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13186 HttpNetworkTransaction
trans(LOW
, session
.get());
13188 HttpRequestInfo request
;
13189 TestCompletionCallback callback
;
13190 EXPECT_EQ(ERR_IO_PENDING
,
13191 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13193 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13194 fake_factory
->last_stream_request();
13195 ASSERT_TRUE(fake_request
!= NULL
);
13196 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13197 ASSERT_TRUE(fake_stream
!= NULL
);
13198 EXPECT_EQ(LOW
, fake_stream
->priority());
13200 trans
.SetPriority(LOWEST
);
13201 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13204 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13205 // The same logic needs to be tested for both ws: and wss: schemes, but this
13206 // test is already parameterised on NextProto, so it uses a loop to verify
13207 // that the different schemes work.
13208 std::string test_cases
[] = {"ws://www.example.org/",
13209 "wss://www.example.org/"};
13210 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13211 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13212 HttpNetworkSessionPeer
peer(session
);
13213 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13214 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13215 peer
.SetHttpStreamFactoryForWebSocket(
13216 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13218 HttpNetworkTransaction
trans(LOW
, session
.get());
13219 trans
.SetWebSocketHandshakeStreamCreateHelper(
13220 &websocket_stream_create_helper
);
13222 HttpRequestInfo request
;
13223 TestCompletionCallback callback
;
13224 request
.method
= "GET";
13225 request
.url
= GURL(test_cases
[i
]);
13227 EXPECT_EQ(ERR_IO_PENDING
,
13228 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13230 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13231 fake_factory
->last_stream_request();
13232 ASSERT_TRUE(fake_request
!= NULL
);
13233 EXPECT_EQ(&websocket_stream_create_helper
,
13234 fake_request
->websocket_stream_create_helper());
13238 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13239 // if the transport socket pool is stalled on the global socket limit.
13240 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13241 ClientSocketPoolManager::set_max_sockets_per_group(
13242 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13243 ClientSocketPoolManager::set_max_sockets_per_pool(
13244 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13246 // Set up SSL request.
13248 HttpRequestInfo ssl_request
;
13249 ssl_request
.method
= "GET";
13250 ssl_request
.url
= GURL("https://www.example.org/");
13252 MockWrite ssl_writes
[] = {
13254 "GET / HTTP/1.1\r\n"
13255 "Host: www.example.org\r\n"
13256 "Connection: keep-alive\r\n\r\n"),
13258 MockRead ssl_reads
[] = {
13259 MockRead("HTTP/1.1 200 OK\r\n"),
13260 MockRead("Content-Length: 11\r\n\r\n"),
13261 MockRead("hello world"),
13262 MockRead(SYNCHRONOUS
, OK
),
13264 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13265 ssl_writes
, arraysize(ssl_writes
));
13266 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13268 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13269 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13271 // Set up HTTP request.
13273 HttpRequestInfo http_request
;
13274 http_request
.method
= "GET";
13275 http_request
.url
= GURL("http://www.example.org/");
13277 MockWrite http_writes
[] = {
13279 "GET / HTTP/1.1\r\n"
13280 "Host: www.example.org\r\n"
13281 "Connection: keep-alive\r\n\r\n"),
13283 MockRead http_reads
[] = {
13284 MockRead("HTTP/1.1 200 OK\r\n"),
13285 MockRead("Content-Length: 7\r\n\r\n"),
13286 MockRead("falafel"),
13287 MockRead(SYNCHRONOUS
, OK
),
13289 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13290 http_writes
, arraysize(http_writes
));
13291 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13293 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13295 // Start the SSL request.
13296 TestCompletionCallback ssl_callback
;
13297 scoped_ptr
<HttpTransaction
> ssl_trans(
13298 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13299 ASSERT_EQ(ERR_IO_PENDING
,
13300 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13303 // Start the HTTP request. Pool should stall.
13304 TestCompletionCallback http_callback
;
13305 scoped_ptr
<HttpTransaction
> http_trans(
13306 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13307 ASSERT_EQ(ERR_IO_PENDING
,
13308 http_trans
->Start(&http_request
, http_callback
.callback(),
13310 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13312 // Wait for response from SSL request.
13313 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13314 std::string response_data
;
13315 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13316 EXPECT_EQ("hello world", response_data
);
13318 // The SSL socket should automatically be closed, so the HTTP request can
13320 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13321 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13323 // The HTTP request can now complete.
13324 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13325 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13326 EXPECT_EQ("falafel", response_data
);
13328 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13331 // Tests that when a SSL connection is established but there's no corresponding
13332 // request that needs it, the new socket is closed if the transport socket pool
13333 // is stalled on the global socket limit.
13334 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13335 ClientSocketPoolManager::set_max_sockets_per_group(
13336 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13337 ClientSocketPoolManager::set_max_sockets_per_pool(
13338 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13340 // Set up an ssl request.
13342 HttpRequestInfo ssl_request
;
13343 ssl_request
.method
= "GET";
13344 ssl_request
.url
= GURL("https://www.foopy.com/");
13346 // No data will be sent on the SSL socket.
13347 StaticSocketDataProvider ssl_data
;
13348 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13350 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13351 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13353 // Set up HTTP request.
13355 HttpRequestInfo http_request
;
13356 http_request
.method
= "GET";
13357 http_request
.url
= GURL("http://www.example.org/");
13359 MockWrite http_writes
[] = {
13361 "GET / HTTP/1.1\r\n"
13362 "Host: www.example.org\r\n"
13363 "Connection: keep-alive\r\n\r\n"),
13365 MockRead http_reads
[] = {
13366 MockRead("HTTP/1.1 200 OK\r\n"),
13367 MockRead("Content-Length: 7\r\n\r\n"),
13368 MockRead("falafel"),
13369 MockRead(SYNCHRONOUS
, OK
),
13371 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13372 http_writes
, arraysize(http_writes
));
13373 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13375 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13377 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13378 // cancelled when a normal transaction is cancelled.
13379 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13380 SSLConfig ssl_config
;
13381 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13382 http_stream_factory
->PreconnectStreams(1, ssl_request
, DEFAULT_PRIORITY
,
13383 ssl_config
, ssl_config
);
13384 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13386 // Start the HTTP request. Pool should stall.
13387 TestCompletionCallback http_callback
;
13388 scoped_ptr
<HttpTransaction
> http_trans(
13389 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13390 ASSERT_EQ(ERR_IO_PENDING
,
13391 http_trans
->Start(&http_request
, http_callback
.callback(),
13393 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13395 // The SSL connection will automatically be closed once the connection is
13396 // established, to let the HTTP request start.
13397 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13398 std::string response_data
;
13399 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13400 EXPECT_EQ("falafel", response_data
);
13402 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13405 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13406 ScopedVector
<UploadElementReader
> element_readers
;
13407 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13408 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13410 HttpRequestInfo request
;
13411 request
.method
= "POST";
13412 request
.url
= GURL("http://www.foo.com/");
13413 request
.upload_data_stream
= &upload_data_stream
;
13414 request
.load_flags
= 0;
13416 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13417 scoped_ptr
<HttpTransaction
> trans(
13418 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13419 // Send headers successfully, but get an error while sending the body.
13420 MockWrite data_writes
[] = {
13421 MockWrite("POST / HTTP/1.1\r\n"
13422 "Host: www.foo.com\r\n"
13423 "Connection: keep-alive\r\n"
13424 "Content-Length: 3\r\n\r\n"),
13425 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13428 MockRead data_reads
[] = {
13429 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13430 MockRead("hello world"),
13431 MockRead(SYNCHRONOUS
, OK
),
13433 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13434 arraysize(data_writes
));
13435 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13437 TestCompletionCallback callback
;
13439 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13442 rv
= callback
.WaitForResult();
13445 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13446 ASSERT_TRUE(response
!= NULL
);
13448 EXPECT_TRUE(response
->headers
.get() != NULL
);
13449 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13451 std::string response_data
;
13452 rv
= ReadTransaction(trans
.get(), &response_data
);
13454 EXPECT_EQ("hello world", response_data
);
13457 // This test makes sure the retry logic doesn't trigger when reading an error
13458 // response from a server that rejected a POST with a CONNECTION_RESET.
13459 TEST_P(HttpNetworkTransactionTest
,
13460 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13461 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13462 MockWrite data_writes
[] = {
13463 MockWrite("GET / HTTP/1.1\r\n"
13464 "Host: www.foo.com\r\n"
13465 "Connection: keep-alive\r\n\r\n"),
13466 MockWrite("POST / HTTP/1.1\r\n"
13467 "Host: www.foo.com\r\n"
13468 "Connection: keep-alive\r\n"
13469 "Content-Length: 3\r\n\r\n"),
13470 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13473 MockRead data_reads
[] = {
13474 MockRead("HTTP/1.1 200 Peachy\r\n"
13475 "Content-Length: 14\r\n\r\n"),
13476 MockRead("first response"),
13477 MockRead("HTTP/1.1 400 Not OK\r\n"
13478 "Content-Length: 15\r\n\r\n"),
13479 MockRead("second response"),
13480 MockRead(SYNCHRONOUS
, OK
),
13482 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13483 arraysize(data_writes
));
13484 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13486 TestCompletionCallback callback
;
13487 HttpRequestInfo request1
;
13488 request1
.method
= "GET";
13489 request1
.url
= GURL("http://www.foo.com/");
13490 request1
.load_flags
= 0;
13492 scoped_ptr
<HttpTransaction
> trans1(
13493 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13494 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13495 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13497 rv
= callback
.WaitForResult();
13500 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13501 ASSERT_TRUE(response1
!= NULL
);
13503 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13504 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13506 std::string response_data1
;
13507 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13509 EXPECT_EQ("first response", response_data1
);
13510 // Delete the transaction to release the socket back into the socket pool.
13513 ScopedVector
<UploadElementReader
> element_readers
;
13514 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13515 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13517 HttpRequestInfo request2
;
13518 request2
.method
= "POST";
13519 request2
.url
= GURL("http://www.foo.com/");
13520 request2
.upload_data_stream
= &upload_data_stream
;
13521 request2
.load_flags
= 0;
13523 scoped_ptr
<HttpTransaction
> trans2(
13524 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13525 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13526 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13528 rv
= callback
.WaitForResult();
13531 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13532 ASSERT_TRUE(response2
!= NULL
);
13534 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13535 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13537 std::string response_data2
;
13538 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13540 EXPECT_EQ("second response", response_data2
);
13543 TEST_P(HttpNetworkTransactionTest
,
13544 PostReadsErrorResponseAfterResetPartialBodySent
) {
13545 ScopedVector
<UploadElementReader
> element_readers
;
13546 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13547 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13549 HttpRequestInfo request
;
13550 request
.method
= "POST";
13551 request
.url
= GURL("http://www.foo.com/");
13552 request
.upload_data_stream
= &upload_data_stream
;
13553 request
.load_flags
= 0;
13555 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13556 scoped_ptr
<HttpTransaction
> trans(
13557 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13558 // Send headers successfully, but get an error while sending the body.
13559 MockWrite data_writes
[] = {
13560 MockWrite("POST / HTTP/1.1\r\n"
13561 "Host: www.foo.com\r\n"
13562 "Connection: keep-alive\r\n"
13563 "Content-Length: 3\r\n\r\n"
13565 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13568 MockRead data_reads
[] = {
13569 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13570 MockRead("hello world"),
13571 MockRead(SYNCHRONOUS
, OK
),
13573 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13574 arraysize(data_writes
));
13575 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13577 TestCompletionCallback callback
;
13579 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13580 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13582 rv
= callback
.WaitForResult();
13585 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13586 ASSERT_TRUE(response
!= NULL
);
13588 EXPECT_TRUE(response
->headers
.get() != NULL
);
13589 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13591 std::string response_data
;
13592 rv
= ReadTransaction(trans
.get(), &response_data
);
13594 EXPECT_EQ("hello world", response_data
);
13597 // This tests the more common case than the previous test, where headers and
13598 // body are not merged into a single request.
13599 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13600 ScopedVector
<UploadElementReader
> element_readers
;
13601 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13602 ChunkedUploadDataStream
upload_data_stream(0);
13604 HttpRequestInfo request
;
13605 request
.method
= "POST";
13606 request
.url
= GURL("http://www.foo.com/");
13607 request
.upload_data_stream
= &upload_data_stream
;
13608 request
.load_flags
= 0;
13610 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13611 scoped_ptr
<HttpTransaction
> trans(
13612 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13613 // Send headers successfully, but get an error while sending the body.
13614 MockWrite data_writes
[] = {
13615 MockWrite("POST / HTTP/1.1\r\n"
13616 "Host: www.foo.com\r\n"
13617 "Connection: keep-alive\r\n"
13618 "Transfer-Encoding: chunked\r\n\r\n"),
13619 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13622 MockRead data_reads
[] = {
13623 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13624 MockRead("hello world"),
13625 MockRead(SYNCHRONOUS
, OK
),
13627 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13628 arraysize(data_writes
));
13629 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13631 TestCompletionCallback callback
;
13633 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13634 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13635 // Make sure the headers are sent before adding a chunk. This ensures that
13636 // they can't be merged with the body in a single send. Not currently
13637 // necessary since a chunked body is never merged with headers, but this makes
13638 // the test more future proof.
13639 base::RunLoop().RunUntilIdle();
13641 upload_data_stream
.AppendData("last chunk", 10, true);
13643 rv
= callback
.WaitForResult();
13646 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13647 ASSERT_TRUE(response
!= NULL
);
13649 EXPECT_TRUE(response
->headers
.get() != NULL
);
13650 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13652 std::string response_data
;
13653 rv
= ReadTransaction(trans
.get(), &response_data
);
13655 EXPECT_EQ("hello world", response_data
);
13658 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
13659 ScopedVector
<UploadElementReader
> element_readers
;
13660 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13661 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13663 HttpRequestInfo request
;
13664 request
.method
= "POST";
13665 request
.url
= GURL("http://www.foo.com/");
13666 request
.upload_data_stream
= &upload_data_stream
;
13667 request
.load_flags
= 0;
13669 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13670 scoped_ptr
<HttpTransaction
> trans(
13671 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13673 MockWrite data_writes
[] = {
13674 MockWrite("POST / HTTP/1.1\r\n"
13675 "Host: www.foo.com\r\n"
13676 "Connection: keep-alive\r\n"
13677 "Content-Length: 3\r\n\r\n"),
13678 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13681 MockRead data_reads
[] = {
13682 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13683 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13684 MockRead("hello world"),
13685 MockRead(SYNCHRONOUS
, OK
),
13687 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13688 arraysize(data_writes
));
13689 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13691 TestCompletionCallback callback
;
13693 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13694 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13696 rv
= callback
.WaitForResult();
13699 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13700 ASSERT_TRUE(response
!= NULL
);
13702 EXPECT_TRUE(response
->headers
.get() != NULL
);
13703 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13705 std::string response_data
;
13706 rv
= ReadTransaction(trans
.get(), &response_data
);
13708 EXPECT_EQ("hello world", response_data
);
13711 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
13712 ScopedVector
<UploadElementReader
> element_readers
;
13713 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13714 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13716 HttpRequestInfo request
;
13717 request
.method
= "POST";
13718 request
.url
= GURL("http://www.foo.com/");
13719 request
.upload_data_stream
= &upload_data_stream
;
13720 request
.load_flags
= 0;
13722 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13723 scoped_ptr
<HttpTransaction
> trans(
13724 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13725 // Send headers successfully, but get an error while sending the body.
13726 MockWrite data_writes
[] = {
13727 MockWrite("POST / HTTP/1.1\r\n"
13728 "Host: www.foo.com\r\n"
13729 "Connection: keep-alive\r\n"
13730 "Content-Length: 3\r\n\r\n"),
13731 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13734 MockRead data_reads
[] = {
13735 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
13736 MockRead("hello world"),
13737 MockRead(SYNCHRONOUS
, OK
),
13739 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13740 arraysize(data_writes
));
13741 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13743 TestCompletionCallback callback
;
13745 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13746 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13748 rv
= callback
.WaitForResult();
13749 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13751 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13752 EXPECT_TRUE(response
== NULL
);
13755 TEST_P(HttpNetworkTransactionTest
,
13756 PostIgnoresNonErrorResponseAfterResetAnd100
) {
13757 ScopedVector
<UploadElementReader
> element_readers
;
13758 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13759 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13761 HttpRequestInfo request
;
13762 request
.method
= "POST";
13763 request
.url
= GURL("http://www.foo.com/");
13764 request
.upload_data_stream
= &upload_data_stream
;
13765 request
.load_flags
= 0;
13767 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13768 scoped_ptr
<HttpTransaction
> trans(
13769 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13770 // Send headers successfully, but get an error while sending the body.
13771 MockWrite data_writes
[] = {
13772 MockWrite("POST / HTTP/1.1\r\n"
13773 "Host: www.foo.com\r\n"
13774 "Connection: keep-alive\r\n"
13775 "Content-Length: 3\r\n\r\n"),
13776 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13779 MockRead data_reads
[] = {
13780 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
13781 MockRead("HTTP/1.0 302 Redirect\r\n"),
13782 MockRead("Location: http://somewhere-else.com/\r\n"),
13783 MockRead("Content-Length: 0\r\n\r\n"),
13784 MockRead(SYNCHRONOUS
, OK
),
13786 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13787 arraysize(data_writes
));
13788 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13790 TestCompletionCallback callback
;
13792 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13793 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13795 rv
= callback
.WaitForResult();
13796 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13798 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13799 EXPECT_TRUE(response
== NULL
);
13802 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
13803 ScopedVector
<UploadElementReader
> element_readers
;
13804 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13805 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13807 HttpRequestInfo request
;
13808 request
.method
= "POST";
13809 request
.url
= GURL("http://www.foo.com/");
13810 request
.upload_data_stream
= &upload_data_stream
;
13811 request
.load_flags
= 0;
13813 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13814 scoped_ptr
<HttpTransaction
> trans(
13815 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13816 // Send headers successfully, but get an error while sending the body.
13817 MockWrite data_writes
[] = {
13818 MockWrite("POST / HTTP/1.1\r\n"
13819 "Host: www.foo.com\r\n"
13820 "Connection: keep-alive\r\n"
13821 "Content-Length: 3\r\n\r\n"),
13822 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13825 MockRead data_reads
[] = {
13826 MockRead("HTTP 0.9 rocks!"),
13827 MockRead(SYNCHRONOUS
, OK
),
13829 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13830 arraysize(data_writes
));
13831 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13833 TestCompletionCallback callback
;
13835 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13836 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13838 rv
= callback
.WaitForResult();
13839 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13841 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13842 EXPECT_TRUE(response
== NULL
);
13845 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
13846 ScopedVector
<UploadElementReader
> element_readers
;
13847 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13848 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13850 HttpRequestInfo request
;
13851 request
.method
= "POST";
13852 request
.url
= GURL("http://www.foo.com/");
13853 request
.upload_data_stream
= &upload_data_stream
;
13854 request
.load_flags
= 0;
13856 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13857 scoped_ptr
<HttpTransaction
> trans(
13858 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13859 // Send headers successfully, but get an error while sending the body.
13860 MockWrite data_writes
[] = {
13861 MockWrite("POST / HTTP/1.1\r\n"
13862 "Host: www.foo.com\r\n"
13863 "Connection: keep-alive\r\n"
13864 "Content-Length: 3\r\n\r\n"),
13865 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13868 MockRead data_reads
[] = {
13869 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
13870 MockRead(SYNCHRONOUS
, OK
),
13872 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13873 arraysize(data_writes
));
13874 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13876 TestCompletionCallback callback
;
13878 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13879 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13881 rv
= callback
.WaitForResult();
13882 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13884 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13885 EXPECT_TRUE(response
== NULL
);
13888 // Verify that proxy headers are not sent to the destination server when
13889 // establishing a tunnel for a secure WebSocket connection.
13890 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
13891 HttpRequestInfo request
;
13892 request
.method
= "GET";
13893 request
.url
= GURL("wss://www.example.org/");
13894 AddWebSocketHeaders(&request
.extra_headers
);
13896 // Configure against proxy server "myproxy:70".
13897 session_deps_
.proxy_service
.reset(
13898 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
13900 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13902 // Since a proxy is configured, try to establish a tunnel.
13903 MockWrite data_writes
[] = {
13905 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13906 "Host: www.example.org\r\n"
13907 "Proxy-Connection: keep-alive\r\n\r\n"),
13909 // After calling trans->RestartWithAuth(), this is the request we should
13910 // be issuing -- the final header line contains the credentials.
13912 "CONNECT www.example.org:443 HTTP/1.1\r\n"
13913 "Host: www.example.org\r\n"
13914 "Proxy-Connection: keep-alive\r\n"
13915 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13918 "GET / HTTP/1.1\r\n"
13919 "Host: www.example.org\r\n"
13920 "Connection: Upgrade\r\n"
13921 "Upgrade: websocket\r\n"
13922 "Origin: http://www.example.org\r\n"
13923 "Sec-WebSocket-Version: 13\r\n"
13924 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
13927 // The proxy responds to the connect with a 407, using a persistent
13929 MockRead data_reads
[] = {
13931 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
13932 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13933 MockRead("Proxy-Connection: close\r\n\r\n"),
13935 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
13937 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
13938 MockRead("Upgrade: websocket\r\n"),
13939 MockRead("Connection: Upgrade\r\n"),
13940 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
13943 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13944 arraysize(data_writes
));
13945 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13946 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13947 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13949 scoped_ptr
<HttpTransaction
> trans(
13950 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13951 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13952 trans
->SetWebSocketHandshakeStreamCreateHelper(
13953 &websocket_stream_create_helper
);
13956 TestCompletionCallback callback
;
13958 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13959 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13961 rv
= callback
.WaitForResult();
13965 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13966 ASSERT_TRUE(response
);
13967 ASSERT_TRUE(response
->headers
.get());
13968 EXPECT_EQ(407, response
->headers
->response_code());
13971 TestCompletionCallback callback
;
13973 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
13974 callback
.callback());
13975 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13977 rv
= callback
.WaitForResult();
13981 response
= trans
->GetResponseInfo();
13982 ASSERT_TRUE(response
);
13983 ASSERT_TRUE(response
->headers
.get());
13985 EXPECT_EQ(101, response
->headers
->response_code());
13988 session
->CloseAllConnections();
13991 // Verify that proxy headers are not sent to the destination server when
13992 // establishing a tunnel for an insecure WebSocket connection.
13993 // This requires the authentication info to be injected into the auth cache
13994 // due to crbug.com/395064
13995 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
13996 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
13997 HttpRequestInfo request
;
13998 request
.method
= "GET";
13999 request
.url
= GURL("ws://www.example.org/");
14000 AddWebSocketHeaders(&request
.extra_headers
);
14002 // Configure against proxy server "myproxy:70".
14003 session_deps_
.proxy_service
.reset(
14004 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14006 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14008 MockWrite data_writes
[] = {
14009 // Try to establish a tunnel for the WebSocket connection, with
14010 // credentials. Because WebSockets have a separate set of socket pools,
14011 // they cannot and will not use the same TCP/IP connection as the
14012 // preflight HTTP request.
14014 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14015 "Host: www.example.org:80\r\n"
14016 "Proxy-Connection: keep-alive\r\n"
14017 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14020 "GET / HTTP/1.1\r\n"
14021 "Host: www.example.org\r\n"
14022 "Connection: Upgrade\r\n"
14023 "Upgrade: websocket\r\n"
14024 "Origin: http://www.example.org\r\n"
14025 "Sec-WebSocket-Version: 13\r\n"
14026 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14029 MockRead data_reads
[] = {
14030 // HTTP CONNECT with credentials.
14031 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14033 // WebSocket connection established inside tunnel.
14034 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14035 MockRead("Upgrade: websocket\r\n"),
14036 MockRead("Connection: Upgrade\r\n"),
14037 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14040 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14041 arraysize(data_writes
));
14042 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14044 session
->http_auth_cache()->Add(
14045 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14046 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14048 scoped_ptr
<HttpTransaction
> trans(
14049 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14050 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14051 trans
->SetWebSocketHandshakeStreamCreateHelper(
14052 &websocket_stream_create_helper
);
14054 TestCompletionCallback callback
;
14056 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14057 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14059 rv
= callback
.WaitForResult();
14062 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14063 ASSERT_TRUE(response
);
14064 ASSERT_TRUE(response
->headers
.get());
14066 EXPECT_EQ(101, response
->headers
->response_code());
14069 session
->CloseAllConnections();