1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_network_transaction.h"
7 #include <math.h> // ceil
12 #include "base/basictypes.h"
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/json/json_writer.h"
17 #include "base/logging.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/run_loop.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_util.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/test/test_file_util.h"
25 #include "base/thread_task_runner_handle.h"
26 #include "net/base/auth.h"
27 #include "net/base/chunked_upload_data_stream.h"
28 #include "net/base/completion_callback.h"
29 #include "net/base/elements_upload_data_stream.h"
30 #include "net/base/load_timing_info.h"
31 #include "net/base/load_timing_info_test_util.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/request_priority.h"
34 #include "net/base/test_completion_callback.h"
35 #include "net/base/test_data_directory.h"
36 #include "net/base/upload_bytes_element_reader.h"
37 #include "net/base/upload_file_element_reader.h"
38 #include "net/cert/mock_cert_verifier.h"
39 #include "net/dns/host_cache.h"
40 #include "net/dns/mock_host_resolver.h"
41 #include "net/http/http_auth_challenge_tokenizer.h"
42 #include "net/http/http_auth_handler_digest.h"
43 #include "net/http/http_auth_handler_mock.h"
44 #include "net/http/http_auth_handler_ntlm.h"
45 #include "net/http/http_basic_state.h"
46 #include "net/http/http_basic_stream.h"
47 #include "net/http/http_network_session.h"
48 #include "net/http/http_network_session_peer.h"
49 #include "net/http/http_request_headers.h"
50 #include "net/http/http_server_properties_impl.h"
51 #include "net/http/http_stream.h"
52 #include "net/http/http_stream_factory.h"
53 #include "net/http/http_stream_parser.h"
54 #include "net/http/http_transaction_test_util.h"
55 #include "net/log/net_log.h"
56 #include "net/log/test_net_log.h"
57 #include "net/log/test_net_log_entry.h"
58 #include "net/log/test_net_log_util.h"
59 #include "net/proxy/mock_proxy_resolver.h"
60 #include "net/proxy/proxy_config_service_fixed.h"
61 #include "net/proxy/proxy_info.h"
62 #include "net/proxy/proxy_resolver.h"
63 #include "net/proxy/proxy_service.h"
64 #include "net/socket/client_socket_factory.h"
65 #include "net/socket/client_socket_pool_manager.h"
66 #include "net/socket/connection_attempts.h"
67 #include "net/socket/mock_client_socket_pool_manager.h"
68 #include "net/socket/next_proto.h"
69 #include "net/socket/socket_test_util.h"
70 #include "net/socket/ssl_client_socket.h"
71 #include "net/spdy/spdy_framer.h"
72 #include "net/spdy/spdy_session.h"
73 #include "net/spdy/spdy_session_pool.h"
74 #include "net/spdy/spdy_test_util_common.h"
75 #include "net/ssl/ssl_cert_request_info.h"
76 #include "net/ssl/ssl_config_service.h"
77 #include "net/ssl/ssl_config_service_defaults.h"
78 #include "net/ssl/ssl_info.h"
79 #include "net/test/cert_test_util.h"
80 #include "net/websockets/websocket_handshake_stream_base.h"
81 #include "testing/gtest/include/gtest/gtest.h"
82 #include "testing/platform_test.h"
85 using base::ASCIIToUTF16
;
87 //-----------------------------------------------------------------------------
93 const base::string16
kBar(ASCIIToUTF16("bar"));
94 const base::string16
kBar2(ASCIIToUTF16("bar2"));
95 const base::string16
kBar3(ASCIIToUTF16("bar3"));
96 const base::string16
kBaz(ASCIIToUTF16("baz"));
97 const base::string16
kFirst(ASCIIToUTF16("first"));
98 const base::string16
kFoo(ASCIIToUTF16("foo"));
99 const base::string16
kFoo2(ASCIIToUTF16("foo2"));
100 const base::string16
kFoo3(ASCIIToUTF16("foo3"));
101 const base::string16
kFou(ASCIIToUTF16("fou"));
102 const base::string16
kSecond(ASCIIToUTF16("second"));
103 const base::string16
kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
104 const base::string16
kWrongPassword(ASCIIToUTF16("wrongpassword"));
106 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession
* session
) {
107 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
111 int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession
* session
) {
112 return session
->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
116 bool IsTransportSocketPoolStalled(HttpNetworkSession
* session
) {
117 return session
->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL
)
121 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
122 // a JSONified list of headers as a single string. Uses single quotes instead
123 // of double quotes for easier comparison. Returns false on failure.
124 bool GetHeaders(base::DictionaryValue
* params
, std::string
* headers
) {
127 base::ListValue
* header_list
;
128 if (!params
->GetList("headers", &header_list
))
130 std::string double_quote_headers
;
131 base::JSONWriter::Write(*header_list
, &double_quote_headers
);
132 base::ReplaceChars(double_quote_headers
, "\"", "'", headers
);
136 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
138 void TestLoadTimingReused(const LoadTimingInfo
& load_timing_info
) {
139 EXPECT_TRUE(load_timing_info
.socket_reused
);
140 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
142 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
143 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
145 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
146 EXPECT_FALSE(load_timing_info
.send_start
.is_null());
148 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
150 // Set at a higher level.
151 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
152 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
153 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
156 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
158 void TestLoadTimingNotReused(const LoadTimingInfo
& load_timing_info
,
159 int connect_timing_flags
) {
160 EXPECT_FALSE(load_timing_info
.socket_reused
);
161 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
163 EXPECT_TRUE(load_timing_info
.proxy_resolve_start
.is_null());
164 EXPECT_TRUE(load_timing_info
.proxy_resolve_end
.is_null());
166 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
167 connect_timing_flags
);
168 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
169 load_timing_info
.send_start
);
171 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
173 // Set at a higher level.
174 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
175 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
176 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
179 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
181 void TestLoadTimingReusedWithPac(const LoadTimingInfo
& load_timing_info
) {
182 EXPECT_TRUE(load_timing_info
.socket_reused
);
183 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
185 ExpectConnectTimingHasNoTimes(load_timing_info
.connect_timing
);
187 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
188 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
189 load_timing_info
.proxy_resolve_end
);
190 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
191 load_timing_info
.send_start
);
192 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
194 // Set at a higher level.
195 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
196 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
197 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
200 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
202 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo
& load_timing_info
,
203 int connect_timing_flags
) {
204 EXPECT_FALSE(load_timing_info
.socket_reused
);
205 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
207 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
208 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
209 load_timing_info
.proxy_resolve_end
);
210 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
211 load_timing_info
.connect_timing
.connect_start
);
212 ExpectConnectTimingHasTimes(load_timing_info
.connect_timing
,
213 connect_timing_flags
);
214 EXPECT_LE(load_timing_info
.connect_timing
.connect_end
,
215 load_timing_info
.send_start
);
217 EXPECT_LE(load_timing_info
.send_start
, load_timing_info
.send_end
);
219 // Set at a higher level.
220 EXPECT_TRUE(load_timing_info
.request_start_time
.is_null());
221 EXPECT_TRUE(load_timing_info
.request_start
.is_null());
222 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
225 void AddWebSocketHeaders(HttpRequestHeaders
* headers
) {
226 headers
->SetHeader("Connection", "Upgrade");
227 headers
->SetHeader("Upgrade", "websocket");
228 headers
->SetHeader("Origin", "http://www.example.org");
229 headers
->SetHeader("Sec-WebSocket-Version", "13");
230 headers
->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
233 HttpNetworkSession
* CreateSession(SpdySessionDependencies
* session_deps
) {
234 return SpdySessionDependencies::SpdyCreateSession(session_deps
);
239 class HttpNetworkTransactionTest
240 : public PlatformTest
,
241 public ::testing::WithParamInterface
<NextProto
> {
243 virtual ~HttpNetworkTransactionTest() {
244 // Important to restore the per-pool limit first, since the pool limit must
245 // always be greater than group limit, and the tests reduce both limits.
246 ClientSocketPoolManager::set_max_sockets_per_pool(
247 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_pool_sockets_
);
248 ClientSocketPoolManager::set_max_sockets_per_group(
249 HttpNetworkSession::NORMAL_SOCKET_POOL
, old_max_group_sockets_
);
253 HttpNetworkTransactionTest()
254 : spdy_util_(GetParam()),
255 session_deps_(GetParam()),
256 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
257 HttpNetworkSession::NORMAL_SOCKET_POOL
)),
258 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
259 HttpNetworkSession::NORMAL_SOCKET_POOL
)) {
262 struct SimpleGetHelperResult
{
264 std::string status_line
;
265 std::string response_data
;
266 int64 totalReceivedBytes
;
267 LoadTimingInfo load_timing_info
;
268 ConnectionAttempts connection_attempts
;
271 void SetUp() override
{
272 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
273 base::MessageLoop::current()->RunUntilIdle();
276 void TearDown() override
{
277 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
278 base::MessageLoop::current()->RunUntilIdle();
279 // Empty the current queue.
280 base::MessageLoop::current()->RunUntilIdle();
281 PlatformTest::TearDown();
282 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
283 base::MessageLoop::current()->RunUntilIdle();
286 const char* GetAlternateProtocolFromParam() {
288 AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam()));
291 std::string
GetAlternativeServiceHttpHeader() {
292 return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() +
293 "=\"www.example.com:443\"\r\n";
296 std::string
GetAlternateProtocolHttpHeader() {
297 return std::string("Alternate-Protocol: 443:") +
298 GetAlternateProtocolFromParam() + "\r\n";
301 // Either |write_failure| specifies a write failure or |read_failure|
302 // specifies a read failure when using a reused socket. In either case, the
303 // failure should cause the network transaction to resend the request, and the
304 // other argument should be NULL.
305 void KeepAliveConnectionResendRequestTest(const MockWrite
* write_failure
,
306 const MockRead
* read_failure
);
308 // Either |write_failure| specifies a write failure or |read_failure|
309 // specifies a read failure when using a reused socket. In either case, the
310 // failure should cause the network transaction to resend the request, and the
311 // other argument should be NULL.
312 void PreconnectErrorResendRequestTest(const MockWrite
* write_failure
,
313 const MockRead
* read_failure
,
316 SimpleGetHelperResult
SimpleGetHelperForData(StaticSocketDataProvider
* data
[],
318 SimpleGetHelperResult out
;
320 HttpRequestInfo request
;
321 request
.method
= "GET";
322 request
.url
= GURL("http://www.example.org/");
323 request
.load_flags
= 0;
326 session_deps_
.net_log
= log
.bound().net_log();
327 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
328 scoped_ptr
<HttpTransaction
> trans(
329 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
331 for (size_t i
= 0; i
< data_count
; ++i
) {
332 session_deps_
.socket_factory
->AddSocketDataProvider(data
[i
]);
335 TestCompletionCallback callback
;
337 EXPECT_TRUE(log
.bound().IsCapturing());
338 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
339 EXPECT_EQ(ERR_IO_PENDING
, rv
);
341 out
.rv
= callback
.WaitForResult();
343 // Even in the failure cases that use this function, connections are always
344 // successfully established before the error.
345 EXPECT_TRUE(trans
->GetLoadTimingInfo(&out
.load_timing_info
));
346 TestLoadTimingNotReused(out
.load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
351 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
352 // Can't use ASSERT_* inside helper functions like this, so
354 if (response
== NULL
|| response
->headers
.get() == NULL
) {
355 out
.rv
= ERR_UNEXPECTED
;
358 out
.status_line
= response
->headers
->GetStatusLine();
360 EXPECT_EQ("127.0.0.1", response
->socket_address
.host());
361 EXPECT_EQ(80, response
->socket_address
.port());
363 rv
= ReadTransaction(trans
.get(), &out
.response_data
);
366 TestNetLogEntry::List entries
;
367 log
.GetEntries(&entries
);
368 size_t pos
= ExpectLogContainsSomewhere(
369 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS
,
371 ExpectLogContainsSomewhere(
373 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS
,
377 EXPECT_TRUE(entries
[pos
].GetStringValue("line", &line
));
378 EXPECT_EQ("GET / HTTP/1.1\r\n", line
);
380 HttpRequestHeaders request_headers
;
381 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
383 EXPECT_TRUE(request_headers
.GetHeader("Host", &value
));
384 EXPECT_EQ("www.example.org", value
);
385 EXPECT_TRUE(request_headers
.GetHeader("Connection", &value
));
386 EXPECT_EQ("keep-alive", value
);
388 std::string response_headers
;
389 EXPECT_TRUE(GetHeaders(entries
[pos
].params
.get(), &response_headers
));
390 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
393 out
.totalReceivedBytes
= trans
->GetTotalReceivedBytes();
394 trans
->GetConnectionAttempts(&out
.connection_attempts
);
398 SimpleGetHelperResult
SimpleGetHelper(MockRead data_reads
[],
399 size_t reads_count
) {
400 StaticSocketDataProvider
reads(data_reads
, reads_count
, NULL
, 0);
401 StaticSocketDataProvider
* data
[] = { &reads
};
402 return SimpleGetHelperForData(data
, 1);
405 int64
ReadsSize(MockRead data_reads
[], size_t reads_count
) {
407 for (size_t i
= 0; i
< reads_count
; ++i
)
408 size
+= data_reads
[i
].data_len
;
412 void ConnectStatusHelperWithExpectedStatus(const MockRead
& status
,
413 int expected_status
);
415 void ConnectStatusHelper(const MockRead
& status
);
417 void BypassHostCacheOnRefreshHelper(int load_flags
);
419 void CheckErrorIsPassedBack(int error
, IoMode mode
);
421 SpdyTestUtil spdy_util_
;
422 SpdySessionDependencies session_deps_
;
424 // Original socket limits. Some tests set these. Safest to always restore
425 // them once each test has been run.
426 int old_max_group_sockets_
;
427 int old_max_pool_sockets_
;
430 INSTANTIATE_TEST_CASE_P(NextProto
,
431 HttpNetworkTransactionTest
,
432 testing::Values(kProtoSPDY31
,
438 class BeforeNetworkStartHandler
{
440 explicit BeforeNetworkStartHandler(bool defer
)
441 : defer_on_before_network_start_(defer
),
442 observed_before_network_start_(false) {}
444 void OnBeforeNetworkStart(bool* defer
) {
445 *defer
= defer_on_before_network_start_
;
446 observed_before_network_start_
= true;
449 bool observed_before_network_start() const {
450 return observed_before_network_start_
;
454 const bool defer_on_before_network_start_
;
455 bool observed_before_network_start_
;
457 DISALLOW_COPY_AND_ASSIGN(BeforeNetworkStartHandler
);
460 class BeforeProxyHeadersSentHandler
{
462 BeforeProxyHeadersSentHandler()
463 : observed_before_proxy_headers_sent_(false) {}
465 void OnBeforeProxyHeadersSent(const ProxyInfo
& proxy_info
,
466 HttpRequestHeaders
* request_headers
) {
467 observed_before_proxy_headers_sent_
= true;
468 observed_proxy_server_uri_
= proxy_info
.proxy_server().ToURI();
471 bool observed_before_proxy_headers_sent() const {
472 return observed_before_proxy_headers_sent_
;
475 std::string
observed_proxy_server_uri() const {
476 return observed_proxy_server_uri_
;
480 bool observed_before_proxy_headers_sent_
;
481 std::string observed_proxy_server_uri_
;
483 DISALLOW_COPY_AND_ASSIGN(BeforeProxyHeadersSentHandler
);
486 // Fill |str| with a long header list that consumes >= |size| bytes.
487 void FillLargeHeadersString(std::string
* str
, int size
) {
489 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
490 const int sizeof_row
= strlen(row
);
491 const int num_rows
= static_cast<int>(
492 ceil(static_cast<float>(size
) / sizeof_row
));
493 const int sizeof_data
= num_rows
* sizeof_row
;
494 DCHECK(sizeof_data
>= size
);
495 str
->reserve(sizeof_data
);
497 for (int i
= 0; i
< num_rows
; ++i
)
498 str
->append(row
, sizeof_row
);
501 #if defined(NTLM_PORTABLE)
502 // Alternative functions that eliminate randomness and dependency on the local
503 // host name so that the generated NTLM messages are reproducible.
504 void MockGenerateRandom1(uint8
* output
, size_t n
) {
505 static const uint8 bytes
[] = {
506 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
508 static size_t current_byte
= 0;
509 for (size_t i
= 0; i
< n
; ++i
) {
510 output
[i
] = bytes
[current_byte
++];
511 current_byte
%= arraysize(bytes
);
515 void MockGenerateRandom2(uint8
* output
, size_t n
) {
516 static const uint8 bytes
[] = {
517 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
518 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
520 static size_t current_byte
= 0;
521 for (size_t i
= 0; i
< n
; ++i
) {
522 output
[i
] = bytes
[current_byte
++];
523 current_byte
%= arraysize(bytes
);
527 std::string
MockGetHostName() {
530 #endif // defined(NTLM_PORTABLE)
532 template<typename ParentPool
>
533 class CaptureGroupNameSocketPool
: public ParentPool
{
535 CaptureGroupNameSocketPool(HostResolver
* host_resolver
,
536 CertVerifier
* cert_verifier
);
538 const std::string
last_group_name_received() const {
539 return last_group_name_
;
542 int RequestSocket(const std::string
& group_name
,
543 const void* socket_params
,
544 RequestPriority priority
,
545 ClientSocketHandle
* handle
,
546 const CompletionCallback
& callback
,
547 const BoundNetLog
& net_log
) override
{
548 last_group_name_
= group_name
;
549 return ERR_IO_PENDING
;
551 void CancelRequest(const std::string
& group_name
,
552 ClientSocketHandle
* handle
) override
{}
553 void ReleaseSocket(const std::string
& group_name
,
554 scoped_ptr
<StreamSocket
> socket
,
556 void CloseIdleSockets() override
{}
557 int IdleSocketCount() const override
{ return 0; }
558 int IdleSocketCountInGroup(const std::string
& group_name
) const override
{
561 LoadState
GetLoadState(const std::string
& group_name
,
562 const ClientSocketHandle
* handle
) const override
{
563 return LOAD_STATE_IDLE
;
565 base::TimeDelta
ConnectionTimeout() const override
{
566 return base::TimeDelta();
570 std::string last_group_name_
;
573 typedef CaptureGroupNameSocketPool
<TransportClientSocketPool
>
574 CaptureGroupNameTransportSocketPool
;
575 typedef CaptureGroupNameSocketPool
<HttpProxyClientSocketPool
>
576 CaptureGroupNameHttpProxySocketPool
;
577 typedef CaptureGroupNameSocketPool
<SOCKSClientSocketPool
>
578 CaptureGroupNameSOCKSSocketPool
;
579 typedef CaptureGroupNameSocketPool
<SSLClientSocketPool
>
580 CaptureGroupNameSSLSocketPool
;
582 template <typename ParentPool
>
583 CaptureGroupNameSocketPool
<ParentPool
>::CaptureGroupNameSocketPool(
584 HostResolver
* host_resolver
,
585 CertVerifier
* /* cert_verifier */)
586 : ParentPool(0, 0, host_resolver
, NULL
, NULL
) {
590 CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
591 HostResolver
* /* host_resolver */,
592 CertVerifier
* /* cert_verifier */)
593 : HttpProxyClientSocketPool(0, 0, NULL
, NULL
, NULL
) {
597 CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
598 HostResolver
* /* host_resolver */,
599 CertVerifier
* cert_verifier
)
600 : SSLClientSocketPool(0,
616 //-----------------------------------------------------------------------------
618 // Helper functions for validating that AuthChallengeInfo's are correctly
619 // configured for common cases.
620 bool CheckBasicServerAuth(const AuthChallengeInfo
* auth_challenge
) {
623 EXPECT_FALSE(auth_challenge
->is_proxy
);
624 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
625 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
626 EXPECT_EQ("basic", auth_challenge
->scheme
);
630 bool CheckBasicProxyAuth(const AuthChallengeInfo
* auth_challenge
) {
633 EXPECT_TRUE(auth_challenge
->is_proxy
);
634 EXPECT_EQ("myproxy:70", auth_challenge
->challenger
.ToString());
635 EXPECT_EQ("MyRealm1", auth_challenge
->realm
);
636 EXPECT_EQ("basic", auth_challenge
->scheme
);
640 bool CheckDigestServerAuth(const AuthChallengeInfo
* auth_challenge
) {
643 EXPECT_FALSE(auth_challenge
->is_proxy
);
644 EXPECT_EQ("www.example.org:80", auth_challenge
->challenger
.ToString());
645 EXPECT_EQ("digestive", auth_challenge
->realm
);
646 EXPECT_EQ("digest", auth_challenge
->scheme
);
650 #if defined(NTLM_PORTABLE)
651 bool CheckNTLMServerAuth(const AuthChallengeInfo
* auth_challenge
) {
654 EXPECT_FALSE(auth_challenge
->is_proxy
);
655 EXPECT_EQ("172.22.68.17:80", auth_challenge
->challenger
.ToString());
656 EXPECT_EQ(std::string(), auth_challenge
->realm
);
657 EXPECT_EQ("ntlm", auth_challenge
->scheme
);
660 #endif // defined(NTLM_PORTABLE)
664 TEST_P(HttpNetworkTransactionTest
, Basic
) {
665 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
666 scoped_ptr
<HttpTransaction
> trans(
667 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
670 TEST_P(HttpNetworkTransactionTest
, SimpleGET
) {
671 MockRead data_reads
[] = {
672 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
673 MockRead("hello world"),
674 MockRead(SYNCHRONOUS
, OK
),
676 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
677 arraysize(data_reads
));
678 EXPECT_EQ(OK
, out
.rv
);
679 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
680 EXPECT_EQ("hello world", out
.response_data
);
681 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
682 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
683 EXPECT_EQ(0u, out
.connection_attempts
.size());
686 // Response with no status line.
687 TEST_P(HttpNetworkTransactionTest
, SimpleGETNoHeaders
) {
688 MockRead data_reads
[] = {
689 MockRead("hello world"),
690 MockRead(SYNCHRONOUS
, OK
),
692 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
693 arraysize(data_reads
));
694 EXPECT_EQ(OK
, out
.rv
);
695 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
696 EXPECT_EQ("hello world", out
.response_data
);
697 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
698 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
701 // Allow up to 4 bytes of junk to precede status line.
702 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk3Bytes
) {
703 MockRead data_reads
[] = {
704 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
705 MockRead(SYNCHRONOUS
, OK
),
707 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
708 arraysize(data_reads
));
709 EXPECT_EQ(OK
, out
.rv
);
710 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
711 EXPECT_EQ("DATA", out
.response_data
);
712 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
713 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
716 // Allow up to 4 bytes of junk to precede status line.
717 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes
) {
718 MockRead data_reads
[] = {
719 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
720 MockRead(SYNCHRONOUS
, OK
),
722 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
723 arraysize(data_reads
));
724 EXPECT_EQ(OK
, out
.rv
);
725 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
726 EXPECT_EQ("DATA", out
.response_data
);
727 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
728 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
731 // Beyond 4 bytes of slop and it should fail to find a status line.
732 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk5Bytes
) {
733 MockRead data_reads
[] = {
734 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
735 MockRead(SYNCHRONOUS
, OK
),
737 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
738 arraysize(data_reads
));
739 EXPECT_EQ(OK
, out
.rv
);
740 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
741 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out
.response_data
);
742 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
743 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
746 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
747 TEST_P(HttpNetworkTransactionTest
, StatusLineJunk4Bytes_Slow
) {
748 MockRead data_reads
[] = {
753 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
754 MockRead(SYNCHRONOUS
, OK
),
756 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
757 arraysize(data_reads
));
758 EXPECT_EQ(OK
, out
.rv
);
759 EXPECT_EQ("HTTP/1.0 404 Not Found", out
.status_line
);
760 EXPECT_EQ("DATA", out
.response_data
);
761 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
762 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
765 // Close the connection before enough bytes to have a status line.
766 TEST_P(HttpNetworkTransactionTest
, StatusLinePartial
) {
767 MockRead data_reads
[] = {
769 MockRead(SYNCHRONOUS
, OK
),
771 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
772 arraysize(data_reads
));
773 EXPECT_EQ(OK
, out
.rv
);
774 EXPECT_EQ("HTTP/0.9 200 OK", out
.status_line
);
775 EXPECT_EQ("HTT", out
.response_data
);
776 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
777 EXPECT_EQ(reads_size
, out
.totalReceivedBytes
);
780 // Simulate a 204 response, lacking a Content-Length header, sent over a
781 // persistent connection. The response should still terminate since a 204
782 // cannot have a response body.
783 TEST_P(HttpNetworkTransactionTest
, StopsReading204
) {
784 char junk
[] = "junk";
785 MockRead data_reads
[] = {
786 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
787 MockRead(junk
), // Should not be read!!
788 MockRead(SYNCHRONOUS
, OK
),
790 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
791 arraysize(data_reads
));
792 EXPECT_EQ(OK
, out
.rv
);
793 EXPECT_EQ("HTTP/1.1 204 No Content", out
.status_line
);
794 EXPECT_EQ("", out
.response_data
);
795 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
796 int64 response_size
= reads_size
- strlen(junk
);
797 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
800 // A simple request using chunked encoding with some extra data after.
801 TEST_P(HttpNetworkTransactionTest
, ChunkedEncoding
) {
802 std::string final_chunk
= "0\r\n\r\n";
803 std::string extra_data
= "HTTP/1.1 200 OK\r\n";
804 std::string last_read
= final_chunk
+ extra_data
;
805 MockRead data_reads
[] = {
806 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
807 MockRead("5\r\nHello\r\n"),
810 MockRead("5\r\nworld\r\n"),
811 MockRead(last_read
.data()),
812 MockRead(SYNCHRONOUS
, OK
),
814 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
815 arraysize(data_reads
));
816 EXPECT_EQ(OK
, out
.rv
);
817 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
818 EXPECT_EQ("Hello world", out
.response_data
);
819 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
820 int64 response_size
= reads_size
- extra_data
.size();
821 EXPECT_EQ(response_size
, out
.totalReceivedBytes
);
824 // Next tests deal with http://crbug.com/56344.
826 TEST_P(HttpNetworkTransactionTest
,
827 MultipleContentLengthHeadersNoTransferEncoding
) {
828 MockRead data_reads
[] = {
829 MockRead("HTTP/1.1 200 OK\r\n"),
830 MockRead("Content-Length: 10\r\n"),
831 MockRead("Content-Length: 5\r\n\r\n"),
833 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
834 arraysize(data_reads
));
835 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
838 TEST_P(HttpNetworkTransactionTest
,
839 DuplicateContentLengthHeadersNoTransferEncoding
) {
840 MockRead data_reads
[] = {
841 MockRead("HTTP/1.1 200 OK\r\n"),
842 MockRead("Content-Length: 5\r\n"),
843 MockRead("Content-Length: 5\r\n\r\n"),
846 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
847 arraysize(data_reads
));
848 EXPECT_EQ(OK
, out
.rv
);
849 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
850 EXPECT_EQ("Hello", out
.response_data
);
853 TEST_P(HttpNetworkTransactionTest
,
854 ComplexContentLengthHeadersNoTransferEncoding
) {
855 // More than 2 dupes.
857 MockRead data_reads
[] = {
858 MockRead("HTTP/1.1 200 OK\r\n"),
859 MockRead("Content-Length: 5\r\n"),
860 MockRead("Content-Length: 5\r\n"),
861 MockRead("Content-Length: 5\r\n\r\n"),
864 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
865 arraysize(data_reads
));
866 EXPECT_EQ(OK
, out
.rv
);
867 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
868 EXPECT_EQ("Hello", out
.response_data
);
872 MockRead data_reads
[] = {
873 MockRead("HTTP/1.0 200 OK\r\n"),
874 MockRead("Content-Length: 5\r\n"),
875 MockRead("Content-Length: 5\r\n"),
876 MockRead("Content-Length: 5\r\n\r\n"),
879 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
880 arraysize(data_reads
));
881 EXPECT_EQ(OK
, out
.rv
);
882 EXPECT_EQ("HTTP/1.0 200 OK", out
.status_line
);
883 EXPECT_EQ("Hello", out
.response_data
);
885 // 2 dupes and one mismatched.
887 MockRead data_reads
[] = {
888 MockRead("HTTP/1.1 200 OK\r\n"),
889 MockRead("Content-Length: 10\r\n"),
890 MockRead("Content-Length: 10\r\n"),
891 MockRead("Content-Length: 5\r\n\r\n"),
893 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
894 arraysize(data_reads
));
895 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
, out
.rv
);
899 TEST_P(HttpNetworkTransactionTest
,
900 MultipleContentLengthHeadersTransferEncoding
) {
901 MockRead data_reads
[] = {
902 MockRead("HTTP/1.1 200 OK\r\n"),
903 MockRead("Content-Length: 666\r\n"),
904 MockRead("Content-Length: 1337\r\n"),
905 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
906 MockRead("5\r\nHello\r\n"),
909 MockRead("5\r\nworld\r\n"),
910 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
911 MockRead(SYNCHRONOUS
, OK
),
913 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
914 arraysize(data_reads
));
915 EXPECT_EQ(OK
, out
.rv
);
916 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
917 EXPECT_EQ("Hello world", out
.response_data
);
920 // Next tests deal with http://crbug.com/98895.
922 // Checks that a single Content-Disposition header results in no error.
923 TEST_P(HttpNetworkTransactionTest
, SingleContentDispositionHeader
) {
924 MockRead data_reads
[] = {
925 MockRead("HTTP/1.1 200 OK\r\n"),
926 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
927 MockRead("Content-Length: 5\r\n\r\n"),
930 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
931 arraysize(data_reads
));
932 EXPECT_EQ(OK
, out
.rv
);
933 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
934 EXPECT_EQ("Hello", out
.response_data
);
937 // Checks that two identical Content-Disposition headers result in no error.
938 TEST_P(HttpNetworkTransactionTest
,
939 TwoIdenticalContentDispositionHeaders
) {
940 MockRead data_reads
[] = {
941 MockRead("HTTP/1.1 200 OK\r\n"),
942 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
943 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
944 MockRead("Content-Length: 5\r\n\r\n"),
947 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
948 arraysize(data_reads
));
949 EXPECT_EQ(OK
, out
.rv
);
950 EXPECT_EQ("HTTP/1.1 200 OK", out
.status_line
);
951 EXPECT_EQ("Hello", out
.response_data
);
954 // Checks that two distinct Content-Disposition headers result in an error.
955 TEST_P(HttpNetworkTransactionTest
, TwoDistinctContentDispositionHeaders
) {
956 MockRead data_reads
[] = {
957 MockRead("HTTP/1.1 200 OK\r\n"),
958 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
959 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
960 MockRead("Content-Length: 5\r\n\r\n"),
963 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
964 arraysize(data_reads
));
965 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
, out
.rv
);
968 // Checks that two identical Location headers result in no error.
969 // Also tests Location header behavior.
970 TEST_P(HttpNetworkTransactionTest
, TwoIdenticalLocationHeaders
) {
971 MockRead data_reads
[] = {
972 MockRead("HTTP/1.1 302 Redirect\r\n"),
973 MockRead("Location: http://good.com/\r\n"),
974 MockRead("Location: http://good.com/\r\n"),
975 MockRead("Content-Length: 0\r\n\r\n"),
976 MockRead(SYNCHRONOUS
, OK
),
979 HttpRequestInfo request
;
980 request
.method
= "GET";
981 request
.url
= GURL("http://redirect.com/");
982 request
.load_flags
= 0;
984 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
985 scoped_ptr
<HttpTransaction
> trans(
986 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
988 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
989 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
991 TestCompletionCallback callback
;
993 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
994 EXPECT_EQ(ERR_IO_PENDING
, rv
);
996 EXPECT_EQ(OK
, callback
.WaitForResult());
998 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
999 ASSERT_TRUE(response
!= NULL
&& response
->headers
.get() != NULL
);
1000 EXPECT_EQ("HTTP/1.1 302 Redirect", response
->headers
->GetStatusLine());
1002 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
1003 EXPECT_EQ("http://good.com/", url
);
1004 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1007 // Checks that two distinct Location headers result in an error.
1008 TEST_P(HttpNetworkTransactionTest
, TwoDistinctLocationHeaders
) {
1009 MockRead data_reads
[] = {
1010 MockRead("HTTP/1.1 302 Redirect\r\n"),
1011 MockRead("Location: http://good.com/\r\n"),
1012 MockRead("Location: http://evil.com/\r\n"),
1013 MockRead("Content-Length: 0\r\n\r\n"),
1014 MockRead(SYNCHRONOUS
, OK
),
1016 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1017 arraysize(data_reads
));
1018 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION
, out
.rv
);
1021 // Do a request using the HEAD method. Verify that we don't try to read the
1022 // message body (since HEAD has none).
1023 TEST_P(HttpNetworkTransactionTest
, Head
) {
1024 HttpRequestInfo request
;
1025 request
.method
= "HEAD";
1026 request
.url
= GURL("http://www.example.org/");
1027 request
.load_flags
= 0;
1029 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1030 scoped_ptr
<HttpTransaction
> trans(
1031 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1032 BeforeProxyHeadersSentHandler proxy_headers_handler
;
1033 trans
->SetBeforeProxyHeadersSentCallback(
1034 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
1035 base::Unretained(&proxy_headers_handler
)));
1037 MockWrite data_writes1
[] = {
1039 "HEAD / HTTP/1.1\r\n"
1040 "Host: www.example.org\r\n"
1041 "Connection: keep-alive\r\n"
1042 "Content-Length: 0\r\n\r\n"),
1044 MockRead data_reads1
[] = {
1045 MockRead("HTTP/1.1 404 Not Found\r\n"),
1046 MockRead("Server: Blah\r\n"),
1047 MockRead("Content-Length: 1234\r\n\r\n"),
1049 // No response body because the test stops reading here.
1050 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1053 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1054 data_writes1
, arraysize(data_writes1
));
1055 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1057 TestCompletionCallback callback1
;
1059 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1060 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1062 rv
= callback1
.WaitForResult();
1065 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1066 ASSERT_TRUE(response
!= NULL
);
1068 // Check that the headers got parsed.
1069 EXPECT_TRUE(response
->headers
.get() != NULL
);
1070 EXPECT_EQ(1234, response
->headers
->GetContentLength());
1071 EXPECT_EQ("HTTP/1.1 404 Not Found", response
->headers
->GetStatusLine());
1072 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1073 EXPECT_FALSE(proxy_headers_handler
.observed_before_proxy_headers_sent());
1075 std::string server_header
;
1077 bool has_server_header
= response
->headers
->EnumerateHeader(
1078 &iter
, "Server", &server_header
);
1079 EXPECT_TRUE(has_server_header
);
1080 EXPECT_EQ("Blah", server_header
);
1082 // Reading should give EOF right away, since there is no message body
1083 // (despite non-zero content-length).
1084 std::string response_data
;
1085 rv
= ReadTransaction(trans
.get(), &response_data
);
1087 EXPECT_EQ("", response_data
);
1090 TEST_P(HttpNetworkTransactionTest
, ReuseConnection
) {
1091 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1093 MockRead data_reads
[] = {
1094 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1096 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1098 MockRead(SYNCHRONOUS
, OK
),
1100 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1103 const char* const kExpectedResponseData
[] = {
1107 for (int i
= 0; i
< 2; ++i
) {
1108 HttpRequestInfo request
;
1109 request
.method
= "GET";
1110 request
.url
= GURL("http://www.example.org/");
1111 request
.load_flags
= 0;
1113 scoped_ptr
<HttpTransaction
> trans(
1114 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1116 TestCompletionCallback callback
;
1118 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1119 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1121 rv
= callback
.WaitForResult();
1124 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1125 ASSERT_TRUE(response
!= NULL
);
1127 EXPECT_TRUE(response
->headers
.get() != NULL
);
1128 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1129 EXPECT_TRUE(response
->proxy_server
.IsEmpty());
1131 std::string response_data
;
1132 rv
= ReadTransaction(trans
.get(), &response_data
);
1134 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1138 TEST_P(HttpNetworkTransactionTest
, Ignores100
) {
1139 ScopedVector
<UploadElementReader
> element_readers
;
1140 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
1141 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
1143 HttpRequestInfo request
;
1144 request
.method
= "POST";
1145 request
.url
= GURL("http://www.foo.com/");
1146 request
.upload_data_stream
= &upload_data_stream
;
1147 request
.load_flags
= 0;
1149 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1150 scoped_ptr
<HttpTransaction
> trans(
1151 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1153 MockRead data_reads
[] = {
1154 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1155 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1156 MockRead("hello world"),
1157 MockRead(SYNCHRONOUS
, OK
),
1159 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1160 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1162 TestCompletionCallback callback
;
1164 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1167 rv
= callback
.WaitForResult();
1170 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1171 ASSERT_TRUE(response
!= NULL
);
1173 EXPECT_TRUE(response
->headers
.get() != NULL
);
1174 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
1176 std::string response_data
;
1177 rv
= ReadTransaction(trans
.get(), &response_data
);
1179 EXPECT_EQ("hello world", response_data
);
1182 // This test is almost the same as Ignores100 above, but the response contains
1183 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1184 // HTTP/1.1 and the two status headers are read in one read.
1185 TEST_P(HttpNetworkTransactionTest
, Ignores1xx
) {
1186 HttpRequestInfo request
;
1187 request
.method
= "GET";
1188 request
.url
= GURL("http://www.foo.com/");
1189 request
.load_flags
= 0;
1191 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1192 scoped_ptr
<HttpTransaction
> trans(
1193 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1195 MockRead data_reads
[] = {
1196 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1197 "HTTP/1.1 200 OK\r\n\r\n"),
1198 MockRead("hello world"),
1199 MockRead(SYNCHRONOUS
, OK
),
1201 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1202 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1204 TestCompletionCallback callback
;
1206 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1209 rv
= callback
.WaitForResult();
1212 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1213 ASSERT_TRUE(response
!= NULL
);
1215 EXPECT_TRUE(response
->headers
.get() != NULL
);
1216 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1218 std::string response_data
;
1219 rv
= ReadTransaction(trans
.get(), &response_data
);
1221 EXPECT_EQ("hello world", response_data
);
1224 TEST_P(HttpNetworkTransactionTest
, Incomplete100ThenEOF
) {
1225 HttpRequestInfo request
;
1226 request
.method
= "POST";
1227 request
.url
= GURL("http://www.foo.com/");
1228 request
.load_flags
= 0;
1230 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1231 scoped_ptr
<HttpTransaction
> trans(
1232 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1234 MockRead data_reads
[] = {
1235 MockRead(SYNCHRONOUS
, "HTTP/1.0 100 Continue\r\n"),
1238 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1239 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1241 TestCompletionCallback callback
;
1243 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1244 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1246 rv
= callback
.WaitForResult();
1249 std::string response_data
;
1250 rv
= ReadTransaction(trans
.get(), &response_data
);
1252 EXPECT_EQ("", response_data
);
1255 TEST_P(HttpNetworkTransactionTest
, EmptyResponse
) {
1256 HttpRequestInfo request
;
1257 request
.method
= "POST";
1258 request
.url
= GURL("http://www.foo.com/");
1259 request
.load_flags
= 0;
1261 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1262 scoped_ptr
<HttpTransaction
> trans(
1263 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1265 MockRead data_reads
[] = {
1268 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1269 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1271 TestCompletionCallback callback
;
1273 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1274 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1276 rv
= callback
.WaitForResult();
1277 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
1280 void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1281 const MockWrite
* write_failure
,
1282 const MockRead
* read_failure
) {
1283 HttpRequestInfo request
;
1284 request
.method
= "GET";
1285 request
.url
= GURL("http://www.foo.com/");
1286 request
.load_flags
= 0;
1289 session_deps_
.net_log
= &net_log
;
1290 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1292 // Written data for successfully sending both requests.
1293 MockWrite data1_writes
[] = {
1294 MockWrite("GET / HTTP/1.1\r\n"
1295 "Host: www.foo.com\r\n"
1296 "Connection: keep-alive\r\n\r\n"),
1297 MockWrite("GET / HTTP/1.1\r\n"
1298 "Host: www.foo.com\r\n"
1299 "Connection: keep-alive\r\n\r\n")
1302 // Read results for the first request.
1303 MockRead data1_reads
[] = {
1304 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1306 MockRead(ASYNC
, OK
),
1309 if (write_failure
) {
1310 ASSERT_FALSE(read_failure
);
1311 data1_writes
[1] = *write_failure
;
1313 ASSERT_TRUE(read_failure
);
1314 data1_reads
[2] = *read_failure
;
1317 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
),
1318 data1_writes
, arraysize(data1_writes
));
1319 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1321 MockRead data2_reads
[] = {
1322 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1324 MockRead(ASYNC
, OK
),
1326 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1327 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1329 const char* const kExpectedResponseData
[] = {
1333 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1334 for (int i
= 0; i
< 2; ++i
) {
1335 TestCompletionCallback callback
;
1337 scoped_ptr
<HttpTransaction
> trans(
1338 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1340 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1341 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1343 rv
= callback
.WaitForResult();
1346 LoadTimingInfo load_timing_info
;
1347 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1348 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1350 first_socket_log_id
= load_timing_info
.socket_log_id
;
1352 // The second request should be using a new socket.
1353 EXPECT_NE(first_socket_log_id
, load_timing_info
.socket_log_id
);
1356 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1357 ASSERT_TRUE(response
!= NULL
);
1359 EXPECT_TRUE(response
->headers
.get() != NULL
);
1360 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1362 std::string response_data
;
1363 rv
= ReadTransaction(trans
.get(), &response_data
);
1365 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
1369 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
1370 const MockWrite
* write_failure
,
1371 const MockRead
* read_failure
,
1373 HttpRequestInfo request
;
1374 request
.method
= "GET";
1375 request
.url
= GURL("https://www.foo.com/");
1376 request
.load_flags
= 0;
1379 session_deps_
.net_log
= &net_log
;
1380 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1382 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
1383 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
1385 ssl1
.SetNextProto(GetParam());
1386 ssl2
.SetNextProto(GetParam());
1388 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
1389 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
1391 // SPDY versions of the request and response.
1392 scoped_ptr
<SpdyFrame
> spdy_request(spdy_util_
.ConstructSpdyGet(
1393 request
.url
.spec().c_str(), false, 1, DEFAULT_PRIORITY
));
1394 scoped_ptr
<SpdyFrame
> spdy_response(
1395 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
1396 scoped_ptr
<SpdyFrame
> spdy_data(
1397 spdy_util_
.ConstructSpdyBodyFrame(1, "hello", 5, true));
1399 // HTTP/1.1 versions of the request and response.
1400 const char kHttpRequest
[] = "GET / HTTP/1.1\r\n"
1401 "Host: www.foo.com\r\n"
1402 "Connection: keep-alive\r\n\r\n";
1403 const char kHttpResponse
[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
1404 const char kHttpData
[] = "hello";
1406 std::vector
<MockRead
> data1_reads
;
1407 std::vector
<MockWrite
> data1_writes
;
1408 if (write_failure
) {
1409 ASSERT_FALSE(read_failure
);
1410 data1_writes
.push_back(*write_failure
);
1411 data1_reads
.push_back(MockRead(ASYNC
, OK
));
1413 ASSERT_TRUE(read_failure
);
1415 data1_writes
.push_back(CreateMockWrite(*spdy_request
));
1417 data1_writes
.push_back(MockWrite(kHttpRequest
));
1419 data1_reads
.push_back(*read_failure
);
1422 StaticSocketDataProvider
data1(&data1_reads
[0], data1_reads
.size(),
1423 &data1_writes
[0], data1_writes
.size());
1424 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1426 std::vector
<MockRead
> data2_reads
;
1427 std::vector
<MockWrite
> data2_writes
;
1430 data2_writes
.push_back(CreateMockWrite(*spdy_request
, 0, ASYNC
));
1432 data2_reads
.push_back(CreateMockRead(*spdy_response
, 1, ASYNC
));
1433 data2_reads
.push_back(CreateMockRead(*spdy_data
, 2, ASYNC
));
1434 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1436 data2_writes
.push_back(
1437 MockWrite(ASYNC
, kHttpRequest
, strlen(kHttpRequest
), 0));
1439 data2_reads
.push_back(
1440 MockRead(ASYNC
, kHttpResponse
, strlen(kHttpResponse
), 1));
1441 data2_reads
.push_back(MockRead(ASYNC
, kHttpData
, strlen(kHttpData
), 2));
1442 data2_reads
.push_back(MockRead(ASYNC
, OK
, 3));
1444 SequencedSocketData
data2(&data2_reads
[0], data2_reads
.size(),
1445 &data2_writes
[0], data2_writes
.size());
1446 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1448 // Preconnect a socket.
1449 SSLConfig ssl_config
;
1450 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
1451 session
->GetNextProtos(&ssl_config
.next_protos
);
1452 session
->http_stream_factory()->PreconnectStreams(1, request
, ssl_config
,
1454 // Wait for the preconnect to complete.
1455 // TODO(davidben): Some way to wait for an idle socket count might be handy.
1456 base::RunLoop().RunUntilIdle();
1457 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
1459 // Make the request.
1460 TestCompletionCallback callback
;
1462 scoped_ptr
<HttpTransaction
> trans(
1463 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1465 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1466 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1468 rv
= callback
.WaitForResult();
1471 LoadTimingInfo load_timing_info
;
1472 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1473 TestLoadTimingNotReused(
1475 CONNECT_TIMING_HAS_DNS_TIMES
|CONNECT_TIMING_HAS_SSL_TIMES
);
1477 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1478 ASSERT_TRUE(response
!= NULL
);
1480 EXPECT_TRUE(response
->headers
.get() != NULL
);
1481 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1483 std::string response_data
;
1484 rv
= ReadTransaction(trans
.get(), &response_data
);
1486 EXPECT_EQ(kHttpData
, response_data
);
1489 TEST_P(HttpNetworkTransactionTest
,
1490 KeepAliveConnectionNotConnectedOnWrite
) {
1491 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1492 KeepAliveConnectionResendRequestTest(&write_failure
, NULL
);
1495 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionReset
) {
1496 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1497 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1500 TEST_P(HttpNetworkTransactionTest
, KeepAliveConnectionEOF
) {
1501 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1502 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1505 // Make sure that on a 408 response (Request Timeout), the request is retried,
1506 // if the socket was a reused keep alive socket.
1507 TEST_P(HttpNetworkTransactionTest
, KeepAlive408
) {
1508 MockRead
read_failure(SYNCHRONOUS
,
1509 "HTTP/1.1 408 Request Timeout\r\n"
1510 "Connection: Keep-Alive\r\n"
1511 "Content-Length: 6\r\n\r\n"
1513 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1516 TEST_P(HttpNetworkTransactionTest
,
1517 PreconnectErrorNotConnectedOnWrite
) {
1518 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1519 PreconnectErrorResendRequestTest(&write_failure
, NULL
, false);
1522 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorReset
) {
1523 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1524 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1527 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorEOF
) {
1528 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1529 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1532 TEST_P(HttpNetworkTransactionTest
, PreconnectErrorAsyncEOF
) {
1533 MockRead
read_failure(ASYNC
, OK
); // EOF
1534 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1537 // Make sure that on a 408 response (Request Timeout), the request is retried,
1538 // if the socket was a preconnected (UNUSED_IDLE) socket.
1539 TEST_P(HttpNetworkTransactionTest
, RetryOnIdle408
) {
1540 MockRead
read_failure(SYNCHRONOUS
,
1541 "HTTP/1.1 408 Request Timeout\r\n"
1542 "Connection: Keep-Alive\r\n"
1543 "Content-Length: 6\r\n\r\n"
1545 KeepAliveConnectionResendRequestTest(NULL
, &read_failure
);
1546 PreconnectErrorResendRequestTest(NULL
, &read_failure
, false);
1549 TEST_P(HttpNetworkTransactionTest
,
1550 SpdyPreconnectErrorNotConnectedOnWrite
) {
1551 MockWrite
write_failure(ASYNC
, ERR_SOCKET_NOT_CONNECTED
);
1552 PreconnectErrorResendRequestTest(&write_failure
, NULL
, true);
1555 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorReset
) {
1556 MockRead
read_failure(ASYNC
, ERR_CONNECTION_RESET
);
1557 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1560 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorEOF
) {
1561 MockRead
read_failure(SYNCHRONOUS
, OK
); // EOF
1562 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1565 TEST_P(HttpNetworkTransactionTest
, SpdyPreconnectErrorAsyncEOF
) {
1566 MockRead
read_failure(ASYNC
, OK
); // EOF
1567 PreconnectErrorResendRequestTest(NULL
, &read_failure
, true);
1570 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionReset
) {
1571 HttpRequestInfo request
;
1572 request
.method
= "GET";
1573 request
.url
= GURL("http://www.example.org/");
1574 request
.load_flags
= 0;
1576 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1577 scoped_ptr
<HttpTransaction
> trans(
1578 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1580 MockRead data_reads
[] = {
1581 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
1582 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1583 MockRead("hello world"),
1584 MockRead(SYNCHRONOUS
, OK
),
1586 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1587 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1589 TestCompletionCallback callback
;
1591 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1592 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1594 rv
= callback
.WaitForResult();
1595 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
1598 // What do various browsers do when the server closes a non-keepalive
1599 // connection without sending any response header or body?
1602 // Safari 3.1.2 (Windows): error page
1603 // Firefox 3.0.1: blank page
1604 // Opera 9.52: after five attempts, blank page
1605 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1606 // Us: error page (EMPTY_RESPONSE)
1607 TEST_P(HttpNetworkTransactionTest
, NonKeepAliveConnectionEOF
) {
1608 MockRead data_reads
[] = {
1609 MockRead(SYNCHRONOUS
, OK
), // EOF
1610 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1611 MockRead("hello world"),
1612 MockRead(SYNCHRONOUS
, OK
),
1614 SimpleGetHelperResult out
= SimpleGetHelper(data_reads
,
1615 arraysize(data_reads
));
1616 EXPECT_EQ(ERR_EMPTY_RESPONSE
, out
.rv
);
1619 // Test that network access can be deferred and resumed.
1620 TEST_P(HttpNetworkTransactionTest
, ThrottleBeforeNetworkStart
) {
1621 HttpRequestInfo request
;
1622 request
.method
= "GET";
1623 request
.url
= GURL("http://www.example.org/");
1624 request
.load_flags
= 0;
1626 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1627 scoped_ptr
<HttpTransaction
> trans(
1628 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1630 // Defer on OnBeforeNetworkStart.
1631 BeforeNetworkStartHandler
net_start_handler(true); // defer
1632 trans
->SetBeforeNetworkStartCallback(
1633 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1634 base::Unretained(&net_start_handler
)));
1636 MockRead data_reads
[] = {
1637 MockRead("HTTP/1.0 200 OK\r\n"),
1638 MockRead("Content-Length: 5\r\n\r\n"),
1640 MockRead(SYNCHRONOUS
, 0),
1642 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1643 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1645 TestCompletionCallback callback
;
1647 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1648 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1649 base::MessageLoop::current()->RunUntilIdle();
1651 // Should have deferred for network start.
1652 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1653 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1655 trans
->ResumeNetworkStart();
1656 rv
= callback
.WaitForResult();
1658 EXPECT_TRUE(trans
->GetResponseInfo() != NULL
);
1660 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1661 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1662 if (rv
== ERR_IO_PENDING
)
1663 rv
= callback
.WaitForResult();
1668 // Test that network use can be deferred and canceled.
1669 TEST_P(HttpNetworkTransactionTest
, ThrottleAndCancelBeforeNetworkStart
) {
1670 HttpRequestInfo request
;
1671 request
.method
= "GET";
1672 request
.url
= GURL("http://www.example.org/");
1673 request
.load_flags
= 0;
1675 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1676 scoped_ptr
<HttpTransaction
> trans(
1677 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1679 // Defer on OnBeforeNetworkStart.
1680 BeforeNetworkStartHandler
net_start_handler(true); // defer
1681 trans
->SetBeforeNetworkStartCallback(
1682 base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart
,
1683 base::Unretained(&net_start_handler
)));
1685 TestCompletionCallback callback
;
1687 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1688 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1689 base::MessageLoop::current()->RunUntilIdle();
1691 // Should have deferred for network start.
1692 EXPECT_TRUE(net_start_handler
.observed_before_network_start());
1693 EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE
, trans
->GetLoadState());
1696 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
1697 // tests. There was a bug causing HttpNetworkTransaction to hang in the
1698 // destructor in such situations.
1699 // See http://crbug.com/154712 and http://crbug.com/156609.
1700 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose
) {
1701 HttpRequestInfo request
;
1702 request
.method
= "GET";
1703 request
.url
= GURL("http://www.example.org/");
1704 request
.load_flags
= 0;
1706 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1707 scoped_ptr
<HttpTransaction
> trans(
1708 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1710 MockRead data_reads
[] = {
1711 MockRead("HTTP/1.0 200 OK\r\n"),
1712 MockRead("Connection: keep-alive\r\n"),
1713 MockRead("Content-Length: 100\r\n\r\n"),
1715 MockRead(SYNCHRONOUS
, 0),
1717 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1718 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1720 TestCompletionCallback callback
;
1722 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1723 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1725 rv
= callback
.WaitForResult();
1728 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1729 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1730 if (rv
== ERR_IO_PENDING
)
1731 rv
= callback
.WaitForResult();
1733 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1734 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1737 base::MessageLoop::current()->RunUntilIdle();
1738 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1741 TEST_P(HttpNetworkTransactionTest
, KeepAliveEarlyClose2
) {
1742 HttpRequestInfo request
;
1743 request
.method
= "GET";
1744 request
.url
= GURL("http://www.example.org/");
1745 request
.load_flags
= 0;
1747 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1748 scoped_ptr
<HttpTransaction
> trans(
1749 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1751 MockRead data_reads
[] = {
1752 MockRead("HTTP/1.0 200 OK\r\n"),
1753 MockRead("Connection: keep-alive\r\n"),
1754 MockRead("Content-Length: 100\r\n\r\n"),
1755 MockRead(SYNCHRONOUS
, 0),
1757 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
1758 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
1760 TestCompletionCallback callback
;
1762 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1763 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1765 rv
= callback
.WaitForResult();
1768 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(100));
1769 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
1770 if (rv
== ERR_IO_PENDING
)
1771 rv
= callback
.WaitForResult();
1772 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
1775 base::MessageLoop::current()->RunUntilIdle();
1776 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
1779 // Test that we correctly reuse a keep-alive connection after not explicitly
1780 // reading the body.
1781 TEST_P(HttpNetworkTransactionTest
, KeepAliveAfterUnreadBody
) {
1782 HttpRequestInfo request
;
1783 request
.method
= "GET";
1784 request
.url
= GURL("http://www.foo.com/");
1785 request
.load_flags
= 0;
1788 session_deps_
.net_log
= &net_log
;
1789 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1791 // Note that because all these reads happen in the same
1792 // StaticSocketDataProvider, it shows that the same socket is being reused for
1793 // all transactions.
1794 MockRead data1_reads
[] = {
1795 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1796 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
1797 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
1798 MockRead("HTTP/1.1 302 Found\r\n"
1799 "Content-Length: 0\r\n\r\n"),
1800 MockRead("HTTP/1.1 302 Found\r\n"
1801 "Content-Length: 5\r\n\r\n"
1803 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1804 "Content-Length: 0\r\n\r\n"),
1805 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1806 "Content-Length: 5\r\n\r\n"
1808 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1811 StaticSocketDataProvider
data1(data1_reads
, arraysize(data1_reads
), NULL
, 0);
1812 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1814 MockRead data2_reads
[] = {
1815 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
1817 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
1818 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1820 const int kNumUnreadBodies
= arraysize(data1_reads
) - 2;
1821 std::string response_lines
[kNumUnreadBodies
];
1823 uint32 first_socket_log_id
= NetLog::Source::kInvalidId
;
1824 for (size_t i
= 0; i
< arraysize(data1_reads
) - 2; ++i
) {
1825 TestCompletionCallback callback
;
1827 scoped_ptr
<HttpTransaction
> trans(
1828 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1830 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1831 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1833 rv
= callback
.WaitForResult();
1836 LoadTimingInfo load_timing_info
;
1837 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
1839 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_DNS_TIMES
);
1840 first_socket_log_id
= load_timing_info
.socket_log_id
;
1842 TestLoadTimingReused(load_timing_info
);
1843 EXPECT_EQ(first_socket_log_id
, load_timing_info
.socket_log_id
);
1846 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1847 ASSERT_TRUE(response
!= NULL
);
1849 ASSERT_TRUE(response
->headers
.get() != NULL
);
1850 response_lines
[i
] = response
->headers
->GetStatusLine();
1852 // We intentionally don't read the response bodies.
1855 const char* const kStatusLines
[] = {
1856 "HTTP/1.1 204 No Content",
1857 "HTTP/1.1 205 Reset Content",
1858 "HTTP/1.1 304 Not Modified",
1859 "HTTP/1.1 302 Found",
1860 "HTTP/1.1 302 Found",
1861 "HTTP/1.1 301 Moved Permanently",
1862 "HTTP/1.1 301 Moved Permanently",
1865 static_assert(kNumUnreadBodies
== arraysize(kStatusLines
),
1866 "forgot to update kStatusLines");
1868 for (int i
= 0; i
< kNumUnreadBodies
; ++i
)
1869 EXPECT_EQ(kStatusLines
[i
], response_lines
[i
]);
1871 TestCompletionCallback callback
;
1872 scoped_ptr
<HttpTransaction
> trans(
1873 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1874 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
1875 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1876 rv
= callback
.WaitForResult();
1878 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1879 ASSERT_TRUE(response
!= NULL
);
1880 ASSERT_TRUE(response
->headers
.get() != NULL
);
1881 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
1882 std::string response_data
;
1883 rv
= ReadTransaction(trans
.get(), &response_data
);
1885 EXPECT_EQ("hello", response_data
);
1888 // Test the request-challenge-retry sequence for basic auth.
1889 // (basic auth is the easiest to mock, because it has no randomness).
1890 TEST_P(HttpNetworkTransactionTest
, BasicAuth
) {
1891 HttpRequestInfo request
;
1892 request
.method
= "GET";
1893 request
.url
= GURL("http://www.example.org/");
1894 request
.load_flags
= 0;
1897 session_deps_
.net_log
= &log
;
1898 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
1899 scoped_ptr
<HttpTransaction
> trans(
1900 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
1902 MockWrite data_writes1
[] = {
1904 "GET / HTTP/1.1\r\n"
1905 "Host: www.example.org\r\n"
1906 "Connection: keep-alive\r\n\r\n"),
1909 MockRead data_reads1
[] = {
1910 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1911 // Give a couple authenticate options (only the middle one is actually
1913 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
1914 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1915 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1916 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1917 // Large content-length -- won't matter, as connection will be reset.
1918 MockRead("Content-Length: 10000\r\n\r\n"),
1919 MockRead(SYNCHRONOUS
, ERR_FAILED
),
1922 // After calling trans->RestartWithAuth(), this is the request we should
1923 // be issuing -- the final header line contains the credentials.
1924 MockWrite data_writes2
[] = {
1926 "GET / HTTP/1.1\r\n"
1927 "Host: www.example.org\r\n"
1928 "Connection: keep-alive\r\n"
1929 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1932 // Lastly, the server responds with the actual content.
1933 MockRead data_reads2
[] = {
1934 MockRead("HTTP/1.0 200 OK\r\n"),
1935 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1936 MockRead("Content-Length: 100\r\n\r\n"),
1937 MockRead(SYNCHRONOUS
, OK
),
1940 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
1941 data_writes1
, arraysize(data_writes1
));
1942 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
1943 data_writes2
, arraysize(data_writes2
));
1944 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
1945 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
1947 TestCompletionCallback callback1
;
1949 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
1950 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1952 rv
= callback1
.WaitForResult();
1955 LoadTimingInfo load_timing_info1
;
1956 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
1957 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
1959 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
1960 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
1962 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
1963 ASSERT_TRUE(response
!= NULL
);
1964 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
1966 TestCompletionCallback callback2
;
1968 rv
= trans
->RestartWithAuth(
1969 AuthCredentials(kFoo
, kBar
), callback2
.callback());
1970 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1972 rv
= callback2
.WaitForResult();
1975 LoadTimingInfo load_timing_info2
;
1976 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
1977 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_DNS_TIMES
);
1978 // The load timing after restart should have a new socket ID, and times after
1979 // those of the first load timing.
1980 EXPECT_LE(load_timing_info1
.receive_headers_end
,
1981 load_timing_info2
.connect_timing
.connect_start
);
1982 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
1984 int64 reads_size2
= ReadsSize(data_reads2
, arraysize(data_reads2
));
1985 EXPECT_EQ(reads_size1
+ reads_size2
, trans
->GetTotalReceivedBytes());
1987 response
= trans
->GetResponseInfo();
1988 ASSERT_TRUE(response
!= NULL
);
1989 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
1990 EXPECT_EQ(100, response
->headers
->GetContentLength());
1993 TEST_P(HttpNetworkTransactionTest
, DoNotSendAuth
) {
1994 HttpRequestInfo request
;
1995 request
.method
= "GET";
1996 request
.url
= GURL("http://www.example.org/");
1997 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
1999 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2000 scoped_ptr
<HttpTransaction
> trans(
2001 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2003 MockWrite data_writes
[] = {
2005 "GET / HTTP/1.1\r\n"
2006 "Host: www.example.org\r\n"
2007 "Connection: keep-alive\r\n\r\n"),
2010 MockRead data_reads
[] = {
2011 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2012 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2013 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2014 // Large content-length -- won't matter, as connection will be reset.
2015 MockRead("Content-Length: 10000\r\n\r\n"),
2016 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2019 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2020 data_writes
, arraysize(data_writes
));
2021 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2022 TestCompletionCallback callback
;
2024 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2025 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2027 rv
= callback
.WaitForResult();
2030 int64 reads_size
= ReadsSize(data_reads
, arraysize(data_reads
));
2031 EXPECT_EQ(reads_size
, trans
->GetTotalReceivedBytes());
2033 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2034 ASSERT_TRUE(response
!= NULL
);
2035 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2038 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2040 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAlive
) {
2041 HttpRequestInfo request
;
2042 request
.method
= "GET";
2043 request
.url
= GURL("http://www.example.org/");
2044 request
.load_flags
= 0;
2047 session_deps_
.net_log
= &log
;
2048 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2050 MockWrite data_writes1
[] = {
2052 "GET / HTTP/1.1\r\n"
2053 "Host: www.example.org\r\n"
2054 "Connection: keep-alive\r\n\r\n"),
2056 // After calling trans->RestartWithAuth(), this is the request we should
2057 // be issuing -- the final header line contains the credentials.
2059 "GET / HTTP/1.1\r\n"
2060 "Host: www.example.org\r\n"
2061 "Connection: keep-alive\r\n"
2062 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2065 MockRead data_reads1
[] = {
2066 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2067 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2068 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2069 MockRead("Content-Length: 14\r\n\r\n"),
2070 MockRead("Unauthorized\r\n"),
2072 // Lastly, the server responds with the actual content.
2073 MockRead("HTTP/1.1 200 OK\r\n"),
2074 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2075 MockRead("Content-Length: 5\r\n\r\n"),
2079 // If there is a regression where we disconnect a Keep-Alive
2080 // connection during an auth roundtrip, we'll end up reading this.
2081 MockRead data_reads2
[] = {
2082 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2085 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2086 data_writes1
, arraysize(data_writes1
));
2087 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2089 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2090 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2092 TestCompletionCallback callback1
;
2094 scoped_ptr
<HttpTransaction
> trans(
2095 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2096 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2097 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2099 rv
= callback1
.WaitForResult();
2102 LoadTimingInfo load_timing_info1
;
2103 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info1
));
2104 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_DNS_TIMES
);
2106 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2107 ASSERT_TRUE(response
!= NULL
);
2108 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2110 TestCompletionCallback callback2
;
2112 rv
= trans
->RestartWithAuth(
2113 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2116 rv
= callback2
.WaitForResult();
2119 LoadTimingInfo load_timing_info2
;
2120 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info2
));
2121 TestLoadTimingReused(load_timing_info2
);
2122 // The load timing after restart should have the same socket ID, and times
2123 // those of the first load timing.
2124 EXPECT_LE(load_timing_info1
.receive_headers_end
,
2125 load_timing_info2
.send_start
);
2126 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
2128 response
= trans
->GetResponseInfo();
2129 ASSERT_TRUE(response
!= NULL
);
2130 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2131 EXPECT_EQ(5, response
->headers
->GetContentLength());
2133 std::string response_data
;
2134 rv
= ReadTransaction(trans
.get(), &response_data
);
2136 int64 reads_size1
= ReadsSize(data_reads1
, arraysize(data_reads1
));
2137 EXPECT_EQ(reads_size1
, trans
->GetTotalReceivedBytes());
2140 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2141 // connection and with no response body to drain.
2142 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveNoBody
) {
2143 HttpRequestInfo request
;
2144 request
.method
= "GET";
2145 request
.url
= GURL("http://www.example.org/");
2146 request
.load_flags
= 0;
2148 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2150 MockWrite data_writes1
[] = {
2152 "GET / HTTP/1.1\r\n"
2153 "Host: www.example.org\r\n"
2154 "Connection: keep-alive\r\n\r\n"),
2156 // After calling trans->RestartWithAuth(), this is the request we should
2157 // be issuing -- the final header line contains the credentials.
2159 "GET / HTTP/1.1\r\n"
2160 "Host: www.example.org\r\n"
2161 "Connection: keep-alive\r\n"
2162 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2165 MockRead data_reads1
[] = {
2166 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2167 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2168 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
2170 // Lastly, the server responds with the actual content.
2171 MockRead("HTTP/1.1 200 OK\r\n"),
2172 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2173 MockRead("Content-Length: 5\r\n\r\n"),
2177 // An incorrect reconnect would cause this to be read.
2178 MockRead data_reads2
[] = {
2179 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2182 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2183 data_writes1
, arraysize(data_writes1
));
2184 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2186 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2187 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2189 TestCompletionCallback callback1
;
2191 scoped_ptr
<HttpTransaction
> trans(
2192 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2193 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2194 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2196 rv
= callback1
.WaitForResult();
2199 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2200 ASSERT_TRUE(response
!= NULL
);
2201 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2203 TestCompletionCallback callback2
;
2205 rv
= trans
->RestartWithAuth(
2206 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2209 rv
= callback2
.WaitForResult();
2212 response
= trans
->GetResponseInfo();
2213 ASSERT_TRUE(response
!= NULL
);
2214 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2215 EXPECT_EQ(5, response
->headers
->GetContentLength());
2218 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2219 // connection and with a large response body to drain.
2220 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveLargeBody
) {
2221 HttpRequestInfo request
;
2222 request
.method
= "GET";
2223 request
.url
= GURL("http://www.example.org/");
2224 request
.load_flags
= 0;
2226 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2228 MockWrite data_writes1
[] = {
2230 "GET / HTTP/1.1\r\n"
2231 "Host: www.example.org\r\n"
2232 "Connection: keep-alive\r\n\r\n"),
2234 // After calling trans->RestartWithAuth(), this is the request we should
2235 // be issuing -- the final header line contains the credentials.
2237 "GET / HTTP/1.1\r\n"
2238 "Host: www.example.org\r\n"
2239 "Connection: keep-alive\r\n"
2240 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2243 // Respond with 5 kb of response body.
2244 std::string
large_body_string("Unauthorized");
2245 large_body_string
.append(5 * 1024, ' ');
2246 large_body_string
.append("\r\n");
2248 MockRead data_reads1
[] = {
2249 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2250 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2251 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2252 // 5134 = 12 + 5 * 1024 + 2
2253 MockRead("Content-Length: 5134\r\n\r\n"),
2254 MockRead(ASYNC
, large_body_string
.data(), large_body_string
.size()),
2256 // Lastly, the server responds with the actual content.
2257 MockRead("HTTP/1.1 200 OK\r\n"),
2258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2259 MockRead("Content-Length: 5\r\n\r\n"),
2263 // An incorrect reconnect would cause this to be read.
2264 MockRead data_reads2
[] = {
2265 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2268 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2269 data_writes1
, arraysize(data_writes1
));
2270 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2272 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2273 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2275 TestCompletionCallback callback1
;
2277 scoped_ptr
<HttpTransaction
> trans(
2278 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2279 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2280 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2282 rv
= callback1
.WaitForResult();
2285 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2286 ASSERT_TRUE(response
!= NULL
);
2287 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2289 TestCompletionCallback callback2
;
2291 rv
= trans
->RestartWithAuth(
2292 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2295 rv
= callback2
.WaitForResult();
2298 response
= trans
->GetResponseInfo();
2299 ASSERT_TRUE(response
!= NULL
);
2300 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2301 EXPECT_EQ(5, response
->headers
->GetContentLength());
2304 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2305 // connection, but the server gets impatient and closes the connection.
2306 TEST_P(HttpNetworkTransactionTest
, BasicAuthKeepAliveImpatientServer
) {
2307 HttpRequestInfo request
;
2308 request
.method
= "GET";
2309 request
.url
= GURL("http://www.example.org/");
2310 request
.load_flags
= 0;
2312 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2314 MockWrite data_writes1
[] = {
2316 "GET / HTTP/1.1\r\n"
2317 "Host: www.example.org\r\n"
2318 "Connection: keep-alive\r\n\r\n"),
2319 // This simulates the seemingly successful write to a closed connection
2320 // if the bug is not fixed.
2322 "GET / HTTP/1.1\r\n"
2323 "Host: www.example.org\r\n"
2324 "Connection: keep-alive\r\n"
2325 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2328 MockRead data_reads1
[] = {
2329 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
2330 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2331 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2332 MockRead("Content-Length: 14\r\n\r\n"),
2333 // Tell MockTCPClientSocket to simulate the server closing the connection.
2334 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
2335 MockRead("Unauthorized\r\n"),
2336 MockRead(SYNCHRONOUS
, OK
), // The server closes the connection.
2339 // After calling trans->RestartWithAuth(), this is the request we should
2340 // be issuing -- the final header line contains the credentials.
2341 MockWrite data_writes2
[] = {
2343 "GET / HTTP/1.1\r\n"
2344 "Host: www.example.org\r\n"
2345 "Connection: keep-alive\r\n"
2346 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2349 // Lastly, the server responds with the actual content.
2350 MockRead data_reads2
[] = {
2351 MockRead("HTTP/1.1 200 OK\r\n"),
2352 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2353 MockRead("Content-Length: 5\r\n\r\n"),
2357 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2358 data_writes1
, arraysize(data_writes1
));
2359 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
2360 data_writes2
, arraysize(data_writes2
));
2361 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2362 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
2364 TestCompletionCallback callback1
;
2366 scoped_ptr
<HttpTransaction
> trans(
2367 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2368 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
2369 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2371 rv
= callback1
.WaitForResult();
2374 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2375 ASSERT_TRUE(response
!= NULL
);
2376 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
2378 TestCompletionCallback callback2
;
2380 rv
= trans
->RestartWithAuth(
2381 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2382 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2384 rv
= callback2
.WaitForResult();
2387 response
= trans
->GetResponseInfo();
2388 ASSERT_TRUE(response
!= NULL
);
2389 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2390 EXPECT_EQ(5, response
->headers
->GetContentLength());
2393 // Test the request-challenge-retry sequence for basic auth, over a connection
2394 // that requires a restart when setting up an SSL tunnel.
2395 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp10
) {
2396 HttpRequestInfo request
;
2397 request
.method
= "GET";
2398 request
.url
= GURL("https://www.example.org/");
2399 // when the no authentication data flag is set.
2400 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2402 // Configure against proxy server "myproxy:70".
2403 session_deps_
.proxy_service
.reset(
2404 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2405 BoundTestNetLog log
;
2406 session_deps_
.net_log
= log
.bound().net_log();
2407 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2409 // Since we have proxy, should try to establish tunnel.
2410 MockWrite data_writes1
[] = {
2412 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2413 "Host: www.example.org\r\n"
2414 "Proxy-Connection: keep-alive\r\n\r\n"),
2416 // After calling trans->RestartWithAuth(), this is the request we should
2417 // be issuing -- the final header line contains the credentials.
2419 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2420 "Host: www.example.org\r\n"
2421 "Proxy-Connection: keep-alive\r\n"
2422 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2425 "GET / HTTP/1.1\r\n"
2426 "Host: www.example.org\r\n"
2427 "Connection: keep-alive\r\n\r\n"),
2430 // The proxy responds to the connect with a 407, using a persistent
2432 MockRead data_reads1
[] = {
2434 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2435 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
2437 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
2439 MockRead("HTTP/1.1 200 OK\r\n"),
2440 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2441 MockRead("Content-Length: 5\r\n\r\n"),
2442 MockRead(SYNCHRONOUS
, "hello"),
2445 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2446 data_writes1
, arraysize(data_writes1
));
2447 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2448 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2449 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2451 TestCompletionCallback callback1
;
2453 scoped_ptr
<HttpTransaction
> trans(
2454 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2456 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2457 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2459 rv
= callback1
.WaitForResult();
2461 TestNetLogEntry::List entries
;
2462 log
.GetEntries(&entries
);
2463 size_t pos
= ExpectLogContainsSomewhere(
2464 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2465 NetLog::PHASE_NONE
);
2466 ExpectLogContainsSomewhere(
2467 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2468 NetLog::PHASE_NONE
);
2470 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2471 ASSERT_TRUE(response
!= NULL
);
2472 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2473 ASSERT_FALSE(response
->headers
.get() == NULL
);
2474 EXPECT_EQ(407, response
->headers
->response_code());
2475 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2476 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2478 LoadTimingInfo load_timing_info
;
2479 // CONNECT requests and responses are handled at the connect job level, so
2480 // the transaction does not yet have a connection.
2481 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2483 TestCompletionCallback callback2
;
2486 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback2
.callback());
2487 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2489 rv
= callback2
.WaitForResult();
2492 response
= trans
->GetResponseInfo();
2493 ASSERT_TRUE(response
!= NULL
);
2495 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2496 EXPECT_EQ(200, response
->headers
->response_code());
2497 EXPECT_EQ(5, response
->headers
->GetContentLength());
2498 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2500 // The password prompt info should not be set.
2501 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2503 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2504 TestLoadTimingNotReusedWithPac(load_timing_info
,
2505 CONNECT_TIMING_HAS_SSL_TIMES
);
2508 session
->CloseAllConnections();
2511 // Test the request-challenge-retry sequence for basic auth, over a connection
2512 // that requires a restart when setting up an SSL tunnel.
2513 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyNoKeepAliveHttp11
) {
2514 HttpRequestInfo request
;
2515 request
.method
= "GET";
2516 request
.url
= GURL("https://www.example.org/");
2517 // when the no authentication data flag is set.
2518 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2520 // Configure against proxy server "myproxy:70".
2521 session_deps_
.proxy_service
.reset(
2522 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
2523 BoundTestNetLog log
;
2524 session_deps_
.net_log
= log
.bound().net_log();
2525 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2527 // Since we have proxy, should try to establish tunnel.
2528 MockWrite data_writes1
[] = {
2530 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2531 "Host: www.example.org\r\n"
2532 "Proxy-Connection: keep-alive\r\n\r\n"),
2534 // After calling trans->RestartWithAuth(), this is the request we should
2535 // be issuing -- the final header line contains the credentials.
2537 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2538 "Host: www.example.org\r\n"
2539 "Proxy-Connection: keep-alive\r\n"
2540 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2543 "GET / HTTP/1.1\r\n"
2544 "Host: www.example.org\r\n"
2545 "Connection: keep-alive\r\n\r\n"),
2548 // The proxy responds to the connect with a 407, using a persistent
2550 MockRead data_reads1
[] = {
2552 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2553 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2554 MockRead("Proxy-Connection: close\r\n\r\n"),
2556 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2558 MockRead("HTTP/1.1 200 OK\r\n"),
2559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2560 MockRead("Content-Length: 5\r\n\r\n"),
2561 MockRead(SYNCHRONOUS
, "hello"),
2564 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2565 data_writes1
, arraysize(data_writes1
));
2566 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2567 SSLSocketDataProvider
ssl(ASYNC
, OK
);
2568 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
2570 TestCompletionCallback callback1
;
2572 scoped_ptr
<HttpTransaction
> trans(
2573 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2575 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2576 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2578 rv
= callback1
.WaitForResult();
2580 TestNetLogEntry::List entries
;
2581 log
.GetEntries(&entries
);
2582 size_t pos
= ExpectLogContainsSomewhere(
2583 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2584 NetLog::PHASE_NONE
);
2585 ExpectLogContainsSomewhere(
2587 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2588 NetLog::PHASE_NONE
);
2590 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2591 ASSERT_TRUE(response
!= NULL
);
2592 EXPECT_FALSE(response
->headers
->IsKeepAlive());
2593 ASSERT_FALSE(response
->headers
.get() == NULL
);
2594 EXPECT_EQ(407, response
->headers
->response_code());
2595 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2596 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2598 LoadTimingInfo load_timing_info
;
2599 // CONNECT requests and responses are handled at the connect job level, so
2600 // the transaction does not yet have a connection.
2601 EXPECT_FALSE(trans
->GetLoadTimingInfo(&load_timing_info
));
2603 TestCompletionCallback callback2
;
2605 rv
= trans
->RestartWithAuth(
2606 AuthCredentials(kFoo
, kBar
), callback2
.callback());
2607 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2609 rv
= callback2
.WaitForResult();
2612 response
= trans
->GetResponseInfo();
2613 ASSERT_TRUE(response
!= NULL
);
2615 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2616 EXPECT_EQ(200, response
->headers
->response_code());
2617 EXPECT_EQ(5, response
->headers
->GetContentLength());
2618 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2620 // The password prompt info should not be set.
2621 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
2623 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
2624 TestLoadTimingNotReusedWithPac(load_timing_info
,
2625 CONNECT_TIMING_HAS_SSL_TIMES
);
2628 session
->CloseAllConnections();
2631 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2632 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
2633 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp10
) {
2634 HttpRequestInfo request
;
2635 request
.method
= "GET";
2636 request
.url
= GURL("https://www.example.org/");
2637 // Ensure that proxy authentication is attempted even
2638 // when the no authentication data flag is set.
2639 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2641 // Configure against proxy server "myproxy:70".
2642 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2643 BoundTestNetLog log
;
2644 session_deps_
.net_log
= log
.bound().net_log();
2645 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2647 scoped_ptr
<HttpTransaction
> trans(
2648 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2650 // Since we have proxy, should try to establish tunnel.
2651 MockWrite data_writes1
[] = {
2653 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2654 "Host: www.example.org\r\n"
2655 "Proxy-Connection: keep-alive\r\n\r\n"),
2657 // After calling trans->RestartWithAuth(), this is the request we should
2658 // be issuing -- the final header line contains the credentials.
2660 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2661 "Host: www.example.org\r\n"
2662 "Proxy-Connection: keep-alive\r\n"
2663 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2666 // The proxy responds to the connect with a 407, using a persistent
2667 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
2668 MockRead data_reads1
[] = {
2670 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2671 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2672 MockRead("Proxy-Connection: keep-alive\r\n"),
2673 MockRead("Content-Length: 10\r\n\r\n"),
2674 MockRead("0123456789"),
2676 // Wrong credentials (wrong password).
2677 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
2678 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2679 MockRead("Proxy-Connection: keep-alive\r\n"),
2680 MockRead("Content-Length: 10\r\n\r\n"),
2681 // No response body because the test stops reading here.
2682 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2685 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2686 data_writes1
, arraysize(data_writes1
));
2687 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2689 TestCompletionCallback callback1
;
2691 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2692 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2694 rv
= callback1
.WaitForResult();
2696 TestNetLogEntry::List entries
;
2697 log
.GetEntries(&entries
);
2698 size_t pos
= ExpectLogContainsSomewhere(
2699 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2700 NetLog::PHASE_NONE
);
2701 ExpectLogContainsSomewhere(
2702 entries
, pos
, NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2703 NetLog::PHASE_NONE
);
2705 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2706 ASSERT_TRUE(response
);
2707 ASSERT_TRUE(response
->headers
);
2708 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2709 EXPECT_EQ(407, response
->headers
->response_code());
2710 EXPECT_EQ(10, response
->headers
->GetContentLength());
2711 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2712 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2714 TestCompletionCallback callback2
;
2716 // Wrong password (should be "bar").
2718 trans
->RestartWithAuth(AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2719 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2721 rv
= callback2
.WaitForResult();
2724 response
= trans
->GetResponseInfo();
2725 ASSERT_TRUE(response
);
2726 ASSERT_TRUE(response
->headers
);
2727 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2728 EXPECT_EQ(407, response
->headers
->response_code());
2729 EXPECT_EQ(10, response
->headers
->GetContentLength());
2730 EXPECT_TRUE(HttpVersion(1, 0) == response
->headers
->GetHttpVersion());
2731 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2733 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2735 session
->CloseAllConnections();
2738 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
2739 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
2740 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyKeepAliveHttp11
) {
2741 HttpRequestInfo request
;
2742 request
.method
= "GET";
2743 request
.url
= GURL("https://www.example.org/");
2744 // Ensure that proxy authentication is attempted even
2745 // when the no authentication data flag is set.
2746 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
2748 // Configure against proxy server "myproxy:70".
2749 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2750 BoundTestNetLog log
;
2751 session_deps_
.net_log
= log
.bound().net_log();
2752 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2754 scoped_ptr
<HttpTransaction
> trans(
2755 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2757 // Since we have proxy, should try to establish tunnel.
2758 MockWrite data_writes1
[] = {
2760 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2761 "Host: www.example.org\r\n"
2762 "Proxy-Connection: keep-alive\r\n\r\n"),
2764 // After calling trans->RestartWithAuth(), this is the request we should
2765 // be issuing -- the final header line contains the credentials.
2767 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2768 "Host: www.example.org\r\n"
2769 "Proxy-Connection: keep-alive\r\n"
2770 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2773 // The proxy responds to the connect with a 407, using a persistent
2775 MockRead data_reads1
[] = {
2777 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2778 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2779 MockRead("Content-Length: 10\r\n\r\n"),
2780 MockRead("0123456789"),
2782 // Wrong credentials (wrong password).
2783 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2784 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2785 MockRead("Content-Length: 10\r\n\r\n"),
2786 // No response body because the test stops reading here.
2787 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2790 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2791 data_writes1
, arraysize(data_writes1
));
2792 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2794 TestCompletionCallback callback1
;
2796 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
2797 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2799 rv
= callback1
.WaitForResult();
2801 TestNetLogEntry::List entries
;
2802 log
.GetEntries(&entries
);
2803 size_t pos
= ExpectLogContainsSomewhere(
2804 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
2805 NetLog::PHASE_NONE
);
2806 ExpectLogContainsSomewhere(
2808 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
2809 NetLog::PHASE_NONE
);
2811 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2812 ASSERT_TRUE(response
);
2813 ASSERT_TRUE(response
->headers
);
2814 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2815 EXPECT_EQ(407, response
->headers
->response_code());
2816 EXPECT_EQ(10, response
->headers
->GetContentLength());
2817 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2818 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2820 TestCompletionCallback callback2
;
2822 // Wrong password (should be "bar").
2823 rv
= trans
->RestartWithAuth(
2824 AuthCredentials(kFoo
, kBaz
), callback2
.callback());
2825 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2827 rv
= callback2
.WaitForResult();
2830 response
= trans
->GetResponseInfo();
2831 ASSERT_TRUE(response
);
2832 ASSERT_TRUE(response
->headers
);
2833 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2834 EXPECT_EQ(407, response
->headers
->response_code());
2835 EXPECT_EQ(10, response
->headers
->GetContentLength());
2836 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2837 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
2839 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
2841 session
->CloseAllConnections();
2844 // Test that we don't read the response body when we fail to establish a tunnel,
2845 // even if the user cancels the proxy's auth attempt.
2846 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyCancelTunnel
) {
2847 HttpRequestInfo request
;
2848 request
.method
= "GET";
2849 request
.url
= GURL("https://www.example.org/");
2850 request
.load_flags
= 0;
2852 // Configure against proxy server "myproxy:70".
2853 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2855 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2857 scoped_ptr
<HttpTransaction
> trans(
2858 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2860 // Since we have proxy, should try to establish tunnel.
2861 MockWrite data_writes
[] = {
2863 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2864 "Host: www.example.org\r\n"
2865 "Proxy-Connection: keep-alive\r\n\r\n"),
2868 // The proxy responds to the connect with a 407.
2869 MockRead data_reads
[] = {
2870 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2871 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2872 MockRead("Content-Length: 10\r\n\r\n"),
2873 MockRead("0123456789"), // Should not be reached.
2874 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
2877 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
2878 data_writes
, arraysize(data_writes
));
2879 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2881 TestCompletionCallback callback
;
2883 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2884 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2886 rv
= callback
.WaitForResult();
2889 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2890 ASSERT_TRUE(response
);
2891 ASSERT_TRUE(response
->headers
);
2892 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2893 EXPECT_EQ(407, response
->headers
->response_code());
2894 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2896 std::string response_data
;
2897 rv
= ReadTransaction(trans
.get(), &response_data
);
2898 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2900 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2901 session
->CloseAllConnections();
2904 // Test that we don't pass extraneous headers from the proxy's response to the
2905 // caller when the proxy responds to CONNECT with 407.
2906 TEST_P(HttpNetworkTransactionTest
, SanitizeProxyAuthHeaders
) {
2907 HttpRequestInfo request
;
2908 request
.method
= "GET";
2909 request
.url
= GURL("https://www.example.org/");
2910 request
.load_flags
= 0;
2912 // Configure against proxy server "myproxy:70".
2913 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
2915 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2917 scoped_ptr
<HttpTransaction
> trans(
2918 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2920 // Since we have proxy, should try to establish tunnel.
2921 MockWrite data_writes
[] = {
2923 "CONNECT www.example.org:443 HTTP/1.1\r\n"
2924 "Host: www.example.org\r\n"
2925 "Proxy-Connection: keep-alive\r\n\r\n"),
2928 // The proxy responds to the connect with a 407.
2929 MockRead data_reads
[] = {
2930 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2931 MockRead("X-Foo: bar\r\n"),
2932 MockRead("Set-Cookie: foo=bar\r\n"),
2933 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2934 MockRead("Content-Length: 10\r\n\r\n"),
2935 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
2938 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
2939 arraysize(data_writes
));
2940 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
2942 TestCompletionCallback callback
;
2944 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
2945 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2947 rv
= callback
.WaitForResult();
2950 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
2951 ASSERT_TRUE(response
);
2952 ASSERT_TRUE(response
->headers
);
2953 EXPECT_TRUE(response
->headers
->IsKeepAlive());
2954 EXPECT_EQ(407, response
->headers
->response_code());
2955 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
2956 EXPECT_FALSE(response
->headers
->HasHeader("X-Foo"));
2957 EXPECT_FALSE(response
->headers
->HasHeader("Set-Cookie"));
2959 std::string response_data
;
2960 rv
= ReadTransaction(trans
.get(), &response_data
);
2961 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
2963 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
2964 session
->CloseAllConnections();
2967 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
2968 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
2969 TEST_P(HttpNetworkTransactionTest
, UnexpectedProxyAuth
) {
2970 HttpRequestInfo request
;
2971 request
.method
= "GET";
2972 request
.url
= GURL("http://www.example.org/");
2973 request
.load_flags
= 0;
2975 // We are using a DIRECT connection (i.e. no proxy) for this session.
2976 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
2977 scoped_ptr
<HttpTransaction
> trans(
2978 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
2980 MockWrite data_writes1
[] = {
2982 "GET / HTTP/1.1\r\n"
2983 "Host: www.example.org\r\n"
2984 "Connection: keep-alive\r\n\r\n"),
2987 MockRead data_reads1
[] = {
2988 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
2989 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2990 // Large content-length -- won't matter, as connection will be reset.
2991 MockRead("Content-Length: 10000\r\n\r\n"),
2992 MockRead(SYNCHRONOUS
, ERR_FAILED
),
2995 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
2996 data_writes1
, arraysize(data_writes1
));
2997 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
2999 TestCompletionCallback callback
;
3001 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
3002 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3004 rv
= callback
.WaitForResult();
3005 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3008 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
3009 // through a non-authenticating proxy. The request should fail with
3010 // ERR_UNEXPECTED_PROXY_AUTH.
3011 // Note that it is impossible to detect if an HTTP server returns a 407 through
3012 // a non-authenticating proxy - there is nothing to indicate whether the
3013 // response came from the proxy or the server, so it is treated as if the proxy
3014 // issued the challenge.
3015 TEST_P(HttpNetworkTransactionTest
,
3016 HttpsServerRequestsProxyAuthThroughProxy
) {
3017 HttpRequestInfo request
;
3018 request
.method
= "GET";
3019 request
.url
= GURL("https://www.example.org/");
3021 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
3022 BoundTestNetLog log
;
3023 session_deps_
.net_log
= log
.bound().net_log();
3024 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3026 // Since we have proxy, should try to establish tunnel.
3027 MockWrite data_writes1
[] = {
3029 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3030 "Host: www.example.org\r\n"
3031 "Proxy-Connection: keep-alive\r\n\r\n"),
3034 "GET / HTTP/1.1\r\n"
3035 "Host: www.example.org\r\n"
3036 "Connection: keep-alive\r\n\r\n"),
3039 MockRead data_reads1
[] = {
3040 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3042 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
3043 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3045 MockRead(SYNCHRONOUS
, OK
),
3048 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3049 data_writes1
, arraysize(data_writes1
));
3050 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3051 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3052 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3054 TestCompletionCallback callback1
;
3056 scoped_ptr
<HttpTransaction
> trans(
3057 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3059 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3060 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3062 rv
= callback1
.WaitForResult();
3063 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH
, rv
);
3064 TestNetLogEntry::List entries
;
3065 log
.GetEntries(&entries
);
3066 size_t pos
= ExpectLogContainsSomewhere(
3067 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
3068 NetLog::PHASE_NONE
);
3069 ExpectLogContainsSomewhere(
3071 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
3072 NetLog::PHASE_NONE
);
3075 // Test the load timing for HTTPS requests with an HTTP proxy.
3076 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingNoPacTwoRequests
) {
3077 HttpRequestInfo request1
;
3078 request1
.method
= "GET";
3079 request1
.url
= GURL("https://www.example.org/1");
3081 HttpRequestInfo request2
;
3082 request2
.method
= "GET";
3083 request2
.url
= GURL("https://www.example.org/2");
3085 // Configure against proxy server "myproxy:70".
3086 session_deps_
.proxy_service
.reset(
3087 ProxyService::CreateFixed("PROXY myproxy:70"));
3088 BoundTestNetLog log
;
3089 session_deps_
.net_log
= log
.bound().net_log();
3090 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3092 // Since we have proxy, should try to establish tunnel.
3093 MockWrite data_writes1
[] = {
3095 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3096 "Host: www.example.org\r\n"
3097 "Proxy-Connection: keep-alive\r\n\r\n"),
3100 "GET /1 HTTP/1.1\r\n"
3101 "Host: www.example.org\r\n"
3102 "Connection: keep-alive\r\n\r\n"),
3105 "GET /2 HTTP/1.1\r\n"
3106 "Host: www.example.org\r\n"
3107 "Connection: keep-alive\r\n\r\n"),
3110 // The proxy responds to the connect with a 407, using a persistent
3112 MockRead data_reads1
[] = {
3113 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3115 MockRead("HTTP/1.1 200 OK\r\n"),
3116 MockRead("Content-Length: 1\r\n\r\n"),
3117 MockRead(SYNCHRONOUS
, "1"),
3119 MockRead("HTTP/1.1 200 OK\r\n"),
3120 MockRead("Content-Length: 2\r\n\r\n"),
3121 MockRead(SYNCHRONOUS
, "22"),
3124 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3125 data_writes1
, arraysize(data_writes1
));
3126 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3127 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3128 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3130 TestCompletionCallback callback1
;
3131 scoped_ptr
<HttpTransaction
> trans1(
3132 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3134 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3135 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3137 rv
= callback1
.WaitForResult();
3140 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3141 ASSERT_TRUE(response1
!= NULL
);
3142 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3143 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3145 LoadTimingInfo load_timing_info1
;
3146 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3147 TestLoadTimingNotReused(load_timing_info1
, CONNECT_TIMING_HAS_SSL_TIMES
);
3151 TestCompletionCallback callback2
;
3152 scoped_ptr
<HttpTransaction
> trans2(
3153 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3155 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3156 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3158 rv
= callback2
.WaitForResult();
3161 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3162 ASSERT_TRUE(response2
!= NULL
);
3163 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3164 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3166 LoadTimingInfo load_timing_info2
;
3167 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3168 TestLoadTimingReused(load_timing_info2
);
3170 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3173 session
->CloseAllConnections();
3176 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
3177 TEST_P(HttpNetworkTransactionTest
, HttpProxyLoadTimingWithPacTwoRequests
) {
3178 HttpRequestInfo request1
;
3179 request1
.method
= "GET";
3180 request1
.url
= GURL("https://www.example.org/1");
3182 HttpRequestInfo request2
;
3183 request2
.method
= "GET";
3184 request2
.url
= GURL("https://www.example.org/2");
3186 // Configure against proxy server "myproxy:70".
3187 session_deps_
.proxy_service
.reset(
3188 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
3189 BoundTestNetLog log
;
3190 session_deps_
.net_log
= log
.bound().net_log();
3191 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3193 // Since we have proxy, should try to establish tunnel.
3194 MockWrite data_writes1
[] = {
3196 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3197 "Host: www.example.org\r\n"
3198 "Proxy-Connection: keep-alive\r\n\r\n"),
3201 "GET /1 HTTP/1.1\r\n"
3202 "Host: www.example.org\r\n"
3203 "Connection: keep-alive\r\n\r\n"),
3206 "GET /2 HTTP/1.1\r\n"
3207 "Host: www.example.org\r\n"
3208 "Connection: keep-alive\r\n\r\n"),
3211 // The proxy responds to the connect with a 407, using a persistent
3213 MockRead data_reads1
[] = {
3214 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3216 MockRead("HTTP/1.1 200 OK\r\n"),
3217 MockRead("Content-Length: 1\r\n\r\n"),
3218 MockRead(SYNCHRONOUS
, "1"),
3220 MockRead("HTTP/1.1 200 OK\r\n"),
3221 MockRead("Content-Length: 2\r\n\r\n"),
3222 MockRead(SYNCHRONOUS
, "22"),
3225 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3226 data_writes1
, arraysize(data_writes1
));
3227 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3228 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3229 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3231 TestCompletionCallback callback1
;
3232 scoped_ptr
<HttpTransaction
> trans1(
3233 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3235 int rv
= trans1
->Start(&request1
, callback1
.callback(), log
.bound());
3236 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3238 rv
= callback1
.WaitForResult();
3241 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
3242 ASSERT_TRUE(response1
!= NULL
);
3243 ASSERT_TRUE(response1
->headers
.get() != NULL
);
3244 EXPECT_EQ(1, response1
->headers
->GetContentLength());
3246 LoadTimingInfo load_timing_info1
;
3247 EXPECT_TRUE(trans1
->GetLoadTimingInfo(&load_timing_info1
));
3248 TestLoadTimingNotReusedWithPac(load_timing_info1
,
3249 CONNECT_TIMING_HAS_SSL_TIMES
);
3253 TestCompletionCallback callback2
;
3254 scoped_ptr
<HttpTransaction
> trans2(
3255 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3257 rv
= trans2
->Start(&request2
, callback2
.callback(), log
.bound());
3258 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3260 rv
= callback2
.WaitForResult();
3263 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
3264 ASSERT_TRUE(response2
!= NULL
);
3265 ASSERT_TRUE(response2
->headers
.get() != NULL
);
3266 EXPECT_EQ(2, response2
->headers
->GetContentLength());
3268 LoadTimingInfo load_timing_info2
;
3269 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3270 TestLoadTimingReusedWithPac(load_timing_info2
);
3272 EXPECT_EQ(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
3275 session
->CloseAllConnections();
3278 // Test a simple get through an HTTPS Proxy.
3279 TEST_P(HttpNetworkTransactionTest
, HttpsProxyGet
) {
3280 HttpRequestInfo request
;
3281 request
.method
= "GET";
3282 request
.url
= GURL("http://www.example.org/");
3284 // Configure against https proxy server "proxy:70".
3285 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3286 "https://proxy:70"));
3287 BoundTestNetLog log
;
3288 session_deps_
.net_log
= log
.bound().net_log();
3289 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3291 // Since we have proxy, should use full url
3292 MockWrite data_writes1
[] = {
3294 "GET http://www.example.org/ HTTP/1.1\r\n"
3295 "Host: www.example.org\r\n"
3296 "Proxy-Connection: keep-alive\r\n\r\n"),
3299 MockRead data_reads1
[] = {
3300 MockRead("HTTP/1.1 200 OK\r\n"),
3301 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3302 MockRead("Content-Length: 100\r\n\r\n"),
3303 MockRead(SYNCHRONOUS
, OK
),
3306 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
3307 data_writes1
, arraysize(data_writes1
));
3308 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
3309 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3310 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3312 TestCompletionCallback callback1
;
3314 scoped_ptr
<HttpTransaction
> trans(
3315 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3317 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3318 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3320 rv
= callback1
.WaitForResult();
3323 LoadTimingInfo load_timing_info
;
3324 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3325 TestLoadTimingNotReused(load_timing_info
,
3326 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
3328 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3329 ASSERT_TRUE(response
!= NULL
);
3331 EXPECT_TRUE(response
->headers
->IsKeepAlive());
3332 EXPECT_EQ(200, response
->headers
->response_code());
3333 EXPECT_EQ(100, response
->headers
->GetContentLength());
3334 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
3336 // The password prompt info should not be set.
3337 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
3340 // Test a SPDY get through an HTTPS Proxy.
3341 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGet
) {
3342 HttpRequestInfo request
;
3343 request
.method
= "GET";
3344 request
.url
= GURL("http://www.example.org/");
3345 request
.load_flags
= 0;
3347 // Configure against https proxy server "proxy:70".
3348 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3349 "https://proxy:70"));
3350 BoundTestNetLog log
;
3351 session_deps_
.net_log
= log
.bound().net_log();
3352 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3354 // fetch http://www.example.org/ via SPDY
3355 scoped_ptr
<SpdyFrame
> req(
3356 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3357 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
3359 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3360 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3361 MockRead spdy_reads
[] = {
3362 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3365 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3366 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
, 0)};
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
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
3426 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3427 arraysize(spdy_writes
));
3428 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3430 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3431 ssl
.SetNextProto(GetParam());
3432 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3434 TestCompletionCallback callback1
;
3436 scoped_ptr
<HttpTransaction
> trans(
3437 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3439 // Stall the hostname resolution begun by the transaction.
3440 session_deps_
.host_resolver
->set_synchronous_mode(false);
3441 session_deps_
.host_resolver
->set_ondemand_mode(true);
3443 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3444 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3446 // Race a session to the proxy, which completes first.
3447 session_deps_
.host_resolver
->set_ondemand_mode(false);
3449 HostPortPair("proxy", 70), ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
3450 base::WeakPtr
<SpdySession
> spdy_session
=
3451 CreateSecureSpdySession(session
, key
, log
.bound());
3453 // Unstall the resolution begun by the transaction.
3454 session_deps_
.host_resolver
->set_ondemand_mode(true);
3455 session_deps_
.host_resolver
->ResolveAllPending();
3457 EXPECT_FALSE(callback1
.have_result());
3458 rv
= callback1
.WaitForResult();
3461 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3462 ASSERT_TRUE(response
!= NULL
);
3463 ASSERT_TRUE(response
->headers
.get() != NULL
);
3464 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3466 std::string response_data
;
3467 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3468 EXPECT_EQ(kUploadData
, response_data
);
3471 // Test a SPDY get through an HTTPS Proxy.
3472 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyGetWithProxyAuth
) {
3473 HttpRequestInfo request
;
3474 request
.method
= "GET";
3475 request
.url
= GURL("http://www.example.org/");
3476 request
.load_flags
= 0;
3478 // Configure against https proxy server "myproxy:70".
3479 session_deps_
.proxy_service
.reset(
3480 ProxyService::CreateFixed("https://myproxy:70"));
3481 BoundTestNetLog log
;
3482 session_deps_
.net_log
= log
.bound().net_log();
3483 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3485 // The first request will be a bare GET, the second request will be a
3486 // GET with a Proxy-Authorization header.
3487 scoped_ptr
<SpdyFrame
> req_get(
3488 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
3489 const char* const kExtraAuthorizationHeaders
[] = {
3490 "proxy-authorization", "Basic Zm9vOmJhcg=="
3492 scoped_ptr
<SpdyFrame
> req_get_authorization(
3493 spdy_util_
.ConstructSpdyGet(kExtraAuthorizationHeaders
,
3494 arraysize(kExtraAuthorizationHeaders
) / 2,
3499 MockWrite spdy_writes
[] = {
3500 CreateMockWrite(*req_get
, 0), CreateMockWrite(*req_get_authorization
, 3),
3503 // The first response is a 407 proxy authentication challenge, and the second
3504 // response will be a 200 response since the second request includes a valid
3505 // Authorization header.
3506 const char* const kExtraAuthenticationHeaders
[] = {
3507 "proxy-authenticate", "Basic realm=\"MyRealm1\""
3509 scoped_ptr
<SpdyFrame
> resp_authentication(
3510 spdy_util_
.ConstructSpdySynReplyError(
3511 "407 Proxy Authentication Required",
3512 kExtraAuthenticationHeaders
, arraysize(kExtraAuthenticationHeaders
)/2,
3514 scoped_ptr
<SpdyFrame
> body_authentication(
3515 spdy_util_
.ConstructSpdyBodyFrame(1, true));
3516 scoped_ptr
<SpdyFrame
> resp_data(
3517 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3518 scoped_ptr
<SpdyFrame
> body_data(spdy_util_
.ConstructSpdyBodyFrame(3, true));
3519 MockRead spdy_reads
[] = {
3520 CreateMockRead(*resp_authentication
, 1),
3521 CreateMockRead(*body_authentication
, 2),
3522 CreateMockRead(*resp_data
, 4),
3523 CreateMockRead(*body_data
, 5),
3524 MockRead(ASYNC
, 0, 6),
3527 SequencedSocketData
data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3528 arraysize(spdy_writes
));
3529 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
3531 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3532 ssl
.SetNextProto(GetParam());
3533 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3535 TestCompletionCallback callback1
;
3537 scoped_ptr
<HttpTransaction
> trans(
3538 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3540 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3541 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3543 rv
= callback1
.WaitForResult();
3546 const HttpResponseInfo
* const response
= trans
->GetResponseInfo();
3548 ASSERT_TRUE(response
!= NULL
);
3549 ASSERT_TRUE(response
->headers
.get() != NULL
);
3550 EXPECT_EQ(407, response
->headers
->response_code());
3551 EXPECT_TRUE(response
->was_fetched_via_spdy
);
3552 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
3554 TestCompletionCallback callback2
;
3556 rv
= trans
->RestartWithAuth(
3557 AuthCredentials(kFoo
, kBar
), callback2
.callback());
3558 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3560 rv
= callback2
.WaitForResult();
3563 const HttpResponseInfo
* const response_restart
= trans
->GetResponseInfo();
3565 ASSERT_TRUE(response_restart
!= NULL
);
3566 ASSERT_TRUE(response_restart
->headers
.get() != NULL
);
3567 EXPECT_EQ(200, response_restart
->headers
->response_code());
3568 // The password prompt info should not be set.
3569 EXPECT_TRUE(response_restart
->auth_challenge
.get() == NULL
);
3572 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
3573 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectHttps
) {
3574 HttpRequestInfo request
;
3575 request
.method
= "GET";
3576 request
.url
= GURL("https://www.example.org/");
3577 request
.load_flags
= 0;
3579 // Configure against https proxy server "proxy:70".
3580 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3581 "https://proxy:70"));
3582 BoundTestNetLog log
;
3583 session_deps_
.net_log
= log
.bound().net_log();
3584 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3586 scoped_ptr
<HttpTransaction
> trans(
3587 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3589 // CONNECT to www.example.org:443 via SPDY
3590 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3591 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3592 // fetch https://www.example.org/ via HTTP
3595 "GET / HTTP/1.1\r\n"
3596 "Host: www.example.org\r\n"
3597 "Connection: keep-alive\r\n\r\n";
3598 scoped_ptr
<SpdyFrame
> wrapped_get(
3599 spdy_util_
.ConstructSpdyBodyFrame(1, get
, strlen(get
), false));
3600 scoped_ptr
<SpdyFrame
> conn_resp(
3601 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3602 const char resp
[] = "HTTP/1.1 200 OK\r\n"
3603 "Content-Length: 10\r\n\r\n";
3604 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3605 spdy_util_
.ConstructSpdyBodyFrame(1, resp
, strlen(resp
), false));
3606 scoped_ptr
<SpdyFrame
> wrapped_body(
3607 spdy_util_
.ConstructSpdyBodyFrame(1, "1234567890", 10, false));
3608 scoped_ptr
<SpdyFrame
> window_update(
3609 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3611 MockWrite spdy_writes
[] = {
3612 CreateMockWrite(*connect
, 0),
3613 CreateMockWrite(*wrapped_get
, 2),
3614 CreateMockWrite(*window_update
, 6),
3617 MockRead spdy_reads
[] = {
3618 CreateMockRead(*conn_resp
, 1, ASYNC
),
3619 CreateMockRead(*wrapped_get_resp
, 3, ASYNC
),
3620 CreateMockRead(*wrapped_body
, 4, ASYNC
),
3621 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3622 MockRead(ASYNC
, 0, 7),
3625 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3626 arraysize(spdy_writes
));
3627 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3629 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3630 ssl
.SetNextProto(GetParam());
3631 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3632 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3633 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3635 TestCompletionCallback callback1
;
3637 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3638 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3640 rv
= callback1
.WaitForResult();
3643 LoadTimingInfo load_timing_info
;
3644 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3645 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3647 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3648 ASSERT_TRUE(response
!= NULL
);
3649 ASSERT_TRUE(response
->headers
.get() != NULL
);
3650 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3652 std::string response_data
;
3653 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3654 EXPECT_EQ("1234567890", response_data
);
3657 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
3658 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectSpdy
) {
3659 HttpRequestInfo request
;
3660 request
.method
= "GET";
3661 request
.url
= GURL("https://www.example.org/");
3662 request
.load_flags
= 0;
3664 // Configure against https proxy server "proxy:70".
3665 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3666 "https://proxy:70"));
3667 BoundTestNetLog log
;
3668 session_deps_
.net_log
= log
.bound().net_log();
3669 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3671 scoped_ptr
<HttpTransaction
> trans(
3672 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3674 // CONNECT to www.example.org:443 via SPDY
3675 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3676 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3677 // fetch https://www.example.org/ via SPDY
3678 const char kMyUrl
[] = "https://www.example.org/";
3679 scoped_ptr
<SpdyFrame
> get(
3680 spdy_util_
.ConstructSpdyGet(kMyUrl
, false, 1, LOWEST
));
3681 scoped_ptr
<SpdyFrame
> wrapped_get(
3682 spdy_util_
.ConstructWrappedSpdyFrame(get
, 1));
3683 scoped_ptr
<SpdyFrame
> conn_resp(
3684 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3685 scoped_ptr
<SpdyFrame
> get_resp(
3686 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3687 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
3688 spdy_util_
.ConstructWrappedSpdyFrame(get_resp
, 1));
3689 scoped_ptr
<SpdyFrame
> body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3690 scoped_ptr
<SpdyFrame
> wrapped_body(
3691 spdy_util_
.ConstructWrappedSpdyFrame(body
, 1));
3692 scoped_ptr
<SpdyFrame
> window_update_get_resp(
3693 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp
->size()));
3694 scoped_ptr
<SpdyFrame
> window_update_body(
3695 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_body
->size()));
3697 MockWrite spdy_writes
[] = {
3698 CreateMockWrite(*connect
, 0),
3699 CreateMockWrite(*wrapped_get
, 2),
3700 CreateMockWrite(*window_update_get_resp
, 6),
3701 CreateMockWrite(*window_update_body
, 7),
3704 MockRead spdy_reads
[] = {
3705 CreateMockRead(*conn_resp
, 1, ASYNC
),
3706 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
3707 CreateMockRead(*wrapped_get_resp
, 4, ASYNC
),
3708 CreateMockRead(*wrapped_body
, 5, ASYNC
),
3709 MockRead(ASYNC
, 0, 8),
3712 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3713 arraysize(spdy_writes
));
3714 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3716 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3717 ssl
.SetNextProto(GetParam());
3718 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3719 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3720 ssl2
.SetNextProto(GetParam());
3721 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3723 TestCompletionCallback callback1
;
3725 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3726 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3728 // Allow the SpdyProxyClientSocket's write callback to complete.
3729 base::MessageLoop::current()->RunUntilIdle();
3730 // Now allow the read of the response to complete.
3731 spdy_data
.CompleteRead();
3732 rv
= callback1
.WaitForResult();
3735 LoadTimingInfo load_timing_info
;
3736 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3737 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3739 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3740 ASSERT_TRUE(response
!= NULL
);
3741 ASSERT_TRUE(response
->headers
.get() != NULL
);
3742 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3744 std::string response_data
;
3745 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
3746 EXPECT_EQ(kUploadData
, response_data
);
3749 // Test a SPDY CONNECT failure through an HTTPS Proxy.
3750 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyConnectFailure
) {
3751 HttpRequestInfo request
;
3752 request
.method
= "GET";
3753 request
.url
= GURL("https://www.example.org/");
3754 request
.load_flags
= 0;
3756 // Configure against https proxy server "proxy:70".
3757 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3758 "https://proxy:70"));
3759 BoundTestNetLog log
;
3760 session_deps_
.net_log
= log
.bound().net_log();
3761 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
3763 scoped_ptr
<HttpTransaction
> trans(
3764 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3766 // CONNECT to www.example.org:443 via SPDY
3767 scoped_ptr
<SpdyFrame
> connect(spdy_util_
.ConstructSpdyConnect(
3768 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3769 scoped_ptr
<SpdyFrame
> get(
3770 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
3772 MockWrite spdy_writes
[] = {
3773 CreateMockWrite(*connect
, 0), CreateMockWrite(*get
, 2),
3776 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdySynReplyError(1));
3777 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
3778 MockRead spdy_reads
[] = {
3779 CreateMockRead(*resp
, 1, ASYNC
), MockRead(ASYNC
, 0, 3),
3782 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3783 arraysize(spdy_writes
));
3784 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3786 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3787 ssl
.SetNextProto(GetParam());
3788 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3789 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3790 ssl2
.SetNextProto(GetParam());
3791 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3793 TestCompletionCallback callback1
;
3795 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
3796 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3798 rv
= callback1
.WaitForResult();
3799 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
3801 // TODO(ttuttle): Anything else to check here?
3804 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3805 // HTTPS Proxy to different servers.
3806 TEST_P(HttpNetworkTransactionTest
,
3807 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers
) {
3808 // Configure against https proxy server "proxy:70".
3809 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3810 "https://proxy:70"));
3811 BoundTestNetLog log
;
3812 session_deps_
.net_log
= log
.bound().net_log();
3813 scoped_refptr
<HttpNetworkSession
> session(
3814 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3816 HttpRequestInfo request1
;
3817 request1
.method
= "GET";
3818 request1
.url
= GURL("https://www.example.org/");
3819 request1
.load_flags
= 0;
3821 HttpRequestInfo request2
;
3822 request2
.method
= "GET";
3823 request2
.url
= GURL("https://mail.example.org/");
3824 request2
.load_flags
= 0;
3826 // CONNECT to www.example.org:443 via SPDY.
3827 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3828 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3829 scoped_ptr
<SpdyFrame
> conn_resp1(
3830 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3832 // Fetch https://www.example.org/ via HTTP.
3834 "GET / HTTP/1.1\r\n"
3835 "Host: www.example.org\r\n"
3836 "Connection: keep-alive\r\n\r\n";
3837 scoped_ptr
<SpdyFrame
> wrapped_get1(
3838 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3839 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3840 "Content-Length: 1\r\n\r\n";
3841 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3842 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3843 scoped_ptr
<SpdyFrame
> wrapped_body1(
3844 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3845 scoped_ptr
<SpdyFrame
> window_update(
3846 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3848 // CONNECT to mail.example.org:443 via SPDY.
3849 SpdyHeaderBlock connect2_block
;
3850 connect2_block
[spdy_util_
.GetMethodKey()] = "CONNECT";
3851 if (GetParam() >= kProtoHTTP2MinimumVersion
) {
3852 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org:443";
3854 connect2_block
[spdy_util_
.GetPathKey()] = "mail.example.org:443";
3855 connect2_block
[spdy_util_
.GetHostKey()] = "mail.example.org";
3857 spdy_util_
.MaybeAddVersionHeader(&connect2_block
);
3858 scoped_ptr
<SpdyFrame
> connect2(
3859 spdy_util_
.ConstructSpdySyn(3, connect2_block
, LOWEST
, false, false));
3861 scoped_ptr
<SpdyFrame
> conn_resp2(
3862 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
3864 // Fetch https://mail.example.org/ via HTTP.
3866 "GET / HTTP/1.1\r\n"
3867 "Host: mail.example.org\r\n"
3868 "Connection: keep-alive\r\n\r\n";
3869 scoped_ptr
<SpdyFrame
> wrapped_get2(
3870 spdy_util_
.ConstructSpdyBodyFrame(3, get2
, strlen(get2
), false));
3871 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3872 "Content-Length: 2\r\n\r\n";
3873 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
3874 spdy_util_
.ConstructSpdyBodyFrame(3, resp2
, strlen(resp2
), false));
3875 scoped_ptr
<SpdyFrame
> wrapped_body2(
3876 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, false));
3878 MockWrite spdy_writes
[] = {
3879 CreateMockWrite(*connect1
, 0),
3880 CreateMockWrite(*wrapped_get1
, 2),
3881 CreateMockWrite(*connect2
, 5),
3882 CreateMockWrite(*wrapped_get2
, 7),
3885 MockRead spdy_reads
[] = {
3886 CreateMockRead(*conn_resp1
, 1, ASYNC
),
3887 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
3888 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
3889 CreateMockRead(*conn_resp2
, 6, ASYNC
),
3890 CreateMockRead(*wrapped_get_resp2
, 8, ASYNC
),
3891 CreateMockRead(*wrapped_body2
, 9, ASYNC
),
3892 MockRead(ASYNC
, 0, 10),
3895 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
3896 arraysize(spdy_writes
));
3897 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
3899 SSLSocketDataProvider
ssl(ASYNC
, OK
);
3900 ssl
.SetNextProto(GetParam());
3901 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
3902 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
3903 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
3904 SSLSocketDataProvider
ssl3(ASYNC
, OK
);
3905 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl3
);
3907 TestCompletionCallback callback
;
3909 scoped_ptr
<HttpTransaction
> trans(
3910 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3911 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
3912 EXPECT_EQ(OK
, callback
.GetResult(rv
));
3914 LoadTimingInfo load_timing_info
;
3915 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
3916 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
3918 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
3919 ASSERT_TRUE(response
!= NULL
);
3920 ASSERT_TRUE(response
->headers
.get() != NULL
);
3921 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
3923 std::string response_data
;
3924 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
3925 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
3926 EXPECT_EQ(1, callback
.GetResult(rv
));
3928 scoped_ptr
<HttpTransaction
> trans2(
3929 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
3930 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
3931 EXPECT_EQ(OK
, callback
.GetResult(rv
));
3933 LoadTimingInfo load_timing_info2
;
3934 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
3935 // Even though the SPDY connection is reused, a new tunnelled connection has
3936 // to be created, so the socket's load timing looks like a fresh connection.
3937 TestLoadTimingNotReused(load_timing_info2
, CONNECT_TIMING_HAS_SSL_TIMES
);
3939 // The requests should have different IDs, since they each are using their own
3941 EXPECT_NE(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
3943 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
3944 EXPECT_EQ(2, callback
.GetResult(rv
));
3947 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
3948 // HTTPS Proxy to the same server.
3949 TEST_P(HttpNetworkTransactionTest
,
3950 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer
) {
3951 // Configure against https proxy server "proxy:70".
3952 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
3953 "https://proxy:70"));
3954 BoundTestNetLog log
;
3955 session_deps_
.net_log
= log
.bound().net_log();
3956 scoped_refptr
<HttpNetworkSession
> session(
3957 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
3959 HttpRequestInfo request1
;
3960 request1
.method
= "GET";
3961 request1
.url
= GURL("https://www.example.org/");
3962 request1
.load_flags
= 0;
3964 HttpRequestInfo request2
;
3965 request2
.method
= "GET";
3966 request2
.url
= GURL("https://www.example.org/2");
3967 request2
.load_flags
= 0;
3969 // CONNECT to www.example.org:443 via SPDY.
3970 scoped_ptr
<SpdyFrame
> connect1(spdy_util_
.ConstructSpdyConnect(
3971 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
3972 scoped_ptr
<SpdyFrame
> conn_resp1(
3973 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
3975 // Fetch https://www.example.org/ via HTTP.
3977 "GET / HTTP/1.1\r\n"
3978 "Host: www.example.org\r\n"
3979 "Connection: keep-alive\r\n\r\n";
3980 scoped_ptr
<SpdyFrame
> wrapped_get1(
3981 spdy_util_
.ConstructSpdyBodyFrame(1, get1
, strlen(get1
), false));
3982 const char resp1
[] = "HTTP/1.1 200 OK\r\n"
3983 "Content-Length: 1\r\n\r\n";
3984 scoped_ptr
<SpdyFrame
> wrapped_get_resp1(
3985 spdy_util_
.ConstructSpdyBodyFrame(1, resp1
, strlen(resp1
), false));
3986 scoped_ptr
<SpdyFrame
> wrapped_body1(
3987 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, false));
3988 scoped_ptr
<SpdyFrame
> window_update(
3989 spdy_util_
.ConstructSpdyWindowUpdate(1, wrapped_get_resp1
->size()));
3991 // Fetch https://www.example.org/2 via HTTP.
3993 "GET /2 HTTP/1.1\r\n"
3994 "Host: www.example.org\r\n"
3995 "Connection: keep-alive\r\n\r\n";
3996 scoped_ptr
<SpdyFrame
> wrapped_get2(
3997 spdy_util_
.ConstructSpdyBodyFrame(1, get2
, strlen(get2
), false));
3998 const char resp2
[] = "HTTP/1.1 200 OK\r\n"
3999 "Content-Length: 2\r\n\r\n";
4000 scoped_ptr
<SpdyFrame
> wrapped_get_resp2(
4001 spdy_util_
.ConstructSpdyBodyFrame(1, resp2
, strlen(resp2
), false));
4002 scoped_ptr
<SpdyFrame
> wrapped_body2(
4003 spdy_util_
.ConstructSpdyBodyFrame(1, "22", 2, false));
4005 MockWrite spdy_writes
[] = {
4006 CreateMockWrite(*connect1
, 0),
4007 CreateMockWrite(*wrapped_get1
, 2),
4008 CreateMockWrite(*wrapped_get2
, 5),
4011 MockRead spdy_reads
[] = {
4012 CreateMockRead(*conn_resp1
, 1, ASYNC
),
4013 CreateMockRead(*wrapped_get_resp1
, 3, ASYNC
),
4014 CreateMockRead(*wrapped_body1
, 4, ASYNC
),
4015 CreateMockRead(*wrapped_get_resp2
, 6, ASYNC
),
4016 CreateMockRead(*wrapped_body2
, 7, ASYNC
),
4017 MockRead(ASYNC
, 0, 8),
4020 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4021 arraysize(spdy_writes
));
4022 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4024 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4025 ssl
.SetNextProto(GetParam());
4026 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4027 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
4028 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
4030 TestCompletionCallback callback
;
4032 scoped_ptr
<HttpTransaction
> trans(
4033 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4034 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4037 rv
= callback
.WaitForResult();
4040 LoadTimingInfo load_timing_info
;
4041 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4042 TestLoadTimingNotReused(load_timing_info
, CONNECT_TIMING_HAS_SSL_TIMES
);
4044 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4045 ASSERT_TRUE(response
!= NULL
);
4046 ASSERT_TRUE(response
->headers
.get() != NULL
);
4047 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4049 std::string response_data
;
4050 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4051 EXPECT_EQ(1, trans
->Read(buf
.get(), 256, callback
.callback()));
4054 scoped_ptr
<HttpTransaction
> trans2(
4055 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4056 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4057 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4059 rv
= callback
.WaitForResult();
4062 LoadTimingInfo load_timing_info2
;
4063 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4064 TestLoadTimingReused(load_timing_info2
);
4066 // The requests should have the same ID.
4067 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4069 EXPECT_EQ(2, trans2
->Read(buf
.get(), 256, callback
.callback()));
4072 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
4073 // Proxy to different servers.
4074 TEST_P(HttpNetworkTransactionTest
, HttpsProxySpdyLoadTimingTwoHttpRequests
) {
4075 // Configure against https proxy server "proxy:70".
4076 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
4077 "https://proxy:70"));
4078 BoundTestNetLog log
;
4079 session_deps_
.net_log
= log
.bound().net_log();
4080 scoped_refptr
<HttpNetworkSession
> session(
4081 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
4083 HttpRequestInfo request1
;
4084 request1
.method
= "GET";
4085 request1
.url
= GURL("http://www.example.org/");
4086 request1
.load_flags
= 0;
4088 HttpRequestInfo request2
;
4089 request2
.method
= "GET";
4090 request2
.url
= GURL("http://mail.example.org/");
4091 request2
.load_flags
= 0;
4093 // http://www.example.org/
4094 scoped_ptr
<SpdyHeaderBlock
> headers(
4095 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
4096 scoped_ptr
<SpdyFrame
> get1(
4097 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
4098 scoped_ptr
<SpdyFrame
> get_resp1(
4099 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
4100 scoped_ptr
<SpdyFrame
> body1(
4101 spdy_util_
.ConstructSpdyBodyFrame(1, "1", 1, true));
4103 // http://mail.example.org/
4104 scoped_ptr
<SpdyHeaderBlock
> headers2(
4105 spdy_util_
.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
4106 scoped_ptr
<SpdyFrame
> get2(
4107 spdy_util_
.ConstructSpdySyn(3, *headers2
, LOWEST
, false, true));
4108 scoped_ptr
<SpdyFrame
> get_resp2(
4109 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
4110 scoped_ptr
<SpdyFrame
> body2(
4111 spdy_util_
.ConstructSpdyBodyFrame(3, "22", 2, true));
4113 MockWrite spdy_writes
[] = {
4114 CreateMockWrite(*get1
, 0),
4115 CreateMockWrite(*get2
, 3),
4118 MockRead spdy_reads
[] = {
4119 CreateMockRead(*get_resp1
, 1, ASYNC
),
4120 CreateMockRead(*body1
, 2, ASYNC
),
4121 CreateMockRead(*get_resp2
, 4, ASYNC
),
4122 CreateMockRead(*body2
, 5, ASYNC
),
4123 MockRead(ASYNC
, 0, 6),
4126 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
4127 arraysize(spdy_writes
));
4128 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
4130 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4131 ssl
.SetNextProto(GetParam());
4132 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4134 TestCompletionCallback callback
;
4136 scoped_ptr
<HttpTransaction
> trans(
4137 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4138 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
4139 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4141 LoadTimingInfo load_timing_info
;
4142 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4143 TestLoadTimingNotReused(load_timing_info
,
4144 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4146 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4147 ASSERT_TRUE(response
!= NULL
);
4148 ASSERT_TRUE(response
->headers
.get() != NULL
);
4149 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
4151 std::string response_data
;
4152 scoped_refptr
<IOBuffer
> buf(new IOBuffer(256));
4153 rv
= trans
->Read(buf
.get(), 256, callback
.callback());
4154 EXPECT_EQ(1, callback
.GetResult(rv
));
4155 // Delete the first request, so the second one can reuse the socket.
4158 scoped_ptr
<HttpTransaction
> trans2(
4159 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4160 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
4161 EXPECT_EQ(OK
, callback
.GetResult(rv
));
4163 LoadTimingInfo load_timing_info2
;
4164 EXPECT_TRUE(trans2
->GetLoadTimingInfo(&load_timing_info2
));
4165 TestLoadTimingReused(load_timing_info2
);
4167 // The requests should have the same ID.
4168 EXPECT_EQ(load_timing_info
.socket_log_id
, load_timing_info2
.socket_log_id
);
4170 rv
= trans2
->Read(buf
.get(), 256, callback
.callback());
4171 EXPECT_EQ(2, callback
.GetResult(rv
));
4174 // Test the challenge-response-retry sequence through an HTTPS Proxy
4175 TEST_P(HttpNetworkTransactionTest
, HttpsProxyAuthRetry
) {
4176 HttpRequestInfo request
;
4177 request
.method
= "GET";
4178 request
.url
= GURL("http://www.example.org/");
4179 // when the no authentication data flag is set.
4180 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
4182 // Configure against https proxy server "myproxy:70".
4183 session_deps_
.proxy_service
.reset(
4184 ProxyService::CreateFixed("https://myproxy:70"));
4185 BoundTestNetLog log
;
4186 session_deps_
.net_log
= log
.bound().net_log();
4187 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4189 // Since we have proxy, should use full url
4190 MockWrite data_writes1
[] = {
4192 "GET http://www.example.org/ HTTP/1.1\r\n"
4193 "Host: www.example.org\r\n"
4194 "Proxy-Connection: keep-alive\r\n\r\n"),
4196 // After calling trans->RestartWithAuth(), this is the request we should
4197 // be issuing -- the final header line contains the credentials.
4199 "GET http://www.example.org/ HTTP/1.1\r\n"
4200 "Host: www.example.org\r\n"
4201 "Proxy-Connection: keep-alive\r\n"
4202 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4205 // The proxy responds to the GET with a 407, using a persistent
4207 MockRead data_reads1
[] = {
4209 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4210 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4211 MockRead("Proxy-Connection: keep-alive\r\n"),
4212 MockRead("Content-Length: 0\r\n\r\n"),
4214 MockRead("HTTP/1.1 200 OK\r\n"),
4215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4216 MockRead("Content-Length: 100\r\n\r\n"),
4217 MockRead(SYNCHRONOUS
, OK
),
4220 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4221 data_writes1
, arraysize(data_writes1
));
4222 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4223 SSLSocketDataProvider
ssl(ASYNC
, OK
);
4224 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
4226 TestCompletionCallback callback1
;
4228 scoped_ptr
<HttpTransaction
> trans(
4229 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4231 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
4232 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4234 rv
= callback1
.WaitForResult();
4237 LoadTimingInfo load_timing_info
;
4238 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4239 TestLoadTimingNotReused(load_timing_info
,
4240 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
4242 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4243 ASSERT_TRUE(response
!= NULL
);
4244 ASSERT_FALSE(response
->headers
.get() == NULL
);
4245 EXPECT_EQ(407, response
->headers
->response_code());
4246 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4247 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4249 TestCompletionCallback callback2
;
4251 rv
= trans
->RestartWithAuth(
4252 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4253 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4255 rv
= callback2
.WaitForResult();
4258 load_timing_info
= LoadTimingInfo();
4259 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
4260 // Retrying with HTTP AUTH is considered to be reusing a socket.
4261 TestLoadTimingReused(load_timing_info
);
4263 response
= trans
->GetResponseInfo();
4264 ASSERT_TRUE(response
!= NULL
);
4266 EXPECT_TRUE(response
->headers
->IsKeepAlive());
4267 EXPECT_EQ(200, response
->headers
->response_code());
4268 EXPECT_EQ(100, response
->headers
->GetContentLength());
4269 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
4271 // The password prompt info should not be set.
4272 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4275 void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
4276 const MockRead
& status
, int expected_status
) {
4277 HttpRequestInfo request
;
4278 request
.method
= "GET";
4279 request
.url
= GURL("https://www.example.org/");
4280 request
.load_flags
= 0;
4282 // Configure against proxy server "myproxy:70".
4283 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4284 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4286 // Since we have proxy, should try to establish tunnel.
4287 MockWrite data_writes
[] = {
4289 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4290 "Host: www.example.org\r\n"
4291 "Proxy-Connection: keep-alive\r\n\r\n"),
4294 MockRead data_reads
[] = {
4296 MockRead("Content-Length: 10\r\n\r\n"),
4297 // No response body because the test stops reading here.
4298 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
4301 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
4302 data_writes
, arraysize(data_writes
));
4303 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4305 TestCompletionCallback callback
;
4307 scoped_ptr
<HttpTransaction
> trans(
4308 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4310 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4311 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4313 rv
= callback
.WaitForResult();
4314 EXPECT_EQ(expected_status
, rv
);
4317 void HttpNetworkTransactionTest::ConnectStatusHelper(
4318 const MockRead
& status
) {
4319 ConnectStatusHelperWithExpectedStatus(
4320 status
, ERR_TUNNEL_CONNECTION_FAILED
);
4323 TEST_P(HttpNetworkTransactionTest
, ConnectStatus100
) {
4324 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
4327 TEST_P(HttpNetworkTransactionTest
, ConnectStatus101
) {
4328 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
4331 TEST_P(HttpNetworkTransactionTest
, ConnectStatus201
) {
4332 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
4335 TEST_P(HttpNetworkTransactionTest
, ConnectStatus202
) {
4336 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
4339 TEST_P(HttpNetworkTransactionTest
, ConnectStatus203
) {
4340 ConnectStatusHelper(
4341 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
4344 TEST_P(HttpNetworkTransactionTest
, ConnectStatus204
) {
4345 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
4348 TEST_P(HttpNetworkTransactionTest
, ConnectStatus205
) {
4349 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
4352 TEST_P(HttpNetworkTransactionTest
, ConnectStatus206
) {
4353 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
4356 TEST_P(HttpNetworkTransactionTest
, ConnectStatus300
) {
4357 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
4360 TEST_P(HttpNetworkTransactionTest
, ConnectStatus301
) {
4361 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
4364 TEST_P(HttpNetworkTransactionTest
, ConnectStatus302
) {
4365 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
4368 TEST_P(HttpNetworkTransactionTest
, ConnectStatus303
) {
4369 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
4372 TEST_P(HttpNetworkTransactionTest
, ConnectStatus304
) {
4373 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
4376 TEST_P(HttpNetworkTransactionTest
, ConnectStatus305
) {
4377 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
4380 TEST_P(HttpNetworkTransactionTest
, ConnectStatus306
) {
4381 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
4384 TEST_P(HttpNetworkTransactionTest
, ConnectStatus307
) {
4385 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
4388 TEST_P(HttpNetworkTransactionTest
, ConnectStatus308
) {
4389 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
4392 TEST_P(HttpNetworkTransactionTest
, ConnectStatus400
) {
4393 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
4396 TEST_P(HttpNetworkTransactionTest
, ConnectStatus401
) {
4397 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
4400 TEST_P(HttpNetworkTransactionTest
, ConnectStatus402
) {
4401 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
4404 TEST_P(HttpNetworkTransactionTest
, ConnectStatus403
) {
4405 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
4408 TEST_P(HttpNetworkTransactionTest
, ConnectStatus404
) {
4409 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
4412 TEST_P(HttpNetworkTransactionTest
, ConnectStatus405
) {
4413 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
4416 TEST_P(HttpNetworkTransactionTest
, ConnectStatus406
) {
4417 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
4420 TEST_P(HttpNetworkTransactionTest
, ConnectStatus407
) {
4421 ConnectStatusHelperWithExpectedStatus(
4422 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4423 ERR_PROXY_AUTH_UNSUPPORTED
);
4426 TEST_P(HttpNetworkTransactionTest
, ConnectStatus408
) {
4427 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
4430 TEST_P(HttpNetworkTransactionTest
, ConnectStatus409
) {
4431 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
4434 TEST_P(HttpNetworkTransactionTest
, ConnectStatus410
) {
4435 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
4438 TEST_P(HttpNetworkTransactionTest
, ConnectStatus411
) {
4439 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
4442 TEST_P(HttpNetworkTransactionTest
, ConnectStatus412
) {
4443 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
4446 TEST_P(HttpNetworkTransactionTest
, ConnectStatus413
) {
4447 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
4450 TEST_P(HttpNetworkTransactionTest
, ConnectStatus414
) {
4451 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
4454 TEST_P(HttpNetworkTransactionTest
, ConnectStatus415
) {
4455 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
4458 TEST_P(HttpNetworkTransactionTest
, ConnectStatus416
) {
4459 ConnectStatusHelper(
4460 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
4463 TEST_P(HttpNetworkTransactionTest
, ConnectStatus417
) {
4464 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
4467 TEST_P(HttpNetworkTransactionTest
, ConnectStatus500
) {
4468 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
4471 TEST_P(HttpNetworkTransactionTest
, ConnectStatus501
) {
4472 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
4475 TEST_P(HttpNetworkTransactionTest
, ConnectStatus502
) {
4476 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
4479 TEST_P(HttpNetworkTransactionTest
, ConnectStatus503
) {
4480 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
4483 TEST_P(HttpNetworkTransactionTest
, ConnectStatus504
) {
4484 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
4487 TEST_P(HttpNetworkTransactionTest
, ConnectStatus505
) {
4488 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
4491 // Test the flow when both the proxy server AND origin server require
4492 // authentication. Again, this uses basic auth for both since that is
4493 // the simplest to mock.
4494 TEST_P(HttpNetworkTransactionTest
, BasicAuthProxyThenServer
) {
4495 HttpRequestInfo request
;
4496 request
.method
= "GET";
4497 request
.url
= GURL("http://www.example.org/");
4498 request
.load_flags
= 0;
4500 // Configure against proxy server "myproxy:70".
4501 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
4502 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4504 scoped_ptr
<HttpTransaction
> trans(
4505 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4507 MockWrite data_writes1
[] = {
4509 "GET http://www.example.org/ HTTP/1.1\r\n"
4510 "Host: www.example.org\r\n"
4511 "Proxy-Connection: keep-alive\r\n\r\n"),
4514 MockRead data_reads1
[] = {
4515 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
4516 // Give a couple authenticate options (only the middle one is actually
4518 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
4519 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4520 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
4521 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4522 // Large content-length -- won't matter, as connection will be reset.
4523 MockRead("Content-Length: 10000\r\n\r\n"),
4524 MockRead(SYNCHRONOUS
, ERR_FAILED
),
4527 // After calling trans->RestartWithAuth() the first time, this is the
4528 // request we should be issuing -- the final header line contains the
4529 // proxy's credentials.
4530 MockWrite data_writes2
[] = {
4532 "GET http://www.example.org/ HTTP/1.1\r\n"
4533 "Host: www.example.org\r\n"
4534 "Proxy-Connection: keep-alive\r\n"
4535 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4538 // Now the proxy server lets the request pass through to origin server.
4539 // The origin server responds with a 401.
4540 MockRead data_reads2
[] = {
4541 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4542 // Note: We are using the same realm-name as the proxy server. This is
4543 // completely valid, as realms are unique across hosts.
4544 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4545 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4546 MockRead("Content-Length: 2000\r\n\r\n"),
4547 MockRead(SYNCHRONOUS
, ERR_FAILED
), // Won't be reached.
4550 // After calling trans->RestartWithAuth() the second time, we should send
4551 // the credentials for both the proxy and origin server.
4552 MockWrite data_writes3
[] = {
4554 "GET http://www.example.org/ HTTP/1.1\r\n"
4555 "Host: www.example.org\r\n"
4556 "Proxy-Connection: keep-alive\r\n"
4557 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4558 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4561 // Lastly we get the desired content.
4562 MockRead data_reads3
[] = {
4563 MockRead("HTTP/1.0 200 OK\r\n"),
4564 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4565 MockRead("Content-Length: 100\r\n\r\n"),
4566 MockRead(SYNCHRONOUS
, OK
),
4569 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4570 data_writes1
, arraysize(data_writes1
));
4571 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4572 data_writes2
, arraysize(data_writes2
));
4573 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4574 data_writes3
, arraysize(data_writes3
));
4575 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4576 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4577 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4579 TestCompletionCallback callback1
;
4581 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4582 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4584 rv
= callback1
.WaitForResult();
4587 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4588 ASSERT_TRUE(response
!= NULL
);
4589 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
4591 TestCompletionCallback callback2
;
4593 rv
= trans
->RestartWithAuth(
4594 AuthCredentials(kFoo
, kBar
), callback2
.callback());
4595 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4597 rv
= callback2
.WaitForResult();
4600 response
= trans
->GetResponseInfo();
4601 ASSERT_TRUE(response
!= NULL
);
4602 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
4604 TestCompletionCallback callback3
;
4606 rv
= trans
->RestartWithAuth(
4607 AuthCredentials(kFoo2
, kBar2
), callback3
.callback());
4608 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4610 rv
= callback3
.WaitForResult();
4613 response
= trans
->GetResponseInfo();
4614 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4615 EXPECT_EQ(100, response
->headers
->GetContentLength());
4618 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
4619 // can't hook into its internals to cause it to generate predictable NTLM
4620 // authorization headers.
4621 #if defined(NTLM_PORTABLE)
4622 // The NTLM authentication unit tests were generated by capturing the HTTP
4623 // requests and responses using Fiddler 2 and inspecting the generated random
4624 // bytes in the debugger.
4626 // Enter the correct password and authenticate successfully.
4627 TEST_P(HttpNetworkTransactionTest
, NTLMAuth1
) {
4628 HttpRequestInfo request
;
4629 request
.method
= "GET";
4630 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4632 // Ensure load is not disrupted by flags which suppress behaviour specific
4633 // to other auth schemes.
4634 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
4636 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom1
,
4638 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4640 MockWrite data_writes1
[] = {
4641 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4642 "Host: 172.22.68.17\r\n"
4643 "Connection: keep-alive\r\n\r\n"),
4646 MockRead data_reads1
[] = {
4647 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4648 // Negotiate and NTLM are often requested together. However, we only want
4649 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4650 // the header that requests Negotiate for this test.
4651 MockRead("WWW-Authenticate: NTLM\r\n"),
4652 MockRead("Connection: close\r\n"),
4653 MockRead("Content-Length: 42\r\n"),
4654 MockRead("Content-Type: text/html\r\n\r\n"),
4655 // Missing content -- won't matter, as connection will be reset.
4656 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4659 MockWrite data_writes2
[] = {
4660 // After restarting with a null identity, this is the
4661 // request we should be issuing -- the final header line contains a Type
4663 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4664 "Host: 172.22.68.17\r\n"
4665 "Connection: keep-alive\r\n"
4666 "Authorization: NTLM "
4667 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4669 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4670 // (the credentials for the origin server). The second request continues
4671 // on the same connection.
4672 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4673 "Host: 172.22.68.17\r\n"
4674 "Connection: keep-alive\r\n"
4675 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4676 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4677 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
4678 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
4679 "ahlhx5I=\r\n\r\n"),
4682 MockRead data_reads2
[] = {
4683 // The origin server responds with a Type 2 message.
4684 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4685 MockRead("WWW-Authenticate: NTLM "
4686 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
4687 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4688 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4689 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4690 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4691 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4693 MockRead("Content-Length: 42\r\n"),
4694 MockRead("Content-Type: text/html\r\n\r\n"),
4695 MockRead("You are not authorized to view this page\r\n"),
4697 // Lastly we get the desired content.
4698 MockRead("HTTP/1.1 200 OK\r\n"),
4699 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4700 MockRead("Content-Length: 13\r\n\r\n"),
4701 MockRead("Please Login\r\n"),
4702 MockRead(SYNCHRONOUS
, OK
),
4705 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4706 data_writes1
, arraysize(data_writes1
));
4707 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4708 data_writes2
, arraysize(data_writes2
));
4709 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4710 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4712 TestCompletionCallback callback1
;
4714 scoped_ptr
<HttpTransaction
> trans(
4715 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4717 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4718 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4720 rv
= callback1
.WaitForResult();
4723 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4725 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4726 ASSERT_FALSE(response
== NULL
);
4727 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4729 TestCompletionCallback callback2
;
4731 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4732 callback2
.callback());
4733 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4735 rv
= callback2
.WaitForResult();
4738 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4740 response
= trans
->GetResponseInfo();
4741 ASSERT_TRUE(response
!= NULL
);
4742 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4744 TestCompletionCallback callback3
;
4746 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4747 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4749 rv
= callback3
.WaitForResult();
4752 response
= trans
->GetResponseInfo();
4753 ASSERT_TRUE(response
!= NULL
);
4754 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4755 EXPECT_EQ(13, response
->headers
->GetContentLength());
4758 // Enter a wrong password, and then the correct one.
4759 TEST_P(HttpNetworkTransactionTest
, NTLMAuth2
) {
4760 HttpRequestInfo request
;
4761 request
.method
= "GET";
4762 request
.url
= GURL("http://172.22.68.17/kids/login.aspx");
4763 request
.load_flags
= 0;
4765 HttpAuthHandlerNTLM::ScopedProcSetter
proc_setter(MockGenerateRandom2
,
4767 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4769 MockWrite data_writes1
[] = {
4770 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4771 "Host: 172.22.68.17\r\n"
4772 "Connection: keep-alive\r\n\r\n"),
4775 MockRead data_reads1
[] = {
4776 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4777 // Negotiate and NTLM are often requested together. However, we only want
4778 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
4779 // the header that requests Negotiate for this test.
4780 MockRead("WWW-Authenticate: NTLM\r\n"),
4781 MockRead("Connection: close\r\n"),
4782 MockRead("Content-Length: 42\r\n"),
4783 MockRead("Content-Type: text/html\r\n\r\n"),
4784 // Missing content -- won't matter, as connection will be reset.
4785 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4788 MockWrite data_writes2
[] = {
4789 // After restarting with a null identity, this is the
4790 // request we should be issuing -- the final header line contains a Type
4792 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4793 "Host: 172.22.68.17\r\n"
4794 "Connection: keep-alive\r\n"
4795 "Authorization: NTLM "
4796 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4798 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4799 // (the credentials for the origin server). The second request continues
4800 // on the same connection.
4801 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4802 "Host: 172.22.68.17\r\n"
4803 "Connection: keep-alive\r\n"
4804 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4805 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4806 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
4807 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
4808 "4Ww7b7E=\r\n\r\n"),
4811 MockRead data_reads2
[] = {
4812 // The origin server responds with a Type 2 message.
4813 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4814 MockRead("WWW-Authenticate: NTLM "
4815 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
4816 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4817 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4818 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4819 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4820 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4822 MockRead("Content-Length: 42\r\n"),
4823 MockRead("Content-Type: text/html\r\n\r\n"),
4824 MockRead("You are not authorized to view this page\r\n"),
4827 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4828 MockRead("WWW-Authenticate: NTLM\r\n"),
4829 MockRead("Connection: close\r\n"),
4830 MockRead("Content-Length: 42\r\n"),
4831 MockRead("Content-Type: text/html\r\n\r\n"),
4832 // Missing content -- won't matter, as connection will be reset.
4833 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
),
4836 MockWrite data_writes3
[] = {
4837 // After restarting with a null identity, this is the
4838 // request we should be issuing -- the final header line contains a Type
4840 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4841 "Host: 172.22.68.17\r\n"
4842 "Connection: keep-alive\r\n"
4843 "Authorization: NTLM "
4844 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
4846 // After calling trans->RestartWithAuth(), we should send a Type 3 message
4847 // (the credentials for the origin server). The second request continues
4848 // on the same connection.
4849 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
4850 "Host: 172.22.68.17\r\n"
4851 "Connection: keep-alive\r\n"
4852 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
4853 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
4854 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
4855 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
4856 "+4MUm7c=\r\n\r\n"),
4859 MockRead data_reads3
[] = {
4860 // The origin server responds with a Type 2 message.
4861 MockRead("HTTP/1.1 401 Access Denied\r\n"),
4862 MockRead("WWW-Authenticate: NTLM "
4863 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
4864 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
4865 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
4866 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
4867 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
4868 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
4870 MockRead("Content-Length: 42\r\n"),
4871 MockRead("Content-Type: text/html\r\n\r\n"),
4872 MockRead("You are not authorized to view this page\r\n"),
4874 // Lastly we get the desired content.
4875 MockRead("HTTP/1.1 200 OK\r\n"),
4876 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
4877 MockRead("Content-Length: 13\r\n\r\n"),
4878 MockRead("Please Login\r\n"),
4879 MockRead(SYNCHRONOUS
, OK
),
4882 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
4883 data_writes1
, arraysize(data_writes1
));
4884 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
4885 data_writes2
, arraysize(data_writes2
));
4886 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
4887 data_writes3
, arraysize(data_writes3
));
4888 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
4889 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
4890 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
4892 TestCompletionCallback callback1
;
4894 scoped_ptr
<HttpTransaction
> trans(
4895 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4897 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
4898 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4900 rv
= callback1
.WaitForResult();
4903 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4905 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
4906 ASSERT_TRUE(response
!= NULL
);
4907 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4909 TestCompletionCallback callback2
;
4911 // Enter the wrong password.
4912 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kWrongPassword
),
4913 callback2
.callback());
4914 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4916 rv
= callback2
.WaitForResult();
4919 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4920 TestCompletionCallback callback3
;
4921 rv
= trans
->RestartWithAuth(AuthCredentials(), callback3
.callback());
4922 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4923 rv
= callback3
.WaitForResult();
4925 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
4927 response
= trans
->GetResponseInfo();
4928 ASSERT_FALSE(response
== NULL
);
4929 EXPECT_TRUE(CheckNTLMServerAuth(response
->auth_challenge
.get()));
4931 TestCompletionCallback callback4
;
4933 // Now enter the right password.
4934 rv
= trans
->RestartWithAuth(AuthCredentials(kTestingNTLM
, kTestingNTLM
),
4935 callback4
.callback());
4936 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4938 rv
= callback4
.WaitForResult();
4941 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
4943 TestCompletionCallback callback5
;
4945 // One more roundtrip
4946 rv
= trans
->RestartWithAuth(AuthCredentials(), callback5
.callback());
4947 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4949 rv
= callback5
.WaitForResult();
4952 response
= trans
->GetResponseInfo();
4953 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
4954 EXPECT_EQ(13, response
->headers
->GetContentLength());
4956 #endif // NTLM_PORTABLE
4958 // Test reading a server response which has only headers, and no body.
4959 // After some maximum number of bytes is consumed, the transaction should
4960 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
4961 TEST_P(HttpNetworkTransactionTest
, LargeHeadersNoBody
) {
4962 HttpRequestInfo request
;
4963 request
.method
= "GET";
4964 request
.url
= GURL("http://www.example.org/");
4965 request
.load_flags
= 0;
4967 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
4968 scoped_ptr
<HttpTransaction
> trans(
4969 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
4971 // Respond with 300 kb of headers (we should fail after 256 kb).
4972 std::string large_headers_string
;
4973 FillLargeHeadersString(&large_headers_string
, 300 * 1024);
4975 MockRead data_reads
[] = {
4976 MockRead("HTTP/1.0 200 OK\r\n"),
4977 MockRead(ASYNC
, large_headers_string
.data(), large_headers_string
.size()),
4978 MockRead("\r\nBODY"),
4979 MockRead(SYNCHRONOUS
, OK
),
4981 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
4982 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
4984 TestCompletionCallback callback
;
4986 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
4987 EXPECT_EQ(ERR_IO_PENDING
, rv
);
4989 rv
= callback
.WaitForResult();
4990 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG
, rv
);
4993 // Make sure that we don't try to reuse a TCPClientSocket when failing to
4994 // establish tunnel.
4995 // http://code.google.com/p/chromium/issues/detail?id=3772
4996 TEST_P(HttpNetworkTransactionTest
,
4997 DontRecycleTransportSocketForSSLTunnel
) {
4998 HttpRequestInfo request
;
4999 request
.method
= "GET";
5000 request
.url
= GURL("https://www.example.org/");
5001 request
.load_flags
= 0;
5003 // Configure against proxy server "myproxy:70".
5004 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
5006 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5008 scoped_ptr
<HttpTransaction
> trans(
5009 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5011 // Since we have proxy, should try to establish tunnel.
5012 MockWrite data_writes1
[] = {
5014 "CONNECT www.example.org:443 HTTP/1.1\r\n"
5015 "Host: www.example.org\r\n"
5016 "Proxy-Connection: keep-alive\r\n\r\n"),
5019 // The proxy responds to the connect with a 404, using a persistent
5020 // connection. Usually a proxy would return 501 (not implemented),
5021 // or 200 (tunnel established).
5022 MockRead data_reads1
[] = {
5023 MockRead("HTTP/1.1 404 Not Found\r\n"),
5024 MockRead("Content-Length: 10\r\n\r\n"),
5025 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
5028 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5029 data_writes1
, arraysize(data_writes1
));
5030 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5032 TestCompletionCallback callback1
;
5034 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5035 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5037 rv
= callback1
.WaitForResult();
5038 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
5040 // Empty the current queue. This is necessary because idle sockets are
5041 // added to the connection pool asynchronously with a PostTask.
5042 base::MessageLoop::current()->RunUntilIdle();
5044 // We now check to make sure the TCPClientSocket was not added back to
5046 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5048 base::MessageLoop::current()->RunUntilIdle();
5049 // Make sure that the socket didn't get recycled after calling the destructor.
5050 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5053 // Make sure that we recycle a socket after reading all of the response body.
5054 TEST_P(HttpNetworkTransactionTest
, RecycleSocket
) {
5055 HttpRequestInfo request
;
5056 request
.method
= "GET";
5057 request
.url
= GURL("http://www.example.org/");
5058 request
.load_flags
= 0;
5060 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5062 scoped_ptr
<HttpTransaction
> trans(
5063 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5065 MockRead data_reads
[] = {
5066 // A part of the response body is received with the response headers.
5067 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
5068 // The rest of the response body is received in two parts.
5071 MockRead("junk"), // Should not be read!!
5072 MockRead(SYNCHRONOUS
, OK
),
5075 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5076 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5078 TestCompletionCallback callback
;
5080 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5081 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5083 rv
= callback
.WaitForResult();
5086 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5087 ASSERT_TRUE(response
!= NULL
);
5089 EXPECT_TRUE(response
->headers
.get() != NULL
);
5090 std::string status_line
= response
->headers
->GetStatusLine();
5091 EXPECT_EQ("HTTP/1.1 200 OK", status_line
);
5093 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5095 std::string response_data
;
5096 rv
= ReadTransaction(trans
.get(), &response_data
);
5098 EXPECT_EQ("hello world", response_data
);
5100 // Empty the current queue. This is necessary because idle sockets are
5101 // added to the connection pool asynchronously with a PostTask.
5102 base::MessageLoop::current()->RunUntilIdle();
5104 // We now check to make sure the socket was added back to the pool.
5105 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5108 // Make sure that we recycle a SSL socket after reading all of the response
5110 TEST_P(HttpNetworkTransactionTest
, RecycleSSLSocket
) {
5111 HttpRequestInfo request
;
5112 request
.method
= "GET";
5113 request
.url
= GURL("https://www.example.org/");
5114 request
.load_flags
= 0;
5116 MockWrite data_writes
[] = {
5118 "GET / HTTP/1.1\r\n"
5119 "Host: www.example.org\r\n"
5120 "Connection: keep-alive\r\n\r\n"),
5123 MockRead data_reads
[] = {
5124 MockRead("HTTP/1.1 200 OK\r\n"),
5125 MockRead("Content-Length: 11\r\n\r\n"),
5126 MockRead("hello world"),
5127 MockRead(SYNCHRONOUS
, OK
),
5130 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5131 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5133 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5134 data_writes
, arraysize(data_writes
));
5135 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5137 TestCompletionCallback callback
;
5139 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5140 scoped_ptr
<HttpTransaction
> trans(
5141 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5143 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5145 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5146 EXPECT_EQ(OK
, callback
.WaitForResult());
5148 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5149 ASSERT_TRUE(response
!= NULL
);
5150 ASSERT_TRUE(response
->headers
.get() != NULL
);
5151 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5153 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5155 std::string response_data
;
5156 rv
= ReadTransaction(trans
.get(), &response_data
);
5158 EXPECT_EQ("hello world", response_data
);
5160 // Empty the current queue. This is necessary because idle sockets are
5161 // added to the connection pool asynchronously with a PostTask.
5162 base::MessageLoop::current()->RunUntilIdle();
5164 // We now check to make sure the socket was added back to the pool.
5165 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5168 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
5169 // from the pool and make sure that we recover okay.
5170 TEST_P(HttpNetworkTransactionTest
, RecycleDeadSSLSocket
) {
5171 HttpRequestInfo request
;
5172 request
.method
= "GET";
5173 request
.url
= GURL("https://www.example.org/");
5174 request
.load_flags
= 0;
5176 MockWrite data_writes
[] = {
5178 "GET / HTTP/1.1\r\n"
5179 "Host: www.example.org\r\n"
5180 "Connection: keep-alive\r\n\r\n"),
5182 "GET / HTTP/1.1\r\n"
5183 "Host: www.example.org\r\n"
5184 "Connection: keep-alive\r\n\r\n"),
5187 MockRead data_reads
[] = {
5188 MockRead("HTTP/1.1 200 OK\r\n"),
5189 MockRead("Content-Length: 11\r\n\r\n"),
5190 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
5191 MockRead("hello world"),
5192 MockRead(ASYNC
, 0, 0) // EOF
5195 SSLSocketDataProvider
ssl(ASYNC
, OK
);
5196 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
5197 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
5198 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
5200 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
5201 data_writes
, arraysize(data_writes
));
5202 StaticSocketDataProvider
data2(data_reads
, arraysize(data_reads
),
5203 data_writes
, arraysize(data_writes
));
5204 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5205 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5207 TestCompletionCallback callback
;
5209 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5210 scoped_ptr
<HttpTransaction
> trans(
5211 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5213 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5215 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5216 EXPECT_EQ(OK
, callback
.WaitForResult());
5218 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5219 ASSERT_TRUE(response
!= NULL
);
5220 ASSERT_TRUE(response
->headers
.get() != NULL
);
5221 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5223 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5225 std::string response_data
;
5226 rv
= ReadTransaction(trans
.get(), &response_data
);
5228 EXPECT_EQ("hello world", response_data
);
5230 // Empty the current queue. This is necessary because idle sockets are
5231 // added to the connection pool asynchronously with a PostTask.
5232 base::MessageLoop::current()->RunUntilIdle();
5234 // We now check to make sure the socket was added back to the pool.
5235 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5237 // Now start the second transaction, which should reuse the previous socket.
5239 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5241 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5243 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5244 EXPECT_EQ(OK
, callback
.WaitForResult());
5246 response
= trans
->GetResponseInfo();
5247 ASSERT_TRUE(response
!= NULL
);
5248 ASSERT_TRUE(response
->headers
.get() != NULL
);
5249 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5251 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5253 rv
= ReadTransaction(trans
.get(), &response_data
);
5255 EXPECT_EQ("hello world", response_data
);
5257 // Empty the current queue. This is necessary because idle sockets are
5258 // added to the connection pool asynchronously with a PostTask.
5259 base::MessageLoop::current()->RunUntilIdle();
5261 // We now check to make sure the socket was added back to the pool.
5262 EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session
.get()));
5265 // Make sure that we recycle a socket after a zero-length response.
5266 // http://crbug.com/9880
5267 TEST_P(HttpNetworkTransactionTest
, RecycleSocketAfterZeroContentLength
) {
5268 HttpRequestInfo request
;
5269 request
.method
= "GET";
5271 "http://www.example.org/csi?v=3&s=web&action=&"
5272 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
5273 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
5274 "rt=prt.2642,ol.2649,xjs.2951");
5275 request
.load_flags
= 0;
5277 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5279 scoped_ptr
<HttpTransaction
> trans(
5280 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5282 MockRead data_reads
[] = {
5283 MockRead("HTTP/1.1 204 No Content\r\n"
5284 "Content-Length: 0\r\n"
5285 "Content-Type: text/html\r\n\r\n"),
5286 MockRead("junk"), // Should not be read!!
5287 MockRead(SYNCHRONOUS
, OK
),
5290 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
5291 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
5293 TestCompletionCallback callback
;
5295 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
5296 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5298 rv
= callback
.WaitForResult();
5301 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5302 ASSERT_TRUE(response
!= NULL
);
5304 EXPECT_TRUE(response
->headers
.get() != NULL
);
5305 std::string status_line
= response
->headers
->GetStatusLine();
5306 EXPECT_EQ("HTTP/1.1 204 No Content", status_line
);
5308 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session
.get()));
5310 std::string response_data
;
5311 rv
= ReadTransaction(trans
.get(), &response_data
);
5313 EXPECT_EQ("", response_data
);
5315 // Empty the current queue. This is necessary because idle sockets are
5316 // added to the connection pool asynchronously with a PostTask.
5317 base::MessageLoop::current()->RunUntilIdle();
5319 // We now check to make sure the socket was added back to the pool.
5320 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
5323 TEST_P(HttpNetworkTransactionTest
, ResendRequestOnWriteBodyError
) {
5324 ScopedVector
<UploadElementReader
> element_readers
;
5325 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
5326 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
5328 HttpRequestInfo request
[2];
5329 // Transaction 1: a GET request that succeeds. The socket is recycled
5331 request
[0].method
= "GET";
5332 request
[0].url
= GURL("http://www.google.com/");
5333 request
[0].load_flags
= 0;
5334 // Transaction 2: a POST request. Reuses the socket kept alive from
5335 // transaction 1. The first attempts fails when writing the POST data.
5336 // This causes the transaction to retry with a new socket. The second
5337 // attempt succeeds.
5338 request
[1].method
= "POST";
5339 request
[1].url
= GURL("http://www.google.com/login.cgi");
5340 request
[1].upload_data_stream
= &upload_data_stream
;
5341 request
[1].load_flags
= 0;
5343 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5345 // The first socket is used for transaction 1 and the first attempt of
5348 // The response of transaction 1.
5349 MockRead data_reads1
[] = {
5350 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
5351 MockRead("hello world"),
5352 MockRead(SYNCHRONOUS
, OK
),
5354 // The mock write results of transaction 1 and the first attempt of
5356 MockWrite data_writes1
[] = {
5357 MockWrite(SYNCHRONOUS
, 64), // GET
5358 MockWrite(SYNCHRONOUS
, 93), // POST
5359 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_ABORTED
), // POST data
5361 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5362 data_writes1
, arraysize(data_writes1
));
5364 // The second socket is used for the second attempt of transaction 2.
5366 // The response of transaction 2.
5367 MockRead data_reads2
[] = {
5368 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
5369 MockRead("welcome"),
5370 MockRead(SYNCHRONOUS
, OK
),
5372 // The mock write results of the second attempt of transaction 2.
5373 MockWrite data_writes2
[] = {
5374 MockWrite(SYNCHRONOUS
, 93), // POST
5375 MockWrite(SYNCHRONOUS
, 3), // POST data
5377 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5378 data_writes2
, arraysize(data_writes2
));
5380 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5381 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5383 const char* const kExpectedResponseData
[] = {
5384 "hello world", "welcome"
5387 for (int i
= 0; i
< 2; ++i
) {
5388 scoped_ptr
<HttpTransaction
> trans(
5389 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5391 TestCompletionCallback callback
;
5393 int rv
= trans
->Start(&request
[i
], callback
.callback(), BoundNetLog());
5394 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5396 rv
= callback
.WaitForResult();
5399 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5400 ASSERT_TRUE(response
!= NULL
);
5402 EXPECT_TRUE(response
->headers
.get() != NULL
);
5403 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
5405 std::string response_data
;
5406 rv
= ReadTransaction(trans
.get(), &response_data
);
5408 EXPECT_EQ(kExpectedResponseData
[i
], response_data
);
5412 // Test the request-challenge-retry sequence for basic auth when there is
5413 // an identity in the URL. The request should be sent as normal, but when
5414 // it fails the identity from the URL is used to answer the challenge.
5415 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURL
) {
5416 HttpRequestInfo request
;
5417 request
.method
= "GET";
5418 request
.url
= GURL("http://foo:b@r@www.example.org/");
5419 request
.load_flags
= LOAD_NORMAL
;
5421 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5422 scoped_ptr
<HttpTransaction
> trans(
5423 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5425 // The password contains an escaped character -- for this test to pass it
5426 // will need to be unescaped by HttpNetworkTransaction.
5427 EXPECT_EQ("b%40r", request
.url
.password());
5429 MockWrite data_writes1
[] = {
5431 "GET / HTTP/1.1\r\n"
5432 "Host: www.example.org\r\n"
5433 "Connection: keep-alive\r\n\r\n"),
5436 MockRead data_reads1
[] = {
5437 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5438 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5439 MockRead("Content-Length: 10\r\n\r\n"),
5440 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5443 // After the challenge above, the transaction will be restarted using the
5444 // identity from the url (foo, b@r) to answer the challenge.
5445 MockWrite data_writes2
[] = {
5447 "GET / HTTP/1.1\r\n"
5448 "Host: www.example.org\r\n"
5449 "Connection: keep-alive\r\n"
5450 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
5453 MockRead data_reads2
[] = {
5454 MockRead("HTTP/1.0 200 OK\r\n"),
5455 MockRead("Content-Length: 100\r\n\r\n"),
5456 MockRead(SYNCHRONOUS
, OK
),
5459 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5460 data_writes1
, arraysize(data_writes1
));
5461 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5462 data_writes2
, arraysize(data_writes2
));
5463 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5464 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5466 TestCompletionCallback callback1
;
5467 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5468 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5469 rv
= callback1
.WaitForResult();
5471 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5473 TestCompletionCallback callback2
;
5474 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5475 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5476 rv
= callback2
.WaitForResult();
5478 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5480 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5481 ASSERT_TRUE(response
!= NULL
);
5483 // There is no challenge info, since the identity in URL worked.
5484 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5486 EXPECT_EQ(100, response
->headers
->GetContentLength());
5488 // Empty the current queue.
5489 base::MessageLoop::current()->RunUntilIdle();
5492 // Test the request-challenge-retry sequence for basic auth when there is an
5493 // incorrect identity in the URL. The identity from the URL should be used only
5495 TEST_P(HttpNetworkTransactionTest
, WrongAuthIdentityInURL
) {
5496 HttpRequestInfo request
;
5497 request
.method
= "GET";
5498 // Note: the URL has a username:password in it. The password "baz" is
5499 // wrong (should be "bar").
5500 request
.url
= GURL("http://foo:baz@www.example.org/");
5502 request
.load_flags
= LOAD_NORMAL
;
5504 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5505 scoped_ptr
<HttpTransaction
> trans(
5506 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5508 MockWrite data_writes1
[] = {
5510 "GET / HTTP/1.1\r\n"
5511 "Host: www.example.org\r\n"
5512 "Connection: keep-alive\r\n\r\n"),
5515 MockRead data_reads1
[] = {
5516 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5517 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5518 MockRead("Content-Length: 10\r\n\r\n"),
5519 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5522 // After the challenge above, the transaction will be restarted using the
5523 // identity from the url (foo, baz) to answer the challenge.
5524 MockWrite data_writes2
[] = {
5526 "GET / HTTP/1.1\r\n"
5527 "Host: www.example.org\r\n"
5528 "Connection: keep-alive\r\n"
5529 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
5532 MockRead data_reads2
[] = {
5533 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5534 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5535 MockRead("Content-Length: 10\r\n\r\n"),
5536 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5539 // After the challenge above, the transaction will be restarted using the
5540 // identity supplied by the user (foo, bar) to answer the challenge.
5541 MockWrite data_writes3
[] = {
5543 "GET / HTTP/1.1\r\n"
5544 "Host: www.example.org\r\n"
5545 "Connection: keep-alive\r\n"
5546 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5549 MockRead data_reads3
[] = {
5550 MockRead("HTTP/1.0 200 OK\r\n"),
5551 MockRead("Content-Length: 100\r\n\r\n"),
5552 MockRead(SYNCHRONOUS
, OK
),
5555 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5556 data_writes1
, arraysize(data_writes1
));
5557 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5558 data_writes2
, arraysize(data_writes2
));
5559 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5560 data_writes3
, arraysize(data_writes3
));
5561 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5562 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5563 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5565 TestCompletionCallback callback1
;
5567 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5570 rv
= callback1
.WaitForResult();
5573 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5574 TestCompletionCallback callback2
;
5575 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5576 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5577 rv
= callback2
.WaitForResult();
5579 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5581 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5582 ASSERT_TRUE(response
!= NULL
);
5583 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5585 TestCompletionCallback callback3
;
5586 rv
= trans
->RestartWithAuth(
5587 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5588 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5589 rv
= callback3
.WaitForResult();
5591 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5593 response
= trans
->GetResponseInfo();
5594 ASSERT_TRUE(response
!= NULL
);
5596 // There is no challenge info, since the identity worked.
5597 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5599 EXPECT_EQ(100, response
->headers
->GetContentLength());
5601 // Empty the current queue.
5602 base::MessageLoop::current()->RunUntilIdle();
5606 // Test the request-challenge-retry sequence for basic auth when there is a
5607 // correct identity in the URL, but its use is being suppressed. The identity
5608 // from the URL should never be used.
5609 TEST_P(HttpNetworkTransactionTest
, AuthIdentityInURLSuppressed
) {
5610 HttpRequestInfo request
;
5611 request
.method
= "GET";
5612 request
.url
= GURL("http://foo:bar@www.example.org/");
5613 request
.load_flags
= LOAD_DO_NOT_USE_EMBEDDED_IDENTITY
;
5615 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5616 scoped_ptr
<HttpTransaction
> trans(
5617 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5619 MockWrite data_writes1
[] = {
5621 "GET / HTTP/1.1\r\n"
5622 "Host: www.example.org\r\n"
5623 "Connection: keep-alive\r\n\r\n"),
5626 MockRead data_reads1
[] = {
5627 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5628 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5629 MockRead("Content-Length: 10\r\n\r\n"),
5630 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5633 // After the challenge above, the transaction will be restarted using the
5634 // identity supplied by the user, not the one in the URL, to answer the
5636 MockWrite data_writes3
[] = {
5638 "GET / HTTP/1.1\r\n"
5639 "Host: www.example.org\r\n"
5640 "Connection: keep-alive\r\n"
5641 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5644 MockRead data_reads3
[] = {
5645 MockRead("HTTP/1.0 200 OK\r\n"),
5646 MockRead("Content-Length: 100\r\n\r\n"),
5647 MockRead(SYNCHRONOUS
, OK
),
5650 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5651 data_writes1
, arraysize(data_writes1
));
5652 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
5653 data_writes3
, arraysize(data_writes3
));
5654 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5655 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
5657 TestCompletionCallback callback1
;
5658 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5659 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5660 rv
= callback1
.WaitForResult();
5662 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5664 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5665 ASSERT_TRUE(response
!= NULL
);
5666 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5668 TestCompletionCallback callback3
;
5669 rv
= trans
->RestartWithAuth(
5670 AuthCredentials(kFoo
, kBar
), callback3
.callback());
5671 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5672 rv
= callback3
.WaitForResult();
5674 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5676 response
= trans
->GetResponseInfo();
5677 ASSERT_TRUE(response
!= NULL
);
5679 // There is no challenge info, since the identity worked.
5680 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5681 EXPECT_EQ(100, response
->headers
->GetContentLength());
5683 // Empty the current queue.
5684 base::MessageLoop::current()->RunUntilIdle();
5687 // Test that previously tried username/passwords for a realm get re-used.
5688 TEST_P(HttpNetworkTransactionTest
, BasicAuthCacheAndPreauth
) {
5689 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
5691 // Transaction 1: authenticate (foo, bar) on MyRealm1
5693 HttpRequestInfo request
;
5694 request
.method
= "GET";
5695 request
.url
= GURL("http://www.example.org/x/y/z");
5696 request
.load_flags
= 0;
5698 scoped_ptr
<HttpTransaction
> trans(
5699 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5701 MockWrite data_writes1
[] = {
5703 "GET /x/y/z HTTP/1.1\r\n"
5704 "Host: www.example.org\r\n"
5705 "Connection: keep-alive\r\n\r\n"),
5708 MockRead data_reads1
[] = {
5709 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5710 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5711 MockRead("Content-Length: 10000\r\n\r\n"),
5712 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5715 // Resend with authorization (username=foo, password=bar)
5716 MockWrite data_writes2
[] = {
5718 "GET /x/y/z HTTP/1.1\r\n"
5719 "Host: www.example.org\r\n"
5720 "Connection: keep-alive\r\n"
5721 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5724 // Sever accepts the authorization.
5725 MockRead data_reads2
[] = {
5726 MockRead("HTTP/1.0 200 OK\r\n"),
5727 MockRead("Content-Length: 100\r\n\r\n"),
5728 MockRead(SYNCHRONOUS
, OK
),
5731 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5732 data_writes1
, arraysize(data_writes1
));
5733 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5734 data_writes2
, arraysize(data_writes2
));
5735 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5736 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5738 TestCompletionCallback callback1
;
5740 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5741 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5743 rv
= callback1
.WaitForResult();
5746 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5747 ASSERT_TRUE(response
!= NULL
);
5748 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
5750 TestCompletionCallback callback2
;
5752 rv
= trans
->RestartWithAuth(
5753 AuthCredentials(kFoo
, kBar
), callback2
.callback());
5754 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5756 rv
= callback2
.WaitForResult();
5759 response
= trans
->GetResponseInfo();
5760 ASSERT_TRUE(response
!= NULL
);
5761 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5762 EXPECT_EQ(100, response
->headers
->GetContentLength());
5765 // ------------------------------------------------------------------------
5767 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
5769 HttpRequestInfo request
;
5770 request
.method
= "GET";
5771 // Note that Transaction 1 was at /x/y/z, so this is in the same
5772 // protection space as MyRealm1.
5773 request
.url
= GURL("http://www.example.org/x/y/a/b");
5774 request
.load_flags
= 0;
5776 scoped_ptr
<HttpTransaction
> trans(
5777 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5779 MockWrite data_writes1
[] = {
5781 "GET /x/y/a/b HTTP/1.1\r\n"
5782 "Host: www.example.org\r\n"
5783 "Connection: keep-alive\r\n"
5784 // Send preemptive authorization for MyRealm1
5785 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5788 // The server didn't like the preemptive authorization, and
5789 // challenges us for a different realm (MyRealm2).
5790 MockRead data_reads1
[] = {
5791 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5792 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
5793 MockRead("Content-Length: 10000\r\n\r\n"),
5794 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5797 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
5798 MockWrite data_writes2
[] = {
5800 "GET /x/y/a/b HTTP/1.1\r\n"
5801 "Host: www.example.org\r\n"
5802 "Connection: keep-alive\r\n"
5803 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
5806 // Sever accepts the authorization.
5807 MockRead data_reads2
[] = {
5808 MockRead("HTTP/1.0 200 OK\r\n"),
5809 MockRead("Content-Length: 100\r\n\r\n"),
5810 MockRead(SYNCHRONOUS
, OK
),
5813 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5814 data_writes1
, arraysize(data_writes1
));
5815 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5816 data_writes2
, arraysize(data_writes2
));
5817 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5818 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5820 TestCompletionCallback callback1
;
5822 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5823 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5825 rv
= callback1
.WaitForResult();
5828 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5829 ASSERT_TRUE(response
!= NULL
);
5830 ASSERT_TRUE(response
->auth_challenge
.get());
5831 EXPECT_FALSE(response
->auth_challenge
->is_proxy
);
5832 EXPECT_EQ("www.example.org:80",
5833 response
->auth_challenge
->challenger
.ToString());
5834 EXPECT_EQ("MyRealm2", response
->auth_challenge
->realm
);
5835 EXPECT_EQ("basic", response
->auth_challenge
->scheme
);
5837 TestCompletionCallback callback2
;
5839 rv
= trans
->RestartWithAuth(
5840 AuthCredentials(kFoo2
, kBar2
), callback2
.callback());
5841 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5843 rv
= callback2
.WaitForResult();
5846 response
= trans
->GetResponseInfo();
5847 ASSERT_TRUE(response
!= NULL
);
5848 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5849 EXPECT_EQ(100, response
->headers
->GetContentLength());
5852 // ------------------------------------------------------------------------
5854 // Transaction 3: Resend a request in MyRealm's protection space --
5855 // succeed with preemptive authorization.
5857 HttpRequestInfo request
;
5858 request
.method
= "GET";
5859 request
.url
= GURL("http://www.example.org/x/y/z2");
5860 request
.load_flags
= 0;
5862 scoped_ptr
<HttpTransaction
> trans(
5863 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5865 MockWrite data_writes1
[] = {
5867 "GET /x/y/z2 HTTP/1.1\r\n"
5868 "Host: www.example.org\r\n"
5869 "Connection: keep-alive\r\n"
5870 // The authorization for MyRealm1 gets sent preemptively
5871 // (since the url is in the same protection space)
5872 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5875 // Sever accepts the preemptive authorization
5876 MockRead data_reads1
[] = {
5877 MockRead("HTTP/1.0 200 OK\r\n"),
5878 MockRead("Content-Length: 100\r\n\r\n"),
5879 MockRead(SYNCHRONOUS
, OK
),
5882 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5883 data_writes1
, arraysize(data_writes1
));
5884 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5886 TestCompletionCallback callback1
;
5888 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5889 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5891 rv
= callback1
.WaitForResult();
5894 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5895 ASSERT_TRUE(response
!= NULL
);
5897 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5898 EXPECT_EQ(100, response
->headers
->GetContentLength());
5901 // ------------------------------------------------------------------------
5903 // Transaction 4: request another URL in MyRealm (however the
5904 // url is not known to belong to the protection space, so no pre-auth).
5906 HttpRequestInfo request
;
5907 request
.method
= "GET";
5908 request
.url
= GURL("http://www.example.org/x/1");
5909 request
.load_flags
= 0;
5911 scoped_ptr
<HttpTransaction
> trans(
5912 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5914 MockWrite data_writes1
[] = {
5916 "GET /x/1 HTTP/1.1\r\n"
5917 "Host: www.example.org\r\n"
5918 "Connection: keep-alive\r\n\r\n"),
5921 MockRead data_reads1
[] = {
5922 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5923 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5924 MockRead("Content-Length: 10000\r\n\r\n"),
5925 MockRead(SYNCHRONOUS
, ERR_FAILED
),
5928 // Resend with authorization from MyRealm's cache.
5929 MockWrite data_writes2
[] = {
5931 "GET /x/1 HTTP/1.1\r\n"
5932 "Host: www.example.org\r\n"
5933 "Connection: keep-alive\r\n"
5934 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5937 // Sever accepts the authorization.
5938 MockRead data_reads2
[] = {
5939 MockRead("HTTP/1.0 200 OK\r\n"),
5940 MockRead("Content-Length: 100\r\n\r\n"),
5941 MockRead(SYNCHRONOUS
, OK
),
5944 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
5945 data_writes1
, arraysize(data_writes1
));
5946 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
5947 data_writes2
, arraysize(data_writes2
));
5948 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
5949 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
5951 TestCompletionCallback callback1
;
5953 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
5954 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5956 rv
= callback1
.WaitForResult();
5959 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
5960 TestCompletionCallback callback2
;
5961 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
5962 EXPECT_EQ(ERR_IO_PENDING
, rv
);
5963 rv
= callback2
.WaitForResult();
5965 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
5967 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
5968 ASSERT_TRUE(response
!= NULL
);
5969 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
5970 EXPECT_EQ(100, response
->headers
->GetContentLength());
5973 // ------------------------------------------------------------------------
5975 // Transaction 5: request a URL in MyRealm, but the server rejects the
5976 // cached identity. Should invalidate and re-prompt.
5978 HttpRequestInfo request
;
5979 request
.method
= "GET";
5980 request
.url
= GURL("http://www.example.org/p/q/t");
5981 request
.load_flags
= 0;
5983 scoped_ptr
<HttpTransaction
> trans(
5984 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
5986 MockWrite data_writes1
[] = {
5988 "GET /p/q/t HTTP/1.1\r\n"
5989 "Host: www.example.org\r\n"
5990 "Connection: keep-alive\r\n\r\n"),
5993 MockRead data_reads1
[] = {
5994 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
5995 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5996 MockRead("Content-Length: 10000\r\n\r\n"),
5997 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6000 // Resend with authorization from cache for MyRealm.
6001 MockWrite data_writes2
[] = {
6003 "GET /p/q/t HTTP/1.1\r\n"
6004 "Host: www.example.org\r\n"
6005 "Connection: keep-alive\r\n"
6006 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6009 // Sever rejects the authorization.
6010 MockRead data_reads2
[] = {
6011 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6012 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6013 MockRead("Content-Length: 10000\r\n\r\n"),
6014 MockRead(SYNCHRONOUS
, ERR_FAILED
),
6017 // At this point we should prompt for new credentials for MyRealm.
6018 // Restart with username=foo3, password=foo4.
6019 MockWrite data_writes3
[] = {
6021 "GET /p/q/t HTTP/1.1\r\n"
6022 "Host: www.example.org\r\n"
6023 "Connection: keep-alive\r\n"
6024 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
6027 // Sever accepts the authorization.
6028 MockRead data_reads3
[] = {
6029 MockRead("HTTP/1.0 200 OK\r\n"),
6030 MockRead("Content-Length: 100\r\n\r\n"),
6031 MockRead(SYNCHRONOUS
, OK
),
6034 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6035 data_writes1
, arraysize(data_writes1
));
6036 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6037 data_writes2
, arraysize(data_writes2
));
6038 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
6039 data_writes3
, arraysize(data_writes3
));
6040 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6041 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6042 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
6044 TestCompletionCallback callback1
;
6046 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6047 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6049 rv
= callback1
.WaitForResult();
6052 EXPECT_TRUE(trans
->IsReadyToRestartForAuth());
6053 TestCompletionCallback callback2
;
6054 rv
= trans
->RestartWithAuth(AuthCredentials(), callback2
.callback());
6055 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6056 rv
= callback2
.WaitForResult();
6058 EXPECT_FALSE(trans
->IsReadyToRestartForAuth());
6060 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6061 ASSERT_TRUE(response
!= NULL
);
6062 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
6064 TestCompletionCallback callback3
;
6066 rv
= trans
->RestartWithAuth(
6067 AuthCredentials(kFoo3
, kBar3
), callback3
.callback());
6068 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6070 rv
= callback3
.WaitForResult();
6073 response
= trans
->GetResponseInfo();
6074 ASSERT_TRUE(response
!= NULL
);
6075 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6076 EXPECT_EQ(100, response
->headers
->GetContentLength());
6080 // Tests that nonce count increments when multiple auth attempts
6081 // are started with the same nonce.
6082 TEST_P(HttpNetworkTransactionTest
, DigestPreAuthNonceCount
) {
6083 HttpAuthHandlerDigest::Factory
* digest_factory
=
6084 new HttpAuthHandlerDigest::Factory();
6085 HttpAuthHandlerDigest::FixedNonceGenerator
* nonce_generator
=
6086 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
6087 digest_factory
->set_nonce_generator(nonce_generator
);
6088 session_deps_
.http_auth_handler_factory
.reset(digest_factory
);
6089 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6091 // Transaction 1: authenticate (foo, bar) on MyRealm1
6093 HttpRequestInfo request
;
6094 request
.method
= "GET";
6095 request
.url
= GURL("http://www.example.org/x/y/z");
6096 request
.load_flags
= 0;
6098 scoped_ptr
<HttpTransaction
> trans(
6099 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6101 MockWrite data_writes1
[] = {
6103 "GET /x/y/z HTTP/1.1\r\n"
6104 "Host: www.example.org\r\n"
6105 "Connection: keep-alive\r\n\r\n"),
6108 MockRead data_reads1
[] = {
6109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
6110 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
6111 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
6112 MockRead(SYNCHRONOUS
, OK
),
6115 // Resend with authorization (username=foo, password=bar)
6116 MockWrite data_writes2
[] = {
6118 "GET /x/y/z HTTP/1.1\r\n"
6119 "Host: www.example.org\r\n"
6120 "Connection: keep-alive\r\n"
6121 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6122 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
6123 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
6124 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6127 // Sever accepts the authorization.
6128 MockRead data_reads2
[] = {
6129 MockRead("HTTP/1.0 200 OK\r\n"),
6130 MockRead(SYNCHRONOUS
, OK
),
6133 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6134 data_writes1
, arraysize(data_writes1
));
6135 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
6136 data_writes2
, arraysize(data_writes2
));
6137 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6138 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
6140 TestCompletionCallback callback1
;
6142 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6143 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6145 rv
= callback1
.WaitForResult();
6148 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6149 ASSERT_TRUE(response
!= NULL
);
6150 EXPECT_TRUE(CheckDigestServerAuth(response
->auth_challenge
.get()));
6152 TestCompletionCallback callback2
;
6154 rv
= trans
->RestartWithAuth(
6155 AuthCredentials(kFoo
, kBar
), callback2
.callback());
6156 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6158 rv
= callback2
.WaitForResult();
6161 response
= trans
->GetResponseInfo();
6162 ASSERT_TRUE(response
!= NULL
);
6163 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6166 // ------------------------------------------------------------------------
6168 // Transaction 2: Request another resource in digestive's protection space.
6169 // This will preemptively add an Authorization header which should have an
6170 // "nc" value of 2 (as compared to 1 in the first use.
6172 HttpRequestInfo request
;
6173 request
.method
= "GET";
6174 // Note that Transaction 1 was at /x/y/z, so this is in the same
6175 // protection space as digest.
6176 request
.url
= GURL("http://www.example.org/x/y/a/b");
6177 request
.load_flags
= 0;
6179 scoped_ptr
<HttpTransaction
> trans(
6180 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6182 MockWrite data_writes1
[] = {
6184 "GET /x/y/a/b HTTP/1.1\r\n"
6185 "Host: www.example.org\r\n"
6186 "Connection: keep-alive\r\n"
6187 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
6188 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
6189 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
6190 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
6193 // Sever accepts the authorization.
6194 MockRead data_reads1
[] = {
6195 MockRead("HTTP/1.0 200 OK\r\n"),
6196 MockRead("Content-Length: 100\r\n\r\n"),
6197 MockRead(SYNCHRONOUS
, OK
),
6200 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
6201 data_writes1
, arraysize(data_writes1
));
6202 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
6204 TestCompletionCallback callback1
;
6206 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
6207 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6209 rv
= callback1
.WaitForResult();
6212 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6213 ASSERT_TRUE(response
!= NULL
);
6214 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6218 // Test the ResetStateForRestart() private method.
6219 TEST_P(HttpNetworkTransactionTest
, ResetStateForRestart
) {
6220 // Create a transaction (the dependencies aren't important).
6221 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6222 scoped_ptr
<HttpNetworkTransaction
> trans(
6223 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6225 // Setup some state (which we expect ResetStateForRestart() will clear).
6226 trans
->read_buf_
= new IOBuffer(15);
6227 trans
->read_buf_len_
= 15;
6228 trans
->request_headers_
.SetHeader("Authorization", "NTLM");
6230 // Setup state in response_
6231 HttpResponseInfo
* response
= &trans
->response_
;
6232 response
->auth_challenge
= new AuthChallengeInfo();
6233 response
->ssl_info
.cert_status
= static_cast<CertStatus
>(-1); // Nonsensical.
6234 response
->response_time
= base::Time::Now();
6235 response
->was_cached
= true; // (Wouldn't ever actually be true...)
6237 { // Setup state for response_.vary_data
6238 HttpRequestInfo request
;
6239 std::string
temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
6240 std::replace(temp
.begin(), temp
.end(), '\n', '\0');
6241 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(temp
));
6242 request
.extra_headers
.SetHeader("Foo", "1");
6243 request
.extra_headers
.SetHeader("bar", "23");
6244 EXPECT_TRUE(response
->vary_data
.Init(request
, *headers
.get()));
6247 // Cause the above state to be reset.
6248 trans
->ResetStateForRestart();
6250 // Verify that the state that needed to be reset, has been reset.
6251 EXPECT_TRUE(trans
->read_buf_
.get() == NULL
);
6252 EXPECT_EQ(0, trans
->read_buf_len_
);
6253 EXPECT_TRUE(trans
->request_headers_
.IsEmpty());
6254 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6255 EXPECT_TRUE(response
->headers
.get() == NULL
);
6256 EXPECT_FALSE(response
->was_cached
);
6257 EXPECT_EQ(0U, response
->ssl_info
.cert_status
);
6258 EXPECT_FALSE(response
->vary_data
.is_valid());
6261 // Test HTTPS connections to a site with a bad certificate
6262 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificate
) {
6263 HttpRequestInfo request
;
6264 request
.method
= "GET";
6265 request
.url
= GURL("https://www.example.org/");
6266 request
.load_flags
= 0;
6268 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6269 scoped_ptr
<HttpTransaction
> trans(
6270 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6272 MockWrite data_writes
[] = {
6274 "GET / HTTP/1.1\r\n"
6275 "Host: www.example.org\r\n"
6276 "Connection: keep-alive\r\n\r\n"),
6279 MockRead data_reads
[] = {
6280 MockRead("HTTP/1.0 200 OK\r\n"),
6281 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6282 MockRead("Content-Length: 100\r\n\r\n"),
6283 MockRead(SYNCHRONOUS
, OK
),
6286 StaticSocketDataProvider ssl_bad_certificate
;
6287 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6288 data_writes
, arraysize(data_writes
));
6289 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6290 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6292 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6293 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6294 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6295 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6297 TestCompletionCallback callback
;
6299 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6300 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6302 rv
= callback
.WaitForResult();
6303 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6305 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6306 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6308 rv
= callback
.WaitForResult();
6311 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6313 ASSERT_TRUE(response
!= NULL
);
6314 EXPECT_EQ(100, response
->headers
->GetContentLength());
6317 // Test HTTPS connections to a site with a bad certificate, going through a
6319 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaProxy
) {
6320 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
6322 HttpRequestInfo request
;
6323 request
.method
= "GET";
6324 request
.url
= GURL("https://www.example.org/");
6325 request
.load_flags
= 0;
6327 MockWrite proxy_writes
[] = {
6329 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6330 "Host: www.example.org\r\n"
6331 "Proxy-Connection: keep-alive\r\n\r\n"),
6334 MockRead proxy_reads
[] = {
6335 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6336 MockRead(SYNCHRONOUS
, OK
)
6339 MockWrite data_writes
[] = {
6341 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6342 "Host: www.example.org\r\n"
6343 "Proxy-Connection: keep-alive\r\n\r\n"),
6345 "GET / HTTP/1.1\r\n"
6346 "Host: www.example.org\r\n"
6347 "Connection: keep-alive\r\n\r\n"),
6350 MockRead data_reads
[] = {
6351 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6352 MockRead("HTTP/1.0 200 OK\r\n"),
6353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6354 MockRead("Content-Length: 100\r\n\r\n"),
6355 MockRead(SYNCHRONOUS
, OK
),
6358 StaticSocketDataProvider
ssl_bad_certificate(
6359 proxy_reads
, arraysize(proxy_reads
),
6360 proxy_writes
, arraysize(proxy_writes
));
6361 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6362 data_writes
, arraysize(data_writes
));
6363 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
6364 SSLSocketDataProvider
ssl(ASYNC
, OK
);
6366 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
6367 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6368 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
6369 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
6371 TestCompletionCallback callback
;
6373 for (int i
= 0; i
< 2; i
++) {
6374 session_deps_
.socket_factory
->ResetNextMockIndexes();
6376 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6377 scoped_ptr
<HttpTransaction
> trans(
6378 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6380 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6381 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6383 rv
= callback
.WaitForResult();
6384 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
6386 rv
= trans
->RestartIgnoringLastError(callback
.callback());
6387 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6389 rv
= callback
.WaitForResult();
6392 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6394 ASSERT_TRUE(response
!= NULL
);
6395 EXPECT_EQ(100, response
->headers
->GetContentLength());
6400 // Test HTTPS connections to a site, going through an HTTPS proxy
6401 TEST_P(HttpNetworkTransactionTest
, HTTPSViaHttpsProxy
) {
6402 session_deps_
.proxy_service
.reset(
6403 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6405 session_deps_
.net_log
= &net_log
;
6407 HttpRequestInfo request
;
6408 request
.method
= "GET";
6409 request
.url
= GURL("https://www.example.org/");
6410 request
.load_flags
= 0;
6412 MockWrite data_writes
[] = {
6414 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6415 "Host: www.example.org\r\n"
6416 "Proxy-Connection: keep-alive\r\n\r\n"),
6418 "GET / HTTP/1.1\r\n"
6419 "Host: www.example.org\r\n"
6420 "Connection: keep-alive\r\n\r\n"),
6423 MockRead data_reads
[] = {
6424 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
6425 MockRead("HTTP/1.1 200 OK\r\n"),
6426 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6427 MockRead("Content-Length: 100\r\n\r\n"),
6428 MockRead(SYNCHRONOUS
, OK
),
6431 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6432 data_writes
, arraysize(data_writes
));
6433 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6434 SSLSocketDataProvider
tunnel_ssl(ASYNC
, OK
); // SSL through the tunnel
6436 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6437 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6438 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&tunnel_ssl
);
6440 TestCompletionCallback callback
;
6442 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6443 scoped_ptr
<HttpTransaction
> trans(
6444 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6446 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6447 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6449 rv
= callback
.WaitForResult();
6451 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6453 ASSERT_TRUE(response
!= NULL
);
6455 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6456 EXPECT_EQ(200, response
->headers
->response_code());
6457 EXPECT_EQ(100, response
->headers
->GetContentLength());
6458 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6460 LoadTimingInfo load_timing_info
;
6461 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6462 TestLoadTimingNotReusedWithPac(load_timing_info
,
6463 CONNECT_TIMING_HAS_SSL_TIMES
);
6466 // Test an HTTPS Proxy's ability to redirect a CONNECT request
6467 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaHttpsProxy
) {
6468 session_deps_
.proxy_service
.reset(
6469 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
6471 session_deps_
.net_log
= &net_log
;
6473 HttpRequestInfo request
;
6474 request
.method
= "GET";
6475 request
.url
= GURL("https://www.example.org/");
6476 request
.load_flags
= 0;
6478 MockWrite data_writes
[] = {
6480 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6481 "Host: www.example.org\r\n"
6482 "Proxy-Connection: keep-alive\r\n\r\n"),
6485 MockRead data_reads
[] = {
6486 MockRead("HTTP/1.1 302 Redirect\r\n"),
6487 MockRead("Location: http://login.example.com/\r\n"),
6488 MockRead("Content-Length: 0\r\n\r\n"),
6489 MockRead(SYNCHRONOUS
, OK
),
6492 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6493 data_writes
, arraysize(data_writes
));
6494 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6496 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6497 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6499 TestCompletionCallback callback
;
6501 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6502 scoped_ptr
<HttpTransaction
> trans(
6503 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6505 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6506 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6508 rv
= callback
.WaitForResult();
6510 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6512 ASSERT_TRUE(response
!= NULL
);
6514 EXPECT_EQ(302, response
->headers
->response_code());
6516 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6517 EXPECT_EQ("http://login.example.com/", url
);
6519 // In the case of redirects from proxies, HttpNetworkTransaction returns
6520 // timing for the proxy connection instead of the connection to the host,
6521 // and no send / receive times.
6522 // See HttpNetworkTransaction::OnHttpsProxyTunnelResponse.
6523 LoadTimingInfo load_timing_info
;
6524 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6526 EXPECT_FALSE(load_timing_info
.socket_reused
);
6527 EXPECT_NE(NetLog::Source::kInvalidId
, load_timing_info
.socket_log_id
);
6529 EXPECT_FALSE(load_timing_info
.proxy_resolve_start
.is_null());
6530 EXPECT_LE(load_timing_info
.proxy_resolve_start
,
6531 load_timing_info
.proxy_resolve_end
);
6532 EXPECT_LE(load_timing_info
.proxy_resolve_end
,
6533 load_timing_info
.connect_timing
.connect_start
);
6534 ExpectConnectTimingHasTimes(
6535 load_timing_info
.connect_timing
,
6536 CONNECT_TIMING_HAS_DNS_TIMES
| CONNECT_TIMING_HAS_SSL_TIMES
);
6538 EXPECT_TRUE(load_timing_info
.send_start
.is_null());
6539 EXPECT_TRUE(load_timing_info
.send_end
.is_null());
6540 EXPECT_TRUE(load_timing_info
.receive_headers_end
.is_null());
6543 // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
6544 TEST_P(HttpNetworkTransactionTest
, RedirectOfHttpsConnectViaSpdyProxy
) {
6545 session_deps_
.proxy_service
.reset(
6546 ProxyService::CreateFixed("https://proxy:70"));
6548 HttpRequestInfo request
;
6549 request
.method
= "GET";
6550 request
.url
= GURL("https://www.example.org/");
6551 request
.load_flags
= 0;
6553 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6554 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6555 scoped_ptr
<SpdyFrame
> goaway(
6556 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6557 MockWrite data_writes
[] = {
6558 CreateMockWrite(*conn
.get(), 0, SYNCHRONOUS
),
6559 CreateMockWrite(*goaway
.get(), 2, SYNCHRONOUS
),
6562 static const char* const kExtraHeaders
[] = {
6564 "http://login.example.com/",
6566 scoped_ptr
<SpdyFrame
> resp(
6567 spdy_util_
.ConstructSpdySynReplyError("302 Redirect", kExtraHeaders
,
6568 arraysize(kExtraHeaders
)/2, 1));
6569 MockRead data_reads
[] = {
6570 CreateMockRead(*resp
.get(), 1), MockRead(ASYNC
, 0, 3), // EOF
6573 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6574 arraysize(data_writes
));
6575 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6576 proxy_ssl
.SetNextProto(GetParam());
6578 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6579 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6581 TestCompletionCallback callback
;
6583 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6584 scoped_ptr
<HttpTransaction
> trans(
6585 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6587 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6588 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6590 rv
= callback
.WaitForResult();
6592 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6594 ASSERT_TRUE(response
!= NULL
);
6596 EXPECT_EQ(302, response
->headers
->response_code());
6598 EXPECT_TRUE(response
->headers
->IsRedirect(&url
));
6599 EXPECT_EQ("http://login.example.com/", url
);
6602 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
6603 TEST_P(HttpNetworkTransactionTest
,
6604 ErrorResponseToHttpsConnectViaHttpsProxy
) {
6605 session_deps_
.proxy_service
.reset(
6606 ProxyService::CreateFixed("https://proxy:70"));
6608 HttpRequestInfo request
;
6609 request
.method
= "GET";
6610 request
.url
= GURL("https://www.example.org/");
6611 request
.load_flags
= 0;
6613 MockWrite data_writes
[] = {
6615 "CONNECT www.example.org:443 HTTP/1.1\r\n"
6616 "Host: www.example.org\r\n"
6617 "Proxy-Connection: keep-alive\r\n\r\n"),
6620 MockRead data_reads
[] = {
6621 MockRead("HTTP/1.1 404 Not Found\r\n"),
6622 MockRead("Content-Length: 23\r\n\r\n"),
6623 MockRead("The host does not exist"),
6624 MockRead(SYNCHRONOUS
, OK
),
6627 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
6628 data_writes
, arraysize(data_writes
));
6629 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6631 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6632 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6634 TestCompletionCallback callback
;
6636 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6637 scoped_ptr
<HttpTransaction
> trans(
6638 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6640 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6641 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6643 rv
= callback
.WaitForResult();
6644 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6646 // TODO(ttuttle): Anything else to check here?
6649 // Test that a SPDY proxy's response to a CONNECT request is filtered.
6650 TEST_P(HttpNetworkTransactionTest
,
6651 ErrorResponseToHttpsConnectViaSpdyProxy
) {
6652 session_deps_
.proxy_service
.reset(
6653 ProxyService::CreateFixed("https://proxy:70"));
6655 HttpRequestInfo request
;
6656 request
.method
= "GET";
6657 request
.url
= GURL("https://www.example.org/");
6658 request
.load_flags
= 0;
6660 scoped_ptr
<SpdyFrame
> conn(spdy_util_
.ConstructSpdyConnect(
6661 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6662 scoped_ptr
<SpdyFrame
> rst(
6663 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6664 MockWrite data_writes
[] = {
6665 CreateMockWrite(*conn
.get(), 0), CreateMockWrite(*rst
.get(), 3),
6668 static const char* const kExtraHeaders
[] = {
6670 "http://login.example.com/",
6672 scoped_ptr
<SpdyFrame
> resp(
6673 spdy_util_
.ConstructSpdySynReplyError("404 Not Found", kExtraHeaders
,
6674 arraysize(kExtraHeaders
)/2, 1));
6675 scoped_ptr
<SpdyFrame
> body(
6676 spdy_util_
.ConstructSpdyBodyFrame(
6677 1, "The host does not exist", 23, true));
6678 MockRead data_reads
[] = {
6679 CreateMockRead(*resp
.get(), 1),
6680 CreateMockRead(*body
.get(), 2),
6681 MockRead(ASYNC
, 0, 4), // EOF
6684 SequencedSocketData
data(data_reads
, arraysize(data_reads
), data_writes
,
6685 arraysize(data_writes
));
6686 SSLSocketDataProvider
proxy_ssl(ASYNC
, OK
); // SSL to the proxy
6687 proxy_ssl
.SetNextProto(GetParam());
6689 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
6690 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy_ssl
);
6692 TestCompletionCallback callback
;
6694 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6695 scoped_ptr
<HttpTransaction
> trans(
6696 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6698 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
6699 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6701 rv
= callback
.WaitForResult();
6702 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
6704 // TODO(ttuttle): Anything else to check here?
6707 // Test the request-challenge-retry sequence for basic auth, through
6708 // a SPDY proxy over a single SPDY session.
6709 TEST_P(HttpNetworkTransactionTest
, BasicAuthSpdyProxy
) {
6710 HttpRequestInfo request
;
6711 request
.method
= "GET";
6712 request
.url
= GURL("https://www.example.org/");
6713 // when the no authentication data flag is set.
6714 request
.load_flags
= LOAD_DO_NOT_SEND_AUTH_DATA
;
6716 // Configure against https proxy server "myproxy:70".
6717 session_deps_
.proxy_service
.reset(
6718 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6719 BoundTestNetLog log
;
6720 session_deps_
.net_log
= log
.bound().net_log();
6721 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6723 // Since we have proxy, should try to establish tunnel.
6724 scoped_ptr
<SpdyFrame
> req(spdy_util_
.ConstructSpdyConnect(
6725 NULL
, 0, 1, LOWEST
, HostPortPair("www.example.org", 443)));
6726 scoped_ptr
<SpdyFrame
> rst(
6727 spdy_util_
.ConstructSpdyRstStream(1, RST_STREAM_CANCEL
));
6729 // After calling trans->RestartWithAuth(), this is the request we should
6730 // be issuing -- the final header line contains the credentials.
6731 const char* const kAuthCredentials
[] = {
6732 "proxy-authorization", "Basic Zm9vOmJhcg==",
6734 scoped_ptr
<SpdyFrame
> connect2(spdy_util_
.ConstructSpdyConnect(
6735 kAuthCredentials
, arraysize(kAuthCredentials
) / 2, 3, LOWEST
,
6736 HostPortPair("www.example.org", 443)));
6737 // fetch https://www.example.org/ via HTTP
6739 "GET / HTTP/1.1\r\n"
6740 "Host: www.example.org\r\n"
6741 "Connection: keep-alive\r\n\r\n";
6742 scoped_ptr
<SpdyFrame
> wrapped_get(
6743 spdy_util_
.ConstructSpdyBodyFrame(3, get
, strlen(get
), false));
6745 MockWrite spdy_writes
[] = {
6746 CreateMockWrite(*req
, 0, ASYNC
),
6747 CreateMockWrite(*rst
, 2, ASYNC
),
6748 CreateMockWrite(*connect2
, 3),
6749 CreateMockWrite(*wrapped_get
, 5),
6752 // The proxy responds to the connect with a 407, using a persistent
6754 const char kAuthStatus
[] = "407";
6755 const char* const kAuthChallenge
[] = {
6756 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
6758 scoped_ptr
<SpdyFrame
> conn_auth_resp(spdy_util_
.ConstructSpdySynReplyError(
6759 kAuthStatus
, kAuthChallenge
, arraysize(kAuthChallenge
) / 2, 1));
6761 scoped_ptr
<SpdyFrame
> conn_resp(
6762 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
6763 const char resp
[] = "HTTP/1.1 200 OK\r\n"
6764 "Content-Length: 5\r\n\r\n";
6766 scoped_ptr
<SpdyFrame
> wrapped_get_resp(
6767 spdy_util_
.ConstructSpdyBodyFrame(3, resp
, strlen(resp
), false));
6768 scoped_ptr
<SpdyFrame
> wrapped_body(
6769 spdy_util_
.ConstructSpdyBodyFrame(3, "hello", 5, false));
6770 MockRead spdy_reads
[] = {
6771 CreateMockRead(*conn_auth_resp
, 1, ASYNC
),
6772 CreateMockRead(*conn_resp
, 4, ASYNC
),
6773 CreateMockRead(*wrapped_get_resp
, 6, ASYNC
),
6774 CreateMockRead(*wrapped_body
, 7, ASYNC
),
6775 MockRead(ASYNC
, OK
, 8), // EOF. May or may not be read.
6778 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6779 arraysize(spdy_writes
));
6780 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6781 // Negotiate SPDY to the proxy
6782 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6783 proxy
.SetNextProto(GetParam());
6784 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6785 // Vanilla SSL to the server
6786 SSLSocketDataProvider
server(ASYNC
, OK
);
6787 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&server
);
6789 TestCompletionCallback callback1
;
6791 scoped_ptr
<HttpTransaction
> trans(
6792 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6794 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
6795 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6797 rv
= callback1
.WaitForResult();
6799 TestNetLogEntry::List entries
;
6800 log
.GetEntries(&entries
);
6801 size_t pos
= ExpectLogContainsSomewhere(
6802 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
6803 NetLog::PHASE_NONE
);
6804 ExpectLogContainsSomewhere(
6806 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
6807 NetLog::PHASE_NONE
);
6809 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6810 ASSERT_TRUE(response
!= NULL
);
6811 ASSERT_FALSE(response
->headers
.get() == NULL
);
6812 EXPECT_EQ(407, response
->headers
->response_code());
6813 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6814 EXPECT_TRUE(response
->auth_challenge
.get() != NULL
);
6815 EXPECT_TRUE(CheckBasicProxyAuth(response
->auth_challenge
.get()));
6817 TestCompletionCallback callback2
;
6819 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
6820 callback2
.callback());
6821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6823 rv
= callback2
.WaitForResult();
6826 response
= trans
->GetResponseInfo();
6827 ASSERT_TRUE(response
!= NULL
);
6829 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6830 EXPECT_EQ(200, response
->headers
->response_code());
6831 EXPECT_EQ(5, response
->headers
->GetContentLength());
6832 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6834 // The password prompt info should not be set.
6835 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
6837 LoadTimingInfo load_timing_info
;
6838 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6839 TestLoadTimingNotReusedWithPac(load_timing_info
,
6840 CONNECT_TIMING_HAS_SSL_TIMES
);
6843 session
->CloseAllConnections();
6846 // Test that an explicitly trusted SPDY proxy can push a resource from an
6847 // origin that is different from that of its associated resource.
6848 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPush
) {
6849 HttpRequestInfo request
;
6850 HttpRequestInfo push_request
;
6852 request
.method
= "GET";
6853 request
.url
= GURL("http://www.example.org/");
6854 push_request
.method
= "GET";
6855 push_request
.url
= GURL("http://www.another-origin.com/foo.dat");
6857 // Configure against https proxy server "myproxy:70".
6858 session_deps_
.proxy_service
.reset(
6859 ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"));
6860 BoundTestNetLog log
;
6861 session_deps_
.net_log
= log
.bound().net_log();
6863 // Enable cross-origin push.
6864 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6866 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6868 scoped_ptr
<SpdyFrame
> stream1_syn(
6869 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6871 MockWrite spdy_writes
[] = {
6872 CreateMockWrite(*stream1_syn
, 0, ASYNC
),
6875 scoped_ptr
<SpdyFrame
>
6876 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6878 scoped_ptr
<SpdyFrame
>
6879 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6881 scoped_ptr
<SpdyFrame
>
6882 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
6886 "http://www.another-origin.com/foo.dat"));
6887 const char kPushedData
[] = "pushed";
6888 scoped_ptr
<SpdyFrame
> stream2_body(
6889 spdy_util_
.ConstructSpdyBodyFrame(
6890 2, kPushedData
, strlen(kPushedData
), true));
6892 MockRead spdy_reads
[] = {
6893 CreateMockRead(*stream1_reply
, 1, ASYNC
),
6894 CreateMockRead(*stream2_syn
, 2, ASYNC
),
6895 CreateMockRead(*stream1_body
, 3, ASYNC
),
6896 CreateMockRead(*stream2_body
, 4, ASYNC
),
6897 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
6900 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
6901 arraysize(spdy_writes
));
6902 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
6903 // Negotiate SPDY to the proxy
6904 SSLSocketDataProvider
proxy(ASYNC
, OK
);
6905 proxy
.SetNextProto(GetParam());
6906 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
6908 scoped_ptr
<HttpTransaction
> trans(
6909 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6910 TestCompletionCallback callback
;
6911 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
6912 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6914 rv
= callback
.WaitForResult();
6916 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
6918 scoped_ptr
<HttpTransaction
> push_trans(
6919 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
6920 rv
= push_trans
->Start(&push_request
, callback
.callback(), log
.bound());
6921 EXPECT_EQ(ERR_IO_PENDING
, rv
);
6923 rv
= callback
.WaitForResult();
6925 const HttpResponseInfo
* push_response
= push_trans
->GetResponseInfo();
6927 ASSERT_TRUE(response
!= NULL
);
6928 EXPECT_TRUE(response
->headers
->IsKeepAlive());
6930 EXPECT_EQ(200, response
->headers
->response_code());
6931 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
6933 std::string response_data
;
6934 rv
= ReadTransaction(trans
.get(), &response_data
);
6936 EXPECT_EQ("hello!", response_data
);
6938 LoadTimingInfo load_timing_info
;
6939 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
6940 TestLoadTimingNotReusedWithPac(load_timing_info
,
6941 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
6943 // Verify the pushed stream.
6944 EXPECT_TRUE(push_response
->headers
.get() != NULL
);
6945 EXPECT_EQ(200, push_response
->headers
->response_code());
6947 rv
= ReadTransaction(push_trans
.get(), &response_data
);
6949 EXPECT_EQ("pushed", response_data
);
6951 LoadTimingInfo push_load_timing_info
;
6952 EXPECT_TRUE(push_trans
->GetLoadTimingInfo(&push_load_timing_info
));
6953 TestLoadTimingReusedWithPac(push_load_timing_info
);
6954 // The transactions should share a socket ID, despite being for different
6956 EXPECT_EQ(load_timing_info
.socket_log_id
,
6957 push_load_timing_info
.socket_log_id
);
6961 session
->CloseAllConnections();
6964 // Test that an explicitly trusted SPDY proxy cannot push HTTPS content.
6965 TEST_P(HttpNetworkTransactionTest
, CrossOriginProxyPushCorrectness
) {
6966 HttpRequestInfo request
;
6968 request
.method
= "GET";
6969 request
.url
= GURL("http://www.example.org/");
6971 // Configure against https proxy server "myproxy:70".
6972 session_deps_
.proxy_service
.reset(
6973 ProxyService::CreateFixed("https://myproxy:70"));
6974 BoundTestNetLog log
;
6975 session_deps_
.net_log
= log
.bound().net_log();
6977 // Enable cross-origin push.
6978 session_deps_
.trusted_spdy_proxy
= "myproxy:70";
6980 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
6982 scoped_ptr
<SpdyFrame
> stream1_syn(
6983 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, false));
6985 scoped_ptr
<SpdyFrame
> push_rst(
6986 spdy_util_
.ConstructSpdyRstStream(2, RST_STREAM_REFUSED_STREAM
));
6988 MockWrite spdy_writes
[] = {
6989 CreateMockWrite(*stream1_syn
, 0, ASYNC
), CreateMockWrite(*push_rst
, 3),
6992 scoped_ptr
<SpdyFrame
>
6993 stream1_reply(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
6995 scoped_ptr
<SpdyFrame
>
6996 stream1_body(spdy_util_
.ConstructSpdyBodyFrame(1, true));
6998 scoped_ptr
<SpdyFrame
>
6999 stream2_syn(spdy_util_
.ConstructSpdyPush(NULL
,
7003 "https://www.another-origin.com/foo.dat"));
7005 MockRead spdy_reads
[] = {
7006 CreateMockRead(*stream1_reply
, 1, ASYNC
),
7007 CreateMockRead(*stream2_syn
, 2, ASYNC
),
7008 CreateMockRead(*stream1_body
, 4, ASYNC
),
7009 MockRead(ASYNC
, ERR_IO_PENDING
, 5), // Force a pause
7012 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
7013 arraysize(spdy_writes
));
7014 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
7015 // Negotiate SPDY to the proxy
7016 SSLSocketDataProvider
proxy(ASYNC
, OK
);
7017 proxy
.SetNextProto(GetParam());
7018 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&proxy
);
7020 scoped_ptr
<HttpTransaction
> trans(
7021 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7022 TestCompletionCallback callback
;
7023 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
7024 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7026 rv
= callback
.WaitForResult();
7028 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7030 ASSERT_TRUE(response
!= NULL
);
7031 EXPECT_TRUE(response
->headers
->IsKeepAlive());
7033 EXPECT_EQ(200, response
->headers
->response_code());
7034 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
7036 std::string response_data
;
7037 rv
= ReadTransaction(trans
.get(), &response_data
);
7039 EXPECT_EQ("hello!", response_data
);
7042 session
->CloseAllConnections();
7045 // Test HTTPS connections to a site with a bad certificate, going through an
7047 TEST_P(HttpNetworkTransactionTest
, HTTPSBadCertificateViaHttpsProxy
) {
7048 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed(
7049 "https://proxy:70"));
7051 HttpRequestInfo request
;
7052 request
.method
= "GET";
7053 request
.url
= GURL("https://www.example.org/");
7054 request
.load_flags
= 0;
7056 // Attempt to fetch the URL from a server with a bad cert
7057 MockWrite bad_cert_writes
[] = {
7059 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7060 "Host: www.example.org\r\n"
7061 "Proxy-Connection: keep-alive\r\n\r\n"),
7064 MockRead bad_cert_reads
[] = {
7065 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7066 MockRead(SYNCHRONOUS
, OK
)
7069 // Attempt to fetch the URL with a good cert
7070 MockWrite good_data_writes
[] = {
7072 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7073 "Host: www.example.org\r\n"
7074 "Proxy-Connection: keep-alive\r\n\r\n"),
7076 "GET / HTTP/1.1\r\n"
7077 "Host: www.example.org\r\n"
7078 "Connection: keep-alive\r\n\r\n"),
7081 MockRead good_cert_reads
[] = {
7082 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
7083 MockRead("HTTP/1.0 200 OK\r\n"),
7084 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7085 MockRead("Content-Length: 100\r\n\r\n"),
7086 MockRead(SYNCHRONOUS
, OK
),
7089 StaticSocketDataProvider
ssl_bad_certificate(
7090 bad_cert_reads
, arraysize(bad_cert_reads
),
7091 bad_cert_writes
, arraysize(bad_cert_writes
));
7092 StaticSocketDataProvider
data(good_cert_reads
, arraysize(good_cert_reads
),
7093 good_data_writes
, arraysize(good_data_writes
));
7094 SSLSocketDataProvider
ssl_bad(ASYNC
, ERR_CERT_AUTHORITY_INVALID
);
7095 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7097 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
7098 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7099 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_bad_certificate
);
7100 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_bad
);
7102 // SSL to the proxy, then CONNECT request, then valid SSL certificate
7103 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7104 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7105 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7107 TestCompletionCallback callback
;
7109 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7110 scoped_ptr
<HttpTransaction
> trans(
7111 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7113 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7114 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7116 rv
= callback
.WaitForResult();
7117 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID
, rv
);
7119 rv
= trans
->RestartIgnoringLastError(callback
.callback());
7120 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7122 rv
= callback
.WaitForResult();
7125 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7127 ASSERT_TRUE(response
!= NULL
);
7128 EXPECT_EQ(100, response
->headers
->GetContentLength());
7131 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgent
) {
7132 HttpRequestInfo request
;
7133 request
.method
= "GET";
7134 request
.url
= GURL("http://www.example.org/");
7135 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7136 "Chromium Ultra Awesome X Edition");
7138 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7139 scoped_ptr
<HttpTransaction
> trans(
7140 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7142 MockWrite data_writes
[] = {
7144 "GET / HTTP/1.1\r\n"
7145 "Host: www.example.org\r\n"
7146 "Connection: keep-alive\r\n"
7147 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7150 // Lastly, the server responds with the actual content.
7151 MockRead data_reads
[] = {
7152 MockRead("HTTP/1.0 200 OK\r\n"),
7153 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7154 MockRead("Content-Length: 100\r\n\r\n"),
7155 MockRead(SYNCHRONOUS
, OK
),
7158 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7159 data_writes
, arraysize(data_writes
));
7160 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7162 TestCompletionCallback callback
;
7164 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7165 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7167 rv
= callback
.WaitForResult();
7171 TEST_P(HttpNetworkTransactionTest
, BuildRequest_UserAgentOverTunnel
) {
7172 HttpRequestInfo request
;
7173 request
.method
= "GET";
7174 request
.url
= GURL("https://www.example.org/");
7175 request
.extra_headers
.SetHeader(HttpRequestHeaders::kUserAgent
,
7176 "Chromium Ultra Awesome X Edition");
7178 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
7179 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7180 scoped_ptr
<HttpTransaction
> trans(
7181 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7183 MockWrite data_writes
[] = {
7185 "CONNECT www.example.org:443 HTTP/1.1\r\n"
7186 "Host: www.example.org\r\n"
7187 "Proxy-Connection: keep-alive\r\n"
7188 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
7190 MockRead data_reads
[] = {
7191 // Return an error, so the transaction stops here (this test isn't
7192 // interested in the rest).
7193 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
7194 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
7195 MockRead("Proxy-Connection: close\r\n\r\n"),
7198 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7199 data_writes
, arraysize(data_writes
));
7200 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7202 TestCompletionCallback callback
;
7204 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7205 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7207 rv
= callback
.WaitForResult();
7211 TEST_P(HttpNetworkTransactionTest
, BuildRequest_Referer
) {
7212 HttpRequestInfo request
;
7213 request
.method
= "GET";
7214 request
.url
= GURL("http://www.example.org/");
7215 request
.load_flags
= 0;
7216 request
.extra_headers
.SetHeader(HttpRequestHeaders::kReferer
,
7217 "http://the.previous.site.com/");
7219 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7220 scoped_ptr
<HttpTransaction
> trans(
7221 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7223 MockWrite data_writes
[] = {
7225 "GET / HTTP/1.1\r\n"
7226 "Host: www.example.org\r\n"
7227 "Connection: keep-alive\r\n"
7228 "Referer: http://the.previous.site.com/\r\n\r\n"),
7231 // Lastly, the server responds with the actual content.
7232 MockRead data_reads
[] = {
7233 MockRead("HTTP/1.0 200 OK\r\n"),
7234 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7235 MockRead("Content-Length: 100\r\n\r\n"),
7236 MockRead(SYNCHRONOUS
, OK
),
7239 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7240 data_writes
, arraysize(data_writes
));
7241 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7243 TestCompletionCallback callback
;
7245 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7246 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7248 rv
= callback
.WaitForResult();
7252 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PostContentLengthZero
) {
7253 HttpRequestInfo request
;
7254 request
.method
= "POST";
7255 request
.url
= GURL("http://www.example.org/");
7257 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7258 scoped_ptr
<HttpTransaction
> trans(
7259 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7261 MockWrite data_writes
[] = {
7263 "POST / HTTP/1.1\r\n"
7264 "Host: www.example.org\r\n"
7265 "Connection: keep-alive\r\n"
7266 "Content-Length: 0\r\n\r\n"),
7269 // Lastly, the server responds with the actual content.
7270 MockRead data_reads
[] = {
7271 MockRead("HTTP/1.0 200 OK\r\n"),
7272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7273 MockRead("Content-Length: 100\r\n\r\n"),
7274 MockRead(SYNCHRONOUS
, OK
),
7277 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7278 data_writes
, arraysize(data_writes
));
7279 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7281 TestCompletionCallback callback
;
7283 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7284 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7286 rv
= callback
.WaitForResult();
7290 TEST_P(HttpNetworkTransactionTest
, BuildRequest_PutContentLengthZero
) {
7291 HttpRequestInfo request
;
7292 request
.method
= "PUT";
7293 request
.url
= GURL("http://www.example.org/");
7295 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7296 scoped_ptr
<HttpTransaction
> trans(
7297 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7299 MockWrite data_writes
[] = {
7301 "PUT / HTTP/1.1\r\n"
7302 "Host: www.example.org\r\n"
7303 "Connection: keep-alive\r\n"
7304 "Content-Length: 0\r\n\r\n"),
7307 // Lastly, the server responds with the actual content.
7308 MockRead data_reads
[] = {
7309 MockRead("HTTP/1.0 200 OK\r\n"),
7310 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7311 MockRead("Content-Length: 100\r\n\r\n"),
7312 MockRead(SYNCHRONOUS
, OK
),
7315 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7316 data_writes
, arraysize(data_writes
));
7317 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7319 TestCompletionCallback callback
;
7321 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7322 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7324 rv
= callback
.WaitForResult();
7328 TEST_P(HttpNetworkTransactionTest
, BuildRequest_HeadContentLengthZero
) {
7329 HttpRequestInfo request
;
7330 request
.method
= "HEAD";
7331 request
.url
= GURL("http://www.example.org/");
7333 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7334 scoped_ptr
<HttpTransaction
> trans(
7335 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7337 MockWrite data_writes
[] = {
7339 "HEAD / HTTP/1.1\r\n"
7340 "Host: www.example.org\r\n"
7341 "Connection: keep-alive\r\n"
7342 "Content-Length: 0\r\n\r\n"),
7345 // Lastly, the server responds with the actual content.
7346 MockRead data_reads
[] = {
7347 MockRead("HTTP/1.0 200 OK\r\n"),
7348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7349 MockRead("Content-Length: 100\r\n\r\n"),
7350 MockRead(SYNCHRONOUS
, OK
),
7353 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7354 data_writes
, arraysize(data_writes
));
7355 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7357 TestCompletionCallback callback
;
7359 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7360 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7362 rv
= callback
.WaitForResult();
7366 TEST_P(HttpNetworkTransactionTest
, BuildRequest_CacheControlNoCache
) {
7367 HttpRequestInfo request
;
7368 request
.method
= "GET";
7369 request
.url
= GURL("http://www.example.org/");
7370 request
.load_flags
= LOAD_BYPASS_CACHE
;
7372 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7373 scoped_ptr
<HttpTransaction
> trans(
7374 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7376 MockWrite data_writes
[] = {
7378 "GET / HTTP/1.1\r\n"
7379 "Host: www.example.org\r\n"
7380 "Connection: keep-alive\r\n"
7381 "Pragma: no-cache\r\n"
7382 "Cache-Control: no-cache\r\n\r\n"),
7385 // Lastly, the server responds with the actual content.
7386 MockRead data_reads
[] = {
7387 MockRead("HTTP/1.0 200 OK\r\n"),
7388 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7389 MockRead("Content-Length: 100\r\n\r\n"),
7390 MockRead(SYNCHRONOUS
, OK
),
7393 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7394 data_writes
, arraysize(data_writes
));
7395 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7397 TestCompletionCallback callback
;
7399 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7402 rv
= callback
.WaitForResult();
7406 TEST_P(HttpNetworkTransactionTest
,
7407 BuildRequest_CacheControlValidateCache
) {
7408 HttpRequestInfo request
;
7409 request
.method
= "GET";
7410 request
.url
= GURL("http://www.example.org/");
7411 request
.load_flags
= LOAD_VALIDATE_CACHE
;
7413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7414 scoped_ptr
<HttpTransaction
> trans(
7415 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7417 MockWrite data_writes
[] = {
7419 "GET / HTTP/1.1\r\n"
7420 "Host: www.example.org\r\n"
7421 "Connection: keep-alive\r\n"
7422 "Cache-Control: max-age=0\r\n\r\n"),
7425 // Lastly, the server responds with the actual content.
7426 MockRead data_reads
[] = {
7427 MockRead("HTTP/1.0 200 OK\r\n"),
7428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7429 MockRead("Content-Length: 100\r\n\r\n"),
7430 MockRead(SYNCHRONOUS
, OK
),
7433 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7434 data_writes
, arraysize(data_writes
));
7435 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7437 TestCompletionCallback callback
;
7439 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7440 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7442 rv
= callback
.WaitForResult();
7446 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeaders
) {
7447 HttpRequestInfo request
;
7448 request
.method
= "GET";
7449 request
.url
= GURL("http://www.example.org/");
7450 request
.extra_headers
.SetHeader("FooHeader", "Bar");
7452 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7453 scoped_ptr
<HttpTransaction
> trans(
7454 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7456 MockWrite data_writes
[] = {
7458 "GET / HTTP/1.1\r\n"
7459 "Host: www.example.org\r\n"
7460 "Connection: keep-alive\r\n"
7461 "FooHeader: Bar\r\n\r\n"),
7464 // Lastly, the server responds with the actual content.
7465 MockRead data_reads
[] = {
7466 MockRead("HTTP/1.0 200 OK\r\n"),
7467 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7468 MockRead("Content-Length: 100\r\n\r\n"),
7469 MockRead(SYNCHRONOUS
, OK
),
7472 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7473 data_writes
, arraysize(data_writes
));
7474 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7476 TestCompletionCallback callback
;
7478 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7479 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7481 rv
= callback
.WaitForResult();
7485 TEST_P(HttpNetworkTransactionTest
, BuildRequest_ExtraHeadersStripped
) {
7486 HttpRequestInfo request
;
7487 request
.method
= "GET";
7488 request
.url
= GURL("http://www.example.org/");
7489 request
.extra_headers
.SetHeader("referer", "www.foo.com");
7490 request
.extra_headers
.SetHeader("hEllo", "Kitty");
7491 request
.extra_headers
.SetHeader("FoO", "bar");
7493 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7494 scoped_ptr
<HttpTransaction
> trans(
7495 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7497 MockWrite data_writes
[] = {
7499 "GET / HTTP/1.1\r\n"
7500 "Host: www.example.org\r\n"
7501 "Connection: keep-alive\r\n"
7502 "referer: www.foo.com\r\n"
7504 "FoO: bar\r\n\r\n"),
7507 // Lastly, the server responds with the actual content.
7508 MockRead data_reads
[] = {
7509 MockRead("HTTP/1.0 200 OK\r\n"),
7510 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7511 MockRead("Content-Length: 100\r\n\r\n"),
7512 MockRead(SYNCHRONOUS
, OK
),
7515 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7516 data_writes
, arraysize(data_writes
));
7517 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7519 TestCompletionCallback callback
;
7521 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7522 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7524 rv
= callback
.WaitForResult();
7528 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET
) {
7529 HttpRequestInfo request
;
7530 request
.method
= "GET";
7531 request
.url
= GURL("http://www.example.org/");
7532 request
.load_flags
= 0;
7534 session_deps_
.proxy_service
.reset(
7535 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7537 session_deps_
.net_log
= &net_log
;
7539 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7540 scoped_ptr
<HttpTransaction
> trans(
7541 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7543 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7544 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7546 MockWrite data_writes
[] = {
7547 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7549 "GET / HTTP/1.1\r\n"
7550 "Host: www.example.org\r\n"
7551 "Connection: keep-alive\r\n\r\n")};
7553 MockRead data_reads
[] = {
7554 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7555 MockRead("HTTP/1.0 200 OK\r\n"),
7556 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7557 MockRead("Payload"),
7558 MockRead(SYNCHRONOUS
, OK
)
7561 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7562 data_writes
, arraysize(data_writes
));
7563 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7565 TestCompletionCallback callback
;
7567 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7568 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7570 rv
= callback
.WaitForResult();
7573 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7574 ASSERT_TRUE(response
!= NULL
);
7576 LoadTimingInfo load_timing_info
;
7577 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7578 TestLoadTimingNotReusedWithPac(load_timing_info
,
7579 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7581 std::string response_text
;
7582 rv
= ReadTransaction(trans
.get(), &response_text
);
7584 EXPECT_EQ("Payload", response_text
);
7587 TEST_P(HttpNetworkTransactionTest
, SOCKS4_SSL_GET
) {
7588 HttpRequestInfo request
;
7589 request
.method
= "GET";
7590 request
.url
= GURL("https://www.example.org/");
7591 request
.load_flags
= 0;
7593 session_deps_
.proxy_service
.reset(
7594 ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"));
7596 session_deps_
.net_log
= &net_log
;
7598 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7599 scoped_ptr
<HttpTransaction
> trans(
7600 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7602 unsigned char write_buffer
[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
7603 unsigned char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7605 MockWrite data_writes
[] = {
7606 MockWrite(ASYNC
, reinterpret_cast<char*>(write_buffer
),
7607 arraysize(write_buffer
)),
7609 "GET / HTTP/1.1\r\n"
7610 "Host: www.example.org\r\n"
7611 "Connection: keep-alive\r\n\r\n")};
7613 MockRead data_reads
[] = {
7614 MockRead(ASYNC
, reinterpret_cast<char*>(read_buffer
),
7615 arraysize(read_buffer
)),
7616 MockRead("HTTP/1.0 200 OK\r\n"),
7617 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7618 MockRead("Payload"),
7619 MockRead(SYNCHRONOUS
, OK
)
7622 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7623 data_writes
, arraysize(data_writes
));
7624 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7626 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7627 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7629 TestCompletionCallback callback
;
7631 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7632 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7634 rv
= callback
.WaitForResult();
7637 LoadTimingInfo load_timing_info
;
7638 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7639 TestLoadTimingNotReusedWithPac(load_timing_info
,
7640 CONNECT_TIMING_HAS_SSL_TIMES
);
7642 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7643 ASSERT_TRUE(response
!= NULL
);
7645 std::string response_text
;
7646 rv
= ReadTransaction(trans
.get(), &response_text
);
7648 EXPECT_EQ("Payload", response_text
);
7651 TEST_P(HttpNetworkTransactionTest
, SOCKS4_HTTP_GET_no_PAC
) {
7652 HttpRequestInfo request
;
7653 request
.method
= "GET";
7654 request
.url
= GURL("http://www.example.org/");
7655 request
.load_flags
= 0;
7657 session_deps_
.proxy_service
.reset(
7658 ProxyService::CreateFixed("socks4://myproxy:1080"));
7660 session_deps_
.net_log
= &net_log
;
7662 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7663 scoped_ptr
<HttpTransaction
> trans(
7664 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7666 char write_buffer
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
7667 char read_buffer
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
7669 MockWrite data_writes
[] = {
7670 MockWrite(ASYNC
, write_buffer
, arraysize(write_buffer
)),
7672 "GET / HTTP/1.1\r\n"
7673 "Host: www.example.org\r\n"
7674 "Connection: keep-alive\r\n\r\n")};
7676 MockRead data_reads
[] = {
7677 MockRead(ASYNC
, read_buffer
, arraysize(read_buffer
)),
7678 MockRead("HTTP/1.0 200 OK\r\n"),
7679 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7680 MockRead("Payload"),
7681 MockRead(SYNCHRONOUS
, OK
)
7684 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7685 data_writes
, arraysize(data_writes
));
7686 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7688 TestCompletionCallback callback
;
7690 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7691 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7693 rv
= callback
.WaitForResult();
7696 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7697 ASSERT_TRUE(response
!= NULL
);
7699 LoadTimingInfo load_timing_info
;
7700 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7701 TestLoadTimingNotReused(load_timing_info
,
7702 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7704 std::string response_text
;
7705 rv
= ReadTransaction(trans
.get(), &response_text
);
7707 EXPECT_EQ("Payload", response_text
);
7710 TEST_P(HttpNetworkTransactionTest
, SOCKS5_HTTP_GET
) {
7711 HttpRequestInfo request
;
7712 request
.method
= "GET";
7713 request
.url
= GURL("http://www.example.org/");
7714 request
.load_flags
= 0;
7716 session_deps_
.proxy_service
.reset(
7717 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7719 session_deps_
.net_log
= &net_log
;
7721 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7722 scoped_ptr
<HttpTransaction
> trans(
7723 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7725 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7726 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7727 const char kSOCKS5OkRequest
[] = {
7729 0x01, // Command (CONNECT)
7731 0x03, // Address type (DOMAINNAME).
7732 0x0F, // Length of domain (15)
7733 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7734 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
7736 const char kSOCKS5OkResponse
[] =
7737 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
7739 MockWrite data_writes
[] = {
7740 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7741 MockWrite(ASYNC
, kSOCKS5OkRequest
, arraysize(kSOCKS5OkRequest
)),
7743 "GET / HTTP/1.1\r\n"
7744 "Host: www.example.org\r\n"
7745 "Connection: keep-alive\r\n\r\n")};
7747 MockRead data_reads
[] = {
7748 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7749 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7750 MockRead("HTTP/1.0 200 OK\r\n"),
7751 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7752 MockRead("Payload"),
7753 MockRead(SYNCHRONOUS
, OK
)
7756 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7757 data_writes
, arraysize(data_writes
));
7758 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7760 TestCompletionCallback callback
;
7762 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7763 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7765 rv
= callback
.WaitForResult();
7768 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7769 ASSERT_TRUE(response
!= NULL
);
7771 LoadTimingInfo load_timing_info
;
7772 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7773 TestLoadTimingNotReusedWithPac(load_timing_info
,
7774 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
7776 std::string response_text
;
7777 rv
= ReadTransaction(trans
.get(), &response_text
);
7779 EXPECT_EQ("Payload", response_text
);
7782 TEST_P(HttpNetworkTransactionTest
, SOCKS5_SSL_GET
) {
7783 HttpRequestInfo request
;
7784 request
.method
= "GET";
7785 request
.url
= GURL("https://www.example.org/");
7786 request
.load_flags
= 0;
7788 session_deps_
.proxy_service
.reset(
7789 ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"));
7791 session_deps_
.net_log
= &net_log
;
7793 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
7794 scoped_ptr
<HttpTransaction
> trans(
7795 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7797 const char kSOCKS5GreetRequest
[] = { 0x05, 0x01, 0x00 };
7798 const char kSOCKS5GreetResponse
[] = { 0x05, 0x00 };
7799 const unsigned char kSOCKS5OkRequest
[] = {
7801 0x01, // Command (CONNECT)
7803 0x03, // Address type (DOMAINNAME).
7804 0x0F, // Length of domain (15)
7805 'w', 'w', 'w', '.', 'e', 'x', 'a', 'm', 'p', 'l', 'e', // Domain string
7806 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
7809 const char kSOCKS5OkResponse
[] =
7810 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
7812 MockWrite data_writes
[] = {
7813 MockWrite(ASYNC
, kSOCKS5GreetRequest
, arraysize(kSOCKS5GreetRequest
)),
7814 MockWrite(ASYNC
, reinterpret_cast<const char*>(kSOCKS5OkRequest
),
7815 arraysize(kSOCKS5OkRequest
)),
7817 "GET / HTTP/1.1\r\n"
7818 "Host: www.example.org\r\n"
7819 "Connection: keep-alive\r\n\r\n")};
7821 MockRead data_reads
[] = {
7822 MockRead(ASYNC
, kSOCKS5GreetResponse
, arraysize(kSOCKS5GreetResponse
)),
7823 MockRead(ASYNC
, kSOCKS5OkResponse
, arraysize(kSOCKS5OkResponse
)),
7824 MockRead("HTTP/1.0 200 OK\r\n"),
7825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
7826 MockRead("Payload"),
7827 MockRead(SYNCHRONOUS
, OK
)
7830 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
7831 data_writes
, arraysize(data_writes
));
7832 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
7834 SSLSocketDataProvider
ssl(ASYNC
, OK
);
7835 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
7837 TestCompletionCallback callback
;
7839 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
7840 EXPECT_EQ(ERR_IO_PENDING
, rv
);
7842 rv
= callback
.WaitForResult();
7845 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
7846 ASSERT_TRUE(response
!= NULL
);
7848 LoadTimingInfo load_timing_info
;
7849 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
7850 TestLoadTimingNotReusedWithPac(load_timing_info
,
7851 CONNECT_TIMING_HAS_SSL_TIMES
);
7853 std::string response_text
;
7854 rv
= ReadTransaction(trans
.get(), &response_text
);
7856 EXPECT_EQ("Payload", response_text
);
7861 // Tests that for connection endpoints the group names are correctly set.
7863 struct GroupNameTest
{
7864 std::string proxy_server
;
7866 std::string expected_group_name
;
7870 scoped_refptr
<HttpNetworkSession
> SetupSessionForGroupNameTests(
7871 NextProto next_proto
,
7872 SpdySessionDependencies
* session_deps_
) {
7873 scoped_refptr
<HttpNetworkSession
> session(CreateSession(session_deps_
));
7875 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
7876 session
->http_server_properties();
7877 AlternativeService
alternative_service(
7878 AlternateProtocolFromNextProto(next_proto
), "", 443);
7879 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
7880 http_server_properties
->SetAlternativeService(
7881 HostPortPair("host.with.alternate", 80), alternative_service
, 1.0,
7887 int GroupNameTransactionHelper(
7888 const std::string
& url
,
7889 const scoped_refptr
<HttpNetworkSession
>& session
) {
7890 HttpRequestInfo request
;
7891 request
.method
= "GET";
7892 request
.url
= GURL(url
);
7893 request
.load_flags
= 0;
7895 scoped_ptr
<HttpTransaction
> trans(
7896 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
7898 TestCompletionCallback callback
;
7900 // We do not complete this request, the dtor will clean the transaction up.
7901 return trans
->Start(&request
, callback
.callback(), BoundNetLog());
7906 TEST_P(HttpNetworkTransactionTest
, GroupNameForDirectConnections
) {
7907 const GroupNameTest tests
[] = {
7910 "http://www.example.org/direct",
7911 "www.example.org:80",
7916 "http://[2001:1418:13:1::25]/direct",
7917 "[2001:1418:13:1::25]:80",
7924 "https://www.example.org/direct_ssl",
7925 "ssl/www.example.org:443",
7930 "https://[2001:1418:13:1::25]/direct",
7931 "ssl/[2001:1418:13:1::25]:443",
7936 "http://host.with.alternate/direct",
7937 "ssl/host.with.alternate:443",
7942 session_deps_
.use_alternate_protocols
= true;
7944 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
7945 session_deps_
.proxy_service
.reset(
7946 ProxyService::CreateFixed(tests
[i
].proxy_server
));
7947 scoped_refptr
<HttpNetworkSession
> session(
7948 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
7950 HttpNetworkSessionPeer
peer(session
);
7951 CaptureGroupNameTransportSocketPool
* transport_conn_pool
=
7952 new CaptureGroupNameTransportSocketPool(NULL
, NULL
);
7953 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
7954 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
7955 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
7956 new MockClientSocketPoolManager
);
7957 mock_pool_manager
->SetTransportSocketPool(transport_conn_pool
);
7958 mock_pool_manager
->SetSSLSocketPool(ssl_conn_pool
);
7959 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
7961 EXPECT_EQ(ERR_IO_PENDING
,
7962 GroupNameTransactionHelper(tests
[i
].url
, session
));
7964 EXPECT_EQ(tests
[i
].expected_group_name
,
7965 ssl_conn_pool
->last_group_name_received());
7967 EXPECT_EQ(tests
[i
].expected_group_name
,
7968 transport_conn_pool
->last_group_name_received());
7973 TEST_P(HttpNetworkTransactionTest
, GroupNameForHTTPProxyConnections
) {
7974 const GroupNameTest tests
[] = {
7977 "http://www.example.org/http_proxy_normal",
7978 "www.example.org:80",
7985 "https://www.example.org/http_connect_ssl",
7986 "ssl/www.example.org:443",
7992 "http://host.with.alternate/direct",
7993 "ssl/host.with.alternate:443",
7999 "ftp://ftp.google.com/http_proxy_normal",
8000 "ftp/ftp.google.com:21",
8005 session_deps_
.use_alternate_protocols
= true;
8007 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8008 session_deps_
.proxy_service
.reset(
8009 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8010 scoped_refptr
<HttpNetworkSession
> session(
8011 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8013 HttpNetworkSessionPeer
peer(session
);
8015 HostPortPair
proxy_host("http_proxy", 80);
8016 CaptureGroupNameHttpProxySocketPool
* http_proxy_pool
=
8017 new CaptureGroupNameHttpProxySocketPool(NULL
, NULL
);
8018 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8019 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8021 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8022 new MockClientSocketPoolManager
);
8023 mock_pool_manager
->SetSocketPoolForHTTPProxy(proxy_host
, http_proxy_pool
);
8024 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8025 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8027 EXPECT_EQ(ERR_IO_PENDING
,
8028 GroupNameTransactionHelper(tests
[i
].url
, session
));
8030 EXPECT_EQ(tests
[i
].expected_group_name
,
8031 ssl_conn_pool
->last_group_name_received());
8033 EXPECT_EQ(tests
[i
].expected_group_name
,
8034 http_proxy_pool
->last_group_name_received());
8038 TEST_P(HttpNetworkTransactionTest
, GroupNameForSOCKSConnections
) {
8039 const GroupNameTest tests
[] = {
8041 "socks4://socks_proxy:1080",
8042 "http://www.example.org/socks4_direct",
8043 "socks4/www.example.org:80",
8047 "socks5://socks_proxy:1080",
8048 "http://www.example.org/socks5_direct",
8049 "socks5/www.example.org:80",
8055 "socks4://socks_proxy:1080",
8056 "https://www.example.org/socks4_ssl",
8057 "socks4/ssl/www.example.org:443",
8061 "socks5://socks_proxy:1080",
8062 "https://www.example.org/socks5_ssl",
8063 "socks5/ssl/www.example.org:443",
8068 "socks4://socks_proxy:1080",
8069 "http://host.with.alternate/direct",
8070 "socks4/ssl/host.with.alternate:443",
8075 session_deps_
.use_alternate_protocols
= true;
8077 for (size_t i
= 0; i
< arraysize(tests
); ++i
) {
8078 session_deps_
.proxy_service
.reset(
8079 ProxyService::CreateFixed(tests
[i
].proxy_server
));
8080 scoped_refptr
<HttpNetworkSession
> session(
8081 SetupSessionForGroupNameTests(GetParam(), &session_deps_
));
8083 HttpNetworkSessionPeer
peer(session
);
8085 HostPortPair
proxy_host("socks_proxy", 1080);
8086 CaptureGroupNameSOCKSSocketPool
* socks_conn_pool
=
8087 new CaptureGroupNameSOCKSSocketPool(NULL
, NULL
);
8088 CaptureGroupNameSSLSocketPool
* ssl_conn_pool
=
8089 new CaptureGroupNameSSLSocketPool(NULL
, NULL
);
8091 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
8092 new MockClientSocketPoolManager
);
8093 mock_pool_manager
->SetSocketPoolForSOCKSProxy(proxy_host
, socks_conn_pool
);
8094 mock_pool_manager
->SetSocketPoolForSSLWithProxy(proxy_host
, ssl_conn_pool
);
8095 peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
8097 scoped_ptr
<HttpTransaction
> trans(
8098 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8100 EXPECT_EQ(ERR_IO_PENDING
,
8101 GroupNameTransactionHelper(tests
[i
].url
, session
));
8103 EXPECT_EQ(tests
[i
].expected_group_name
,
8104 ssl_conn_pool
->last_group_name_received());
8106 EXPECT_EQ(tests
[i
].expected_group_name
,
8107 socks_conn_pool
->last_group_name_received());
8111 TEST_P(HttpNetworkTransactionTest
, ReconsiderProxyAfterFailedConnection
) {
8112 HttpRequestInfo request
;
8113 request
.method
= "GET";
8114 request
.url
= GURL("http://www.example.org/");
8116 session_deps_
.proxy_service
.reset(
8117 ProxyService::CreateFixed("myproxy:70;foobar:80"));
8119 // This simulates failure resolving all hostnames; that means we will fail
8120 // connecting to both proxies (myproxy:70 and foobar:80).
8121 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("*");
8123 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8124 scoped_ptr
<HttpTransaction
> trans(
8125 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8127 TestCompletionCallback callback
;
8129 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8130 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8132 rv
= callback
.WaitForResult();
8133 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
8136 // Base test to make sure that when the load flags for a request specify to
8137 // bypass the cache, the DNS cache is not used.
8138 void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
8140 // Issue a request, asking to bypass the cache(s).
8141 HttpRequestInfo request
;
8142 request
.method
= "GET";
8143 request
.load_flags
= load_flags
;
8144 request
.url
= GURL("http://www.example.org/");
8146 // Select a host resolver that does caching.
8147 session_deps_
.host_resolver
.reset(new MockCachingHostResolver
);
8149 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8150 scoped_ptr
<HttpTransaction
> trans(
8151 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8153 // Warm up the host cache so it has an entry for "www.example.org".
8154 AddressList addrlist
;
8155 TestCompletionCallback callback
;
8156 int rv
= session_deps_
.host_resolver
->Resolve(
8157 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8158 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8159 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8160 rv
= callback
.WaitForResult();
8163 // Verify that it was added to host cache, by doing a subsequent async lookup
8164 // and confirming it completes synchronously.
8165 rv
= session_deps_
.host_resolver
->Resolve(
8166 HostResolver::RequestInfo(HostPortPair("www.example.org", 80)),
8167 DEFAULT_PRIORITY
, &addrlist
, callback
.callback(), NULL
, BoundNetLog());
8170 // Inject a failure the next time that "www.example.org" is resolved. This way
8171 // we can tell if the next lookup hit the cache, or the "network".
8172 // (cache --> success, "network" --> failure).
8173 session_deps_
.host_resolver
->rules()->AddSimulatedFailure("www.example.org");
8175 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
8176 // first read -- this won't be reached as the host resolution will fail first.
8177 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
) };
8178 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8179 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8182 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8183 ASSERT_EQ(ERR_IO_PENDING
, rv
);
8184 rv
= callback
.WaitForResult();
8186 // If we bypassed the cache, we would have gotten a failure while resolving
8187 // "www.example.org".
8188 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
8191 // There are multiple load flags that should trigger the host cache bypass.
8192 // Test each in isolation:
8193 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh1
) {
8194 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE
);
8197 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh2
) {
8198 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE
);
8201 TEST_P(HttpNetworkTransactionTest
, BypassHostCacheOnRefresh3
) {
8202 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE
);
8205 // Make sure we can handle an error when writing the request.
8206 TEST_P(HttpNetworkTransactionTest
, RequestWriteError
) {
8207 HttpRequestInfo request
;
8208 request
.method
= "GET";
8209 request
.url
= GURL("http://www.foo.com/");
8210 request
.load_flags
= 0;
8212 MockWrite write_failure
[] = {
8213 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
8215 StaticSocketDataProvider
data(NULL
, 0,
8216 write_failure
, arraysize(write_failure
));
8217 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8218 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8220 TestCompletionCallback callback
;
8222 scoped_ptr
<HttpTransaction
> trans(
8223 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8225 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8226 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8228 rv
= callback
.WaitForResult();
8229 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
8232 // Check that a connection closed after the start of the headers finishes ok.
8233 TEST_P(HttpNetworkTransactionTest
, ConnectionClosedAfterStartOfHeaders
) {
8234 HttpRequestInfo request
;
8235 request
.method
= "GET";
8236 request
.url
= GURL("http://www.foo.com/");
8237 request
.load_flags
= 0;
8239 MockRead data_reads
[] = {
8240 MockRead("HTTP/1."),
8241 MockRead(SYNCHRONOUS
, OK
),
8244 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8245 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8246 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8248 TestCompletionCallback callback
;
8250 scoped_ptr
<HttpTransaction
> trans(
8251 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8253 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8256 rv
= callback
.WaitForResult();
8259 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8260 ASSERT_TRUE(response
!= NULL
);
8262 EXPECT_TRUE(response
->headers
.get() != NULL
);
8263 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8265 std::string response_data
;
8266 rv
= ReadTransaction(trans
.get(), &response_data
);
8268 EXPECT_EQ("", response_data
);
8271 // Make sure that a dropped connection while draining the body for auth
8272 // restart does the right thing.
8273 TEST_P(HttpNetworkTransactionTest
, DrainResetOK
) {
8274 HttpRequestInfo request
;
8275 request
.method
= "GET";
8276 request
.url
= GURL("http://www.example.org/");
8277 request
.load_flags
= 0;
8279 MockWrite data_writes1
[] = {
8281 "GET / HTTP/1.1\r\n"
8282 "Host: www.example.org\r\n"
8283 "Connection: keep-alive\r\n\r\n"),
8286 MockRead data_reads1
[] = {
8287 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
8288 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
8289 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8290 MockRead("Content-Length: 14\r\n\r\n"),
8292 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
8295 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8296 data_writes1
, arraysize(data_writes1
));
8297 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8299 // After calling trans->RestartWithAuth(), this is the request we should
8300 // be issuing -- the final header line contains the credentials.
8301 MockWrite data_writes2
[] = {
8303 "GET / HTTP/1.1\r\n"
8304 "Host: www.example.org\r\n"
8305 "Connection: keep-alive\r\n"
8306 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
8309 // Lastly, the server responds with the actual content.
8310 MockRead data_reads2
[] = {
8311 MockRead("HTTP/1.1 200 OK\r\n"),
8312 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8313 MockRead("Content-Length: 100\r\n\r\n"),
8314 MockRead(SYNCHRONOUS
, OK
),
8317 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8318 data_writes2
, arraysize(data_writes2
));
8319 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8320 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8322 TestCompletionCallback callback1
;
8324 scoped_ptr
<HttpTransaction
> trans(
8325 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8327 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8328 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8330 rv
= callback1
.WaitForResult();
8333 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8334 ASSERT_TRUE(response
!= NULL
);
8335 EXPECT_TRUE(CheckBasicServerAuth(response
->auth_challenge
.get()));
8337 TestCompletionCallback callback2
;
8339 rv
= trans
->RestartWithAuth(
8340 AuthCredentials(kFoo
, kBar
), callback2
.callback());
8341 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8343 rv
= callback2
.WaitForResult();
8346 response
= trans
->GetResponseInfo();
8347 ASSERT_TRUE(response
!= NULL
);
8348 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8349 EXPECT_EQ(100, response
->headers
->GetContentLength());
8352 // Test HTTPS connections going through a proxy that sends extra data.
8353 TEST_P(HttpNetworkTransactionTest
, HTTPSViaProxyWithExtraData
) {
8354 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
8356 HttpRequestInfo request
;
8357 request
.method
= "GET";
8358 request
.url
= GURL("https://www.example.org/");
8359 request
.load_flags
= 0;
8361 MockRead proxy_reads
[] = {
8362 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
8363 MockRead(SYNCHRONOUS
, OK
)
8366 StaticSocketDataProvider
data(proxy_reads
, arraysize(proxy_reads
), NULL
, 0);
8367 SSLSocketDataProvider
ssl(ASYNC
, OK
);
8369 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8370 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
8372 TestCompletionCallback callback
;
8374 session_deps_
.socket_factory
->ResetNextMockIndexes();
8376 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8377 scoped_ptr
<HttpTransaction
> trans(
8378 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8380 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8381 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8383 rv
= callback
.WaitForResult();
8384 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED
, rv
);
8387 TEST_P(HttpNetworkTransactionTest
, LargeContentLengthThenClose
) {
8388 HttpRequestInfo request
;
8389 request
.method
= "GET";
8390 request
.url
= GURL("http://www.example.org/");
8391 request
.load_flags
= 0;
8393 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8394 scoped_ptr
<HttpTransaction
> trans(
8395 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8397 MockRead data_reads
[] = {
8398 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
8399 MockRead(SYNCHRONOUS
, OK
),
8402 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8403 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8405 TestCompletionCallback callback
;
8407 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8408 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8410 EXPECT_EQ(OK
, callback
.WaitForResult());
8412 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8413 ASSERT_TRUE(response
!= NULL
);
8415 EXPECT_TRUE(response
->headers
.get() != NULL
);
8416 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8418 std::string response_data
;
8419 rv
= ReadTransaction(trans
.get(), &response_data
);
8420 EXPECT_EQ(ERR_CONTENT_LENGTH_MISMATCH
, rv
);
8423 TEST_P(HttpNetworkTransactionTest
, UploadFileSmallerThanLength
) {
8424 base::FilePath temp_file_path
;
8425 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path
));
8426 const uint64 kFakeSize
= 100000; // file is actually blank
8427 UploadFileElementReader::ScopedOverridingContentLengthForTests
8428 overriding_content_length(kFakeSize
);
8430 ScopedVector
<UploadElementReader
> element_readers
;
8431 element_readers
.push_back(
8432 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8433 temp_file_path
, 0, kuint64max
, base::Time()));
8434 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8436 HttpRequestInfo request
;
8437 request
.method
= "POST";
8438 request
.url
= GURL("http://www.example.org/upload");
8439 request
.upload_data_stream
= &upload_data_stream
;
8440 request
.load_flags
= 0;
8442 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8443 scoped_ptr
<HttpTransaction
> trans(
8444 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8446 MockRead data_reads
[] = {
8447 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8448 MockRead("hello world"),
8449 MockRead(SYNCHRONOUS
, OK
),
8451 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8452 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8454 TestCompletionCallback callback
;
8456 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8457 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8459 rv
= callback
.WaitForResult();
8462 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8463 ASSERT_TRUE(response
!= NULL
);
8465 EXPECT_TRUE(response
->headers
.get() != NULL
);
8466 EXPECT_EQ("HTTP/1.0 200 OK", response
->headers
->GetStatusLine());
8468 std::string response_data
;
8469 rv
= ReadTransaction(trans
.get(), &response_data
);
8471 EXPECT_EQ("hello world", response_data
);
8473 base::DeleteFile(temp_file_path
, false);
8476 TEST_P(HttpNetworkTransactionTest
, UploadUnreadableFile
) {
8477 base::FilePath temp_file
;
8478 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file
));
8479 std::string
temp_file_content("Unreadable file.");
8480 ASSERT_TRUE(base::WriteFile(temp_file
, temp_file_content
.c_str(),
8481 temp_file_content
.length()));
8482 ASSERT_TRUE(base::MakeFileUnreadable(temp_file
));
8484 ScopedVector
<UploadElementReader
> element_readers
;
8485 element_readers
.push_back(
8486 new UploadFileElementReader(base::ThreadTaskRunnerHandle::Get().get(),
8487 temp_file
, 0, kuint64max
, base::Time()));
8488 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8490 HttpRequestInfo request
;
8491 request
.method
= "POST";
8492 request
.url
= GURL("http://www.example.org/upload");
8493 request
.upload_data_stream
= &upload_data_stream
;
8494 request
.load_flags
= 0;
8496 // If we try to upload an unreadable file, the transaction should fail.
8497 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8498 scoped_ptr
<HttpTransaction
> trans(
8499 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8501 StaticSocketDataProvider
data(NULL
, 0, NULL
, 0);
8502 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8504 TestCompletionCallback callback
;
8506 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8507 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8509 rv
= callback
.WaitForResult();
8510 EXPECT_EQ(ERR_ACCESS_DENIED
, rv
);
8512 base::DeleteFile(temp_file
, false);
8515 TEST_P(HttpNetworkTransactionTest
, CancelDuringInitRequestBody
) {
8516 class FakeUploadElementReader
: public UploadElementReader
{
8518 FakeUploadElementReader() {}
8519 ~FakeUploadElementReader() override
{}
8521 const CompletionCallback
& callback() const { return callback_
; }
8523 // UploadElementReader overrides:
8524 int Init(const CompletionCallback
& callback
) override
{
8525 callback_
= callback
;
8526 return ERR_IO_PENDING
;
8528 uint64
GetContentLength() const override
{ return 0; }
8529 uint64
BytesRemaining() const override
{ return 0; }
8530 int Read(IOBuffer
* buf
,
8532 const CompletionCallback
& callback
) override
{
8537 CompletionCallback callback_
;
8540 FakeUploadElementReader
* fake_reader
= new FakeUploadElementReader
;
8541 ScopedVector
<UploadElementReader
> element_readers
;
8542 element_readers
.push_back(fake_reader
);
8543 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
8545 HttpRequestInfo request
;
8546 request
.method
= "POST";
8547 request
.url
= GURL("http://www.example.org/upload");
8548 request
.upload_data_stream
= &upload_data_stream
;
8549 request
.load_flags
= 0;
8551 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8552 scoped_ptr
<HttpTransaction
> trans(
8553 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8555 StaticSocketDataProvider data
;
8556 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8558 TestCompletionCallback callback
;
8559 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8560 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8561 base::MessageLoop::current()->RunUntilIdle();
8563 // Transaction is pending on request body initialization.
8564 ASSERT_FALSE(fake_reader
->callback().is_null());
8566 // Return Init()'s result after the transaction gets destroyed.
8568 fake_reader
->callback().Run(OK
); // Should not crash.
8571 // Tests that changes to Auth realms are treated like auth rejections.
8572 TEST_P(HttpNetworkTransactionTest
, ChangeAuthRealms
) {
8574 HttpRequestInfo request
;
8575 request
.method
= "GET";
8576 request
.url
= GURL("http://www.example.org/");
8577 request
.load_flags
= 0;
8579 // First transaction will request a resource and receive a Basic challenge
8580 // with realm="first_realm".
8581 MockWrite data_writes1
[] = {
8583 "GET / HTTP/1.1\r\n"
8584 "Host: www.example.org\r\n"
8585 "Connection: keep-alive\r\n"
8588 MockRead data_reads1
[] = {
8589 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8590 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8594 // After calling trans->RestartWithAuth(), provide an Authentication header
8595 // for first_realm. The server will reject and provide a challenge with
8597 MockWrite data_writes2
[] = {
8599 "GET / HTTP/1.1\r\n"
8600 "Host: www.example.org\r\n"
8601 "Connection: keep-alive\r\n"
8602 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
8605 MockRead data_reads2
[] = {
8606 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8607 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
8611 // This again fails, and goes back to first_realm. Make sure that the
8612 // entry is removed from cache.
8613 MockWrite data_writes3
[] = {
8615 "GET / HTTP/1.1\r\n"
8616 "Host: www.example.org\r\n"
8617 "Connection: keep-alive\r\n"
8618 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
8621 MockRead data_reads3
[] = {
8622 MockRead("HTTP/1.1 401 Unauthorized\r\n"
8623 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
8627 // Try one last time (with the correct password) and get the resource.
8628 MockWrite data_writes4
[] = {
8630 "GET / HTTP/1.1\r\n"
8631 "Host: www.example.org\r\n"
8632 "Connection: keep-alive\r\n"
8633 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
8636 MockRead data_reads4
[] = {
8637 MockRead("HTTP/1.1 200 OK\r\n"
8638 "Content-Type: text/html; charset=iso-8859-1\r\n"
8639 "Content-Length: 5\r\n"
8644 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
8645 data_writes1
, arraysize(data_writes1
));
8646 StaticSocketDataProvider
data2(data_reads2
, arraysize(data_reads2
),
8647 data_writes2
, arraysize(data_writes2
));
8648 StaticSocketDataProvider
data3(data_reads3
, arraysize(data_reads3
),
8649 data_writes3
, arraysize(data_writes3
));
8650 StaticSocketDataProvider
data4(data_reads4
, arraysize(data_reads4
),
8651 data_writes4
, arraysize(data_writes4
));
8652 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
8653 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
8654 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
8655 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
8657 TestCompletionCallback callback1
;
8659 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8660 scoped_ptr
<HttpTransaction
> trans(
8661 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8663 // Issue the first request with Authorize headers. There should be a
8664 // password prompt for first_realm waiting to be filled in after the
8665 // transaction completes.
8666 int rv
= trans
->Start(&request
, callback1
.callback(), BoundNetLog());
8667 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8668 rv
= callback1
.WaitForResult();
8670 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8671 ASSERT_TRUE(response
!= NULL
);
8672 const AuthChallengeInfo
* challenge
= response
->auth_challenge
.get();
8673 ASSERT_FALSE(challenge
== NULL
);
8674 EXPECT_FALSE(challenge
->is_proxy
);
8675 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8676 EXPECT_EQ("first_realm", challenge
->realm
);
8677 EXPECT_EQ("basic", challenge
->scheme
);
8679 // Issue the second request with an incorrect password. There should be a
8680 // password prompt for second_realm waiting to be filled in after the
8681 // transaction completes.
8682 TestCompletionCallback callback2
;
8683 rv
= trans
->RestartWithAuth(
8684 AuthCredentials(kFirst
, kBaz
), callback2
.callback());
8685 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8686 rv
= callback2
.WaitForResult();
8688 response
= trans
->GetResponseInfo();
8689 ASSERT_TRUE(response
!= NULL
);
8690 challenge
= response
->auth_challenge
.get();
8691 ASSERT_FALSE(challenge
== NULL
);
8692 EXPECT_FALSE(challenge
->is_proxy
);
8693 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8694 EXPECT_EQ("second_realm", challenge
->realm
);
8695 EXPECT_EQ("basic", challenge
->scheme
);
8697 // Issue the third request with another incorrect password. There should be
8698 // a password prompt for first_realm waiting to be filled in. If the password
8699 // prompt is not present, it indicates that the HttpAuthCacheEntry for
8700 // first_realm was not correctly removed.
8701 TestCompletionCallback callback3
;
8702 rv
= trans
->RestartWithAuth(
8703 AuthCredentials(kSecond
, kFou
), callback3
.callback());
8704 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8705 rv
= callback3
.WaitForResult();
8707 response
= trans
->GetResponseInfo();
8708 ASSERT_TRUE(response
!= NULL
);
8709 challenge
= response
->auth_challenge
.get();
8710 ASSERT_FALSE(challenge
== NULL
);
8711 EXPECT_FALSE(challenge
->is_proxy
);
8712 EXPECT_EQ("www.example.org:80", challenge
->challenger
.ToString());
8713 EXPECT_EQ("first_realm", challenge
->realm
);
8714 EXPECT_EQ("basic", challenge
->scheme
);
8716 // Issue the fourth request with the correct password and username.
8717 TestCompletionCallback callback4
;
8718 rv
= trans
->RestartWithAuth(
8719 AuthCredentials(kFirst
, kBar
), callback4
.callback());
8720 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8721 rv
= callback4
.WaitForResult();
8723 response
= trans
->GetResponseInfo();
8724 ASSERT_TRUE(response
!= NULL
);
8725 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
8728 TEST_P(HttpNetworkTransactionTest
, HonorAlternativeServiceHeader
) {
8729 session_deps_
.next_protos
= SpdyNextProtos();
8730 session_deps_
.use_alternate_protocols
= true;
8732 std::string alternative_service_http_header
=
8733 GetAlternativeServiceHttpHeader();
8735 MockRead data_reads
[] = {
8736 MockRead("HTTP/1.1 200 OK\r\n"),
8737 MockRead(alternative_service_http_header
.c_str()),
8739 MockRead("hello world"),
8740 MockRead(SYNCHRONOUS
, OK
),
8743 HttpRequestInfo request
;
8744 request
.method
= "GET";
8745 request
.url
= GURL("http://www.example.org/");
8746 request
.load_flags
= 0;
8748 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8750 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8752 TestCompletionCallback callback
;
8754 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8755 scoped_ptr
<HttpTransaction
> trans(
8756 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8758 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8759 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8761 HostPortPair
http_host_port_pair("www.example.org", 80);
8762 HttpServerProperties
& http_server_properties
=
8763 *session
->http_server_properties();
8764 AlternativeServiceVector alternative_service_vector
=
8765 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8766 EXPECT_TRUE(alternative_service_vector
.empty());
8768 EXPECT_EQ(OK
, callback
.WaitForResult());
8770 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8771 ASSERT_TRUE(response
!= NULL
);
8772 ASSERT_TRUE(response
->headers
.get() != NULL
);
8773 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8774 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8775 EXPECT_FALSE(response
->was_npn_negotiated
);
8777 std::string response_data
;
8778 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8779 EXPECT_EQ("hello world", response_data
);
8781 alternative_service_vector
=
8782 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8783 ASSERT_EQ(1u, alternative_service_vector
.size());
8784 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8785 alternative_service_vector
[0].protocol
);
8786 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8787 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8790 TEST_P(HttpNetworkTransactionTest
, HonorMultipleAlternativeServiceHeader
) {
8791 session_deps_
.next_protos
= SpdyNextProtos();
8792 session_deps_
.use_alternate_protocols
= true;
8794 MockRead data_reads
[] = {
8795 MockRead("HTTP/1.1 200 OK\r\n"),
8796 MockRead("Alt-Svc: "),
8797 MockRead(GetAlternateProtocolFromParam()),
8798 MockRead("=\"www.example.com:443\";p=1.0,"),
8799 MockRead("quic=\":1234\"\r\n\r\n"),
8800 MockRead("hello world"),
8801 MockRead(SYNCHRONOUS
, OK
),
8804 HttpRequestInfo request
;
8805 request
.method
= "GET";
8806 request
.url
= GURL("http://www.example.org/");
8807 request
.load_flags
= 0;
8809 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8811 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8813 TestCompletionCallback callback
;
8815 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8816 scoped_ptr
<HttpTransaction
> trans(
8817 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8819 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8820 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8822 HostPortPair
http_host_port_pair("www.example.org", 80);
8823 HttpServerProperties
& http_server_properties
=
8824 *session
->http_server_properties();
8825 AlternativeServiceVector alternative_service_vector
=
8826 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8827 EXPECT_TRUE(alternative_service_vector
.empty());
8829 EXPECT_EQ(OK
, callback
.WaitForResult());
8831 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8832 ASSERT_TRUE(response
!= NULL
);
8833 ASSERT_TRUE(response
->headers
.get() != NULL
);
8834 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8835 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8836 EXPECT_FALSE(response
->was_npn_negotiated
);
8838 std::string response_data
;
8839 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8840 EXPECT_EQ("hello world", response_data
);
8842 alternative_service_vector
=
8843 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8844 ASSERT_EQ(2u, alternative_service_vector
.size());
8845 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8846 alternative_service_vector
[0].protocol
);
8847 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
8848 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8849 EXPECT_EQ(QUIC
, alternative_service_vector
[1].protocol
);
8850 EXPECT_EQ("www.example.org", alternative_service_vector
[1].host
);
8851 EXPECT_EQ(1234, alternative_service_vector
[1].port
);
8854 TEST_P(HttpNetworkTransactionTest
, HonorAlternateProtocolHeader
) {
8855 session_deps_
.next_protos
= SpdyNextProtos();
8856 session_deps_
.use_alternate_protocols
= true;
8858 std::string alternate_protocol_http_header
=
8859 GetAlternateProtocolHttpHeader();
8861 MockRead data_reads
[] = {
8862 MockRead("HTTP/1.1 200 OK\r\n"),
8863 MockRead(alternate_protocol_http_header
.c_str()),
8865 MockRead("hello world"),
8866 MockRead(SYNCHRONOUS
, OK
),
8869 HttpRequestInfo request
;
8870 request
.method
= "GET";
8871 request
.url
= GURL("http://www.example.org/");
8872 request
.load_flags
= 0;
8874 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8876 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8878 TestCompletionCallback callback
;
8880 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8881 scoped_ptr
<HttpTransaction
> trans(
8882 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8884 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8885 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8887 HostPortPair
http_host_port_pair("www.example.org", 80);
8888 HttpServerProperties
& http_server_properties
=
8889 *session
->http_server_properties();
8890 AlternativeServiceVector alternative_service_vector
=
8891 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8892 EXPECT_TRUE(alternative_service_vector
.empty());
8894 EXPECT_EQ(OK
, callback
.WaitForResult());
8896 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8897 ASSERT_TRUE(response
!= NULL
);
8898 ASSERT_TRUE(response
->headers
.get() != NULL
);
8899 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8900 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8901 EXPECT_FALSE(response
->was_npn_negotiated
);
8903 std::string response_data
;
8904 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8905 EXPECT_EQ("hello world", response_data
);
8907 alternative_service_vector
=
8908 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8909 ASSERT_EQ(1u, alternative_service_vector
.size());
8910 EXPECT_EQ(443, alternative_service_vector
[0].port
);
8911 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
8912 alternative_service_vector
[0].protocol
);
8915 TEST_P(HttpNetworkTransactionTest
, EmptyAlternateProtocolHeader
) {
8916 session_deps_
.next_protos
= SpdyNextProtos();
8917 session_deps_
.use_alternate_protocols
= true;
8919 MockRead data_reads
[] = {
8920 MockRead("HTTP/1.1 200 OK\r\n"),
8921 MockRead("Alternate-Protocol: \r\n\r\n"),
8922 MockRead("hello world"),
8923 MockRead(SYNCHRONOUS
, OK
),
8926 HttpRequestInfo request
;
8927 request
.method
= "GET";
8928 request
.url
= GURL("http://www.example.org/");
8929 request
.load_flags
= 0;
8931 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
8933 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
8935 TestCompletionCallback callback
;
8937 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
8939 HostPortPair
http_host_port_pair("www.example.org", 80);
8940 HttpServerProperties
& http_server_properties
=
8941 *session
->http_server_properties();
8942 AlternativeService
alternative_service(QUIC
, "", 80);
8943 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
8944 http_server_properties
.SetAlternativeService(
8945 http_host_port_pair
, alternative_service
, 1.0, expiration
);
8947 AlternativeServiceVector alternative_service_vector
=
8948 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8949 ASSERT_EQ(1u, alternative_service_vector
.size());
8950 EXPECT_EQ(QUIC
, alternative_service_vector
[0].protocol
);
8952 scoped_ptr
<HttpTransaction
> trans(
8953 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
8955 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
8956 EXPECT_EQ(ERR_IO_PENDING
, rv
);
8958 EXPECT_EQ(OK
, callback
.WaitForResult());
8960 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
8961 ASSERT_TRUE(response
!= NULL
);
8962 ASSERT_TRUE(response
->headers
.get() != NULL
);
8963 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
8964 EXPECT_FALSE(response
->was_fetched_via_spdy
);
8965 EXPECT_FALSE(response
->was_npn_negotiated
);
8967 std::string response_data
;
8968 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
8969 EXPECT_EQ("hello world", response_data
);
8971 alternative_service_vector
=
8972 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
8973 EXPECT_TRUE(alternative_service_vector
.empty());
8976 TEST_P(HttpNetworkTransactionTest
, AltSvcOverwritesAlternateProtocol
) {
8977 session_deps_
.next_protos
= SpdyNextProtos();
8978 session_deps_
.use_alternate_protocols
= true;
8980 std::string alternative_service_http_header
=
8981 GetAlternativeServiceHttpHeader();
8982 std::string alternate_protocol_http_header
= GetAlternateProtocolHttpHeader();
8984 MockRead data_reads
[] = {
8985 MockRead("HTTP/1.1 200 OK\r\n"),
8986 MockRead(alternative_service_http_header
.c_str()),
8987 MockRead(alternate_protocol_http_header
.c_str()),
8989 MockRead("hello world"),
8990 MockRead(SYNCHRONOUS
, OK
),
8993 HttpRequestInfo request
;
8994 request
.method
= "GET";
8995 request
.url
= GURL("http://www.example.org/");
8996 request
.load_flags
= 0;
8998 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
9000 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9002 TestCompletionCallback callback
;
9004 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9005 scoped_ptr
<HttpTransaction
> trans(
9006 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9008 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9009 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9011 HostPortPair
http_host_port_pair("www.example.org", 80);
9012 HttpServerProperties
& http_server_properties
=
9013 *session
->http_server_properties();
9014 AlternativeServiceVector alternative_service_vector
=
9015 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9016 EXPECT_TRUE(alternative_service_vector
.empty());
9018 EXPECT_EQ(OK
, callback
.WaitForResult());
9020 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9021 ASSERT_TRUE(response
!= NULL
);
9022 ASSERT_TRUE(response
->headers
.get() != NULL
);
9023 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9024 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9025 EXPECT_FALSE(response
->was_npn_negotiated
);
9027 std::string response_data
;
9028 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9029 EXPECT_EQ("hello world", response_data
);
9031 alternative_service_vector
=
9032 http_server_properties
.GetAlternativeServices(http_host_port_pair
);
9033 ASSERT_EQ(1u, alternative_service_vector
.size());
9034 EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()),
9035 alternative_service_vector
[0].protocol
);
9036 EXPECT_EQ("www.example.com", alternative_service_vector
[0].host
);
9037 EXPECT_EQ(443, alternative_service_vector
[0].port
);
9040 TEST_P(HttpNetworkTransactionTest
,
9041 MarkBrokenAlternateProtocolAndFallback
) {
9042 session_deps_
.use_alternate_protocols
= true;
9044 HttpRequestInfo request
;
9045 request
.method
= "GET";
9046 request
.url
= GURL("http://www.example.org/");
9047 request
.load_flags
= 0;
9049 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9050 StaticSocketDataProvider first_data
;
9051 first_data
.set_connect_data(mock_connect
);
9052 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9054 MockRead data_reads
[] = {
9055 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9056 MockRead("hello world"),
9057 MockRead(ASYNC
, OK
),
9059 StaticSocketDataProvider
second_data(
9060 data_reads
, arraysize(data_reads
), NULL
, 0);
9061 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9063 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9065 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9066 session
->http_server_properties();
9067 const HostPortPair host_port_pair
= HostPortPair::FromURL(request
.url
);
9068 // Port must be < 1024, or the header will be ignored (since initial port was
9069 // port 80 (another restricted port).
9070 const AlternativeService
alternative_service(
9071 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9072 666); // Port is ignored by MockConnect anyway.
9073 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9074 http_server_properties
->SetAlternativeService(
9075 host_port_pair
, alternative_service
, 1.0, expiration
);
9077 scoped_ptr
<HttpTransaction
> trans(
9078 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9079 TestCompletionCallback callback
;
9081 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9082 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9083 EXPECT_EQ(OK
, callback
.WaitForResult());
9085 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9086 ASSERT_TRUE(response
!= NULL
);
9087 ASSERT_TRUE(response
->headers
.get() != NULL
);
9088 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9090 std::string response_data
;
9091 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9092 EXPECT_EQ("hello world", response_data
);
9094 const AlternativeServiceVector alternative_service_vector
=
9095 http_server_properties
->GetAlternativeServices(host_port_pair
);
9096 ASSERT_EQ(1u, alternative_service_vector
.size());
9097 EXPECT_EQ(alternative_service
, alternative_service_vector
[0]);
9098 EXPECT_TRUE(http_server_properties
->IsAlternativeServiceBroken(
9099 alternative_service_vector
[0]));
9102 TEST_P(HttpNetworkTransactionTest
,
9103 AlternateProtocolPortRestrictedBlocked
) {
9104 // Ensure that we're not allowed to redirect traffic via an alternate
9105 // protocol to an unrestricted (port >= 1024) when the original traffic was
9106 // on a restricted port (port < 1024). Ensure that we can redirect in all
9108 session_deps_
.use_alternate_protocols
= true;
9110 HttpRequestInfo restricted_port_request
;
9111 restricted_port_request
.method
= "GET";
9112 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9113 restricted_port_request
.load_flags
= 0;
9115 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9116 StaticSocketDataProvider first_data
;
9117 first_data
.set_connect_data(mock_connect
);
9118 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9120 MockRead data_reads
[] = {
9121 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9122 MockRead("hello world"),
9123 MockRead(ASYNC
, OK
),
9125 StaticSocketDataProvider
second_data(
9126 data_reads
, arraysize(data_reads
), NULL
, 0);
9127 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9129 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9131 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9132 session
->http_server_properties();
9133 const int kUnrestrictedAlternatePort
= 1024;
9134 AlternativeService
alternative_service(
9135 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9136 kUnrestrictedAlternatePort
);
9137 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9138 http_server_properties
->SetAlternativeService(
9139 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9142 scoped_ptr
<HttpTransaction
> trans(
9143 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9144 TestCompletionCallback callback
;
9146 int rv
= trans
->Start(
9147 &restricted_port_request
,
9148 callback
.callback(), BoundNetLog());
9149 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9150 // Invalid change to unrestricted port should fail.
9151 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback
.WaitForResult());
9154 TEST_P(HttpNetworkTransactionTest
,
9155 AlternateProtocolPortRestrictedPermitted
) {
9156 // Ensure that we're allowed to redirect traffic via an alternate
9157 // protocol to an unrestricted (port >= 1024) when the original traffic was
9158 // on a restricted port (port < 1024) if we set
9159 // enable_user_alternate_protocol_ports.
9161 session_deps_
.use_alternate_protocols
= true;
9162 session_deps_
.enable_user_alternate_protocol_ports
= true;
9164 HttpRequestInfo restricted_port_request
;
9165 restricted_port_request
.method
= "GET";
9166 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9167 restricted_port_request
.load_flags
= 0;
9169 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9170 StaticSocketDataProvider first_data
;
9171 first_data
.set_connect_data(mock_connect
);
9172 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9174 MockRead data_reads
[] = {
9175 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9176 MockRead("hello world"),
9177 MockRead(ASYNC
, OK
),
9179 StaticSocketDataProvider
second_data(
9180 data_reads
, arraysize(data_reads
), NULL
, 0);
9181 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9183 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9185 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9186 session
->http_server_properties();
9187 const int kUnrestrictedAlternatePort
= 1024;
9188 AlternativeService
alternative_service(
9189 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9190 kUnrestrictedAlternatePort
);
9191 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9192 http_server_properties
->SetAlternativeService(
9193 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9196 scoped_ptr
<HttpTransaction
> trans(
9197 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9198 TestCompletionCallback callback
;
9200 EXPECT_EQ(ERR_IO_PENDING
, trans
->Start(
9201 &restricted_port_request
,
9202 callback
.callback(), BoundNetLog()));
9203 // Change to unrestricted port should succeed.
9204 EXPECT_EQ(OK
, callback
.WaitForResult());
9207 TEST_P(HttpNetworkTransactionTest
,
9208 AlternateProtocolPortRestrictedAllowed
) {
9209 // Ensure that we're not allowed to redirect traffic via an alternate
9210 // protocol to an unrestricted (port >= 1024) when the original traffic was
9211 // on a restricted port (port < 1024). Ensure that we can redirect in all
9213 session_deps_
.use_alternate_protocols
= true;
9215 HttpRequestInfo restricted_port_request
;
9216 restricted_port_request
.method
= "GET";
9217 restricted_port_request
.url
= GURL("http://www.example.org:1023/");
9218 restricted_port_request
.load_flags
= 0;
9220 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9221 StaticSocketDataProvider first_data
;
9222 first_data
.set_connect_data(mock_connect
);
9223 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
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
second_data(
9231 data_reads
, arraysize(data_reads
), NULL
, 0);
9232 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9234 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9236 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9237 session
->http_server_properties();
9238 const int kRestrictedAlternatePort
= 80;
9239 AlternativeService
alternative_service(
9240 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9241 kRestrictedAlternatePort
);
9242 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9243 http_server_properties
->SetAlternativeService(
9244 HostPortPair::FromURL(restricted_port_request
.url
), alternative_service
,
9247 scoped_ptr
<HttpTransaction
> trans(
9248 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9249 TestCompletionCallback callback
;
9251 int rv
= trans
->Start(
9252 &restricted_port_request
,
9253 callback
.callback(), BoundNetLog());
9254 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9255 // Valid change to restricted port should pass.
9256 EXPECT_EQ(OK
, callback
.WaitForResult());
9259 TEST_P(HttpNetworkTransactionTest
,
9260 AlternateProtocolPortUnrestrictedAllowed1
) {
9261 // Ensure that we're not allowed to redirect traffic via an alternate
9262 // protocol to an unrestricted (port >= 1024) when the original traffic was
9263 // on a restricted port (port < 1024). Ensure that we can redirect in all
9265 session_deps_
.use_alternate_protocols
= true;
9267 HttpRequestInfo unrestricted_port_request
;
9268 unrestricted_port_request
.method
= "GET";
9269 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9270 unrestricted_port_request
.load_flags
= 0;
9272 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9273 StaticSocketDataProvider first_data
;
9274 first_data
.set_connect_data(mock_connect
);
9275 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9277 MockRead data_reads
[] = {
9278 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9279 MockRead("hello world"),
9280 MockRead(ASYNC
, OK
),
9282 StaticSocketDataProvider
second_data(
9283 data_reads
, arraysize(data_reads
), NULL
, 0);
9284 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9286 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9288 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9289 session
->http_server_properties();
9290 const int kRestrictedAlternatePort
= 80;
9291 AlternativeService
alternative_service(
9292 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9293 kRestrictedAlternatePort
);
9294 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9295 http_server_properties
->SetAlternativeService(
9296 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9299 scoped_ptr
<HttpTransaction
> trans(
9300 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9301 TestCompletionCallback callback
;
9303 int rv
= trans
->Start(
9304 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9305 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9306 // Valid change to restricted port should pass.
9307 EXPECT_EQ(OK
, callback
.WaitForResult());
9310 TEST_P(HttpNetworkTransactionTest
,
9311 AlternateProtocolPortUnrestrictedAllowed2
) {
9312 // Ensure that we're not allowed to redirect traffic via an alternate
9313 // protocol to an unrestricted (port >= 1024) when the original traffic was
9314 // on a restricted port (port < 1024). Ensure that we can redirect in all
9316 session_deps_
.use_alternate_protocols
= true;
9318 HttpRequestInfo unrestricted_port_request
;
9319 unrestricted_port_request
.method
= "GET";
9320 unrestricted_port_request
.url
= GURL("http://www.example.org:1024/");
9321 unrestricted_port_request
.load_flags
= 0;
9323 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
9324 StaticSocketDataProvider first_data
;
9325 first_data
.set_connect_data(mock_connect
);
9326 session_deps_
.socket_factory
->AddSocketDataProvider(&first_data
);
9328 MockRead data_reads
[] = {
9329 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9330 MockRead("hello world"),
9331 MockRead(ASYNC
, OK
),
9333 StaticSocketDataProvider
second_data(
9334 data_reads
, arraysize(data_reads
), NULL
, 0);
9335 session_deps_
.socket_factory
->AddSocketDataProvider(&second_data
);
9337 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9339 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9340 session
->http_server_properties();
9341 const int kUnrestrictedAlternatePort
= 1025;
9342 AlternativeService
alternative_service(
9343 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9344 kUnrestrictedAlternatePort
);
9345 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9346 http_server_properties
->SetAlternativeService(
9347 HostPortPair::FromURL(unrestricted_port_request
.url
), alternative_service
,
9350 scoped_ptr
<HttpTransaction
> trans(
9351 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9352 TestCompletionCallback callback
;
9354 int rv
= trans
->Start(
9355 &unrestricted_port_request
, callback
.callback(), BoundNetLog());
9356 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9357 // Valid change to an unrestricted port should pass.
9358 EXPECT_EQ(OK
, callback
.WaitForResult());
9361 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolUnsafeBlocked
) {
9362 // Ensure that we're not allowed to redirect traffic via an alternate
9363 // protocol to an unsafe port, and that we resume the second
9364 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
9365 session_deps_
.use_alternate_protocols
= true;
9367 HttpRequestInfo request
;
9368 request
.method
= "GET";
9369 request
.url
= GURL("http://www.example.org/");
9370 request
.load_flags
= 0;
9372 // The alternate protocol request will error out before we attempt to connect,
9373 // so only the standard HTTP request will try to connect.
9374 MockRead data_reads
[] = {
9375 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
9376 MockRead("hello world"),
9377 MockRead(ASYNC
, OK
),
9379 StaticSocketDataProvider
data(
9380 data_reads
, arraysize(data_reads
), NULL
, 0);
9381 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
9383 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9385 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
9386 session
->http_server_properties();
9387 const int kUnsafePort
= 7;
9388 AlternativeService
alternative_service(
9389 AlternateProtocolFromNextProto(GetParam()), "www.example.org",
9391 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
9392 http_server_properties
->SetAlternativeService(
9393 HostPortPair::FromURL(request
.url
), alternative_service
, 1.0, expiration
);
9395 scoped_ptr
<HttpTransaction
> trans(
9396 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9397 TestCompletionCallback callback
;
9399 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9400 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9401 // The HTTP request should succeed.
9402 EXPECT_EQ(OK
, callback
.WaitForResult());
9404 // Disable alternate protocol before the asserts.
9405 // HttpStreamFactory::set_use_alternate_protocols(false);
9407 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9408 ASSERT_TRUE(response
!= NULL
);
9409 ASSERT_TRUE(response
->headers
.get() != NULL
);
9410 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9412 std::string response_data
;
9413 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9414 EXPECT_EQ("hello world", response_data
);
9417 TEST_P(HttpNetworkTransactionTest
, UseAlternateProtocolForNpnSpdy
) {
9418 session_deps_
.use_alternate_protocols
= true;
9419 session_deps_
.next_protos
= SpdyNextProtos();
9421 HttpRequestInfo request
;
9422 request
.method
= "GET";
9423 request
.url
= GURL("http://www.example.org/");
9424 request
.load_flags
= 0;
9426 std::string alternate_protocol_http_header
=
9427 GetAlternateProtocolHttpHeader();
9429 MockRead data_reads
[] = {
9430 MockRead("HTTP/1.1 200 OK\r\n"),
9431 MockRead(alternate_protocol_http_header
.c_str()),
9433 MockRead("hello world"),
9434 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9435 MockRead(ASYNC
, OK
)};
9437 StaticSocketDataProvider
first_transaction(
9438 data_reads
, arraysize(data_reads
), NULL
, 0);
9439 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9441 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9442 ssl
.SetNextProto(GetParam());
9443 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9444 ASSERT_TRUE(ssl
.cert
.get());
9445 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9447 scoped_ptr
<SpdyFrame
> req(
9448 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9449 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9451 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9452 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9453 MockRead spdy_reads
[] = {
9454 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9457 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9458 arraysize(spdy_writes
));
9459 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9461 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9462 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9464 hanging_non_alternate_protocol_socket
.set_connect_data(
9465 never_finishing_connect
);
9466 session_deps_
.socket_factory
->AddSocketDataProvider(
9467 &hanging_non_alternate_protocol_socket
);
9469 TestCompletionCallback callback
;
9471 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9472 scoped_ptr
<HttpTransaction
> trans(
9473 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9475 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9476 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9477 EXPECT_EQ(OK
, callback
.WaitForResult());
9479 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9480 ASSERT_TRUE(response
!= NULL
);
9481 ASSERT_TRUE(response
->headers
.get() != NULL
);
9482 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9484 std::string response_data
;
9485 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9486 EXPECT_EQ("hello world", response_data
);
9488 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9490 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9491 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9492 EXPECT_EQ(OK
, callback
.WaitForResult());
9494 response
= trans
->GetResponseInfo();
9495 ASSERT_TRUE(response
!= NULL
);
9496 ASSERT_TRUE(response
->headers
.get() != NULL
);
9497 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9498 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9499 EXPECT_TRUE(response
->was_npn_negotiated
);
9501 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9502 EXPECT_EQ("hello!", response_data
);
9505 TEST_P(HttpNetworkTransactionTest
, AlternateProtocolWithSpdyLateBinding
) {
9506 session_deps_
.use_alternate_protocols
= true;
9507 session_deps_
.next_protos
= SpdyNextProtos();
9509 HttpRequestInfo request
;
9510 request
.method
= "GET";
9511 request
.url
= GURL("http://www.example.org/");
9512 request
.load_flags
= 0;
9514 std::string alternate_protocol_http_header
=
9515 GetAlternateProtocolHttpHeader();
9517 MockRead data_reads
[] = {
9518 MockRead("HTTP/1.1 200 OK\r\n"),
9519 MockRead(alternate_protocol_http_header
.c_str()),
9521 MockRead("hello world"),
9522 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9523 MockRead(ASYNC
, OK
),
9526 StaticSocketDataProvider
first_transaction(
9527 data_reads
, arraysize(data_reads
), NULL
, 0);
9528 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
9529 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9531 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9532 StaticSocketDataProvider
hanging_socket(
9534 hanging_socket
.set_connect_data(never_finishing_connect
);
9535 // Socket 2 and 3 are the hanging Alternate-Protocol and
9536 // non-Alternate-Protocol jobs from the 2nd transaction.
9537 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9538 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9540 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9541 ssl
.SetNextProto(GetParam());
9542 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9543 ASSERT_TRUE(ssl
.cert
.get());
9544 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9546 scoped_ptr
<SpdyFrame
> req1(
9547 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9548 scoped_ptr
<SpdyFrame
> req2(
9549 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 3, LOWEST
, true));
9550 MockWrite spdy_writes
[] = {
9551 CreateMockWrite(*req1
, 0), CreateMockWrite(*req2
, 1),
9553 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9554 scoped_ptr
<SpdyFrame
> data1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9555 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
9556 scoped_ptr
<SpdyFrame
> data2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
9557 MockRead spdy_reads
[] = {
9558 CreateMockRead(*resp1
, 2),
9559 CreateMockRead(*data1
, 3),
9560 CreateMockRead(*resp2
, 4),
9561 CreateMockRead(*data2
, 5),
9562 MockRead(ASYNC
, 0, 6),
9565 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9566 arraysize(spdy_writes
));
9567 // Socket 4 is the successful Alternate-Protocol for transaction 3.
9568 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9570 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
9571 session_deps_
.socket_factory
->AddSocketDataProvider(&hanging_socket
);
9573 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9574 TestCompletionCallback callback1
;
9575 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
9577 int rv
= trans1
.Start(&request
, callback1
.callback(), BoundNetLog());
9578 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9579 EXPECT_EQ(OK
, callback1
.WaitForResult());
9581 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
9582 ASSERT_TRUE(response
!= NULL
);
9583 ASSERT_TRUE(response
->headers
.get() != NULL
);
9584 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9586 std::string response_data
;
9587 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
9588 EXPECT_EQ("hello world", response_data
);
9590 TestCompletionCallback callback2
;
9591 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
9592 rv
= trans2
.Start(&request
, callback2
.callback(), BoundNetLog());
9593 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9595 TestCompletionCallback callback3
;
9596 HttpNetworkTransaction
trans3(DEFAULT_PRIORITY
, session
.get());
9597 rv
= trans3
.Start(&request
, callback3
.callback(), BoundNetLog());
9598 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9600 EXPECT_EQ(OK
, callback2
.WaitForResult());
9601 EXPECT_EQ(OK
, callback3
.WaitForResult());
9603 response
= trans2
.GetResponseInfo();
9604 ASSERT_TRUE(response
!= NULL
);
9605 ASSERT_TRUE(response
->headers
.get() != NULL
);
9606 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9607 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9608 EXPECT_TRUE(response
->was_npn_negotiated
);
9609 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
9610 EXPECT_EQ("hello!", response_data
);
9612 response
= trans3
.GetResponseInfo();
9613 ASSERT_TRUE(response
!= NULL
);
9614 ASSERT_TRUE(response
->headers
.get() != NULL
);
9615 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9616 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9617 EXPECT_TRUE(response
->was_npn_negotiated
);
9618 ASSERT_EQ(OK
, ReadTransaction(&trans3
, &response_data
));
9619 EXPECT_EQ("hello!", response_data
);
9622 TEST_P(HttpNetworkTransactionTest
, StallAlternateProtocolForNpnSpdy
) {
9623 session_deps_
.use_alternate_protocols
= true;
9624 session_deps_
.next_protos
= SpdyNextProtos();
9626 HttpRequestInfo request
;
9627 request
.method
= "GET";
9628 request
.url
= GURL("http://www.example.org/");
9629 request
.load_flags
= 0;
9631 std::string alternate_protocol_http_header
=
9632 GetAlternateProtocolHttpHeader();
9634 MockRead data_reads
[] = {
9635 MockRead("HTTP/1.1 200 OK\r\n"),
9636 MockRead(alternate_protocol_http_header
.c_str()),
9638 MockRead("hello world"),
9639 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9640 MockRead(ASYNC
, OK
),
9643 StaticSocketDataProvider
first_transaction(
9644 data_reads
, arraysize(data_reads
), NULL
, 0);
9645 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9647 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9648 ssl
.SetNextProto(GetParam());
9649 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9651 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9652 StaticSocketDataProvider
hanging_alternate_protocol_socket(
9654 hanging_alternate_protocol_socket
.set_connect_data(
9655 never_finishing_connect
);
9656 session_deps_
.socket_factory
->AddSocketDataProvider(
9657 &hanging_alternate_protocol_socket
);
9659 // 2nd request is just a copy of the first one, over HTTP again.
9660 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9662 TestCompletionCallback callback
;
9664 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9665 scoped_ptr
<HttpTransaction
> trans(
9666 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9668 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9669 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9670 EXPECT_EQ(OK
, callback
.WaitForResult());
9672 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9673 ASSERT_TRUE(response
!= NULL
);
9674 ASSERT_TRUE(response
->headers
.get() != NULL
);
9675 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9677 std::string response_data
;
9678 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9679 EXPECT_EQ("hello world", response_data
);
9681 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9683 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9684 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9685 EXPECT_EQ(OK
, callback
.WaitForResult());
9687 response
= trans
->GetResponseInfo();
9688 ASSERT_TRUE(response
!= NULL
);
9689 ASSERT_TRUE(response
->headers
.get() != NULL
);
9690 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9691 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9692 EXPECT_FALSE(response
->was_npn_negotiated
);
9694 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9695 EXPECT_EQ("hello world", response_data
);
9698 class CapturingProxyResolver
: public ProxyResolver
{
9700 CapturingProxyResolver() {}
9701 ~CapturingProxyResolver() override
{}
9703 int GetProxyForURL(const GURL
& url
,
9705 const CompletionCallback
& callback
,
9706 RequestHandle
* request
,
9707 const BoundNetLog
& net_log
) override
{
9708 ProxyServer
proxy_server(ProxyServer::SCHEME_HTTP
,
9709 HostPortPair("myproxy", 80));
9710 results
->UseProxyServer(proxy_server
);
9711 resolved_
.push_back(url
);
9715 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
9717 LoadState
GetLoadState(RequestHandle request
) const override
{
9719 return LOAD_STATE_IDLE
;
9722 const std::vector
<GURL
>& resolved() const { return resolved_
; }
9725 std::vector
<GURL
> resolved_
;
9727 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver
);
9730 class CapturingProxyResolverFactory
: public ProxyResolverFactory
{
9732 explicit CapturingProxyResolverFactory(CapturingProxyResolver
* resolver
)
9733 : ProxyResolverFactory(false), resolver_(resolver
) {}
9735 int CreateProxyResolver(
9736 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
9737 scoped_ptr
<ProxyResolver
>* resolver
,
9738 const net::CompletionCallback
& callback
,
9739 scoped_ptr
<Request
>* request
) override
{
9740 resolver
->reset(new ForwardingProxyResolver(resolver_
));
9745 ProxyResolver
* resolver_
;
9748 TEST_P(HttpNetworkTransactionTest
,
9749 UseAlternateProtocolForTunneledNpnSpdy
) {
9750 session_deps_
.use_alternate_protocols
= true;
9751 session_deps_
.next_protos
= SpdyNextProtos();
9753 ProxyConfig proxy_config
;
9754 proxy_config
.set_auto_detect(true);
9755 proxy_config
.set_pac_url(GURL("http://fooproxyurl"));
9757 CapturingProxyResolver capturing_proxy_resolver
;
9758 session_deps_
.proxy_service
.reset(new ProxyService(
9759 new ProxyConfigServiceFixed(proxy_config
),
9761 new CapturingProxyResolverFactory(&capturing_proxy_resolver
)),
9764 session_deps_
.net_log
= &net_log
;
9766 HttpRequestInfo request
;
9767 request
.method
= "GET";
9768 request
.url
= GURL("http://www.example.org/");
9769 request
.load_flags
= 0;
9771 std::string alternate_protocol_http_header
=
9772 GetAlternateProtocolHttpHeader();
9774 MockRead data_reads
[] = {
9775 MockRead("HTTP/1.1 200 OK\r\n"),
9776 MockRead(alternate_protocol_http_header
.c_str()),
9778 MockRead("hello world"),
9779 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
9780 MockRead(ASYNC
, OK
),
9783 StaticSocketDataProvider
first_transaction(
9784 data_reads
, arraysize(data_reads
), NULL
, 0);
9785 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9787 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9788 ssl
.SetNextProto(GetParam());
9789 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9790 ASSERT_TRUE(ssl
.cert
.get());
9791 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9793 scoped_ptr
<SpdyFrame
> req(
9794 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9795 MockWrite spdy_writes
[] = {
9797 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9798 "Host: www.example.org\r\n"
9799 "Proxy-Connection: keep-alive\r\n\r\n"),
9800 CreateMockWrite(*req
, 2),
9803 const char kCONNECTResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
9805 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9806 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9807 MockRead spdy_reads
[] = {
9808 MockRead(ASYNC
, 1, kCONNECTResponse
),
9809 CreateMockRead(*resp
.get(), 3),
9810 CreateMockRead(*data
.get(), 4),
9811 MockRead(ASYNC
, ERR_IO_PENDING
, 5),
9814 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9815 arraysize(spdy_writes
));
9816 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9818 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
9819 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
9821 hanging_non_alternate_protocol_socket
.set_connect_data(
9822 never_finishing_connect
);
9823 session_deps_
.socket_factory
->AddSocketDataProvider(
9824 &hanging_non_alternate_protocol_socket
);
9826 TestCompletionCallback callback
;
9828 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9829 scoped_ptr
<HttpTransaction
> trans(
9830 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9832 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9833 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9834 EXPECT_EQ(OK
, callback
.WaitForResult());
9836 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9837 ASSERT_TRUE(response
!= NULL
);
9838 ASSERT_TRUE(response
->headers
.get() != NULL
);
9839 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9840 EXPECT_FALSE(response
->was_fetched_via_spdy
);
9841 EXPECT_FALSE(response
->was_npn_negotiated
);
9843 std::string response_data
;
9844 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9845 EXPECT_EQ("hello world", response_data
);
9847 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9849 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9850 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9851 EXPECT_EQ(OK
, callback
.WaitForResult());
9853 response
= trans
->GetResponseInfo();
9854 ASSERT_TRUE(response
!= NULL
);
9855 ASSERT_TRUE(response
->headers
.get() != NULL
);
9856 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9857 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9858 EXPECT_TRUE(response
->was_npn_negotiated
);
9860 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9861 EXPECT_EQ("hello!", response_data
);
9862 ASSERT_EQ(3u, capturing_proxy_resolver
.resolved().size());
9863 EXPECT_EQ("http://www.example.org/",
9864 capturing_proxy_resolver
.resolved()[0].spec());
9865 EXPECT_EQ("https://www.example.org/",
9866 capturing_proxy_resolver
.resolved()[1].spec());
9868 LoadTimingInfo load_timing_info
;
9869 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
9870 TestLoadTimingNotReusedWithPac(load_timing_info
,
9871 CONNECT_TIMING_HAS_SSL_TIMES
);
9874 TEST_P(HttpNetworkTransactionTest
,
9875 UseAlternateProtocolForNpnSpdyWithExistingSpdySession
) {
9876 session_deps_
.use_alternate_protocols
= true;
9877 session_deps_
.next_protos
= SpdyNextProtos();
9879 HttpRequestInfo request
;
9880 request
.method
= "GET";
9881 request
.url
= GURL("http://www.example.org/");
9882 request
.load_flags
= 0;
9884 std::string alternate_protocol_http_header
=
9885 GetAlternateProtocolHttpHeader();
9887 MockRead data_reads
[] = {
9888 MockRead("HTTP/1.1 200 OK\r\n"),
9889 MockRead(alternate_protocol_http_header
.c_str()),
9891 MockRead("hello world"),
9892 MockRead(ASYNC
, OK
),
9895 StaticSocketDataProvider
first_transaction(
9896 data_reads
, arraysize(data_reads
), NULL
, 0);
9897 session_deps_
.socket_factory
->AddSocketDataProvider(&first_transaction
);
9899 SSLSocketDataProvider
ssl(ASYNC
, OK
);
9900 ssl
.SetNextProto(GetParam());
9901 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
9902 ASSERT_TRUE(ssl
.cert
.get());
9903 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
9905 scoped_ptr
<SpdyFrame
> req(
9906 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
9907 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
9909 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
9910 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
9911 MockRead spdy_reads
[] = {
9912 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
9915 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
9916 arraysize(spdy_writes
));
9917 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
9919 TestCompletionCallback callback
;
9921 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
9923 scoped_ptr
<HttpTransaction
> trans(
9924 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9926 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9927 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9928 EXPECT_EQ(OK
, callback
.WaitForResult());
9930 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
9931 ASSERT_TRUE(response
!= NULL
);
9932 ASSERT_TRUE(response
->headers
.get() != NULL
);
9933 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9935 std::string response_data
;
9936 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9937 EXPECT_EQ("hello world", response_data
);
9939 // Set up an initial SpdySession in the pool to reuse.
9940 HostPortPair
host_port_pair("www.example.org", 443);
9941 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
9942 PRIVACY_MODE_DISABLED
);
9943 base::WeakPtr
<SpdySession
> spdy_session
=
9944 CreateSecureSpdySession(session
, key
, BoundNetLog());
9946 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
9948 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
9949 EXPECT_EQ(ERR_IO_PENDING
, rv
);
9950 EXPECT_EQ(OK
, callback
.WaitForResult());
9952 response
= trans
->GetResponseInfo();
9953 ASSERT_TRUE(response
!= NULL
);
9954 ASSERT_TRUE(response
->headers
.get() != NULL
);
9955 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
9956 EXPECT_TRUE(response
->was_fetched_via_spdy
);
9957 EXPECT_TRUE(response
->was_npn_negotiated
);
9959 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
9960 EXPECT_EQ("hello!", response_data
);
9963 // GenerateAuthToken is a mighty big test.
9964 // It tests all permutation of GenerateAuthToken behavior:
9965 // - Synchronous and Asynchronous completion.
9966 // - OK or error on completion.
9967 // - Direct connection, non-authenticating proxy, and authenticating proxy.
9968 // - HTTP or HTTPS backend (to include proxy tunneling).
9969 // - Non-authenticating and authenticating backend.
9971 // In all, there are 44 reasonable permuations (for example, if there are
9972 // problems generating an auth token for an authenticating proxy, we don't
9973 // need to test all permutations of the backend server).
9975 // The test proceeds by going over each of the configuration cases, and
9976 // potentially running up to three rounds in each of the tests. The TestConfig
9977 // specifies both the configuration for the test as well as the expectations
9979 TEST_P(HttpNetworkTransactionTest
, GenerateAuthToken
) {
9980 static const char kServer
[] = "http://www.example.com";
9981 static const char kSecureServer
[] = "https://www.example.com";
9982 static const char kProxy
[] = "myproxy:70";
9983 const int kAuthErr
= ERR_INVALID_AUTH_CREDENTIALS
;
9991 const MockWrite
kGet(
9992 "GET / HTTP/1.1\r\n"
9993 "Host: www.example.com\r\n"
9994 "Connection: keep-alive\r\n\r\n");
9995 const MockWrite
kGetProxy(
9996 "GET http://www.example.com/ HTTP/1.1\r\n"
9997 "Host: www.example.com\r\n"
9998 "Proxy-Connection: keep-alive\r\n\r\n");
9999 const MockWrite
kGetAuth(
10000 "GET / HTTP/1.1\r\n"
10001 "Host: www.example.com\r\n"
10002 "Connection: keep-alive\r\n"
10003 "Authorization: auth_token\r\n\r\n");
10004 const MockWrite
kGetProxyAuth(
10005 "GET http://www.example.com/ HTTP/1.1\r\n"
10006 "Host: www.example.com\r\n"
10007 "Proxy-Connection: keep-alive\r\n"
10008 "Proxy-Authorization: auth_token\r\n\r\n");
10009 const MockWrite
kGetAuthThroughProxy(
10010 "GET http://www.example.com/ HTTP/1.1\r\n"
10011 "Host: www.example.com\r\n"
10012 "Proxy-Connection: keep-alive\r\n"
10013 "Authorization: auth_token\r\n\r\n");
10014 const MockWrite
kGetAuthWithProxyAuth(
10015 "GET http://www.example.com/ HTTP/1.1\r\n"
10016 "Host: www.example.com\r\n"
10017 "Proxy-Connection: keep-alive\r\n"
10018 "Proxy-Authorization: auth_token\r\n"
10019 "Authorization: auth_token\r\n\r\n");
10020 const MockWrite
kConnect(
10021 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10022 "Host: www.example.com\r\n"
10023 "Proxy-Connection: keep-alive\r\n\r\n");
10024 const MockWrite
kConnectProxyAuth(
10025 "CONNECT www.example.com:443 HTTP/1.1\r\n"
10026 "Host: www.example.com\r\n"
10027 "Proxy-Connection: keep-alive\r\n"
10028 "Proxy-Authorization: auth_token\r\n\r\n");
10030 const MockRead
kSuccess(
10031 "HTTP/1.1 200 OK\r\n"
10032 "Content-Type: text/html; charset=iso-8859-1\r\n"
10033 "Content-Length: 3\r\n\r\n"
10035 const MockRead
kFailure(
10036 "Should not be called.");
10037 const MockRead
kServerChallenge(
10038 "HTTP/1.1 401 Unauthorized\r\n"
10039 "WWW-Authenticate: Mock realm=server\r\n"
10040 "Content-Type: text/html; charset=iso-8859-1\r\n"
10041 "Content-Length: 14\r\n\r\n"
10042 "Unauthorized\r\n");
10043 const MockRead
kProxyChallenge(
10044 "HTTP/1.1 407 Unauthorized\r\n"
10045 "Proxy-Authenticate: Mock realm=proxy\r\n"
10046 "Proxy-Connection: close\r\n"
10047 "Content-Type: text/html; charset=iso-8859-1\r\n"
10048 "Content-Length: 14\r\n\r\n"
10049 "Unauthorized\r\n");
10050 const MockRead
kProxyConnected(
10051 "HTTP/1.1 200 Connection Established\r\n\r\n");
10053 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
10054 // no constructors, but the C++ compiler on Windows warns about
10055 // unspecified data in compound literals. So, moved to using constructors,
10056 // and TestRound's created with the default constructor should not be used.
10059 : expected_rv(ERR_UNEXPECTED
),
10063 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10064 int expected_rv_arg
)
10065 : write(write_arg
),
10067 expected_rv(expected_rv_arg
),
10071 TestRound(const MockWrite
& write_arg
, const MockRead
& read_arg
,
10072 int expected_rv_arg
, const MockWrite
* extra_write_arg
,
10073 const MockRead
* extra_read_arg
)
10074 : write(write_arg
),
10076 expected_rv(expected_rv_arg
),
10077 extra_write(extra_write_arg
),
10078 extra_read(extra_read_arg
) {
10083 const MockWrite
* extra_write
;
10084 const MockRead
* extra_read
;
10087 static const int kNoSSL
= 500;
10089 struct TestConfig
{
10090 const char* const proxy_url
;
10091 AuthTiming proxy_auth_timing
;
10093 const char* const server_url
;
10094 AuthTiming server_auth_timing
;
10095 int server_auth_rv
;
10096 int num_auth_rounds
;
10097 int first_ssl_round
;
10098 TestRound rounds
[3];
10099 } test_configs
[] = {
10100 // Non-authenticating HTTP server with a direct connection.
10101 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10102 { TestRound(kGet
, kSuccess
, OK
)}},
10103 // Authenticating HTTP server with a direct connection.
10104 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10105 { TestRound(kGet
, kServerChallenge
, OK
),
10106 TestRound(kGetAuth
, kSuccess
, OK
)}},
10107 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10108 { TestRound(kGet
, kServerChallenge
, OK
),
10109 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10110 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10111 { TestRound(kGet
, kServerChallenge
, OK
),
10112 TestRound(kGetAuth
, kSuccess
, OK
)}},
10113 { NULL
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10114 { TestRound(kGet
, kServerChallenge
, OK
),
10115 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10116 // Non-authenticating HTTP server through a non-authenticating proxy.
10117 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_NONE
, OK
, 1, kNoSSL
,
10118 { TestRound(kGetProxy
, kSuccess
, OK
)}},
10119 // Authenticating HTTP server through a non-authenticating proxy.
10120 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, OK
, 2, kNoSSL
,
10121 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10122 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10123 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 2, kNoSSL
,
10124 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10125 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10126 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, OK
, 2, kNoSSL
,
10127 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10128 TestRound(kGetAuthThroughProxy
, kSuccess
, OK
)}},
10129 { kProxy
, AUTH_NONE
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 2, kNoSSL
,
10130 { TestRound(kGetProxy
, kServerChallenge
, OK
),
10131 TestRound(kGetAuthThroughProxy
, kFailure
, kAuthErr
)}},
10132 // Non-authenticating HTTP server through an authenticating proxy.
10133 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10134 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10135 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10136 { kProxy
, AUTH_SYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10137 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10138 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10139 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10140 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10141 TestRound(kGetProxyAuth
, kSuccess
, OK
)}},
10142 { kProxy
, AUTH_ASYNC
, kAuthErr
, kServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10143 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10144 TestRound(kGetProxyAuth
, kFailure
, kAuthErr
)}},
10145 // Authenticating HTTP server through an authenticating proxy.
10146 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10147 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10148 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10149 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10150 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10151 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10152 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10153 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10154 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, OK
, 3, kNoSSL
,
10155 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10156 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10157 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10158 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_SYNC
, kAuthErr
, 3, kNoSSL
,
10159 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10160 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10161 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10162 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10163 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10164 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10165 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10166 { kProxy
, AUTH_SYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10167 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10168 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10169 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10170 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, OK
, 3, kNoSSL
,
10171 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10172 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10173 TestRound(kGetAuthWithProxyAuth
, kSuccess
, OK
)}},
10174 { kProxy
, AUTH_ASYNC
, OK
, kServer
, AUTH_ASYNC
, kAuthErr
, 3, kNoSSL
,
10175 { TestRound(kGetProxy
, kProxyChallenge
, OK
),
10176 TestRound(kGetProxyAuth
, kServerChallenge
, OK
),
10177 TestRound(kGetAuthWithProxyAuth
, kFailure
, kAuthErr
)}},
10178 // Non-authenticating HTTPS server with a direct connection.
10179 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10180 { TestRound(kGet
, kSuccess
, OK
)}},
10181 // Authenticating HTTPS server with a direct connection.
10182 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10183 { TestRound(kGet
, kServerChallenge
, OK
),
10184 TestRound(kGetAuth
, kSuccess
, OK
)}},
10185 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10186 { TestRound(kGet
, kServerChallenge
, OK
),
10187 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10188 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10189 { TestRound(kGet
, kServerChallenge
, OK
),
10190 TestRound(kGetAuth
, kSuccess
, OK
)}},
10191 { NULL
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10192 { TestRound(kGet
, kServerChallenge
, OK
),
10193 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10194 // Non-authenticating HTTPS server with a non-authenticating proxy.
10195 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_NONE
, OK
, 1, 0,
10196 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10197 // Authenticating HTTPS server through a non-authenticating proxy.
10198 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 2, 0,
10199 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10200 TestRound(kGetAuth
, kSuccess
, OK
)}},
10201 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 2, 0,
10202 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10203 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10204 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 2, 0,
10205 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10206 TestRound(kGetAuth
, kSuccess
, OK
)}},
10207 { kProxy
, AUTH_NONE
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 2, 0,
10208 { TestRound(kConnect
, kProxyConnected
, OK
, &kGet
, &kServerChallenge
),
10209 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10210 // Non-Authenticating HTTPS server through an authenticating proxy.
10211 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10212 { TestRound(kConnect
, kProxyChallenge
, OK
),
10213 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10214 { kProxy
, AUTH_SYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10215 { TestRound(kConnect
, kProxyChallenge
, OK
),
10216 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10217 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_NONE
, OK
, 2, 1,
10218 { TestRound(kConnect
, kProxyChallenge
, OK
),
10219 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
, &kGet
, &kSuccess
)}},
10220 { kProxy
, AUTH_ASYNC
, kAuthErr
, kSecureServer
, AUTH_NONE
, OK
, 2, kNoSSL
,
10221 { TestRound(kConnect
, kProxyChallenge
, OK
),
10222 TestRound(kConnectProxyAuth
, kFailure
, kAuthErr
)}},
10223 // Authenticating HTTPS server through an authenticating proxy.
10224 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10225 { TestRound(kConnect
, kProxyChallenge
, OK
),
10226 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10227 &kGet
, &kServerChallenge
),
10228 TestRound(kGetAuth
, kSuccess
, OK
)}},
10229 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10230 { TestRound(kConnect
, kProxyChallenge
, OK
),
10231 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10232 &kGet
, &kServerChallenge
),
10233 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10234 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, OK
, 3, 1,
10235 { TestRound(kConnect
, kProxyChallenge
, OK
),
10236 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10237 &kGet
, &kServerChallenge
),
10238 TestRound(kGetAuth
, kSuccess
, OK
)}},
10239 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_SYNC
, kAuthErr
, 3, 1,
10240 { TestRound(kConnect
, kProxyChallenge
, OK
),
10241 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10242 &kGet
, &kServerChallenge
),
10243 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10244 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10245 { TestRound(kConnect
, kProxyChallenge
, OK
),
10246 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10247 &kGet
, &kServerChallenge
),
10248 TestRound(kGetAuth
, kSuccess
, OK
)}},
10249 { kProxy
, AUTH_SYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10250 { TestRound(kConnect
, kProxyChallenge
, OK
),
10251 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10252 &kGet
, &kServerChallenge
),
10253 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10254 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, OK
, 3, 1,
10255 { TestRound(kConnect
, kProxyChallenge
, OK
),
10256 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10257 &kGet
, &kServerChallenge
),
10258 TestRound(kGetAuth
, kSuccess
, OK
)}},
10259 { kProxy
, AUTH_ASYNC
, OK
, kSecureServer
, AUTH_ASYNC
, kAuthErr
, 3, 1,
10260 { TestRound(kConnect
, kProxyChallenge
, OK
),
10261 TestRound(kConnectProxyAuth
, kProxyConnected
, OK
,
10262 &kGet
, &kServerChallenge
),
10263 TestRound(kGetAuth
, kFailure
, kAuthErr
)}},
10266 for (size_t i
= 0; i
< arraysize(test_configs
); ++i
) {
10267 HttpAuthHandlerMock::Factory
* auth_factory(
10268 new HttpAuthHandlerMock::Factory());
10269 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10270 const TestConfig
& test_config
= test_configs
[i
];
10272 // Set up authentication handlers as necessary.
10273 if (test_config
.proxy_auth_timing
!= AUTH_NONE
) {
10274 for (int n
= 0; n
< 2; n
++) {
10275 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10276 std::string auth_challenge
= "Mock realm=proxy";
10277 GURL
origin(test_config
.proxy_url
);
10278 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10279 auth_challenge
.end());
10280 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_PROXY
,
10281 origin
, BoundNetLog());
10282 auth_handler
->SetGenerateExpectation(
10283 test_config
.proxy_auth_timing
== AUTH_ASYNC
,
10284 test_config
.proxy_auth_rv
);
10285 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10288 if (test_config
.server_auth_timing
!= AUTH_NONE
) {
10289 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10290 std::string auth_challenge
= "Mock realm=server";
10291 GURL
origin(test_config
.server_url
);
10292 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10293 auth_challenge
.end());
10294 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10295 origin
, BoundNetLog());
10296 auth_handler
->SetGenerateExpectation(
10297 test_config
.server_auth_timing
== AUTH_ASYNC
,
10298 test_config
.server_auth_rv
);
10299 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10301 if (test_config
.proxy_url
) {
10302 session_deps_
.proxy_service
.reset(
10303 ProxyService::CreateFixed(test_config
.proxy_url
));
10305 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10308 HttpRequestInfo request
;
10309 request
.method
= "GET";
10310 request
.url
= GURL(test_config
.server_url
);
10311 request
.load_flags
= 0;
10313 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10314 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10316 SSLSocketDataProvider
ssl_socket_data_provider(SYNCHRONOUS
, OK
);
10318 std::vector
<std::vector
<MockRead
>> mock_reads(1);
10319 std::vector
<std::vector
<MockWrite
>> mock_writes(1);
10320 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10321 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10323 // Set up expected reads and writes.
10324 mock_reads
.back().push_back(read_write_round
.read
);
10325 mock_writes
.back().push_back(read_write_round
.write
);
10327 // kProxyChallenge uses Proxy-Connection: close which means that the
10328 // socket is closed and a new one will be created for the next request.
10329 if (read_write_round
.read
.data
== kProxyChallenge
.data
&&
10330 read_write_round
.write
.data
!= kConnect
.data
) {
10331 mock_reads
.push_back(std::vector
<MockRead
>());
10332 mock_writes
.push_back(std::vector
<MockWrite
>());
10335 if (read_write_round
.extra_read
) {
10336 mock_reads
.back().push_back(*read_write_round
.extra_read
);
10338 if (read_write_round
.extra_write
) {
10339 mock_writes
.back().push_back(*read_write_round
.extra_write
);
10342 // Add an SSL sequence if necessary.
10343 if (round
>= test_config
.first_ssl_round
)
10344 session_deps_
.socket_factory
->AddSSLSocketDataProvider(
10345 &ssl_socket_data_provider
);
10348 ScopedVector
<StaticSocketDataProvider
> data_providers
;
10349 for (size_t i
= 0; i
< mock_reads
.size(); ++i
) {
10350 data_providers
.push_back(new StaticSocketDataProvider(
10351 vector_as_array(&mock_reads
[i
]), mock_reads
[i
].size(),
10352 vector_as_array(&mock_writes
[i
]), mock_writes
[i
].size()));
10353 session_deps_
.socket_factory
->AddSocketDataProvider(
10354 data_providers
.back());
10357 for (int round
= 0; round
< test_config
.num_auth_rounds
; ++round
) {
10358 const TestRound
& read_write_round
= test_config
.rounds
[round
];
10359 // Start or restart the transaction.
10360 TestCompletionCallback callback
;
10363 rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10365 rv
= trans
.RestartWithAuth(
10366 AuthCredentials(kFoo
, kBar
), callback
.callback());
10368 if (rv
== ERR_IO_PENDING
)
10369 rv
= callback
.WaitForResult();
10371 // Compare results with expected data.
10372 EXPECT_EQ(read_write_round
.expected_rv
, rv
);
10373 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10374 if (read_write_round
.expected_rv
!= OK
) {
10375 EXPECT_EQ(round
+ 1, test_config
.num_auth_rounds
);
10378 if (round
+ 1 < test_config
.num_auth_rounds
) {
10379 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10381 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10387 TEST_P(HttpNetworkTransactionTest
, MultiRoundAuth
) {
10388 // Do multi-round authentication and make sure it works correctly.
10389 HttpAuthHandlerMock::Factory
* auth_factory(
10390 new HttpAuthHandlerMock::Factory());
10391 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10392 session_deps_
.proxy_service
.reset(ProxyService::CreateDirect());
10393 session_deps_
.host_resolver
->rules()->AddRule("www.example.com", "10.0.0.1");
10394 session_deps_
.host_resolver
->set_synchronous_mode(true);
10396 HttpAuthHandlerMock
* auth_handler(new HttpAuthHandlerMock());
10397 auth_handler
->set_connection_based(true);
10398 std::string auth_challenge
= "Mock realm=server";
10399 GURL
origin("http://www.example.com");
10400 HttpAuthChallengeTokenizer
tokenizer(auth_challenge
.begin(),
10401 auth_challenge
.end());
10402 auth_handler
->InitFromChallenge(&tokenizer
, HttpAuth::AUTH_SERVER
,
10403 origin
, BoundNetLog());
10404 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_SERVER
);
10407 const HttpResponseInfo
* response
= NULL
;
10408 HttpRequestInfo request
;
10409 request
.method
= "GET";
10410 request
.url
= origin
;
10411 request
.load_flags
= 0;
10413 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10415 // Use a TCP Socket Pool with only one connection per group. This is used
10416 // to validate that the TCP socket is not released to the pool between
10417 // each round of multi-round authentication.
10418 HttpNetworkSessionPeer
session_peer(session
);
10419 TransportClientSocketPool
* transport_pool
= new TransportClientSocketPool(
10420 50, // Max sockets for pool
10421 1, // Max sockets per group
10422 session_deps_
.host_resolver
.get(),
10423 session_deps_
.socket_factory
.get(),
10424 session_deps_
.net_log
);
10425 scoped_ptr
<MockClientSocketPoolManager
> mock_pool_manager(
10426 new MockClientSocketPoolManager
);
10427 mock_pool_manager
->SetTransportSocketPool(transport_pool
);
10428 session_peer
.SetClientSocketPoolManager(mock_pool_manager
.Pass());
10430 scoped_ptr
<HttpTransaction
> trans(
10431 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10432 TestCompletionCallback callback
;
10434 const MockWrite
kGet(
10435 "GET / HTTP/1.1\r\n"
10436 "Host: www.example.com\r\n"
10437 "Connection: keep-alive\r\n\r\n");
10438 const MockWrite
kGetAuth(
10439 "GET / HTTP/1.1\r\n"
10440 "Host: www.example.com\r\n"
10441 "Connection: keep-alive\r\n"
10442 "Authorization: auth_token\r\n\r\n");
10444 const MockRead
kServerChallenge(
10445 "HTTP/1.1 401 Unauthorized\r\n"
10446 "WWW-Authenticate: Mock realm=server\r\n"
10447 "Content-Type: text/html; charset=iso-8859-1\r\n"
10448 "Content-Length: 14\r\n\r\n"
10449 "Unauthorized\r\n");
10450 const MockRead
kSuccess(
10451 "HTTP/1.1 200 OK\r\n"
10452 "Content-Type: text/html; charset=iso-8859-1\r\n"
10453 "Content-Length: 3\r\n\r\n"
10456 MockWrite writes
[] = {
10465 // Competing request
10468 MockRead reads
[] = {
10477 // Competing response
10480 StaticSocketDataProvider
data_provider(reads
, arraysize(reads
),
10481 writes
, arraysize(writes
));
10482 session_deps_
.socket_factory
->AddSocketDataProvider(&data_provider
);
10484 const char kSocketGroup
[] = "www.example.com:80";
10486 // First round of authentication.
10487 auth_handler
->SetGenerateExpectation(false, OK
);
10488 rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10489 if (rv
== ERR_IO_PENDING
)
10490 rv
= callback
.WaitForResult();
10492 response
= trans
->GetResponseInfo();
10493 ASSERT_TRUE(response
!= NULL
);
10494 EXPECT_FALSE(response
->auth_challenge
.get() == NULL
);
10495 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10497 // In between rounds, another request comes in for the same domain.
10498 // It should not be able to grab the TCP socket that trans has already
10500 scoped_ptr
<HttpTransaction
> trans_compete(
10501 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10502 TestCompletionCallback callback_compete
;
10503 rv
= trans_compete
->Start(
10504 &request
, callback_compete
.callback(), BoundNetLog());
10505 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10506 // callback_compete.WaitForResult at this point would stall forever,
10507 // since the HttpNetworkTransaction does not release the request back to
10508 // the pool until after authentication completes.
10510 // Second round of authentication.
10511 auth_handler
->SetGenerateExpectation(false, OK
);
10512 rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
), callback
.callback());
10513 if (rv
== ERR_IO_PENDING
)
10514 rv
= callback
.WaitForResult();
10516 response
= trans
->GetResponseInfo();
10517 ASSERT_TRUE(response
!= NULL
);
10518 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10519 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10521 // Third round of authentication.
10522 auth_handler
->SetGenerateExpectation(false, OK
);
10523 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10524 if (rv
== ERR_IO_PENDING
)
10525 rv
= callback
.WaitForResult();
10527 response
= trans
->GetResponseInfo();
10528 ASSERT_TRUE(response
!= NULL
);
10529 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10530 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10532 // Fourth round of authentication, which completes successfully.
10533 auth_handler
->SetGenerateExpectation(false, OK
);
10534 rv
= trans
->RestartWithAuth(AuthCredentials(), callback
.callback());
10535 if (rv
== ERR_IO_PENDING
)
10536 rv
= callback
.WaitForResult();
10538 response
= trans
->GetResponseInfo();
10539 ASSERT_TRUE(response
!= NULL
);
10540 EXPECT_TRUE(response
->auth_challenge
.get() == NULL
);
10541 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10543 // Read the body since the fourth round was successful. This will also
10544 // release the socket back to the pool.
10545 scoped_refptr
<IOBufferWithSize
> io_buf(new IOBufferWithSize(50));
10546 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10547 if (rv
== ERR_IO_PENDING
)
10548 rv
= callback
.WaitForResult();
10550 rv
= trans
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10552 // There are still 0 idle sockets, since the trans_compete transaction
10553 // will be handed it immediately after trans releases it to the group.
10554 EXPECT_EQ(0, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10556 // The competing request can now finish. Wait for the headers and then
10558 rv
= callback_compete
.WaitForResult();
10560 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10561 if (rv
== ERR_IO_PENDING
)
10562 rv
= callback
.WaitForResult();
10564 rv
= trans_compete
->Read(io_buf
.get(), io_buf
->size(), callback
.callback());
10567 // Finally, the socket is released to the group.
10568 EXPECT_EQ(1, transport_pool
->IdleSocketCountInGroup(kSocketGroup
));
10571 // This tests the case that a request is issued via http instead of spdy after
10572 // npn is negotiated.
10573 TEST_P(HttpNetworkTransactionTest
, NpnWithHttpOverSSL
) {
10574 session_deps_
.use_alternate_protocols
= true;
10575 NextProtoVector next_protos
;
10576 next_protos
.push_back(kProtoHTTP11
);
10577 session_deps_
.next_protos
= next_protos
;
10579 HttpRequestInfo request
;
10580 request
.method
= "GET";
10581 request
.url
= GURL("https://www.example.org/");
10582 request
.load_flags
= 0;
10584 MockWrite data_writes
[] = {
10586 "GET / HTTP/1.1\r\n"
10587 "Host: www.example.org\r\n"
10588 "Connection: keep-alive\r\n\r\n"),
10591 std::string alternate_protocol_http_header
=
10592 GetAlternateProtocolHttpHeader();
10594 MockRead data_reads
[] = {
10595 MockRead("HTTP/1.1 200 OK\r\n"),
10596 MockRead(alternate_protocol_http_header
.c_str()),
10598 MockRead("hello world"),
10599 MockRead(SYNCHRONOUS
, OK
),
10602 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10603 ssl
.SetNextProto(kProtoHTTP11
);
10605 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10607 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
10608 data_writes
, arraysize(data_writes
));
10609 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10611 TestCompletionCallback callback
;
10613 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10614 scoped_ptr
<HttpTransaction
> trans(
10615 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10617 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10619 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10620 EXPECT_EQ(OK
, callback
.WaitForResult());
10622 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10623 ASSERT_TRUE(response
!= NULL
);
10624 ASSERT_TRUE(response
->headers
.get() != NULL
);
10625 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10627 std::string response_data
;
10628 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
10629 EXPECT_EQ("hello world", response_data
);
10631 EXPECT_FALSE(response
->was_fetched_via_spdy
);
10632 EXPECT_TRUE(response
->was_npn_negotiated
);
10635 TEST_P(HttpNetworkTransactionTest
, SpdyPostNPNServerHangup
) {
10636 // Simulate the SSL handshake completing with an NPN negotiation
10637 // followed by an immediate server closing of the socket.
10638 // Fix crash: http://crbug.com/46369
10639 session_deps_
.use_alternate_protocols
= true;
10640 session_deps_
.next_protos
= SpdyNextProtos();
10642 HttpRequestInfo request
;
10643 request
.method
= "GET";
10644 request
.url
= GURL("https://www.example.org/");
10645 request
.load_flags
= 0;
10647 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10648 ssl
.SetNextProto(GetParam());
10649 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10651 scoped_ptr
<SpdyFrame
> req(
10652 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10653 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 1)};
10655 MockRead spdy_reads
[] = {
10656 MockRead(SYNCHRONOUS
, 0, 0) // Not async - return 0 immediately.
10659 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
10660 arraysize(spdy_writes
));
10661 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
10663 TestCompletionCallback callback
;
10665 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10666 scoped_ptr
<HttpTransaction
> trans(
10667 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10669 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
10670 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10671 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback
.WaitForResult());
10674 // A subclass of HttpAuthHandlerMock that records the request URL when
10675 // it gets it. This is needed since the auth handler may get destroyed
10676 // before we get a chance to query it.
10677 class UrlRecordingHttpAuthHandlerMock
: public HttpAuthHandlerMock
{
10679 explicit UrlRecordingHttpAuthHandlerMock(GURL
* url
) : url_(url
) {}
10681 ~UrlRecordingHttpAuthHandlerMock() override
{}
10684 int GenerateAuthTokenImpl(const AuthCredentials
* credentials
,
10685 const HttpRequestInfo
* request
,
10686 const CompletionCallback
& callback
,
10687 std::string
* auth_token
) override
{
10688 *url_
= request
->url
;
10689 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
10690 credentials
, request
, callback
, auth_token
);
10697 TEST_P(HttpNetworkTransactionTest
, SpdyAlternateProtocolThroughProxy
) {
10698 // This test ensures that the URL passed into the proxy is upgraded
10699 // to https when doing an Alternate Protocol upgrade.
10700 session_deps_
.use_alternate_protocols
= true;
10701 session_deps_
.next_protos
= SpdyNextProtos();
10703 session_deps_
.proxy_service
.reset(
10704 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10705 TestNetLog net_log
;
10706 session_deps_
.net_log
= &net_log
;
10709 HttpAuthHandlerMock::Factory
* auth_factory
=
10710 new HttpAuthHandlerMock::Factory();
10711 UrlRecordingHttpAuthHandlerMock
* auth_handler
=
10712 new UrlRecordingHttpAuthHandlerMock(&request_url
);
10713 auth_factory
->AddMockHandler(auth_handler
, HttpAuth::AUTH_PROXY
);
10714 auth_factory
->set_do_init_from_challenge(true);
10715 session_deps_
.http_auth_handler_factory
.reset(auth_factory
);
10718 HttpRequestInfo request
;
10719 request
.method
= "GET";
10720 request
.url
= GURL("http://www.example.org");
10721 request
.load_flags
= 0;
10723 // First round goes unauthenticated through the proxy.
10724 MockWrite data_writes_1
[] = {
10726 "GET http://www.example.org/ HTTP/1.1\r\n"
10727 "Host: www.example.org\r\n"
10728 "Proxy-Connection: keep-alive\r\n"
10731 MockRead data_reads_1
[] = {
10732 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
10733 MockRead("HTTP/1.1 200 OK\r\n"),
10734 MockRead("Alternate-Protocol: 443:"),
10735 MockRead(GetAlternateProtocolFromParam()),
10737 MockRead("Proxy-Connection: close\r\n"),
10740 StaticSocketDataProvider
data_1(data_reads_1
, arraysize(data_reads_1
),
10741 data_writes_1
, arraysize(data_writes_1
));
10743 // Second round tries to tunnel to www.example.org due to the
10744 // Alternate-Protocol announcement in the first round. It fails due
10745 // to a proxy authentication challenge.
10746 // After the failure, a tunnel is established to www.example.org using
10747 // Proxy-Authorization headers. There is then a SPDY request round.
10749 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
10750 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
10751 // does a Disconnect and Connect on the same socket, rather than trying
10752 // to obtain a new one.
10754 // NOTE: Originally, the proxy response to the second CONNECT request
10755 // simply returned another 407 so the unit test could skip the SSL connection
10756 // establishment and SPDY framing issues. Alas, the
10757 // retry-http-when-alternate-protocol fails logic kicks in, which was more
10758 // complicated to set up expectations for than the SPDY session.
10760 scoped_ptr
<SpdyFrame
> req(
10761 spdy_util_
.ConstructSpdyGet(NULL
, 0, false, 1, LOWEST
, true));
10762 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
10763 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
10765 MockWrite data_writes_2
[] = {
10766 // First connection attempt without Proxy-Authorization.
10767 MockWrite(ASYNC
, 0,
10768 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10769 "Host: www.example.org\r\n"
10770 "Proxy-Connection: keep-alive\r\n"
10773 // Second connection attempt with Proxy-Authorization.
10774 MockWrite(ASYNC
, 2,
10775 "CONNECT www.example.org:443 HTTP/1.1\r\n"
10776 "Host: www.example.org\r\n"
10777 "Proxy-Connection: keep-alive\r\n"
10778 "Proxy-Authorization: auth_token\r\n"
10782 CreateMockWrite(*req
, 4),
10784 const char kRejectConnectResponse
[] = ("HTTP/1.1 407 Unauthorized\r\n"
10785 "Proxy-Authenticate: Mock\r\n"
10786 "Proxy-Connection: close\r\n"
10788 const char kAcceptConnectResponse
[] = "HTTP/1.1 200 Connected\r\n\r\n";
10789 MockRead data_reads_2
[] = {
10790 // First connection attempt fails
10791 MockRead(ASYNC
, kRejectConnectResponse
,
10792 arraysize(kRejectConnectResponse
) - 1, 1),
10794 // Second connection attempt passes
10795 MockRead(ASYNC
, kAcceptConnectResponse
,
10796 arraysize(kAcceptConnectResponse
) - 1, 3),
10799 CreateMockRead(*resp
.get(), 5),
10800 CreateMockRead(*data
.get(), 6),
10801 MockRead(ASYNC
, 0, 0, 7),
10803 SequencedSocketData
data_2(data_reads_2
, arraysize(data_reads_2
),
10804 data_writes_2
, arraysize(data_writes_2
));
10806 SSLSocketDataProvider
ssl(ASYNC
, OK
);
10807 ssl
.SetNextProto(GetParam());
10808 ssl
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
10809 ASSERT_TRUE(ssl
.cert
.get());
10811 MockConnect
never_finishing_connect(SYNCHRONOUS
, ERR_IO_PENDING
);
10812 StaticSocketDataProvider
hanging_non_alternate_protocol_socket(
10814 hanging_non_alternate_protocol_socket
.set_connect_data(
10815 never_finishing_connect
);
10817 session_deps_
.socket_factory
->AddSocketDataProvider(&data_1
);
10818 session_deps_
.socket_factory
->AddSocketDataProvider(&data_2
);
10819 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
10820 session_deps_
.socket_factory
->AddSocketDataProvider(
10821 &hanging_non_alternate_protocol_socket
);
10822 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10824 // First round should work and provide the Alternate-Protocol state.
10825 TestCompletionCallback callback_1
;
10826 scoped_ptr
<HttpTransaction
> trans_1(
10827 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10828 int rv
= trans_1
->Start(&request
, callback_1
.callback(), BoundNetLog());
10829 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10830 EXPECT_EQ(OK
, callback_1
.WaitForResult());
10832 // Second round should attempt a tunnel connect and get an auth challenge.
10833 TestCompletionCallback callback_2
;
10834 scoped_ptr
<HttpTransaction
> trans_2(
10835 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10836 rv
= trans_2
->Start(&request
, callback_2
.callback(), BoundNetLog());
10837 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10838 EXPECT_EQ(OK
, callback_2
.WaitForResult());
10839 const HttpResponseInfo
* response
= trans_2
->GetResponseInfo();
10840 ASSERT_TRUE(response
!= NULL
);
10841 ASSERT_FALSE(response
->auth_challenge
.get() == NULL
);
10843 // Restart with auth. Tunnel should work and response received.
10844 TestCompletionCallback callback_3
;
10845 rv
= trans_2
->RestartWithAuth(
10846 AuthCredentials(kFoo
, kBar
), callback_3
.callback());
10847 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10848 EXPECT_EQ(OK
, callback_3
.WaitForResult());
10850 // After all that work, these two lines (or actually, just the scheme) are
10851 // what this test is all about. Make sure it happens correctly.
10852 EXPECT_EQ("https", request_url
.scheme());
10853 EXPECT_EQ("www.example.org", request_url
.host());
10855 LoadTimingInfo load_timing_info
;
10856 EXPECT_TRUE(trans_2
->GetLoadTimingInfo(&load_timing_info
));
10857 TestLoadTimingNotReusedWithPac(load_timing_info
,
10858 CONNECT_TIMING_HAS_SSL_TIMES
);
10861 // Test that if we cancel the transaction as the connection is completing, that
10862 // everything tears down correctly.
10863 TEST_P(HttpNetworkTransactionTest
, SimpleCancel
) {
10864 // Setup everything about the connection to complete synchronously, so that
10865 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
10866 // for is the callback from the HttpStreamRequest.
10867 // Then cancel the transaction.
10868 // Verify that we don't crash.
10869 MockConnect
mock_connect(SYNCHRONOUS
, OK
);
10870 MockRead data_reads
[] = {
10871 MockRead(SYNCHRONOUS
, "HTTP/1.0 200 OK\r\n\r\n"),
10872 MockRead(SYNCHRONOUS
, "hello world"),
10873 MockRead(SYNCHRONOUS
, OK
),
10876 HttpRequestInfo request
;
10877 request
.method
= "GET";
10878 request
.url
= GURL("http://www.example.org/");
10879 request
.load_flags
= 0;
10881 session_deps_
.host_resolver
->set_synchronous_mode(true);
10882 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10883 scoped_ptr
<HttpTransaction
> trans(
10884 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10886 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10887 data
.set_connect_data(mock_connect
);
10888 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10890 TestCompletionCallback callback
;
10892 BoundTestNetLog log
;
10893 int rv
= trans
->Start(&request
, callback
.callback(), log
.bound());
10894 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10895 trans
.reset(); // Cancel the transaction here.
10897 base::MessageLoop::current()->RunUntilIdle();
10900 // Test that if a transaction is cancelled after receiving the headers, the
10901 // stream is drained properly and added back to the socket pool. The main
10902 // purpose of this test is to make sure that an HttpStreamParser can be read
10903 // from after the HttpNetworkTransaction and the objects it owns have been
10905 // See http://crbug.com/368418
10906 TEST_P(HttpNetworkTransactionTest
, CancelAfterHeaders
) {
10907 MockRead data_reads
[] = {
10908 MockRead(ASYNC
, "HTTP/1.1 200 OK\r\n"),
10909 MockRead(ASYNC
, "Content-Length: 2\r\n"),
10910 MockRead(ASYNC
, "Connection: Keep-Alive\r\n\r\n"),
10911 MockRead(ASYNC
, "1"),
10912 // 2 async reads are necessary to trigger a ReadResponseBody call after the
10913 // HttpNetworkTransaction has been deleted.
10914 MockRead(ASYNC
, "2"),
10915 MockRead(SYNCHRONOUS
, ERR_IO_PENDING
), // Should never read this.
10917 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), NULL
, 0);
10918 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
10920 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10923 HttpRequestInfo request
;
10924 request
.method
= "GET";
10925 request
.url
= GURL("http://www.example.org/");
10926 request
.load_flags
= 0;
10928 HttpNetworkTransaction
trans(DEFAULT_PRIORITY
, session
.get());
10929 TestCompletionCallback callback
;
10931 int rv
= trans
.Start(&request
, callback
.callback(), BoundNetLog());
10932 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10933 callback
.WaitForResult();
10935 const HttpResponseInfo
* response
= trans
.GetResponseInfo();
10936 ASSERT_TRUE(response
!= NULL
);
10937 EXPECT_TRUE(response
->headers
.get() != NULL
);
10938 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
10940 // The transaction and HttpRequestInfo are deleted.
10943 // Let the HttpResponseBodyDrainer drain the socket.
10944 base::MessageLoop::current()->RunUntilIdle();
10946 // Socket should now be idle, waiting to be reused.
10947 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
10950 // Test a basic GET request through a proxy.
10951 TEST_P(HttpNetworkTransactionTest
, ProxyGet
) {
10952 session_deps_
.proxy_service
.reset(
10953 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
10954 BoundTestNetLog log
;
10955 session_deps_
.net_log
= log
.bound().net_log();
10956 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
10958 HttpRequestInfo request
;
10959 request
.method
= "GET";
10960 request
.url
= GURL("http://www.example.org/");
10962 MockWrite data_writes1
[] = {
10964 "GET http://www.example.org/ HTTP/1.1\r\n"
10965 "Host: www.example.org\r\n"
10966 "Proxy-Connection: keep-alive\r\n\r\n"),
10969 MockRead data_reads1
[] = {
10970 MockRead("HTTP/1.1 200 OK\r\n"),
10971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10972 MockRead("Content-Length: 100\r\n\r\n"),
10973 MockRead(SYNCHRONOUS
, OK
),
10976 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
10977 data_writes1
, arraysize(data_writes1
));
10978 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
10980 TestCompletionCallback callback1
;
10982 scoped_ptr
<HttpTransaction
> trans(
10983 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
10984 BeforeProxyHeadersSentHandler proxy_headers_handler
;
10985 trans
->SetBeforeProxyHeadersSentCallback(
10986 base::Bind(&BeforeProxyHeadersSentHandler::OnBeforeProxyHeadersSent
,
10987 base::Unretained(&proxy_headers_handler
)));
10989 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
10990 EXPECT_EQ(ERR_IO_PENDING
, rv
);
10992 rv
= callback1
.WaitForResult();
10995 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
10996 ASSERT_TRUE(response
!= NULL
);
10998 EXPECT_TRUE(response
->headers
->IsKeepAlive());
10999 EXPECT_EQ(200, response
->headers
->response_code());
11000 EXPECT_EQ(100, response
->headers
->GetContentLength());
11001 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11003 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11004 EXPECT_TRUE(proxy_headers_handler
.observed_before_proxy_headers_sent());
11005 EXPECT_EQ("myproxy:70", proxy_headers_handler
.observed_proxy_server_uri());
11006 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11008 LoadTimingInfo load_timing_info
;
11009 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11010 TestLoadTimingNotReusedWithPac(load_timing_info
,
11011 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY
);
11014 // Test a basic HTTPS GET request through a proxy.
11015 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGet
) {
11016 session_deps_
.proxy_service
.reset(
11017 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
11018 BoundTestNetLog log
;
11019 session_deps_
.net_log
= log
.bound().net_log();
11020 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11022 HttpRequestInfo request
;
11023 request
.method
= "GET";
11024 request
.url
= GURL("https://www.example.org/");
11026 // Since we have proxy, should try to establish tunnel.
11027 MockWrite data_writes1
[] = {
11029 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11030 "Host: www.example.org\r\n"
11031 "Proxy-Connection: keep-alive\r\n\r\n"),
11034 "GET / HTTP/1.1\r\n"
11035 "Host: www.example.org\r\n"
11036 "Connection: keep-alive\r\n\r\n"),
11039 MockRead data_reads1
[] = {
11040 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11042 MockRead("HTTP/1.1 200 OK\r\n"),
11043 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11044 MockRead("Content-Length: 100\r\n\r\n"),
11045 MockRead(SYNCHRONOUS
, OK
),
11048 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11049 data_writes1
, arraysize(data_writes1
));
11050 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11051 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11052 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11054 TestCompletionCallback callback1
;
11056 scoped_ptr
<HttpTransaction
> trans(
11057 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11059 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11060 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11062 rv
= callback1
.WaitForResult();
11064 TestNetLogEntry::List entries
;
11065 log
.GetEntries(&entries
);
11066 size_t pos
= ExpectLogContainsSomewhere(
11067 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11068 NetLog::PHASE_NONE
);
11069 ExpectLogContainsSomewhere(
11071 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11072 NetLog::PHASE_NONE
);
11074 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
11075 ASSERT_TRUE(response
!= NULL
);
11077 EXPECT_TRUE(response
->headers
->IsKeepAlive());
11078 EXPECT_EQ(200, response
->headers
->response_code());
11079 EXPECT_EQ(100, response
->headers
->GetContentLength());
11080 EXPECT_TRUE(HttpVersion(1, 1) == response
->headers
->GetHttpVersion());
11081 EXPECT_TRUE(response
->was_fetched_via_proxy
);
11083 response
->proxy_server
.Equals(HostPortPair::FromString("myproxy:70")));
11085 LoadTimingInfo load_timing_info
;
11086 EXPECT_TRUE(trans
->GetLoadTimingInfo(&load_timing_info
));
11087 TestLoadTimingNotReusedWithPac(load_timing_info
,
11088 CONNECT_TIMING_HAS_SSL_TIMES
);
11091 // Test a basic HTTPS GET request through a proxy, but the server hangs up
11092 // while establishing the tunnel.
11093 TEST_P(HttpNetworkTransactionTest
, ProxyTunnelGetHangup
) {
11094 session_deps_
.proxy_service
.reset(ProxyService::CreateFixed("myproxy:70"));
11095 BoundTestNetLog log
;
11096 session_deps_
.net_log
= log
.bound().net_log();
11097 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11099 HttpRequestInfo request
;
11100 request
.method
= "GET";
11101 request
.url
= GURL("https://www.example.org/");
11103 // Since we have proxy, should try to establish tunnel.
11104 MockWrite data_writes1
[] = {
11106 "CONNECT www.example.org:443 HTTP/1.1\r\n"
11107 "Host: www.example.org\r\n"
11108 "Proxy-Connection: keep-alive\r\n\r\n"),
11111 "GET / HTTP/1.1\r\n"
11112 "Host: www.example.org\r\n"
11113 "Connection: keep-alive\r\n\r\n"),
11116 MockRead data_reads1
[] = {
11117 MockRead(SYNCHRONOUS
, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ
),
11118 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
11119 MockRead(ASYNC
, 0, 0), // EOF
11122 StaticSocketDataProvider
data1(data_reads1
, arraysize(data_reads1
),
11123 data_writes1
, arraysize(data_writes1
));
11124 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11125 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11126 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11128 TestCompletionCallback callback1
;
11130 scoped_ptr
<HttpTransaction
> trans(
11131 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11133 int rv
= trans
->Start(&request
, callback1
.callback(), log
.bound());
11134 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11136 rv
= callback1
.WaitForResult();
11137 EXPECT_EQ(ERR_EMPTY_RESPONSE
, rv
);
11138 TestNetLogEntry::List entries
;
11139 log
.GetEntries(&entries
);
11140 size_t pos
= ExpectLogContainsSomewhere(
11141 entries
, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS
,
11142 NetLog::PHASE_NONE
);
11143 ExpectLogContainsSomewhere(
11145 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS
,
11146 NetLog::PHASE_NONE
);
11149 // Test for crbug.com/55424.
11150 TEST_P(HttpNetworkTransactionTest
, PreconnectWithExistingSpdySession
) {
11151 scoped_ptr
<SpdyFrame
> req(
11152 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11153 MockWrite spdy_writes
[] = {CreateMockWrite(*req
, 0)};
11155 scoped_ptr
<SpdyFrame
> resp(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11156 scoped_ptr
<SpdyFrame
> data(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11157 MockRead spdy_reads
[] = {
11158 CreateMockRead(*resp
, 1), CreateMockRead(*data
, 2), MockRead(ASYNC
, 0, 3),
11161 SequencedSocketData
spdy_data(spdy_reads
, arraysize(spdy_reads
), spdy_writes
,
11162 arraysize(spdy_writes
));
11163 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11165 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11166 ssl
.SetNextProto(GetParam());
11167 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11169 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11171 // Set up an initial SpdySession in the pool to reuse.
11172 HostPortPair
host_port_pair("www.example.org", 443);
11173 SpdySessionKey
key(host_port_pair
, ProxyServer::Direct(),
11174 PRIVACY_MODE_DISABLED
);
11175 base::WeakPtr
<SpdySession
> spdy_session
=
11176 CreateInsecureSpdySession(session
, key
, BoundNetLog());
11178 HttpRequestInfo request
;
11179 request
.method
= "GET";
11180 request
.url
= GURL("https://www.example.org/");
11181 request
.load_flags
= 0;
11183 // This is the important line that marks this as a preconnect.
11184 request
.motivation
= HttpRequestInfo::PRECONNECT_MOTIVATED
;
11186 scoped_ptr
<HttpTransaction
> trans(
11187 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11189 TestCompletionCallback callback
;
11190 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
11191 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11192 EXPECT_EQ(OK
, callback
.WaitForResult());
11195 // Given a net error, cause that error to be returned from the first Write()
11196 // call and verify that the HttpTransaction fails with that error.
11197 void HttpNetworkTransactionTest::CheckErrorIsPassedBack(
11198 int error
, IoMode mode
) {
11199 HttpRequestInfo request_info
;
11200 request_info
.url
= GURL("https://www.example.com/");
11201 request_info
.method
= "GET";
11202 request_info
.load_flags
= LOAD_NORMAL
;
11204 SSLSocketDataProvider
ssl_data(mode
, OK
);
11205 MockWrite data_writes
[] = {
11206 MockWrite(mode
, error
),
11208 StaticSocketDataProvider
data(NULL
, 0, data_writes
, arraysize(data_writes
));
11209 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
11210 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data
);
11212 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11213 scoped_ptr
<HttpTransaction
> trans(
11214 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11216 TestCompletionCallback callback
;
11217 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11218 if (rv
== ERR_IO_PENDING
)
11219 rv
= callback
.WaitForResult();
11220 ASSERT_EQ(error
, rv
);
11223 TEST_P(HttpNetworkTransactionTest
, SSLWriteCertError
) {
11224 // Just check a grab bag of cert errors.
11225 static const int kErrors
[] = {
11226 ERR_CERT_COMMON_NAME_INVALID
,
11227 ERR_CERT_AUTHORITY_INVALID
,
11228 ERR_CERT_DATE_INVALID
,
11230 for (size_t i
= 0; i
< arraysize(kErrors
); i
++) {
11231 CheckErrorIsPassedBack(kErrors
[i
], ASYNC
);
11232 CheckErrorIsPassedBack(kErrors
[i
], SYNCHRONOUS
);
11236 // Ensure that a client certificate is removed from the SSL client auth
11238 // 1) No proxy is involved.
11239 // 2) TLS False Start is disabled.
11240 // 3) The initial TLS handshake requests a client certificate.
11241 // 4) The client supplies an invalid/unacceptable certificate.
11242 TEST_P(HttpNetworkTransactionTest
,
11243 ClientAuthCertCache_Direct_NoFalseStart
) {
11244 HttpRequestInfo request_info
;
11245 request_info
.url
= GURL("https://www.example.com/");
11246 request_info
.method
= "GET";
11247 request_info
.load_flags
= LOAD_NORMAL
;
11249 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11250 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11252 // [ssl_]data1 contains the data for the first SSL handshake. When a
11253 // CertificateRequest is received for the first time, the handshake will
11254 // be aborted to allow the caller to provide a certificate.
11255 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11256 ssl_data1
.cert_request_info
= cert_request
.get();
11257 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11258 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11259 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11261 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
11262 // False Start is not being used, the result of the SSL handshake will be
11263 // returned as part of the SSLClientSocket::Connect() call. This test
11264 // matches the result of a server sending a handshake_failure alert,
11265 // rather than a Finished message, because it requires a client
11266 // certificate and none was supplied.
11267 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11268 ssl_data2
.cert_request_info
= cert_request
.get();
11269 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11270 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11271 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11273 // [ssl_]data3 contains the data for the third SSL handshake. When a
11274 // connection to a server fails during an SSL handshake,
11275 // HttpNetworkTransaction will attempt to fallback to TLSv1.1 if the previous
11276 // connection was attempted with TLSv1.2. This is transparent to the caller
11277 // of the HttpNetworkTransaction. Because this test failure is due to
11278 // requiring a client certificate, this fallback handshake should also
11280 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11281 ssl_data3
.cert_request_info
= cert_request
.get();
11282 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11283 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11284 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11286 // [ssl_]data4 contains the data for the fourth SSL handshake. When a
11287 // connection to a server fails during an SSL handshake,
11288 // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
11289 // connection was attempted with TLSv1.1. This is transparent to the caller
11290 // of the HttpNetworkTransaction. Because this test failure is due to
11291 // requiring a client certificate, this fallback handshake should also
11293 SSLSocketDataProvider
ssl_data4(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11294 ssl_data4
.cert_request_info
= cert_request
.get();
11295 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11296 StaticSocketDataProvider
data4(NULL
, 0, NULL
, 0);
11297 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11299 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11300 scoped_ptr
<HttpTransaction
> trans(
11301 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11303 // Begin the SSL handshake with the peer. This consumes ssl_data1.
11304 TestCompletionCallback callback
;
11305 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11306 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11308 // Complete the SSL handshake, which should abort due to requiring a
11309 // client certificate.
11310 rv
= callback
.WaitForResult();
11311 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11313 // Indicate that no certificate should be supplied. From the perspective
11314 // of SSLClientCertCache, NULL is just as meaningful as a real
11315 // certificate, so this is the same as supply a
11316 // legitimate-but-unacceptable certificate.
11317 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11318 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11320 // Ensure the certificate was added to the client auth cache before
11321 // allowing the connection to continue restarting.
11322 scoped_refptr
<X509Certificate
> client_cert
;
11323 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11324 HostPortPair("www.example.com", 443), &client_cert
));
11325 ASSERT_EQ(NULL
, client_cert
.get());
11327 // Restart the handshake. This will consume ssl_data2, which fails, and
11328 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11329 // The result code is checked against what ssl_data4 should return.
11330 rv
= callback
.WaitForResult();
11331 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11333 // Ensure that the client certificate is removed from the cache on a
11334 // handshake failure.
11335 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11336 HostPortPair("www.example.com", 443), &client_cert
));
11339 // Ensure that a client certificate is removed from the SSL client auth
11341 // 1) No proxy is involved.
11342 // 2) TLS False Start is enabled.
11343 // 3) The initial TLS handshake requests a client certificate.
11344 // 4) The client supplies an invalid/unacceptable certificate.
11345 TEST_P(HttpNetworkTransactionTest
,
11346 ClientAuthCertCache_Direct_FalseStart
) {
11347 HttpRequestInfo request_info
;
11348 request_info
.url
= GURL("https://www.example.com/");
11349 request_info
.method
= "GET";
11350 request_info
.load_flags
= LOAD_NORMAL
;
11352 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11353 cert_request
->host_and_port
= HostPortPair("www.example.com", 443);
11355 // When TLS False Start is used, SSLClientSocket::Connect() calls will
11356 // return successfully after reading up to the peer's Certificate message.
11357 // This is to allow the caller to call SSLClientSocket::Write(), which can
11358 // enqueue application data to be sent in the same packet as the
11359 // ChangeCipherSpec and Finished messages.
11360 // The actual handshake will be finished when SSLClientSocket::Read() is
11361 // called, which expects to process the peer's ChangeCipherSpec and
11362 // Finished messages. If there was an error negotiating with the peer,
11363 // such as due to the peer requiring a client certificate when none was
11364 // supplied, the alert sent by the peer won't be processed until Read() is
11367 // Like the non-False Start case, when a client certificate is requested by
11368 // the peer, the handshake is aborted during the Connect() call.
11369 // [ssl_]data1 represents the initial SSL handshake with the peer.
11370 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11371 ssl_data1
.cert_request_info
= cert_request
.get();
11372 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11373 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11374 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11376 // When a client certificate is supplied, Connect() will not be aborted
11377 // when the peer requests the certificate. Instead, the handshake will
11378 // artificially succeed, allowing the caller to write the HTTP request to
11379 // the socket. The handshake messages are not processed until Read() is
11380 // called, which then detects that the handshake was aborted, due to the
11381 // peer sending a handshake_failure because it requires a client
11383 SSLSocketDataProvider
ssl_data2(ASYNC
, OK
);
11384 ssl_data2
.cert_request_info
= cert_request
.get();
11385 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11386 MockRead data2_reads
[] = {
11387 MockRead(ASYNC
/* async */, ERR_SSL_PROTOCOL_ERROR
),
11389 StaticSocketDataProvider
data2(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11390 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11392 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
11393 // the data for the SSL handshake once the TLSv1.1 connection falls back to
11394 // TLSv1. It has the same behaviour as [ssl_]data2.
11395 SSLSocketDataProvider
ssl_data3(ASYNC
, OK
);
11396 ssl_data3
.cert_request_info
= cert_request
.get();
11397 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11398 StaticSocketDataProvider
data3(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11399 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11401 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
11402 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
11403 SSLSocketDataProvider
ssl_data4(ASYNC
, OK
);
11404 ssl_data4
.cert_request_info
= cert_request
.get();
11405 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data4
);
11406 StaticSocketDataProvider
data4(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11407 session_deps_
.socket_factory
->AddSocketDataProvider(&data4
);
11409 // Need one more if TLSv1.2 is enabled.
11410 SSLSocketDataProvider
ssl_data5(ASYNC
, OK
);
11411 ssl_data5
.cert_request_info
= cert_request
.get();
11412 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data5
);
11413 StaticSocketDataProvider
data5(data2_reads
, arraysize(data2_reads
), NULL
, 0);
11414 session_deps_
.socket_factory
->AddSocketDataProvider(&data5
);
11416 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11417 scoped_ptr
<HttpTransaction
> trans(
11418 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11420 // Begin the initial SSL handshake.
11421 TestCompletionCallback callback
;
11422 int rv
= trans
->Start(&request_info
, callback
.callback(), BoundNetLog());
11423 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11425 // Complete the SSL handshake, which should abort due to requiring a
11426 // client certificate.
11427 rv
= callback
.WaitForResult();
11428 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11430 // Indicate that no certificate should be supplied. From the perspective
11431 // of SSLClientCertCache, NULL is just as meaningful as a real
11432 // certificate, so this is the same as supply a
11433 // legitimate-but-unacceptable certificate.
11434 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11435 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11437 // Ensure the certificate was added to the client auth cache before
11438 // allowing the connection to continue restarting.
11439 scoped_refptr
<X509Certificate
> client_cert
;
11440 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11441 HostPortPair("www.example.com", 443), &client_cert
));
11442 ASSERT_EQ(NULL
, client_cert
.get());
11444 // Restart the handshake. This will consume ssl_data2, which fails, and
11445 // then consume ssl_data3 and ssl_data4, both of which should also fail.
11446 // The result code is checked against what ssl_data4 should return.
11447 rv
= callback
.WaitForResult();
11448 ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR
, rv
);
11450 // Ensure that the client certificate is removed from the cache on a
11451 // handshake failure.
11452 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11453 HostPortPair("www.example.com", 443), &client_cert
));
11456 // Ensure that a client certificate is removed from the SSL client auth
11458 // 1) An HTTPS proxy is involved.
11459 // 3) The HTTPS proxy requests a client certificate.
11460 // 4) The client supplies an invalid/unacceptable certificate for the
11462 // The test is repeated twice, first for connecting to an HTTPS endpoint,
11463 // then for connecting to an HTTP endpoint.
11464 TEST_P(HttpNetworkTransactionTest
, ClientAuthCertCache_Proxy_Fail
) {
11465 session_deps_
.proxy_service
.reset(
11466 ProxyService::CreateFixed("https://proxy:70"));
11467 BoundTestNetLog log
;
11468 session_deps_
.net_log
= log
.bound().net_log();
11470 scoped_refptr
<SSLCertRequestInfo
> cert_request(new SSLCertRequestInfo());
11471 cert_request
->host_and_port
= HostPortPair("proxy", 70);
11473 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
11474 // [ssl_]data[1-3]. Rather than represending the endpoint
11475 // (www.example.com:443), they represent failures with the HTTPS proxy
11477 SSLSocketDataProvider
ssl_data1(ASYNC
, ERR_SSL_CLIENT_AUTH_CERT_NEEDED
);
11478 ssl_data1
.cert_request_info
= cert_request
.get();
11479 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data1
);
11480 StaticSocketDataProvider
data1(NULL
, 0, NULL
, 0);
11481 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11483 SSLSocketDataProvider
ssl_data2(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11484 ssl_data2
.cert_request_info
= cert_request
.get();
11485 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data2
);
11486 StaticSocketDataProvider
data2(NULL
, 0, NULL
, 0);
11487 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11489 // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
11491 SSLSocketDataProvider
ssl_data3(ASYNC
, ERR_SSL_PROTOCOL_ERROR
);
11492 ssl_data3
.cert_request_info
= cert_request
.get();
11493 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl_data3
);
11494 StaticSocketDataProvider
data3(NULL
, 0, NULL
, 0);
11495 session_deps_
.socket_factory
->AddSocketDataProvider(&data3
);
11498 HttpRequestInfo requests
[2];
11499 requests
[0].url
= GURL("https://www.example.com/");
11500 requests
[0].method
= "GET";
11501 requests
[0].load_flags
= LOAD_NORMAL
;
11503 requests
[1].url
= GURL("http://www.example.com/");
11504 requests
[1].method
= "GET";
11505 requests
[1].load_flags
= LOAD_NORMAL
;
11507 for (size_t i
= 0; i
< arraysize(requests
); ++i
) {
11508 session_deps_
.socket_factory
->ResetNextMockIndexes();
11509 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11510 scoped_ptr
<HttpNetworkTransaction
> trans(
11511 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
11513 // Begin the SSL handshake with the proxy.
11514 TestCompletionCallback callback
;
11515 int rv
= trans
->Start(&requests
[i
], callback
.callback(), BoundNetLog());
11516 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11518 // Complete the SSL handshake, which should abort due to requiring a
11519 // client certificate.
11520 rv
= callback
.WaitForResult();
11521 ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED
, rv
);
11523 // Indicate that no certificate should be supplied. From the perspective
11524 // of SSLClientCertCache, NULL is just as meaningful as a real
11525 // certificate, so this is the same as supply a
11526 // legitimate-but-unacceptable certificate.
11527 rv
= trans
->RestartWithCertificate(NULL
, callback
.callback());
11528 ASSERT_EQ(ERR_IO_PENDING
, rv
);
11530 // Ensure the certificate was added to the client auth cache before
11531 // allowing the connection to continue restarting.
11532 scoped_refptr
<X509Certificate
> client_cert
;
11533 ASSERT_TRUE(session
->ssl_client_auth_cache()->Lookup(
11534 HostPortPair("proxy", 70), &client_cert
));
11535 ASSERT_EQ(NULL
, client_cert
.get());
11536 // Ensure the certificate was NOT cached for the endpoint. This only
11537 // applies to HTTPS requests, but is fine to check for HTTP requests.
11538 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11539 HostPortPair("www.example.com", 443), &client_cert
));
11541 // Restart the handshake. This will consume ssl_data2, which fails, and
11542 // then consume ssl_data3, which should also fail. The result code is
11543 // checked against what ssl_data3 should return.
11544 rv
= callback
.WaitForResult();
11545 ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED
, rv
);
11547 // Now that the new handshake has failed, ensure that the client
11548 // certificate was removed from the client auth cache.
11549 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11550 HostPortPair("proxy", 70), &client_cert
));
11551 ASSERT_FALSE(session
->ssl_client_auth_cache()->Lookup(
11552 HostPortPair("www.example.com", 443), &client_cert
));
11556 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPooling
) {
11557 session_deps_
.use_alternate_protocols
= true;
11558 session_deps_
.next_protos
= SpdyNextProtos();
11560 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11561 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11562 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11563 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11564 pool_peer
.DisableDomainAuthenticationVerification();
11566 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11567 ssl
.SetNextProto(GetParam());
11568 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11570 scoped_ptr
<SpdyFrame
> host1_req(
11571 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11572 scoped_ptr
<SpdyFrame
> host2_req(
11573 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11574 MockWrite spdy_writes
[] = {
11575 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11577 scoped_ptr
<SpdyFrame
> host1_resp(
11578 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11579 scoped_ptr
<SpdyFrame
> host1_resp_body(
11580 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11581 scoped_ptr
<SpdyFrame
> host2_resp(
11582 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11583 scoped_ptr
<SpdyFrame
> host2_resp_body(
11584 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11585 MockRead spdy_reads
[] = {
11586 CreateMockRead(*host1_resp
, 1),
11587 CreateMockRead(*host1_resp_body
, 2),
11588 CreateMockRead(*host2_resp
, 4),
11589 CreateMockRead(*host2_resp_body
, 5),
11590 MockRead(ASYNC
, 0, 6),
11593 IPAddressNumber ip
;
11594 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11595 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11596 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11597 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11598 spdy_writes
, arraysize(spdy_writes
));
11599 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11601 TestCompletionCallback callback
;
11602 HttpRequestInfo request1
;
11603 request1
.method
= "GET";
11604 request1
.url
= GURL("https://www.example.org/");
11605 request1
.load_flags
= 0;
11606 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11608 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11609 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11610 EXPECT_EQ(OK
, callback
.WaitForResult());
11612 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11613 ASSERT_TRUE(response
!= NULL
);
11614 ASSERT_TRUE(response
->headers
.get() != NULL
);
11615 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11617 std::string response_data
;
11618 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11619 EXPECT_EQ("hello!", response_data
);
11621 // Preload www.gmail.com into HostCache.
11622 HostPortPair
host_port("www.gmail.com", 443);
11623 HostResolver::RequestInfo
resolve_info(host_port
);
11624 AddressList ignored
;
11625 rv
= session_deps_
.host_resolver
->Resolve(resolve_info
,
11628 callback
.callback(),
11631 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11632 rv
= callback
.WaitForResult();
11635 HttpRequestInfo request2
;
11636 request2
.method
= "GET";
11637 request2
.url
= GURL("https://www.gmail.com/");
11638 request2
.load_flags
= 0;
11639 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11641 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11642 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11643 EXPECT_EQ(OK
, callback
.WaitForResult());
11645 response
= trans2
.GetResponseInfo();
11646 ASSERT_TRUE(response
!= NULL
);
11647 ASSERT_TRUE(response
->headers
.get() != NULL
);
11648 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11649 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11650 EXPECT_TRUE(response
->was_npn_negotiated
);
11651 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11652 EXPECT_EQ("hello!", response_data
);
11655 TEST_P(HttpNetworkTransactionTest
, UseIPConnectionPoolingAfterResolution
) {
11656 session_deps_
.use_alternate_protocols
= true;
11657 session_deps_
.next_protos
= SpdyNextProtos();
11659 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
11660 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
11661 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11662 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11663 pool_peer
.DisableDomainAuthenticationVerification();
11665 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11666 ssl
.SetNextProto(GetParam());
11667 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11669 scoped_ptr
<SpdyFrame
> host1_req(
11670 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11671 scoped_ptr
<SpdyFrame
> host2_req(
11672 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11673 MockWrite spdy_writes
[] = {
11674 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11676 scoped_ptr
<SpdyFrame
> host1_resp(
11677 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11678 scoped_ptr
<SpdyFrame
> host1_resp_body(
11679 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11680 scoped_ptr
<SpdyFrame
> host2_resp(
11681 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11682 scoped_ptr
<SpdyFrame
> host2_resp_body(
11683 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11684 MockRead spdy_reads
[] = {
11685 CreateMockRead(*host1_resp
, 1),
11686 CreateMockRead(*host1_resp_body
, 2),
11687 CreateMockRead(*host2_resp
, 4),
11688 CreateMockRead(*host2_resp_body
, 5),
11689 MockRead(ASYNC
, 0, 6),
11692 IPAddressNumber ip
;
11693 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11694 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11695 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11696 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11697 spdy_writes
, arraysize(spdy_writes
));
11698 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11700 TestCompletionCallback callback
;
11701 HttpRequestInfo request1
;
11702 request1
.method
= "GET";
11703 request1
.url
= GURL("https://www.example.org/");
11704 request1
.load_flags
= 0;
11705 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11707 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11708 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11709 EXPECT_EQ(OK
, callback
.WaitForResult());
11711 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11712 ASSERT_TRUE(response
!= NULL
);
11713 ASSERT_TRUE(response
->headers
.get() != NULL
);
11714 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11716 std::string response_data
;
11717 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11718 EXPECT_EQ("hello!", response_data
);
11720 HttpRequestInfo request2
;
11721 request2
.method
= "GET";
11722 request2
.url
= GURL("https://www.gmail.com/");
11723 request2
.load_flags
= 0;
11724 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11726 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11727 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11728 EXPECT_EQ(OK
, callback
.WaitForResult());
11730 response
= trans2
.GetResponseInfo();
11731 ASSERT_TRUE(response
!= NULL
);
11732 ASSERT_TRUE(response
->headers
.get() != NULL
);
11733 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11734 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11735 EXPECT_TRUE(response
->was_npn_negotiated
);
11736 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11737 EXPECT_EQ("hello!", response_data
);
11740 class OneTimeCachingHostResolver
: public HostResolver
{
11742 explicit OneTimeCachingHostResolver(const HostPortPair
& host_port
)
11743 : host_port_(host_port
) {}
11744 ~OneTimeCachingHostResolver() override
{}
11746 RuleBasedHostResolverProc
* rules() { return host_resolver_
.rules(); }
11748 // HostResolver methods:
11749 int Resolve(const RequestInfo
& info
,
11750 RequestPriority priority
,
11751 AddressList
* addresses
,
11752 const CompletionCallback
& callback
,
11753 RequestHandle
* out_req
,
11754 const BoundNetLog
& net_log
) override
{
11755 return host_resolver_
.Resolve(
11756 info
, priority
, addresses
, callback
, out_req
, net_log
);
11759 int ResolveFromCache(const RequestInfo
& info
,
11760 AddressList
* addresses
,
11761 const BoundNetLog
& net_log
) override
{
11762 int rv
= host_resolver_
.ResolveFromCache(info
, addresses
, net_log
);
11763 if (rv
== OK
&& info
.host_port_pair().Equals(host_port_
))
11764 host_resolver_
.GetHostCache()->clear();
11768 void CancelRequest(RequestHandle req
) override
{
11769 host_resolver_
.CancelRequest(req
);
11772 MockCachingHostResolver
* GetMockHostResolver() {
11773 return &host_resolver_
;
11777 MockCachingHostResolver host_resolver_
;
11778 const HostPortPair host_port_
;
11781 TEST_P(HttpNetworkTransactionTest
,
11782 UseIPConnectionPoolingWithHostCacheExpiration
) {
11783 session_deps_
.use_alternate_protocols
= true;
11784 session_deps_
.next_protos
= SpdyNextProtos();
11786 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
11787 OneTimeCachingHostResolver
host_resolver(HostPortPair("www.gmail.com", 443));
11788 HttpNetworkSession::Params params
=
11789 SpdySessionDependencies::CreateSessionParams(&session_deps_
);
11790 params
.host_resolver
= &host_resolver
;
11791 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11792 SpdySessionPoolPeer
pool_peer(session
->spdy_session_pool());
11793 pool_peer
.DisableDomainAuthenticationVerification();
11795 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11796 ssl
.SetNextProto(GetParam());
11797 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11799 scoped_ptr
<SpdyFrame
> host1_req(
11800 spdy_util_
.ConstructSpdyGet("https://www.example.org", false, 1, LOWEST
));
11801 scoped_ptr
<SpdyFrame
> host2_req(
11802 spdy_util_
.ConstructSpdyGet("https://www.gmail.com", false, 3, LOWEST
));
11803 MockWrite spdy_writes
[] = {
11804 CreateMockWrite(*host1_req
, 0), CreateMockWrite(*host2_req
, 3),
11806 scoped_ptr
<SpdyFrame
> host1_resp(
11807 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11808 scoped_ptr
<SpdyFrame
> host1_resp_body(
11809 spdy_util_
.ConstructSpdyBodyFrame(1, true));
11810 scoped_ptr
<SpdyFrame
> host2_resp(
11811 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
11812 scoped_ptr
<SpdyFrame
> host2_resp_body(
11813 spdy_util_
.ConstructSpdyBodyFrame(3, true));
11814 MockRead spdy_reads
[] = {
11815 CreateMockRead(*host1_resp
, 1),
11816 CreateMockRead(*host1_resp_body
, 2),
11817 CreateMockRead(*host2_resp
, 4),
11818 CreateMockRead(*host2_resp_body
, 5),
11819 MockRead(ASYNC
, 0, 6),
11822 IPAddressNumber ip
;
11823 ASSERT_TRUE(ParseIPLiteralToNumber("127.0.0.1", &ip
));
11824 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
11825 MockConnect
connect(ASYNC
, OK
, peer_addr
);
11826 SequencedSocketData
spdy_data(connect
, spdy_reads
, arraysize(spdy_reads
),
11827 spdy_writes
, arraysize(spdy_writes
));
11828 session_deps_
.socket_factory
->AddSocketDataProvider(&spdy_data
);
11830 TestCompletionCallback callback
;
11831 HttpRequestInfo request1
;
11832 request1
.method
= "GET";
11833 request1
.url
= GURL("https://www.example.org/");
11834 request1
.load_flags
= 0;
11835 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
11837 int rv
= trans1
.Start(&request1
, callback
.callback(), BoundNetLog());
11838 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11839 EXPECT_EQ(OK
, callback
.WaitForResult());
11841 const HttpResponseInfo
* response
= trans1
.GetResponseInfo();
11842 ASSERT_TRUE(response
!= NULL
);
11843 ASSERT_TRUE(response
->headers
.get() != NULL
);
11844 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11846 std::string response_data
;
11847 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data
));
11848 EXPECT_EQ("hello!", response_data
);
11850 // Preload cache entries into HostCache.
11851 HostResolver::RequestInfo
resolve_info(HostPortPair("www.gmail.com", 443));
11852 AddressList ignored
;
11853 rv
= host_resolver
.Resolve(resolve_info
,
11856 callback
.callback(),
11859 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11860 rv
= callback
.WaitForResult();
11863 HttpRequestInfo request2
;
11864 request2
.method
= "GET";
11865 request2
.url
= GURL("https://www.gmail.com/");
11866 request2
.load_flags
= 0;
11867 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
11869 rv
= trans2
.Start(&request2
, callback
.callback(), BoundNetLog());
11870 EXPECT_EQ(ERR_IO_PENDING
, rv
);
11871 EXPECT_EQ(OK
, callback
.WaitForResult());
11873 response
= trans2
.GetResponseInfo();
11874 ASSERT_TRUE(response
!= NULL
);
11875 ASSERT_TRUE(response
->headers
.get() != NULL
);
11876 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
11877 EXPECT_TRUE(response
->was_fetched_via_spdy
);
11878 EXPECT_TRUE(response
->was_npn_negotiated
);
11879 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data
));
11880 EXPECT_EQ("hello!", response_data
);
11883 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttp
) {
11884 const std::string https_url
= "https://www.example.org:8080/";
11885 const std::string http_url
= "http://www.example.org:8080/";
11887 // SPDY GET for HTTPS URL
11888 scoped_ptr
<SpdyFrame
> req1(
11889 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
11891 MockWrite writes1
[] = {
11892 CreateMockWrite(*req1
, 0),
11895 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
11896 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
11897 MockRead reads1
[] = {
11898 CreateMockRead(*resp1
, 1),
11899 CreateMockRead(*body1
, 2),
11900 MockRead(ASYNC
, ERR_IO_PENDING
, 3)
11903 SequencedSocketData
data1(reads1
, arraysize(reads1
), writes1
,
11904 arraysize(writes1
));
11905 MockConnect
connect_data1(ASYNC
, OK
);
11906 data1
.set_connect_data(connect_data1
);
11908 // HTTP GET for the HTTP URL
11909 MockWrite writes2
[] = {
11910 MockWrite(ASYNC
, 0,
11911 "GET / HTTP/1.1\r\n"
11912 "Host: www.example.org:8080\r\n"
11913 "Connection: keep-alive\r\n\r\n"),
11916 MockRead reads2
[] = {
11917 MockRead(ASYNC
, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
11918 MockRead(ASYNC
, 2, "hello"),
11919 MockRead(ASYNC
, OK
, 3),
11922 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
11923 arraysize(writes2
));
11925 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11926 ssl
.SetNextProto(GetParam());
11927 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11928 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
11929 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
11931 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
11933 // Start the first transaction to set up the SpdySession
11934 HttpRequestInfo request1
;
11935 request1
.method
= "GET";
11936 request1
.url
= GURL(https_url
);
11937 request1
.load_flags
= 0;
11938 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
11939 TestCompletionCallback callback1
;
11940 EXPECT_EQ(ERR_IO_PENDING
,
11941 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
11942 base::MessageLoop::current()->RunUntilIdle();
11944 EXPECT_EQ(OK
, callback1
.WaitForResult());
11945 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
11947 // Now, start the HTTP request
11948 HttpRequestInfo request2
;
11949 request2
.method
= "GET";
11950 request2
.url
= GURL(http_url
);
11951 request2
.load_flags
= 0;
11952 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
11953 TestCompletionCallback callback2
;
11954 EXPECT_EQ(ERR_IO_PENDING
,
11955 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
11956 base::MessageLoop::current()->RunUntilIdle();
11958 EXPECT_EQ(OK
, callback2
.WaitForResult());
11959 EXPECT_FALSE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
11962 class AltSvcCertificateVerificationTest
: public HttpNetworkTransactionTest
{
11964 void Run(bool pooling
, bool valid
) {
11965 HostPortPair
origin(valid
? "mail.example.org" : "invalid.example.org",
11967 HostPortPair
alternative("www.example.org", 443);
11969 base::FilePath certs_dir
= GetTestCertsDirectory();
11970 scoped_refptr
<X509Certificate
> cert(
11971 ImportCertFromFile(certs_dir
, "spdy_pooling.pem"));
11972 ASSERT_TRUE(cert
.get());
11973 bool common_name_fallback_used
;
11975 cert
->VerifyNameMatch(origin
.host(), &common_name_fallback_used
));
11977 cert
->VerifyNameMatch(alternative
.host(), &common_name_fallback_used
));
11978 SSLSocketDataProvider
ssl(ASYNC
, OK
);
11979 ssl
.SetNextProto(GetParam());
11981 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
11983 // If pooling, then start a request to alternative first to create a
11985 std::string url0
= "https://www.example.org:443";
11986 // Second request to origin, which has an alternative service, and could
11987 // open a connection to the alternative host or pool to the existing one.
11988 std::string
url1("https://");
11989 url1
.append(origin
.host());
11990 url1
.append(":443");
11992 scoped_ptr
<SpdyFrame
> req0
;
11993 scoped_ptr
<SpdyFrame
> req1
;
11994 scoped_ptr
<SpdyFrame
> resp0
;
11995 scoped_ptr
<SpdyFrame
> body0
;
11996 scoped_ptr
<SpdyFrame
> resp1
;
11997 scoped_ptr
<SpdyFrame
> body1
;
11998 std::vector
<MockWrite
> writes
;
11999 std::vector
<MockRead
> reads
;
12002 req0
.reset(spdy_util_
.ConstructSpdyGet(url0
.c_str(), false, 1, LOWEST
));
12003 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 3, LOWEST
));
12005 writes
.push_back(CreateMockWrite(*req0
, 0));
12006 writes
.push_back(CreateMockWrite(*req1
, 3));
12008 resp0
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12009 body0
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12010 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12011 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12013 reads
.push_back(CreateMockRead(*resp0
, 1));
12014 reads
.push_back(CreateMockRead(*body0
, 2));
12015 reads
.push_back(MockRead(ASYNC
, ERR_IO_PENDING
, 4));
12016 reads
.push_back(CreateMockRead(*resp1
, 5));
12017 reads
.push_back(CreateMockRead(*body1
, 6));
12018 reads
.push_back(MockRead(ASYNC
, OK
, 7));
12020 req1
.reset(spdy_util_
.ConstructSpdyGet(url1
.c_str(), false, 1, LOWEST
));
12022 writes
.push_back(CreateMockWrite(*req1
, 0));
12024 resp1
.reset(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12025 body1
.reset(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12027 reads
.push_back(CreateMockRead(*resp1
, 1));
12028 reads
.push_back(CreateMockRead(*body1
, 2));
12029 reads
.push_back(MockRead(ASYNC
, OK
, 3));
12032 SequencedSocketData
data(vector_as_array(&reads
), reads
.size(),
12033 vector_as_array(&writes
), writes
.size());
12034 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12036 // Connection to the origin fails.
12037 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12038 StaticSocketDataProvider data_refused
;
12039 data_refused
.set_connect_data(mock_connect
);
12040 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12042 session_deps_
.use_alternate_protocols
= true;
12043 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12044 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12045 session
->http_server_properties();
12046 AlternativeService
alternative_service(
12047 AlternateProtocolFromNextProto(GetParam()), alternative
);
12048 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12049 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12052 // First request to alternative.
12054 scoped_ptr
<HttpTransaction
> trans0(
12055 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12056 HttpRequestInfo request0
;
12057 request0
.method
= "GET";
12058 request0
.url
= GURL(url0
);
12059 request0
.load_flags
= 0;
12060 TestCompletionCallback callback0
;
12062 int rv
= trans0
->Start(&request0
, callback0
.callback(), BoundNetLog());
12063 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12064 rv
= callback0
.WaitForResult();
12068 // Second request to origin.
12069 scoped_ptr
<HttpTransaction
> trans1(
12070 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12071 HttpRequestInfo request1
;
12072 request1
.method
= "GET";
12073 request1
.url
= GURL(url1
);
12074 request1
.load_flags
= 0;
12075 TestCompletionCallback callback1
;
12077 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12078 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12079 base::MessageLoop::current()->RunUntilIdle();
12080 if (data
.IsReadPaused()) {
12081 data
.CompleteRead();
12083 rv
= callback1
.WaitForResult();
12088 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12090 EXPECT_EQ(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN
, rv
);
12096 INSTANTIATE_TEST_CASE_P(NextProto
,
12097 AltSvcCertificateVerificationTest
,
12098 testing::Values(kProtoSPDY31
,
12102 // The alternative service host must exhibit a certificate that is valid for the
12103 // origin host. Test that this is enforced when pooling to an existing
12105 TEST_P(AltSvcCertificateVerificationTest
, PoolingValid
) {
12109 TEST_P(AltSvcCertificateVerificationTest
, PoolingInvalid
) {
12113 // The alternative service host must exhibit a certificate that is valid for the
12114 // origin host. Test that this is enforced when opening a new connection.
12115 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionValid
) {
12119 TEST_P(AltSvcCertificateVerificationTest
, NewConnectionInvalid
) {
12123 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
12124 // with the alternative server. That connection should not be used.
12125 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceNotOnHttp11
) {
12126 HostPortPair
origin("origin.example.org", 443);
12127 HostPortPair
alternative("alternative.example.org", 443);
12129 // Negotiate HTTP/1.1 with alternative.example.org.
12130 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12131 ssl
.SetNextProto(kProtoHTTP11
);
12132 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12134 // No data should be read from the alternative, because HTTP/1.1 is
12136 StaticSocketDataProvider data
;
12137 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12139 // This test documents that an alternate Job should not be used if HTTP/1.1 is
12140 // negotiated. In order to test this, a failed connection to the origin is
12141 // mocked. This way the request relies on the alternate Job.
12142 StaticSocketDataProvider data_refused
;
12143 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12144 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12146 // Set up alternative service for origin.
12147 session_deps_
.use_alternate_protocols
= true;
12148 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12149 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12150 session
->http_server_properties();
12151 AlternativeService
alternative_service(
12152 AlternateProtocolFromNextProto(GetParam()), alternative
);
12153 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12154 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12157 scoped_ptr
<HttpTransaction
> trans(
12158 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12159 HttpRequestInfo request
;
12160 request
.method
= "GET";
12161 request
.url
= GURL("https://origin.example.org:443");
12162 request
.load_flags
= 0;
12163 TestCompletionCallback callback
;
12165 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
12166 // negotiated, the alternate Job should fail with ERR_NPN_NEGOTIATION_FAILED.
12167 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12168 EXPECT_EQ(ERR_NPN_NEGOTIATION_FAILED
, callback
.GetResult(rv
));
12171 // A request to a server with an alternative service fires two Jobs: one to the
12172 // origin, and an alternate one to the alternative server. If the former
12173 // succeeds, the request should succeed, even if the latter fails because
12174 // HTTP/1.1 is negotiated which is insufficient for alternative service.
12175 TEST_P(HttpNetworkTransactionTest
, FailedAlternativeServiceIsNotUserVisible
) {
12176 HostPortPair
origin("origin.example.org", 443);
12177 HostPortPair
alternative("alternative.example.org", 443);
12179 // Negotiate HTTP/1.1 with alternative.
12180 SSLSocketDataProvider
alternative_ssl(ASYNC
, OK
);
12181 alternative_ssl
.SetNextProto(kProtoHTTP11
);
12182 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&alternative_ssl
);
12184 // No data should be read from the alternative, because HTTP/1.1 is
12186 StaticSocketDataProvider data
;
12187 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12189 // Negotiate HTTP/1.1 with origin.
12190 SSLSocketDataProvider
origin_ssl(ASYNC
, OK
);
12191 origin_ssl
.SetNextProto(kProtoHTTP11
);
12192 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&origin_ssl
);
12194 MockWrite http_writes
[] = {
12196 "GET / HTTP/1.1\r\n"
12197 "Host: origin.example.org\r\n"
12198 "Connection: keep-alive\r\n\r\n"),
12200 "GET /second HTTP/1.1\r\n"
12201 "Host: origin.example.org\r\n"
12202 "Connection: keep-alive\r\n\r\n"),
12205 MockRead http_reads
[] = {
12206 MockRead("HTTP/1.1 200 OK\r\n"),
12207 MockRead("Content-Type: text/html\r\n"),
12208 MockRead("Content-Length: 6\r\n\r\n"),
12209 MockRead("foobar"),
12210 MockRead("HTTP/1.1 200 OK\r\n"),
12211 MockRead("Content-Type: text/html\r\n"),
12212 MockRead("Content-Length: 7\r\n\r\n"),
12213 MockRead("another"),
12215 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12216 http_writes
, arraysize(http_writes
));
12217 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12219 // Set up alternative service for origin.
12220 session_deps_
.use_alternate_protocols
= true;
12221 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12222 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12223 session
->http_server_properties();
12224 AlternativeService
alternative_service(
12225 AlternateProtocolFromNextProto(GetParam()), alternative
);
12226 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12227 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12230 HttpNetworkTransaction
trans1(DEFAULT_PRIORITY
, session
.get());
12231 HttpRequestInfo request1
;
12232 request1
.method
= "GET";
12233 request1
.url
= GURL("https://origin.example.org:443");
12234 request1
.load_flags
= 0;
12235 TestCompletionCallback callback1
;
12237 int rv
= trans1
.Start(&request1
, callback1
.callback(), BoundNetLog());
12238 rv
= callback1
.GetResult(rv
);
12241 const HttpResponseInfo
* response1
= trans1
.GetResponseInfo();
12242 ASSERT_TRUE(response1
!= nullptr);
12243 ASSERT_TRUE(response1
->headers
.get() != nullptr);
12244 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12246 std::string response_data1
;
12247 ASSERT_EQ(OK
, ReadTransaction(&trans1
, &response_data1
));
12248 EXPECT_EQ("foobar", response_data1
);
12250 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
12251 // for alternative service.
12253 http_server_properties
->IsAlternativeServiceBroken(alternative_service
));
12255 // Since |alternative_service| is broken, a second transaction to origin
12256 // should not start an alternate Job. It should pool to existing connection
12258 HttpNetworkTransaction
trans2(DEFAULT_PRIORITY
, session
.get());
12259 HttpRequestInfo request2
;
12260 request2
.method
= "GET";
12261 request2
.url
= GURL("https://origin.example.org:443/second");
12262 request2
.load_flags
= 0;
12263 TestCompletionCallback callback2
;
12265 rv
= trans2
.Start(&request2
, callback2
.callback(), BoundNetLog());
12266 rv
= callback2
.GetResult(rv
);
12269 const HttpResponseInfo
* response2
= trans2
.GetResponseInfo();
12270 ASSERT_TRUE(response2
!= nullptr);
12271 ASSERT_TRUE(response2
->headers
.get() != nullptr);
12272 EXPECT_EQ("HTTP/1.1 200 OK", response2
->headers
->GetStatusLine());
12274 std::string response_data2
;
12275 ASSERT_EQ(OK
, ReadTransaction(&trans2
, &response_data2
));
12276 EXPECT_EQ("another", response_data2
);
12279 // Alternative service requires HTTP/2 (or SPDY), but there is already a
12280 // HTTP/1.1 socket open to the alternative server. That socket should not be
12282 TEST_P(HttpNetworkTransactionTest
, AlternativeServiceShouldNotPoolToHttp11
) {
12283 HostPortPair
origin("origin.example.org", 443);
12284 HostPortPair
alternative("alternative.example.org", 443);
12285 std::string origin_url
= "https://origin.example.org:443";
12286 std::string alternative_url
= "https://alternative.example.org:443";
12288 // Negotiate HTTP/1.1 with alternative.example.org.
12289 SSLSocketDataProvider
ssl(ASYNC
, OK
);
12290 ssl
.SetNextProto(kProtoHTTP11
);
12291 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
12293 // HTTP/1.1 data for |request1| and |request2|.
12294 MockWrite http_writes
[] = {
12296 "GET / HTTP/1.1\r\n"
12297 "Host: alternative.example.org\r\n"
12298 "Connection: keep-alive\r\n\r\n"),
12300 "GET / HTTP/1.1\r\n"
12301 "Host: alternative.example.org\r\n"
12302 "Connection: keep-alive\r\n\r\n"),
12305 MockRead http_reads
[] = {
12307 "HTTP/1.1 200 OK\r\n"
12308 "Content-Type: text/html; charset=iso-8859-1\r\n"
12309 "Content-Length: 40\r\n\r\n"
12310 "first HTTP/1.1 response from alternative"),
12312 "HTTP/1.1 200 OK\r\n"
12313 "Content-Type: text/html; charset=iso-8859-1\r\n"
12314 "Content-Length: 41\r\n\r\n"
12315 "second HTTP/1.1 response from alternative"),
12317 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
12318 http_writes
, arraysize(http_writes
));
12319 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12321 // This test documents that an alternate Job should not pool to an already
12322 // existing HTTP/1.1 connection. In order to test this, a failed connection
12323 // to the origin is mocked. This way |request2| relies on the alternate Job.
12324 StaticSocketDataProvider data_refused
;
12325 data_refused
.set_connect_data(MockConnect(ASYNC
, ERR_CONNECTION_REFUSED
));
12326 session_deps_
.socket_factory
->AddSocketDataProvider(&data_refused
);
12328 // Set up alternative service for origin.
12329 session_deps_
.use_alternate_protocols
= true;
12330 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12331 base::WeakPtr
<HttpServerProperties
> http_server_properties
=
12332 session
->http_server_properties();
12333 AlternativeService
alternative_service(
12334 AlternateProtocolFromNextProto(GetParam()), alternative
);
12335 base::Time expiration
= base::Time::Now() + base::TimeDelta::FromDays(1);
12336 http_server_properties
->SetAlternativeService(origin
, alternative_service
,
12339 // First transaction to alternative to open an HTTP/1.1 socket.
12340 scoped_ptr
<HttpTransaction
> trans1(
12341 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12342 HttpRequestInfo request1
;
12343 request1
.method
= "GET";
12344 request1
.url
= GURL(alternative_url
);
12345 request1
.load_flags
= 0;
12346 TestCompletionCallback callback1
;
12348 int rv
= trans1
->Start(&request1
, callback1
.callback(), BoundNetLog());
12349 EXPECT_EQ(OK
, callback1
.GetResult(rv
));
12350 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
12351 ASSERT_TRUE(response1
);
12352 ASSERT_TRUE(response1
->headers
.get());
12353 EXPECT_EQ("HTTP/1.1 200 OK", response1
->headers
->GetStatusLine());
12354 EXPECT_TRUE(response1
->was_npn_negotiated
);
12355 EXPECT_FALSE(response1
->was_fetched_via_spdy
);
12356 std::string response_data1
;
12357 ASSERT_EQ(OK
, ReadTransaction(trans1
.get(), &response_data1
));
12358 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1
);
12360 // Request for origin.example.org, which has an alternative service. This
12361 // will start two Jobs: the alternative looks for connections to pool to,
12362 // finds one which is HTTP/1.1, and should ignore it, and should not try to
12363 // open other connections to alternative server. The Job to origin fails, so
12364 // this request fails.
12365 scoped_ptr
<HttpTransaction
> trans2(
12366 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12367 HttpRequestInfo request2
;
12368 request2
.method
= "GET";
12369 request2
.url
= GURL(origin_url
);
12370 request2
.load_flags
= 0;
12371 TestCompletionCallback callback2
;
12373 rv
= trans2
->Start(&request2
, callback2
.callback(), BoundNetLog());
12374 EXPECT_EQ(ERR_CONNECTION_REFUSED
, callback2
.GetResult(rv
));
12376 // Another transaction to alternative. This is to test that the HTTP/1.1
12377 // socket is still open and in the pool.
12378 scoped_ptr
<HttpTransaction
> trans3(
12379 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12380 HttpRequestInfo request3
;
12381 request3
.method
= "GET";
12382 request3
.url
= GURL(alternative_url
);
12383 request3
.load_flags
= 0;
12384 TestCompletionCallback callback3
;
12386 rv
= trans3
->Start(&request3
, callback3
.callback(), BoundNetLog());
12387 EXPECT_EQ(OK
, callback3
.GetResult(rv
));
12388 const HttpResponseInfo
* response3
= trans3
->GetResponseInfo();
12389 ASSERT_TRUE(response3
);
12390 ASSERT_TRUE(response3
->headers
.get());
12391 EXPECT_EQ("HTTP/1.1 200 OK", response3
->headers
->GetStatusLine());
12392 EXPECT_TRUE(response3
->was_npn_negotiated
);
12393 EXPECT_FALSE(response3
->was_fetched_via_spdy
);
12394 std::string response_data3
;
12395 ASSERT_EQ(OK
, ReadTransaction(trans3
.get(), &response_data3
));
12396 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3
);
12399 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionForHttpOverTunnel
) {
12400 const std::string https_url
= "https://www.example.org:8080/";
12401 const std::string http_url
= "http://www.example.org:8080/";
12403 // SPDY GET for HTTPS URL (through CONNECT tunnel)
12404 const HostPortPair
host_port_pair("www.example.org", 8080);
12405 scoped_ptr
<SpdyFrame
> connect(
12406 spdy_util_
.ConstructSpdyConnect(NULL
, 0, 1, LOWEST
, host_port_pair
));
12407 scoped_ptr
<SpdyFrame
> req1(
12408 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, LOWEST
));
12409 scoped_ptr
<SpdyFrame
> wrapped_req1(
12410 spdy_util_
.ConstructWrappedSpdyFrame(req1
, 1));
12412 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
12413 SpdyHeaderBlock req2_block
;
12414 req2_block
[spdy_util_
.GetMethodKey()] = "GET";
12415 req2_block
[spdy_util_
.GetPathKey()] = "/";
12416 req2_block
[spdy_util_
.GetHostKey()] = "www.example.org:8080";
12417 req2_block
[spdy_util_
.GetSchemeKey()] = "http";
12418 spdy_util_
.MaybeAddVersionHeader(&req2_block
);
12419 scoped_ptr
<SpdyFrame
> req2(
12420 spdy_util_
.ConstructSpdySyn(3, req2_block
, MEDIUM
, false, true));
12422 MockWrite writes1
[] = {
12423 CreateMockWrite(*connect
, 0),
12424 CreateMockWrite(*wrapped_req1
, 2),
12425 CreateMockWrite(*req2
, 5),
12428 scoped_ptr
<SpdyFrame
> conn_resp(
12429 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12430 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12431 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12432 scoped_ptr
<SpdyFrame
> wrapped_resp1(
12433 spdy_util_
.ConstructWrappedSpdyFrame(resp1
, 1));
12434 scoped_ptr
<SpdyFrame
> wrapped_body1(
12435 spdy_util_
.ConstructWrappedSpdyFrame(body1
, 1));
12436 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 3));
12437 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(3, true));
12438 MockRead reads1
[] = {
12439 CreateMockRead(*conn_resp
, 1),
12440 CreateMockRead(*wrapped_resp1
, 3),
12441 CreateMockRead(*wrapped_body1
, 4),
12442 CreateMockRead(*resp2
, 6),
12443 CreateMockRead(*body2
, 7),
12444 MockRead(ASYNC
, ERR_IO_PENDING
, 8)
12447 DeterministicSocketData
data1(reads1
, arraysize(reads1
),
12448 writes1
, arraysize(writes1
));
12449 MockConnect
connect_data1(ASYNC
, OK
);
12450 data1
.set_connect_data(connect_data1
);
12452 session_deps_
.proxy_service
.reset(
12453 ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"));
12455 session_deps_
.net_log
= &log
;
12456 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12457 ssl1
.SetNextProto(GetParam());
12458 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12459 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12460 ssl2
.SetNextProto(GetParam());
12461 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12462 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(&data1
);
12464 scoped_refptr
<HttpNetworkSession
> session(
12465 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12467 // Start the first transaction to set up the SpdySession
12468 HttpRequestInfo request1
;
12469 request1
.method
= "GET";
12470 request1
.url
= GURL(https_url
);
12471 request1
.load_flags
= 0;
12472 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12473 TestCompletionCallback callback1
;
12474 EXPECT_EQ(ERR_IO_PENDING
,
12475 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12476 base::MessageLoop::current()->RunUntilIdle();
12479 EXPECT_EQ(OK
, callback1
.WaitForResult());
12480 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12482 LoadTimingInfo load_timing_info1
;
12483 EXPECT_TRUE(trans1
.GetLoadTimingInfo(&load_timing_info1
));
12484 TestLoadTimingNotReusedWithPac(load_timing_info1
,
12485 CONNECT_TIMING_HAS_SSL_TIMES
);
12487 // Now, start the HTTP request
12488 HttpRequestInfo request2
;
12489 request2
.method
= "GET";
12490 request2
.url
= GURL(http_url
);
12491 request2
.load_flags
= 0;
12492 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12493 TestCompletionCallback callback2
;
12494 EXPECT_EQ(ERR_IO_PENDING
,
12495 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12496 base::MessageLoop::current()->RunUntilIdle();
12499 EXPECT_EQ(OK
, callback2
.WaitForResult());
12500 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12502 LoadTimingInfo load_timing_info2
;
12503 EXPECT_TRUE(trans2
.GetLoadTimingInfo(&load_timing_info2
));
12504 // The established SPDY sessions is considered reused by the HTTP request.
12505 TestLoadTimingReusedWithPac(load_timing_info2
);
12506 // HTTP requests over a SPDY session should have a different connection
12507 // socket_log_id than requests over a tunnel.
12508 EXPECT_NE(load_timing_info1
.socket_log_id
, load_timing_info2
.socket_log_id
);
12511 // Test that in the case where we have a SPDY session to a SPDY proxy
12512 // that we do not pool other origins that resolve to the same IP when
12513 // the certificate does not match the new origin.
12514 // http://crbug.com/134690
12515 TEST_P(HttpNetworkTransactionTest
, DoNotUseSpdySessionIfCertDoesNotMatch
) {
12516 const std::string url1
= "http://www.example.org/";
12517 const std::string url2
= "https://news.example.org/";
12518 const std::string ip_addr
= "1.2.3.4";
12520 // SPDY GET for HTTP URL (through SPDY proxy)
12521 scoped_ptr
<SpdyHeaderBlock
> headers(
12522 spdy_util_
.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
12523 scoped_ptr
<SpdyFrame
> req1(
12524 spdy_util_
.ConstructSpdySyn(1, *headers
, LOWEST
, false, true));
12526 MockWrite writes1
[] = {
12527 CreateMockWrite(*req1
, 0),
12530 scoped_ptr
<SpdyFrame
> resp1(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12531 scoped_ptr
<SpdyFrame
> body1(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12532 MockRead reads1
[] = {
12533 CreateMockRead(*resp1
, 1),
12534 CreateMockRead(*body1
, 2),
12535 MockRead(ASYNC
, OK
, 3) // EOF
12538 scoped_ptr
<DeterministicSocketData
> data1(
12539 new DeterministicSocketData(reads1
, arraysize(reads1
),
12540 writes1
, arraysize(writes1
)));
12541 IPAddressNumber ip
;
12542 ASSERT_TRUE(ParseIPLiteralToNumber(ip_addr
, &ip
));
12543 IPEndPoint peer_addr
= IPEndPoint(ip
, 443);
12544 MockConnect
connect_data1(ASYNC
, OK
, peer_addr
);
12545 data1
->set_connect_data(connect_data1
);
12547 // SPDY GET for HTTPS URL (direct)
12548 scoped_ptr
<SpdyFrame
> req2(
12549 spdy_util_
.ConstructSpdyGet(url2
.c_str(), false, 1, MEDIUM
));
12551 MockWrite writes2
[] = {
12552 CreateMockWrite(*req2
, 0),
12555 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12556 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12557 MockRead reads2
[] = {
12558 CreateMockRead(*resp2
, 1),
12559 CreateMockRead(*body2
, 2),
12560 MockRead(ASYNC
, OK
, 3) // EOF
12563 scoped_ptr
<DeterministicSocketData
> data2(
12564 new DeterministicSocketData(reads2
, arraysize(reads2
),
12565 writes2
, arraysize(writes2
)));
12566 MockConnect
connect_data2(ASYNC
, OK
);
12567 data2
->set_connect_data(connect_data2
);
12569 // Set up a proxy config that sends HTTP requests to a proxy, and
12570 // all others direct.
12571 ProxyConfig proxy_config
;
12572 proxy_config
.proxy_rules().ParseFromString("http=https://proxy:443");
12573 session_deps_
.proxy_service
.reset(new ProxyService(
12574 new ProxyConfigServiceFixed(proxy_config
), nullptr, NULL
));
12576 SSLSocketDataProvider
ssl1(ASYNC
, OK
); // to the proxy
12577 ssl1
.SetNextProto(GetParam());
12578 // Load a valid cert. Note, that this does not need to
12579 // be valid for proxy because the MockSSLClientSocket does
12580 // not actually verify it. But SpdySession will use this
12581 // to see if it is valid for the new origin
12582 ssl1
.cert
= ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
12583 ASSERT_TRUE(ssl1
.cert
.get());
12584 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12585 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12588 SSLSocketDataProvider
ssl2(ASYNC
, OK
); // to the server
12589 ssl2
.SetNextProto(GetParam());
12590 session_deps_
.deterministic_socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12591 session_deps_
.deterministic_socket_factory
->AddSocketDataProvider(
12594 session_deps_
.host_resolver
.reset(new MockCachingHostResolver());
12595 session_deps_
.host_resolver
->rules()->AddRule("news.example.org", ip_addr
);
12596 session_deps_
.host_resolver
->rules()->AddRule("proxy", ip_addr
);
12598 scoped_refptr
<HttpNetworkSession
> session(
12599 SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_
));
12601 // Start the first transaction to set up the SpdySession
12602 HttpRequestInfo request1
;
12603 request1
.method
= "GET";
12604 request1
.url
= GURL(url1
);
12605 request1
.load_flags
= 0;
12606 HttpNetworkTransaction
trans1(LOWEST
, session
.get());
12607 TestCompletionCallback callback1
;
12608 ASSERT_EQ(ERR_IO_PENDING
,
12609 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12612 ASSERT_TRUE(callback1
.have_result());
12613 EXPECT_EQ(OK
, callback1
.WaitForResult());
12614 EXPECT_TRUE(trans1
.GetResponseInfo()->was_fetched_via_spdy
);
12616 // Now, start the HTTP request
12617 HttpRequestInfo request2
;
12618 request2
.method
= "GET";
12619 request2
.url
= GURL(url2
);
12620 request2
.load_flags
= 0;
12621 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12622 TestCompletionCallback callback2
;
12623 EXPECT_EQ(ERR_IO_PENDING
,
12624 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12625 base::MessageLoop::current()->RunUntilIdle();
12628 ASSERT_TRUE(callback2
.have_result());
12629 EXPECT_EQ(OK
, callback2
.WaitForResult());
12630 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12633 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
12634 // error) in SPDY session, removes the socket from pool and closes the SPDY
12635 // session. Verify that new url's from the same HttpNetworkSession (and a new
12636 // SpdySession) do work. http://crbug.com/224701
12637 TEST_P(HttpNetworkTransactionTest
, ErrorSocketNotConnected
) {
12638 const std::string https_url
= "https://www.example.org/";
12640 MockRead reads1
[] = {
12641 MockRead(SYNCHRONOUS
, ERR_CONNECTION_CLOSED
, 0)
12644 SequencedSocketData
data1(reads1
, arraysize(reads1
), NULL
, 0);
12646 scoped_ptr
<SpdyFrame
> req2(
12647 spdy_util_
.ConstructSpdyGet(https_url
.c_str(), false, 1, MEDIUM
));
12648 MockWrite writes2
[] = {
12649 CreateMockWrite(*req2
, 0),
12652 scoped_ptr
<SpdyFrame
> resp2(spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12653 scoped_ptr
<SpdyFrame
> body2(spdy_util_
.ConstructSpdyBodyFrame(1, true));
12654 MockRead reads2
[] = {
12655 CreateMockRead(*resp2
, 1),
12656 CreateMockRead(*body2
, 2),
12657 MockRead(ASYNC
, OK
, 3) // EOF
12660 SequencedSocketData
data2(reads2
, arraysize(reads2
), writes2
,
12661 arraysize(writes2
));
12663 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12664 ssl1
.SetNextProto(GetParam());
12665 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12666 session_deps_
.socket_factory
->AddSocketDataProvider(&data1
);
12668 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12669 ssl2
.SetNextProto(GetParam());
12670 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12671 session_deps_
.socket_factory
->AddSocketDataProvider(&data2
);
12673 scoped_refptr
<HttpNetworkSession
> session(
12674 SpdySessionDependencies::SpdyCreateSession(&session_deps_
));
12676 // Start the first transaction to set up the SpdySession and verify that
12677 // connection was closed.
12678 HttpRequestInfo request1
;
12679 request1
.method
= "GET";
12680 request1
.url
= GURL(https_url
);
12681 request1
.load_flags
= 0;
12682 HttpNetworkTransaction
trans1(MEDIUM
, session
.get());
12683 TestCompletionCallback callback1
;
12684 EXPECT_EQ(ERR_IO_PENDING
,
12685 trans1
.Start(&request1
, callback1
.callback(), BoundNetLog()));
12686 EXPECT_EQ(ERR_CONNECTION_CLOSED
, callback1
.WaitForResult());
12688 // Now, start the second request and make sure it succeeds.
12689 HttpRequestInfo request2
;
12690 request2
.method
= "GET";
12691 request2
.url
= GURL(https_url
);
12692 request2
.load_flags
= 0;
12693 HttpNetworkTransaction
trans2(MEDIUM
, session
.get());
12694 TestCompletionCallback callback2
;
12695 EXPECT_EQ(ERR_IO_PENDING
,
12696 trans2
.Start(&request2
, callback2
.callback(), BoundNetLog()));
12698 ASSERT_EQ(OK
, callback2
.WaitForResult());
12699 EXPECT_TRUE(trans2
.GetResponseInfo()->was_fetched_via_spdy
);
12702 TEST_P(HttpNetworkTransactionTest
, CloseIdleSpdySessionToOpenNewOne
) {
12703 session_deps_
.next_protos
= SpdyNextProtos();
12704 ClientSocketPoolManager::set_max_sockets_per_group(
12705 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12706 ClientSocketPoolManager::set_max_sockets_per_pool(
12707 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
12709 // Use two different hosts with different IPs so they don't get pooled.
12710 session_deps_
.host_resolver
->rules()->AddRule("www.a.com", "10.0.0.1");
12711 session_deps_
.host_resolver
->rules()->AddRule("www.b.com", "10.0.0.2");
12712 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12714 SSLSocketDataProvider
ssl1(ASYNC
, OK
);
12715 ssl1
.SetNextProto(GetParam());
12716 SSLSocketDataProvider
ssl2(ASYNC
, OK
);
12717 ssl2
.SetNextProto(GetParam());
12718 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl1
);
12719 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl2
);
12721 scoped_ptr
<SpdyFrame
> host1_req(spdy_util_
.ConstructSpdyGet(
12722 "https://www.a.com", false, 1, DEFAULT_PRIORITY
));
12723 MockWrite spdy1_writes
[] = {
12724 CreateMockWrite(*host1_req
, 0),
12726 scoped_ptr
<SpdyFrame
> host1_resp(
12727 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12728 scoped_ptr
<SpdyFrame
> host1_resp_body(
12729 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12730 MockRead spdy1_reads
[] = {
12731 CreateMockRead(*host1_resp
, 1),
12732 CreateMockRead(*host1_resp_body
, 2),
12733 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12736 scoped_ptr
<SequencedSocketData
> spdy1_data(
12737 new SequencedSocketData(spdy1_reads
, arraysize(spdy1_reads
), spdy1_writes
,
12738 arraysize(spdy1_writes
)));
12739 session_deps_
.socket_factory
->AddSocketDataProvider(spdy1_data
.get());
12741 scoped_ptr
<SpdyFrame
> host2_req(spdy_util_
.ConstructSpdyGet(
12742 "https://www.b.com", false, 1, DEFAULT_PRIORITY
));
12743 MockWrite spdy2_writes
[] = {
12744 CreateMockWrite(*host2_req
, 0),
12746 scoped_ptr
<SpdyFrame
> host2_resp(
12747 spdy_util_
.ConstructSpdyGetSynReply(NULL
, 0, 1));
12748 scoped_ptr
<SpdyFrame
> host2_resp_body(
12749 spdy_util_
.ConstructSpdyBodyFrame(1, true));
12750 MockRead spdy2_reads
[] = {
12751 CreateMockRead(*host2_resp
, 1),
12752 CreateMockRead(*host2_resp_body
, 2),
12753 MockRead(ASYNC
, ERR_IO_PENDING
, 3),
12756 scoped_ptr
<SequencedSocketData
> spdy2_data(
12757 new SequencedSocketData(spdy2_reads
, arraysize(spdy2_reads
), spdy2_writes
,
12758 arraysize(spdy2_writes
)));
12759 session_deps_
.socket_factory
->AddSocketDataProvider(spdy2_data
.get());
12761 MockWrite http_write
[] = {
12762 MockWrite("GET / HTTP/1.1\r\n"
12763 "Host: www.a.com\r\n"
12764 "Connection: keep-alive\r\n\r\n"),
12767 MockRead http_read
[] = {
12768 MockRead("HTTP/1.1 200 OK\r\n"),
12769 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
12770 MockRead("Content-Length: 6\r\n\r\n"),
12771 MockRead("hello!"),
12773 StaticSocketDataProvider
http_data(http_read
, arraysize(http_read
),
12774 http_write
, arraysize(http_write
));
12775 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
12777 HostPortPair
host_port_pair_a("www.a.com", 443);
12778 SpdySessionKey
spdy_session_key_a(
12779 host_port_pair_a
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12781 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12783 TestCompletionCallback callback
;
12784 HttpRequestInfo request1
;
12785 request1
.method
= "GET";
12786 request1
.url
= GURL("https://www.a.com/");
12787 request1
.load_flags
= 0;
12788 scoped_ptr
<HttpNetworkTransaction
> trans(
12789 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12791 int rv
= trans
->Start(&request1
, callback
.callback(), BoundNetLog());
12792 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12793 EXPECT_EQ(OK
, callback
.WaitForResult());
12795 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
12796 ASSERT_TRUE(response
!= NULL
);
12797 ASSERT_TRUE(response
->headers
.get() != NULL
);
12798 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12799 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12800 EXPECT_TRUE(response
->was_npn_negotiated
);
12802 std::string response_data
;
12803 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12804 EXPECT_EQ("hello!", response_data
);
12807 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12809 HostPortPair
host_port_pair_b("www.b.com", 443);
12810 SpdySessionKey
spdy_session_key_b(
12811 host_port_pair_b
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12813 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12814 HttpRequestInfo request2
;
12815 request2
.method
= "GET";
12816 request2
.url
= GURL("https://www.b.com/");
12817 request2
.load_flags
= 0;
12818 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12820 rv
= trans
->Start(&request2
, callback
.callback(), BoundNetLog());
12821 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12822 EXPECT_EQ(OK
, callback
.WaitForResult());
12824 response
= trans
->GetResponseInfo();
12825 ASSERT_TRUE(response
!= NULL
);
12826 ASSERT_TRUE(response
->headers
.get() != NULL
);
12827 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12828 EXPECT_TRUE(response
->was_fetched_via_spdy
);
12829 EXPECT_TRUE(response
->was_npn_negotiated
);
12830 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12831 EXPECT_EQ("hello!", response_data
);
12833 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12835 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12837 HostPortPair
host_port_pair_a1("www.a.com", 80);
12838 SpdySessionKey
spdy_session_key_a1(
12839 host_port_pair_a1
, ProxyServer::Direct(), PRIVACY_MODE_DISABLED
);
12841 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a1
));
12842 HttpRequestInfo request3
;
12843 request3
.method
= "GET";
12844 request3
.url
= GURL("http://www.a.com/");
12845 request3
.load_flags
= 0;
12846 trans
.reset(new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12848 rv
= trans
->Start(&request3
, callback
.callback(), BoundNetLog());
12849 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12850 EXPECT_EQ(OK
, callback
.WaitForResult());
12852 response
= trans
->GetResponseInfo();
12853 ASSERT_TRUE(response
!= NULL
);
12854 ASSERT_TRUE(response
->headers
.get() != NULL
);
12855 EXPECT_EQ("HTTP/1.1 200 OK", response
->headers
->GetStatusLine());
12856 EXPECT_FALSE(response
->was_fetched_via_spdy
);
12857 EXPECT_FALSE(response
->was_npn_negotiated
);
12858 ASSERT_EQ(OK
, ReadTransaction(trans
.get(), &response_data
));
12859 EXPECT_EQ("hello!", response_data
);
12861 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_a
));
12863 HasSpdySession(session
->spdy_session_pool(), spdy_session_key_b
));
12866 TEST_P(HttpNetworkTransactionTest
, HttpSyncConnectError
) {
12867 HttpRequestInfo request
;
12868 request
.method
= "GET";
12869 request
.url
= GURL("http://www.example.org/");
12870 request
.load_flags
= 0;
12872 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12873 scoped_ptr
<HttpTransaction
> trans(
12874 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12876 MockConnect
mock_connect(SYNCHRONOUS
, ERR_CONNECTION_REFUSED
);
12877 StaticSocketDataProvider data
;
12878 data
.set_connect_data(mock_connect
);
12879 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12881 TestCompletionCallback callback
;
12883 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12884 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12886 rv
= callback
.WaitForResult();
12887 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12889 // We don't care whether this succeeds or fails, but it shouldn't crash.
12890 HttpRequestHeaders request_headers
;
12891 trans
->GetFullRequestHeaders(&request_headers
);
12893 ConnectionAttempts attempts
;
12894 trans
->GetConnectionAttempts(&attempts
);
12895 ASSERT_EQ(1u, attempts
.size());
12896 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12899 TEST_P(HttpNetworkTransactionTest
, HttpAsyncConnectError
) {
12900 HttpRequestInfo request
;
12901 request
.method
= "GET";
12902 request
.url
= GURL("http://www.example.org/");
12903 request
.load_flags
= 0;
12905 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12906 scoped_ptr
<HttpTransaction
> trans(
12907 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12909 MockConnect
mock_connect(ASYNC
, ERR_CONNECTION_REFUSED
);
12910 StaticSocketDataProvider data
;
12911 data
.set_connect_data(mock_connect
);
12912 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12914 TestCompletionCallback callback
;
12916 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12917 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12919 rv
= callback
.WaitForResult();
12920 EXPECT_EQ(ERR_CONNECTION_REFUSED
, rv
);
12922 // We don't care whether this succeeds or fails, but it shouldn't crash.
12923 HttpRequestHeaders request_headers
;
12924 trans
->GetFullRequestHeaders(&request_headers
);
12926 ConnectionAttempts attempts
;
12927 trans
->GetConnectionAttempts(&attempts
);
12928 ASSERT_EQ(1u, attempts
.size());
12929 EXPECT_EQ(ERR_CONNECTION_REFUSED
, attempts
[0].result
);
12932 TEST_P(HttpNetworkTransactionTest
, HttpSyncWriteError
) {
12933 HttpRequestInfo request
;
12934 request
.method
= "GET";
12935 request
.url
= GURL("http://www.example.org/");
12936 request
.load_flags
= 0;
12938 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12939 scoped_ptr
<HttpTransaction
> trans(
12940 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12942 MockWrite data_writes
[] = {
12943 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
12945 MockRead data_reads
[] = {
12946 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12949 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12950 data_writes
, arraysize(data_writes
));
12951 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12953 TestCompletionCallback callback
;
12955 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12956 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12958 rv
= callback
.WaitForResult();
12959 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12961 HttpRequestHeaders request_headers
;
12962 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12963 EXPECT_TRUE(request_headers
.HasHeader("Host"));
12966 TEST_P(HttpNetworkTransactionTest
, HttpAsyncWriteError
) {
12967 HttpRequestInfo request
;
12968 request
.method
= "GET";
12969 request
.url
= GURL("http://www.example.org/");
12970 request
.load_flags
= 0;
12972 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
12973 scoped_ptr
<HttpTransaction
> trans(
12974 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
12976 MockWrite data_writes
[] = {
12977 MockWrite(ASYNC
, ERR_CONNECTION_RESET
),
12979 MockRead data_reads
[] = {
12980 MockRead(SYNCHRONOUS
, ERR_UNEXPECTED
), // Should not be reached.
12983 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
12984 data_writes
, arraysize(data_writes
));
12985 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
12987 TestCompletionCallback callback
;
12989 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
12990 EXPECT_EQ(ERR_IO_PENDING
, rv
);
12992 rv
= callback
.WaitForResult();
12993 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
12995 HttpRequestHeaders request_headers
;
12996 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
12997 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13000 TEST_P(HttpNetworkTransactionTest
, HttpSyncReadError
) {
13001 HttpRequestInfo request
;
13002 request
.method
= "GET";
13003 request
.url
= GURL("http://www.example.org/");
13004 request
.load_flags
= 0;
13006 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13007 scoped_ptr
<HttpTransaction
> trans(
13008 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13010 MockWrite data_writes
[] = {
13012 "GET / HTTP/1.1\r\n"
13013 "Host: www.example.org\r\n"
13014 "Connection: keep-alive\r\n\r\n"),
13016 MockRead data_reads
[] = {
13017 MockRead(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13020 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13021 data_writes
, arraysize(data_writes
));
13022 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13024 TestCompletionCallback callback
;
13026 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13027 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13029 rv
= callback
.WaitForResult();
13030 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13032 HttpRequestHeaders request_headers
;
13033 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13034 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13037 TEST_P(HttpNetworkTransactionTest
, HttpAsyncReadError
) {
13038 HttpRequestInfo request
;
13039 request
.method
= "GET";
13040 request
.url
= GURL("http://www.example.org/");
13041 request
.load_flags
= 0;
13043 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13044 scoped_ptr
<HttpTransaction
> trans(
13045 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13047 MockWrite data_writes
[] = {
13049 "GET / HTTP/1.1\r\n"
13050 "Host: www.example.org\r\n"
13051 "Connection: keep-alive\r\n\r\n"),
13053 MockRead data_reads
[] = {
13054 MockRead(ASYNC
, ERR_CONNECTION_RESET
),
13057 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13058 data_writes
, arraysize(data_writes
));
13059 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13061 TestCompletionCallback callback
;
13063 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13064 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13066 rv
= callback
.WaitForResult();
13067 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
13069 HttpRequestHeaders request_headers
;
13070 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13071 EXPECT_TRUE(request_headers
.HasHeader("Host"));
13074 TEST_P(HttpNetworkTransactionTest
, GetFullRequestHeadersIncludesExtraHeader
) {
13075 HttpRequestInfo request
;
13076 request
.method
= "GET";
13077 request
.url
= GURL("http://www.example.org/");
13078 request
.load_flags
= 0;
13079 request
.extra_headers
.SetHeader("X-Foo", "bar");
13081 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13082 scoped_ptr
<HttpTransaction
> trans(
13083 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13085 MockWrite data_writes
[] = {
13087 "GET / HTTP/1.1\r\n"
13088 "Host: www.example.org\r\n"
13089 "Connection: keep-alive\r\n"
13090 "X-Foo: bar\r\n\r\n"),
13092 MockRead data_reads
[] = {
13093 MockRead("HTTP/1.1 200 OK\r\n"
13094 "Content-Length: 5\r\n\r\n"
13096 MockRead(ASYNC
, ERR_UNEXPECTED
),
13099 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
),
13100 data_writes
, arraysize(data_writes
));
13101 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13103 TestCompletionCallback callback
;
13105 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13106 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13108 rv
= callback
.WaitForResult();
13111 HttpRequestHeaders request_headers
;
13112 EXPECT_TRUE(trans
->GetFullRequestHeaders(&request_headers
));
13114 EXPECT_TRUE(request_headers
.GetHeader("X-Foo", &foo
));
13115 EXPECT_EQ("bar", foo
);
13120 // Fake HttpStream that simply records calls to SetPriority().
13121 class FakeStream
: public HttpStream
,
13122 public base::SupportsWeakPtr
<FakeStream
> {
13124 explicit FakeStream(RequestPriority priority
) : priority_(priority
) {}
13125 ~FakeStream() override
{}
13127 RequestPriority
priority() const { return priority_
; }
13129 int InitializeStream(const HttpRequestInfo
* request_info
,
13130 RequestPriority priority
,
13131 const BoundNetLog
& net_log
,
13132 const CompletionCallback
& callback
) override
{
13133 return ERR_IO_PENDING
;
13136 int SendRequest(const HttpRequestHeaders
& request_headers
,
13137 HttpResponseInfo
* response
,
13138 const CompletionCallback
& callback
) override
{
13140 return ERR_UNEXPECTED
;
13143 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13145 return ERR_UNEXPECTED
;
13148 int ReadResponseBody(IOBuffer
* buf
,
13150 const CompletionCallback
& callback
) override
{
13152 return ERR_UNEXPECTED
;
13155 void Close(bool not_reusable
) override
{}
13157 bool IsResponseBodyComplete() const override
{
13162 bool CanFindEndOfResponse() const override
{ return false; }
13164 bool IsConnectionReused() const override
{
13169 void SetConnectionReused() override
{ ADD_FAILURE(); }
13171 bool IsConnectionReusable() const override
{
13176 int64
GetTotalReceivedBytes() const override
{
13181 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13186 void GetSSLInfo(SSLInfo
* ssl_info
) override
{ ADD_FAILURE(); }
13188 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13192 bool IsSpdyHttpStream() const override
{
13197 void Drain(HttpNetworkSession
* session
) override
{ ADD_FAILURE(); }
13199 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13201 UploadProgress
GetUploadProgress() const override
{ return UploadProgress(); }
13203 HttpStream
* RenewStreamForAuth() override
{ return NULL
; }
13206 RequestPriority priority_
;
13208 DISALLOW_COPY_AND_ASSIGN(FakeStream
);
13211 // Fake HttpStreamRequest that simply records calls to SetPriority()
13212 // and vends FakeStreams with its current priority.
13213 class FakeStreamRequest
: public HttpStreamRequest
,
13214 public base::SupportsWeakPtr
<FakeStreamRequest
> {
13216 FakeStreamRequest(RequestPriority priority
,
13217 HttpStreamRequest::Delegate
* delegate
)
13218 : priority_(priority
),
13219 delegate_(delegate
),
13220 websocket_stream_create_helper_(NULL
) {}
13222 FakeStreamRequest(RequestPriority priority
,
13223 HttpStreamRequest::Delegate
* delegate
,
13224 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
)
13225 : priority_(priority
),
13226 delegate_(delegate
),
13227 websocket_stream_create_helper_(create_helper
) {}
13229 ~FakeStreamRequest() override
{}
13231 RequestPriority
priority() const { return priority_
; }
13233 const WebSocketHandshakeStreamBase::CreateHelper
*
13234 websocket_stream_create_helper() const {
13235 return websocket_stream_create_helper_
;
13238 // Create a new FakeStream and pass it to the request's
13239 // delegate. Returns a weak pointer to the FakeStream.
13240 base::WeakPtr
<FakeStream
> FinishStreamRequest() {
13241 FakeStream
* fake_stream
= new FakeStream(priority_
);
13242 // Do this before calling OnStreamReady() as OnStreamReady() may
13243 // immediately delete |fake_stream|.
13244 base::WeakPtr
<FakeStream
> weak_stream
= fake_stream
->AsWeakPtr();
13245 delegate_
->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream
);
13246 return weak_stream
;
13249 int RestartTunnelWithProxyAuth(const AuthCredentials
& credentials
) override
{
13251 return ERR_UNEXPECTED
;
13254 LoadState
GetLoadState() const override
{
13256 return LoadState();
13259 void SetPriority(RequestPriority priority
) override
{ priority_
= priority
; }
13261 bool was_npn_negotiated() const override
{ return false; }
13263 NextProto
protocol_negotiated() const override
{ return kProtoUnknown
; }
13265 bool using_spdy() const override
{ return false; }
13267 const ConnectionAttempts
& connection_attempts() const override
{
13268 static ConnectionAttempts no_attempts
;
13269 return no_attempts
;
13273 RequestPriority priority_
;
13274 HttpStreamRequest::Delegate
* const delegate_
;
13275 WebSocketHandshakeStreamBase::CreateHelper
* websocket_stream_create_helper_
;
13277 DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest
);
13280 // Fake HttpStreamFactory that vends FakeStreamRequests.
13281 class FakeStreamFactory
: public HttpStreamFactory
{
13283 FakeStreamFactory() {}
13284 ~FakeStreamFactory() override
{}
13286 // Returns a WeakPtr<> to the last HttpStreamRequest returned by
13287 // RequestStream() (which may be NULL if it was destroyed already).
13288 base::WeakPtr
<FakeStreamRequest
> last_stream_request() {
13289 return last_stream_request_
;
13292 HttpStreamRequest
* RequestStream(const HttpRequestInfo
& info
,
13293 RequestPriority priority
,
13294 const SSLConfig
& server_ssl_config
,
13295 const SSLConfig
& proxy_ssl_config
,
13296 HttpStreamRequest::Delegate
* delegate
,
13297 const BoundNetLog
& net_log
) override
{
13298 FakeStreamRequest
* fake_request
= new FakeStreamRequest(priority
, delegate
);
13299 last_stream_request_
= fake_request
->AsWeakPtr();
13300 return fake_request
;
13303 HttpStreamRequest
* RequestWebSocketHandshakeStream(
13304 const HttpRequestInfo
& info
,
13305 RequestPriority priority
,
13306 const SSLConfig
& server_ssl_config
,
13307 const SSLConfig
& proxy_ssl_config
,
13308 HttpStreamRequest::Delegate
* delegate
,
13309 WebSocketHandshakeStreamBase::CreateHelper
* create_helper
,
13310 const BoundNetLog
& net_log
) override
{
13311 FakeStreamRequest
* fake_request
=
13312 new FakeStreamRequest(priority
, delegate
, create_helper
);
13313 last_stream_request_
= fake_request
->AsWeakPtr();
13314 return fake_request
;
13317 void PreconnectStreams(int num_streams
,
13318 const HttpRequestInfo
& info
,
13319 const SSLConfig
& server_ssl_config
,
13320 const SSLConfig
& proxy_ssl_config
) override
{
13324 const HostMappingRules
* GetHostMappingRules() const override
{
13330 base::WeakPtr
<FakeStreamRequest
> last_stream_request_
;
13332 DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory
);
13335 // TODO(ricea): Maybe unify this with the one in
13336 // url_request_http_job_unittest.cc ?
13337 class FakeWebSocketBasicHandshakeStream
: public WebSocketHandshakeStreamBase
{
13339 FakeWebSocketBasicHandshakeStream(scoped_ptr
<ClientSocketHandle
> connection
,
13341 : state_(connection
.release(), using_proxy
) {}
13343 // Fake implementation of HttpStreamBase methods.
13344 // This ends up being quite "real" because this object has to really send data
13345 // on the mock socket. It might be easier to use the real implementation, but
13346 // the fact that the WebSocket code is not compiled on iOS makes that
13348 int InitializeStream(const HttpRequestInfo
* request_info
,
13349 RequestPriority priority
,
13350 const BoundNetLog
& net_log
,
13351 const CompletionCallback
& callback
) override
{
13352 state_
.Initialize(request_info
, priority
, net_log
, callback
);
13356 int SendRequest(const HttpRequestHeaders
& request_headers
,
13357 HttpResponseInfo
* response
,
13358 const CompletionCallback
& callback
) override
{
13359 return parser()->SendRequest(state_
.GenerateRequestLine(), request_headers
,
13360 response
, callback
);
13363 int ReadResponseHeaders(const CompletionCallback
& callback
) override
{
13364 return parser()->ReadResponseHeaders(callback
);
13367 int ReadResponseBody(IOBuffer
* buf
,
13369 const CompletionCallback
& callback
) override
{
13371 return ERR_IO_PENDING
;
13374 void Close(bool not_reusable
) override
{
13376 parser()->Close(true);
13379 bool IsResponseBodyComplete() const override
{
13384 bool CanFindEndOfResponse() const override
{
13385 return parser()->CanFindEndOfResponse();
13388 bool IsConnectionReused() const override
{
13392 void SetConnectionReused() override
{ NOTREACHED(); }
13394 bool IsConnectionReusable() const override
{
13399 int64
GetTotalReceivedBytes() const override
{
13404 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const override
{
13409 void GetSSLInfo(SSLInfo
* ssl_info
) override
{}
13411 void GetSSLCertRequestInfo(SSLCertRequestInfo
* cert_request_info
) override
{
13415 bool IsSpdyHttpStream() const override
{
13420 void Drain(HttpNetworkSession
* session
) override
{ NOTREACHED(); }
13422 void SetPriority(RequestPriority priority
) override
{ NOTREACHED(); }
13424 UploadProgress
GetUploadProgress() const override
{
13426 return UploadProgress();
13429 HttpStream
* RenewStreamForAuth() override
{
13434 // Fake implementation of WebSocketHandshakeStreamBase method(s)
13435 scoped_ptr
<WebSocketStream
> Upgrade() override
{
13437 return scoped_ptr
<WebSocketStream
>();
13441 HttpStreamParser
* parser() const { return state_
.parser(); }
13442 HttpBasicState state_
;
13444 DISALLOW_COPY_AND_ASSIGN(FakeWebSocketBasicHandshakeStream
);
13447 // TODO(yhirano): Split this class out into a net/websockets file, if it is
13449 class FakeWebSocketStreamCreateHelper
:
13450 public WebSocketHandshakeStreamBase::CreateHelper
{
13452 WebSocketHandshakeStreamBase
* CreateBasicStream(
13453 scoped_ptr
<ClientSocketHandle
> connection
,
13454 bool using_proxy
) override
{
13455 return new FakeWebSocketBasicHandshakeStream(connection
.Pass(),
13459 WebSocketHandshakeStreamBase
* CreateSpdyStream(
13460 const base::WeakPtr
<SpdySession
>& session
,
13461 bool use_relative_url
) override
{
13466 ~FakeWebSocketStreamCreateHelper() override
{}
13468 virtual scoped_ptr
<WebSocketStream
> Upgrade() {
13470 return scoped_ptr
<WebSocketStream
>();
13476 // Make sure that HttpNetworkTransaction passes on its priority to its
13477 // stream request on start.
13478 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriorityOnStart
) {
13479 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13480 HttpNetworkSessionPeer
peer(session
);
13481 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13482 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13484 HttpNetworkTransaction
trans(LOW
, session
.get());
13486 ASSERT_TRUE(fake_factory
->last_stream_request() == NULL
);
13488 HttpRequestInfo request
;
13489 TestCompletionCallback callback
;
13490 EXPECT_EQ(ERR_IO_PENDING
,
13491 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13493 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13494 fake_factory
->last_stream_request();
13495 ASSERT_TRUE(fake_request
!= NULL
);
13496 EXPECT_EQ(LOW
, fake_request
->priority());
13499 // Make sure that HttpNetworkTransaction passes on its priority
13500 // updates to its stream request.
13501 TEST_P(HttpNetworkTransactionTest
, SetStreamRequestPriority
) {
13502 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13503 HttpNetworkSessionPeer
peer(session
);
13504 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13505 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13507 HttpNetworkTransaction
trans(LOW
, session
.get());
13509 HttpRequestInfo request
;
13510 TestCompletionCallback callback
;
13511 EXPECT_EQ(ERR_IO_PENDING
,
13512 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13514 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13515 fake_factory
->last_stream_request();
13516 ASSERT_TRUE(fake_request
!= NULL
);
13517 EXPECT_EQ(LOW
, fake_request
->priority());
13519 trans
.SetPriority(LOWEST
);
13520 ASSERT_TRUE(fake_request
!= NULL
);
13521 EXPECT_EQ(LOWEST
, fake_request
->priority());
13524 // Make sure that HttpNetworkTransaction passes on its priority
13525 // updates to its stream.
13526 TEST_P(HttpNetworkTransactionTest
, SetStreamPriority
) {
13527 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13528 HttpNetworkSessionPeer
peer(session
);
13529 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13530 peer
.SetHttpStreamFactory(scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13532 HttpNetworkTransaction
trans(LOW
, session
.get());
13534 HttpRequestInfo request
;
13535 TestCompletionCallback callback
;
13536 EXPECT_EQ(ERR_IO_PENDING
,
13537 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13539 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13540 fake_factory
->last_stream_request();
13541 ASSERT_TRUE(fake_request
!= NULL
);
13542 base::WeakPtr
<FakeStream
> fake_stream
= fake_request
->FinishStreamRequest();
13543 ASSERT_TRUE(fake_stream
!= NULL
);
13544 EXPECT_EQ(LOW
, fake_stream
->priority());
13546 trans
.SetPriority(LOWEST
);
13547 EXPECT_EQ(LOWEST
, fake_stream
->priority());
13550 TEST_P(HttpNetworkTransactionTest
, CreateWebSocketHandshakeStream
) {
13551 // The same logic needs to be tested for both ws: and wss: schemes, but this
13552 // test is already parameterised on NextProto, so it uses a loop to verify
13553 // that the different schemes work.
13554 std::string test_cases
[] = {"ws://www.example.org/",
13555 "wss://www.example.org/"};
13556 for (size_t i
= 0; i
< arraysize(test_cases
); ++i
) {
13557 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13558 HttpNetworkSessionPeer
peer(session
);
13559 FakeStreamFactory
* fake_factory
= new FakeStreamFactory();
13560 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
13561 peer
.SetHttpStreamFactoryForWebSocket(
13562 scoped_ptr
<HttpStreamFactory
>(fake_factory
));
13564 HttpNetworkTransaction
trans(LOW
, session
.get());
13565 trans
.SetWebSocketHandshakeStreamCreateHelper(
13566 &websocket_stream_create_helper
);
13568 HttpRequestInfo request
;
13569 TestCompletionCallback callback
;
13570 request
.method
= "GET";
13571 request
.url
= GURL(test_cases
[i
]);
13573 EXPECT_EQ(ERR_IO_PENDING
,
13574 trans
.Start(&request
, callback
.callback(), BoundNetLog()));
13576 base::WeakPtr
<FakeStreamRequest
> fake_request
=
13577 fake_factory
->last_stream_request();
13578 ASSERT_TRUE(fake_request
!= NULL
);
13579 EXPECT_EQ(&websocket_stream_create_helper
,
13580 fake_request
->websocket_stream_create_helper());
13584 // Tests that when a used socket is returned to the SSL socket pool, it's closed
13585 // if the transport socket pool is stalled on the global socket limit.
13586 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest
) {
13587 ClientSocketPoolManager::set_max_sockets_per_group(
13588 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13589 ClientSocketPoolManager::set_max_sockets_per_pool(
13590 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13592 // Set up SSL request.
13594 HttpRequestInfo ssl_request
;
13595 ssl_request
.method
= "GET";
13596 ssl_request
.url
= GURL("https://www.example.org/");
13598 MockWrite ssl_writes
[] = {
13600 "GET / HTTP/1.1\r\n"
13601 "Host: www.example.org\r\n"
13602 "Connection: keep-alive\r\n\r\n"),
13604 MockRead ssl_reads
[] = {
13605 MockRead("HTTP/1.1 200 OK\r\n"),
13606 MockRead("Content-Length: 11\r\n\r\n"),
13607 MockRead("hello world"),
13608 MockRead(SYNCHRONOUS
, OK
),
13610 StaticSocketDataProvider
ssl_data(ssl_reads
, arraysize(ssl_reads
),
13611 ssl_writes
, arraysize(ssl_writes
));
13612 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13614 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13615 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13617 // Set up HTTP request.
13619 HttpRequestInfo http_request
;
13620 http_request
.method
= "GET";
13621 http_request
.url
= GURL("http://www.example.org/");
13623 MockWrite http_writes
[] = {
13625 "GET / HTTP/1.1\r\n"
13626 "Host: www.example.org\r\n"
13627 "Connection: keep-alive\r\n\r\n"),
13629 MockRead http_reads
[] = {
13630 MockRead("HTTP/1.1 200 OK\r\n"),
13631 MockRead("Content-Length: 7\r\n\r\n"),
13632 MockRead("falafel"),
13633 MockRead(SYNCHRONOUS
, OK
),
13635 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13636 http_writes
, arraysize(http_writes
));
13637 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13639 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13641 // Start the SSL request.
13642 TestCompletionCallback ssl_callback
;
13643 scoped_ptr
<HttpTransaction
> ssl_trans(
13644 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13645 ASSERT_EQ(ERR_IO_PENDING
,
13646 ssl_trans
->Start(&ssl_request
, ssl_callback
.callback(),
13649 // Start the HTTP request. Pool should stall.
13650 TestCompletionCallback http_callback
;
13651 scoped_ptr
<HttpTransaction
> http_trans(
13652 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13653 ASSERT_EQ(ERR_IO_PENDING
,
13654 http_trans
->Start(&http_request
, http_callback
.callback(),
13656 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13658 // Wait for response from SSL request.
13659 ASSERT_EQ(OK
, ssl_callback
.WaitForResult());
13660 std::string response_data
;
13661 ASSERT_EQ(OK
, ReadTransaction(ssl_trans
.get(), &response_data
));
13662 EXPECT_EQ("hello world", response_data
);
13664 // The SSL socket should automatically be closed, so the HTTP request can
13666 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13667 ASSERT_FALSE(IsTransportSocketPoolStalled(session
.get()));
13669 // The HTTP request can now complete.
13670 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13671 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13672 EXPECT_EQ("falafel", response_data
);
13674 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13677 // Tests that when a SSL connection is established but there's no corresponding
13678 // request that needs it, the new socket is closed if the transport socket pool
13679 // is stalled on the global socket limit.
13680 TEST_P(HttpNetworkTransactionTest
, CloseSSLSocketOnIdleForHttpRequest2
) {
13681 ClientSocketPoolManager::set_max_sockets_per_group(
13682 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13683 ClientSocketPoolManager::set_max_sockets_per_pool(
13684 HttpNetworkSession::NORMAL_SOCKET_POOL
, 1);
13686 // Set up an ssl request.
13688 HttpRequestInfo ssl_request
;
13689 ssl_request
.method
= "GET";
13690 ssl_request
.url
= GURL("https://www.foopy.com/");
13692 // No data will be sent on the SSL socket.
13693 StaticSocketDataProvider ssl_data
;
13694 session_deps_
.socket_factory
->AddSocketDataProvider(&ssl_data
);
13696 SSLSocketDataProvider
ssl(ASYNC
, OK
);
13697 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
13699 // Set up HTTP request.
13701 HttpRequestInfo http_request
;
13702 http_request
.method
= "GET";
13703 http_request
.url
= GURL("http://www.example.org/");
13705 MockWrite http_writes
[] = {
13707 "GET / HTTP/1.1\r\n"
13708 "Host: www.example.org\r\n"
13709 "Connection: keep-alive\r\n\r\n"),
13711 MockRead http_reads
[] = {
13712 MockRead("HTTP/1.1 200 OK\r\n"),
13713 MockRead("Content-Length: 7\r\n\r\n"),
13714 MockRead("falafel"),
13715 MockRead(SYNCHRONOUS
, OK
),
13717 StaticSocketDataProvider
http_data(http_reads
, arraysize(http_reads
),
13718 http_writes
, arraysize(http_writes
));
13719 session_deps_
.socket_factory
->AddSocketDataProvider(&http_data
);
13721 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13723 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
13724 // cancelled when a normal transaction is cancelled.
13725 HttpStreamFactory
* http_stream_factory
= session
->http_stream_factory();
13726 SSLConfig ssl_config
;
13727 session
->ssl_config_service()->GetSSLConfig(&ssl_config
);
13728 http_stream_factory
->PreconnectStreams(1, ssl_request
, ssl_config
,
13730 EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session
.get()));
13732 // Start the HTTP request. Pool should stall.
13733 TestCompletionCallback http_callback
;
13734 scoped_ptr
<HttpTransaction
> http_trans(
13735 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13736 ASSERT_EQ(ERR_IO_PENDING
,
13737 http_trans
->Start(&http_request
, http_callback
.callback(),
13739 EXPECT_TRUE(IsTransportSocketPoolStalled(session
.get()));
13741 // The SSL connection will automatically be closed once the connection is
13742 // established, to let the HTTP request start.
13743 ASSERT_EQ(OK
, http_callback
.WaitForResult());
13744 std::string response_data
;
13745 ASSERT_EQ(OK
, ReadTransaction(http_trans
.get(), &response_data
));
13746 EXPECT_EQ("falafel", response_data
);
13748 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session
.get()));
13751 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterReset
) {
13752 ScopedVector
<UploadElementReader
> element_readers
;
13753 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13754 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13756 HttpRequestInfo request
;
13757 request
.method
= "POST";
13758 request
.url
= GURL("http://www.foo.com/");
13759 request
.upload_data_stream
= &upload_data_stream
;
13760 request
.load_flags
= 0;
13762 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13763 scoped_ptr
<HttpTransaction
> trans(
13764 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13765 // Send headers successfully, but get an error while sending the body.
13766 MockWrite data_writes
[] = {
13767 MockWrite("POST / HTTP/1.1\r\n"
13768 "Host: www.foo.com\r\n"
13769 "Connection: keep-alive\r\n"
13770 "Content-Length: 3\r\n\r\n"),
13771 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13774 MockRead data_reads
[] = {
13775 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13776 MockRead("hello world"),
13777 MockRead(SYNCHRONOUS
, OK
),
13779 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13780 arraysize(data_writes
));
13781 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13783 TestCompletionCallback callback
;
13785 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13786 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13788 rv
= callback
.WaitForResult();
13791 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13792 ASSERT_TRUE(response
!= NULL
);
13794 EXPECT_TRUE(response
->headers
.get() != NULL
);
13795 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13797 std::string response_data
;
13798 rv
= ReadTransaction(trans
.get(), &response_data
);
13800 EXPECT_EQ("hello world", response_data
);
13803 // This test makes sure the retry logic doesn't trigger when reading an error
13804 // response from a server that rejected a POST with a CONNECTION_RESET.
13805 TEST_P(HttpNetworkTransactionTest
,
13806 PostReadsErrorResponseAfterResetOnReusedSocket
) {
13807 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13808 MockWrite data_writes
[] = {
13809 MockWrite("GET / HTTP/1.1\r\n"
13810 "Host: www.foo.com\r\n"
13811 "Connection: keep-alive\r\n\r\n"),
13812 MockWrite("POST / HTTP/1.1\r\n"
13813 "Host: www.foo.com\r\n"
13814 "Connection: keep-alive\r\n"
13815 "Content-Length: 3\r\n\r\n"),
13816 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13819 MockRead data_reads
[] = {
13820 MockRead("HTTP/1.1 200 Peachy\r\n"
13821 "Content-Length: 14\r\n\r\n"),
13822 MockRead("first response"),
13823 MockRead("HTTP/1.1 400 Not OK\r\n"
13824 "Content-Length: 15\r\n\r\n"),
13825 MockRead("second response"),
13826 MockRead(SYNCHRONOUS
, OK
),
13828 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13829 arraysize(data_writes
));
13830 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13832 TestCompletionCallback callback
;
13833 HttpRequestInfo request1
;
13834 request1
.method
= "GET";
13835 request1
.url
= GURL("http://www.foo.com/");
13836 request1
.load_flags
= 0;
13838 scoped_ptr
<HttpTransaction
> trans1(
13839 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13840 int rv
= trans1
->Start(&request1
, callback
.callback(), BoundNetLog());
13841 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13843 rv
= callback
.WaitForResult();
13846 const HttpResponseInfo
* response1
= trans1
->GetResponseInfo();
13847 ASSERT_TRUE(response1
!= NULL
);
13849 EXPECT_TRUE(response1
->headers
.get() != NULL
);
13850 EXPECT_EQ("HTTP/1.1 200 Peachy", response1
->headers
->GetStatusLine());
13852 std::string response_data1
;
13853 rv
= ReadTransaction(trans1
.get(), &response_data1
);
13855 EXPECT_EQ("first response", response_data1
);
13856 // Delete the transaction to release the socket back into the socket pool.
13859 ScopedVector
<UploadElementReader
> element_readers
;
13860 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13861 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13863 HttpRequestInfo request2
;
13864 request2
.method
= "POST";
13865 request2
.url
= GURL("http://www.foo.com/");
13866 request2
.upload_data_stream
= &upload_data_stream
;
13867 request2
.load_flags
= 0;
13869 scoped_ptr
<HttpTransaction
> trans2(
13870 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13871 rv
= trans2
->Start(&request2
, callback
.callback(), BoundNetLog());
13872 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13874 rv
= callback
.WaitForResult();
13877 const HttpResponseInfo
* response2
= trans2
->GetResponseInfo();
13878 ASSERT_TRUE(response2
!= NULL
);
13880 EXPECT_TRUE(response2
->headers
.get() != NULL
);
13881 EXPECT_EQ("HTTP/1.1 400 Not OK", response2
->headers
->GetStatusLine());
13883 std::string response_data2
;
13884 rv
= ReadTransaction(trans2
.get(), &response_data2
);
13886 EXPECT_EQ("second response", response_data2
);
13889 TEST_P(HttpNetworkTransactionTest
,
13890 PostReadsErrorResponseAfterResetPartialBodySent
) {
13891 ScopedVector
<UploadElementReader
> element_readers
;
13892 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13893 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
13895 HttpRequestInfo request
;
13896 request
.method
= "POST";
13897 request
.url
= GURL("http://www.foo.com/");
13898 request
.upload_data_stream
= &upload_data_stream
;
13899 request
.load_flags
= 0;
13901 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13902 scoped_ptr
<HttpTransaction
> trans(
13903 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13904 // Send headers successfully, but get an error while sending the body.
13905 MockWrite data_writes
[] = {
13906 MockWrite("POST / HTTP/1.1\r\n"
13907 "Host: www.foo.com\r\n"
13908 "Connection: keep-alive\r\n"
13909 "Content-Length: 3\r\n\r\n"
13911 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13914 MockRead data_reads
[] = {
13915 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13916 MockRead("hello world"),
13917 MockRead(SYNCHRONOUS
, OK
),
13919 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13920 arraysize(data_writes
));
13921 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13923 TestCompletionCallback callback
;
13925 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13926 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13928 rv
= callback
.WaitForResult();
13931 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13932 ASSERT_TRUE(response
!= NULL
);
13934 EXPECT_TRUE(response
->headers
.get() != NULL
);
13935 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13937 std::string response_data
;
13938 rv
= ReadTransaction(trans
.get(), &response_data
);
13940 EXPECT_EQ("hello world", response_data
);
13943 // This tests the more common case than the previous test, where headers and
13944 // body are not merged into a single request.
13945 TEST_P(HttpNetworkTransactionTest
, ChunkedPostReadsErrorResponseAfterReset
) {
13946 ScopedVector
<UploadElementReader
> element_readers
;
13947 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
13948 ChunkedUploadDataStream
upload_data_stream(0);
13950 HttpRequestInfo request
;
13951 request
.method
= "POST";
13952 request
.url
= GURL("http://www.foo.com/");
13953 request
.upload_data_stream
= &upload_data_stream
;
13954 request
.load_flags
= 0;
13956 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
13957 scoped_ptr
<HttpTransaction
> trans(
13958 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
13959 // Send headers successfully, but get an error while sending the body.
13960 MockWrite data_writes
[] = {
13961 MockWrite("POST / HTTP/1.1\r\n"
13962 "Host: www.foo.com\r\n"
13963 "Connection: keep-alive\r\n"
13964 "Transfer-Encoding: chunked\r\n\r\n"),
13965 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
13968 MockRead data_reads
[] = {
13969 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
13970 MockRead("hello world"),
13971 MockRead(SYNCHRONOUS
, OK
),
13973 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
13974 arraysize(data_writes
));
13975 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
13977 TestCompletionCallback callback
;
13979 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
13980 EXPECT_EQ(ERR_IO_PENDING
, rv
);
13981 // Make sure the headers are sent before adding a chunk. This ensures that
13982 // they can't be merged with the body in a single send. Not currently
13983 // necessary since a chunked body is never merged with headers, but this makes
13984 // the test more future proof.
13985 base::RunLoop().RunUntilIdle();
13987 upload_data_stream
.AppendData("last chunk", 10, true);
13989 rv
= callback
.WaitForResult();
13992 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
13993 ASSERT_TRUE(response
!= NULL
);
13995 EXPECT_TRUE(response
->headers
.get() != NULL
);
13996 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
13998 std::string response_data
;
13999 rv
= ReadTransaction(trans
.get(), &response_data
);
14001 EXPECT_EQ("hello world", response_data
);
14004 TEST_P(HttpNetworkTransactionTest
, PostReadsErrorResponseAfterResetAnd100
) {
14005 ScopedVector
<UploadElementReader
> element_readers
;
14006 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14007 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14009 HttpRequestInfo request
;
14010 request
.method
= "POST";
14011 request
.url
= GURL("http://www.foo.com/");
14012 request
.upload_data_stream
= &upload_data_stream
;
14013 request
.load_flags
= 0;
14015 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14016 scoped_ptr
<HttpTransaction
> trans(
14017 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14019 MockWrite data_writes
[] = {
14020 MockWrite("POST / HTTP/1.1\r\n"
14021 "Host: www.foo.com\r\n"
14022 "Connection: keep-alive\r\n"
14023 "Content-Length: 3\r\n\r\n"),
14024 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14027 MockRead data_reads
[] = {
14028 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14029 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
14030 MockRead("hello world"),
14031 MockRead(SYNCHRONOUS
, OK
),
14033 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14034 arraysize(data_writes
));
14035 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14037 TestCompletionCallback callback
;
14039 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14040 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14042 rv
= callback
.WaitForResult();
14045 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14046 ASSERT_TRUE(response
!= NULL
);
14048 EXPECT_TRUE(response
->headers
.get() != NULL
);
14049 EXPECT_EQ("HTTP/1.0 400 Not OK", response
->headers
->GetStatusLine());
14051 std::string response_data
;
14052 rv
= ReadTransaction(trans
.get(), &response_data
);
14054 EXPECT_EQ("hello world", response_data
);
14057 TEST_P(HttpNetworkTransactionTest
, PostIgnoresNonErrorResponseAfterReset
) {
14058 ScopedVector
<UploadElementReader
> element_readers
;
14059 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14060 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14062 HttpRequestInfo request
;
14063 request
.method
= "POST";
14064 request
.url
= GURL("http://www.foo.com/");
14065 request
.upload_data_stream
= &upload_data_stream
;
14066 request
.load_flags
= 0;
14068 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14069 scoped_ptr
<HttpTransaction
> trans(
14070 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14071 // Send headers successfully, but get an error while sending the body.
14072 MockWrite data_writes
[] = {
14073 MockWrite("POST / HTTP/1.1\r\n"
14074 "Host: www.foo.com\r\n"
14075 "Connection: keep-alive\r\n"
14076 "Content-Length: 3\r\n\r\n"),
14077 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14080 MockRead data_reads
[] = {
14081 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
14082 MockRead("hello world"),
14083 MockRead(SYNCHRONOUS
, OK
),
14085 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14086 arraysize(data_writes
));
14087 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14089 TestCompletionCallback callback
;
14091 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14092 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14094 rv
= callback
.WaitForResult();
14095 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14098 TEST_P(HttpNetworkTransactionTest
,
14099 PostIgnoresNonErrorResponseAfterResetAnd100
) {
14100 ScopedVector
<UploadElementReader
> element_readers
;
14101 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14102 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14104 HttpRequestInfo request
;
14105 request
.method
= "POST";
14106 request
.url
= GURL("http://www.foo.com/");
14107 request
.upload_data_stream
= &upload_data_stream
;
14108 request
.load_flags
= 0;
14110 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14111 scoped_ptr
<HttpTransaction
> trans(
14112 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14113 // Send headers successfully, but get an error while sending the body.
14114 MockWrite data_writes
[] = {
14115 MockWrite("POST / HTTP/1.1\r\n"
14116 "Host: www.foo.com\r\n"
14117 "Connection: keep-alive\r\n"
14118 "Content-Length: 3\r\n\r\n"),
14119 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14122 MockRead data_reads
[] = {
14123 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
14124 MockRead("HTTP/1.0 302 Redirect\r\n"),
14125 MockRead("Location: http://somewhere-else.com/\r\n"),
14126 MockRead("Content-Length: 0\r\n\r\n"),
14127 MockRead(SYNCHRONOUS
, OK
),
14129 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14130 arraysize(data_writes
));
14131 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14133 TestCompletionCallback callback
;
14135 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14136 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14138 rv
= callback
.WaitForResult();
14139 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14142 TEST_P(HttpNetworkTransactionTest
, PostIgnoresHttp09ResponseAfterReset
) {
14143 ScopedVector
<UploadElementReader
> element_readers
;
14144 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14145 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14147 HttpRequestInfo request
;
14148 request
.method
= "POST";
14149 request
.url
= GURL("http://www.foo.com/");
14150 request
.upload_data_stream
= &upload_data_stream
;
14151 request
.load_flags
= 0;
14153 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14154 scoped_ptr
<HttpTransaction
> trans(
14155 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14156 // Send headers successfully, but get an error while sending the body.
14157 MockWrite data_writes
[] = {
14158 MockWrite("POST / HTTP/1.1\r\n"
14159 "Host: www.foo.com\r\n"
14160 "Connection: keep-alive\r\n"
14161 "Content-Length: 3\r\n\r\n"),
14162 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14165 MockRead data_reads
[] = {
14166 MockRead("HTTP 0.9 rocks!"),
14167 MockRead(SYNCHRONOUS
, OK
),
14169 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14170 arraysize(data_writes
));
14171 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14173 TestCompletionCallback callback
;
14175 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14176 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14178 rv
= callback
.WaitForResult();
14179 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14182 TEST_P(HttpNetworkTransactionTest
, PostIgnoresPartial400HeadersAfterReset
) {
14183 ScopedVector
<UploadElementReader
> element_readers
;
14184 element_readers
.push_back(new UploadBytesElementReader("foo", 3));
14185 ElementsUploadDataStream
upload_data_stream(element_readers
.Pass(), 0);
14187 HttpRequestInfo request
;
14188 request
.method
= "POST";
14189 request
.url
= GURL("http://www.foo.com/");
14190 request
.upload_data_stream
= &upload_data_stream
;
14191 request
.load_flags
= 0;
14193 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14194 scoped_ptr
<HttpTransaction
> trans(
14195 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14196 // Send headers successfully, but get an error while sending the body.
14197 MockWrite data_writes
[] = {
14198 MockWrite("POST / HTTP/1.1\r\n"
14199 "Host: www.foo.com\r\n"
14200 "Connection: keep-alive\r\n"
14201 "Content-Length: 3\r\n\r\n"),
14202 MockWrite(SYNCHRONOUS
, ERR_CONNECTION_RESET
),
14205 MockRead data_reads
[] = {
14206 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
14207 MockRead(SYNCHRONOUS
, OK
),
14209 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14210 arraysize(data_writes
));
14211 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14213 TestCompletionCallback callback
;
14215 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14216 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14218 rv
= callback
.WaitForResult();
14219 EXPECT_EQ(ERR_CONNECTION_RESET
, rv
);
14222 // Verify that proxy headers are not sent to the destination server when
14223 // establishing a tunnel for a secure WebSocket connection.
14224 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWssTunnel
) {
14225 HttpRequestInfo request
;
14226 request
.method
= "GET";
14227 request
.url
= GURL("wss://www.example.org/");
14228 AddWebSocketHeaders(&request
.extra_headers
);
14230 // Configure against proxy server "myproxy:70".
14231 session_deps_
.proxy_service
.reset(
14232 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14234 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14236 // Since a proxy is configured, try to establish a tunnel.
14237 MockWrite data_writes
[] = {
14239 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14240 "Host: www.example.org\r\n"
14241 "Proxy-Connection: keep-alive\r\n\r\n"),
14243 // After calling trans->RestartWithAuth(), this is the request we should
14244 // be issuing -- the final header line contains the credentials.
14246 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14247 "Host: www.example.org\r\n"
14248 "Proxy-Connection: keep-alive\r\n"
14249 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14252 "GET / HTTP/1.1\r\n"
14253 "Host: www.example.org\r\n"
14254 "Connection: Upgrade\r\n"
14255 "Upgrade: websocket\r\n"
14256 "Origin: http://www.example.org\r\n"
14257 "Sec-WebSocket-Version: 13\r\n"
14258 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14261 // The proxy responds to the connect with a 407, using a persistent
14263 MockRead data_reads
[] = {
14265 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14266 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14267 MockRead("Proxy-Connection: close\r\n\r\n"),
14269 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14271 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14272 MockRead("Upgrade: websocket\r\n"),
14273 MockRead("Connection: Upgrade\r\n"),
14274 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14277 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14278 arraysize(data_writes
));
14279 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14280 SSLSocketDataProvider
ssl(ASYNC
, OK
);
14281 session_deps_
.socket_factory
->AddSSLSocketDataProvider(&ssl
);
14283 scoped_ptr
<HttpTransaction
> trans(
14284 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14285 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14286 trans
->SetWebSocketHandshakeStreamCreateHelper(
14287 &websocket_stream_create_helper
);
14290 TestCompletionCallback callback
;
14292 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14295 rv
= callback
.WaitForResult();
14299 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14300 ASSERT_TRUE(response
);
14301 ASSERT_TRUE(response
->headers
.get());
14302 EXPECT_EQ(407, response
->headers
->response_code());
14305 TestCompletionCallback callback
;
14307 int rv
= trans
->RestartWithAuth(AuthCredentials(kFoo
, kBar
),
14308 callback
.callback());
14309 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14311 rv
= callback
.WaitForResult();
14315 response
= trans
->GetResponseInfo();
14316 ASSERT_TRUE(response
);
14317 ASSERT_TRUE(response
->headers
.get());
14319 EXPECT_EQ(101, response
->headers
->response_code());
14322 session
->CloseAllConnections();
14325 // Verify that proxy headers are not sent to the destination server when
14326 // establishing a tunnel for an insecure WebSocket connection.
14327 // This requires the authentication info to be injected into the auth cache
14328 // due to crbug.com/395064
14329 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
14330 TEST_P(HttpNetworkTransactionTest
, ProxyHeadersNotSentOverWsTunnel
) {
14331 HttpRequestInfo request
;
14332 request
.method
= "GET";
14333 request
.url
= GURL("ws://www.example.org/");
14334 AddWebSocketHeaders(&request
.extra_headers
);
14336 // Configure against proxy server "myproxy:70".
14337 session_deps_
.proxy_service
.reset(
14338 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"));
14340 scoped_refptr
<HttpNetworkSession
> session(CreateSession(&session_deps_
));
14342 MockWrite data_writes
[] = {
14343 // Try to establish a tunnel for the WebSocket connection, with
14344 // credentials. Because WebSockets have a separate set of socket pools,
14345 // they cannot and will not use the same TCP/IP connection as the
14346 // preflight HTTP request.
14348 "CONNECT www.example.org:80 HTTP/1.1\r\n"
14349 "Host: www.example.org:80\r\n"
14350 "Proxy-Connection: keep-alive\r\n"
14351 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
14354 "GET / HTTP/1.1\r\n"
14355 "Host: www.example.org\r\n"
14356 "Connection: Upgrade\r\n"
14357 "Upgrade: websocket\r\n"
14358 "Origin: http://www.example.org\r\n"
14359 "Sec-WebSocket-Version: 13\r\n"
14360 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"),
14363 MockRead data_reads
[] = {
14364 // HTTP CONNECT with credentials.
14365 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
14367 // WebSocket connection established inside tunnel.
14368 MockRead("HTTP/1.1 101 Switching Protocols\r\n"),
14369 MockRead("Upgrade: websocket\r\n"),
14370 MockRead("Connection: Upgrade\r\n"),
14371 MockRead("Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
14374 StaticSocketDataProvider
data(data_reads
, arraysize(data_reads
), data_writes
,
14375 arraysize(data_writes
));
14376 session_deps_
.socket_factory
->AddSocketDataProvider(&data
);
14378 session
->http_auth_cache()->Add(
14379 GURL("http://myproxy:70/"), "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC
,
14380 "Basic realm=MyRealm1", AuthCredentials(kFoo
, kBar
), "/");
14382 scoped_ptr
<HttpTransaction
> trans(
14383 new HttpNetworkTransaction(DEFAULT_PRIORITY
, session
.get()));
14384 FakeWebSocketStreamCreateHelper websocket_stream_create_helper
;
14385 trans
->SetWebSocketHandshakeStreamCreateHelper(
14386 &websocket_stream_create_helper
);
14388 TestCompletionCallback callback
;
14390 int rv
= trans
->Start(&request
, callback
.callback(), BoundNetLog());
14391 EXPECT_EQ(ERR_IO_PENDING
, rv
);
14393 rv
= callback
.WaitForResult();
14396 const HttpResponseInfo
* response
= trans
->GetResponseInfo();
14397 ASSERT_TRUE(response
);
14398 ASSERT_TRUE(response
->headers
.get());
14400 EXPECT_EQ(101, response
->headers
->response_code());
14403 session
->CloseAllConnections();